Marshaling: The process by which parameters are packaged and sent across
apartment, process or machine boundaries. In COM, marshaling is implemented by interface-specific proxies/stubs.
Proxy: An interface-specific COM object that runs in the address space of the caller (sender). Its purpose is to package the parameters specified by the client and then to transmit them to a corresponding stub that lives in the address space of the receiver.
Stub: An interface-specific COM object that runs in the address space of the callee (receiver). Its purpose is to un-package the parameters for that interface after they were marshaled across the process boundary, and then to make the actual method call on the actual object.
Marshaling Mechanism: Marshaling involves two basic steps
In all cases of marshaling, there will be a proxy object on the client side and a stub object on the server side.
| Type | Notes |
| Standard |
|
| Type Library |
|
| Manual |
|
| Custom |
|
Manual marshaling can be implemented in four different ways:
// Thread 1 ( has access to the object)
/* Create an object exposing an IThreadInfo interface */
IThreadInfoPtr spOb( __uuidof(ThreadInfo) );
/* Create a global stream object */
IStream *g_pMarshalPtr;
hr = CreateStreamOnHGlobal
(
NULL, // Allocate a new shared mem block of size 0
TRUE, // Release mem hndl when stream is released
&g_pMarshalPtr // output that gets IStream pointer
);
if (FAILED(hr))
_com_issue_error( hr );
/* Marshal the interface into the global stream object. Note that the
MSHLFLAGS_NORMAL flag means that the interface can be unmarshaled only once
*/
hr = CoMarshalInterface( g_pMarshalPtr,
__uuidof(spOb),
spOb,
MSHCTX_INPROC,
NULL,
MSHLFLAGS_NORMAL );
if ( FAILED(hr) )
{
g_pMarshalPtr->Release();
g_pMarshalPtr = NULL;
_com_issue_error( hr );
}
/* Let the other thread know that we’re done marshaling the interface
*/
SetEvent( g_hEvent );
...
// Thread 2 is requesting an interface on an object from thread 1
(above)
// Wait until the first thread finished marshaling
WaitForSingleObject( g_hEvent, INIFINITE);
// Unmarshal the interface pointer. First point to the beginning of the stream
IThreadInfoPtr spOb;
LARGE_INTEGER l;
l.QuadPart = 0;
g_pMarshalPtr->Seek( l, STREAM_SEEK_SET, NULL);
// Use the stream to unmarshal the interface pointer
hr = CoUnmarshalInterface( g_pMarshalPtr, __uuidof( spOb ), (void**) &spOb);
// Clean up marshaling code
g_pMarshalPtr->Release();
g_pMarshalPtr = NULL;
if (FAILED(hr))
_com_issue_error( hr );
...
ATL wraps the two pieces of code above with AtlMarshalInProc() and
AtlUnmarshalPtr() functions. Internally,
AtlMarshalInProc() uses the MSHLFLAGS_TABLESTRONG flag for
CoMarshalInterface() which means that the interface can be unmarshaled from its stream many times.
Note that AtlMarshalInProcc() an only be used on a pointer to an in-proc
object.
// Thread 1 has access to the object
// Create the object
IThreadInfoPtr spOb( __uuidof(ThreadInfo) );
// Marshal the interface
AtlMarshalInProc( spOb, __uuidof( soOb ), & g_pMarshalPtr );
// Let the other thread know that we’re done marshaling the interface
SetEvent( g_hEvent );
// Thread 2 is requesting an interface on an object from thread 1
// Wait until the first thread finished marshaling
WaitForSingleObject( g_hEvent , INFINITE);
// Unmarshal the interface pointer. First point to the beginning of the stream
IThreadInfoPtr spOb;
AtlUnmarshalPtr( g_pMarshalPtr, , __uuidof( spOb ), (IUnknown**) &spOb)
// Use the object
spOb->SomeMethod();
// When you don’t want to marshal the interface any more, release the stream
AtlFreeMarshalStream( g_pMarshalPtr );
CoMarshalInterThreadInterfaceInStream() is the same as
AtlMarshlPtrInProc() except that the former uses normal marshaling as opposed to strong table marshaling by the latter.
CoGetInterfaceAndReleaseStream() is equivalent to
calling AtlMarshalPtr() then AtlFreeMarshalStream().
When a client request that an object be created, COM will always QI for IMarshal. When a client queries for another interface on an object, COM will also QI for IMarshal.
If no interface is returned, COM uses standard marshaling (proxy/stub DLL or Universal Marshaler).
If IMarshal was supported, then COM will marshal the interface using the custom marshaling implemented by the object. This custom marshaling goes something like this –
The purpose of this section is to provide an overview of the standard marshaling architecture. This overview is for reading only to know what is going on under the hood. It helps to understand the overall picture.
Standard marshaling is used when we have built & registered the proxy/stub DLL or we are using type library marshaling. We cannot control it. It all happens automatically. How it happens is summarized below

This section will identify all components used in standard marshaling. How these components interact will then be discussed.
Interface Proxy: Interface-specific piece of code living in the address space of the client. It is responsible for marshaling arguments, and for unmarshaling return values and out parameters, that are passed back and forth in subsequent calls to its remote interface.
Proxy Manager: A COM object provided by the COM library that manages the client object identity and which dynamically loads the interface proxies as needed (as per QueryInterface calls). The object exposes IUnknown and IMarshal interfaces.
Object Proxy: A COM object created by the COM library that results from aggregating the interface proxies and the proxy manager. All the interfaces exposed by the interface proxies and the proxy manager are therefore, exposed by the object proxy through aggregation. A client holding a pointer to the object proxy “believes” it is holding a pointer to the actual object
Interface Stub: Interface-specific piece of code living in the address space of the server. It is responsible for unmarshaling arguments and pass them along to the original object. It also marshals the return values and out parameters that the object returns.
For any interface, the proxy and stub are implemented in the same class which is listed for each interface in the system registry under ProxyStubClsid32. This entry maps the interface’s IID to the CLSID of its proxy/stub object. When COM needs to marshal an interface, it looks up the CLSID identified by ProxyStubClsid32 and then it loads it up. This class can be either the one generated by the MIDL if proxy/stub DLL was built from ATL’s code, or it can be OLEAUT32.DLL is type library marshaling was used.
Stub Manager: A conceptual COM object created by COM to uniquely identify a COM object across a network. Therefore, each COM object using standard marshaling will have a stub manager.
RPC Channel: The proxy and stub communicate with each other using the RPC channel which is a piece of code that provides infrastructure for interprocess communication. The RPC channel implements IRpcChannelBuffer interface which is used by both the proxy and stub to exchange marshaling data.
| Action : The client creates an object | |
| Client | Server |
| COM library loads the object server into memory | |
| Action: Client requests a pointer to an interface for the first time | |
| Client | Server |
| 1. COM creates an IClassFactory stub and uses it to marshal the pointer back to the client. | |
| 1. COM loads the proxy manager for the class factory. COM then calls its IMarshal implementation to unmarshal the IClassFactory pointer. | |
| 2. COM creates an interface proxy for the class factory and hands it a pointer to the RPC channel. The combination of steps 1 & 2 are aggregated to give us the proxy object. Note: The interface proxy exposes its own interface (IClassFactory) directly to the client. | |
| 3. COM returns the IClassFactory pointer to the client that uses it to call IClassFactory::CreateInstance() passing it the required IID | |
| 2. COM now creates a new instance of the object. | |
| 3. COM also creates an interface stub for the requested interface. The stub is now used to marshal the interface pointer back to the client. | |
|
Note: The above three steps are new repeated for the requested interface
4. COM loads the proxy manager for the COM object that exposes the requested interface. COM then calls its IMarshal implementation to unmarshal the requested pointer. |
|
|
5. COM creates an interface proxy for the requested interface and hands it a pointer to the RPC channel. The combination of steps 4 & 5 are aggregated to give us the proxy
object. Note: The interface proxy exposes its own interface (the requested interface)) directly to the client. |
|
| 6. COM returns the requested interface back to the client which can now use to invoke methods on the object. | |
| Action: Client invokes a method on the interface | |
| Client | Server |
| 1. The interface pointer that the client has is exposed directly from the interface proxy which also has an unexposed interface, IRpcChannelBuffer. The interface proxy calls IRpcChannelBuffer::GetBuffer to obtain a marshaling packet from its RPC channel | |
| 2. The interface proxy marshals the method arguments into this buffer | |
| 3. When marshaling is complete, the interface proxy invokes IRpcChannelBuffer::SendReceive to send the marshaling packet to the stub (IRpcChannelBuffer::SendReceive knows how to identify the server process and the object within the server process.) | |
| 1. The interface stub receives the packet sent by IRpcChannelBuffer::SendReceive and it unmarshals the arguments. | |
| 2. The interface stub then calls the actual object method, and marshals the return values into a new buffer allocated by IRpcChannelBuffer::GetBuffer. The channel then transmits the data into the interface proxy which is still in the middle of the IRpcChannelBuffer::SendReceive function call. | |
| 4. When IRpcChannelBuffer::SendReceive returns, its buffer would have been replaced by a new buffer containing values marshaled by the interface stub. The interface proxy now unmarshals these values and invokes IRpcChannelBuffer::FreeBuffer to free the buffer. | |
| 5.The interface proxy finally returns the unmarshaled data to the client. | |