IMarshal (Compact 2013)

3/26/2014

This interface enables a COM object to define and manage the marshaling of its interface pointers. The alternative is to use COM's default implementation, the preferred choice in all but a few special cases (see the When to Implement section).

Marshaling is the process of packaging data into packets for transmission to a different process or machine. Unmarshaling is the process of recovering that data at the receiving end. In any given call, method arguments are marshaled and unmarshaled in one direction, while return values are marshaled and unmarshaled in the other.

Although marshaling applies to all data types, interface pointers require special handling. The fundamental problem is how client code running in one address space can correctly dereference a pointer to an interface on an object residing in a different address space.

COM's solution is for a client application to communicate with the original object through a surrogate object, or proxy, which lives in the client's process. The proxy holds a reference to an interface on the original object and hands the client a pointer to an interface on itself.

When the client calls an interface method on the original object, its call is actually going to the proxy. Therefore, from the client's point of view, all calls are in-process.

On receiving a call, the proxy marshals the method arguments and, through some means of interprocess communication, such as RPC, passes them along to code in the server process, which unmarshals the arguments and passes them to the original object.

This same code marshals return values for transmission back to the proxy, which unmarshals the values and passes them to the client application.

IMarshal provides methods for creating, initializing, and managing a proxy in a client process; it does not dictate how the proxy should communicate with the original object. COM's default implementation of IMarshal uses RPC.

When you implement this interface yourself, you are free to choose any method of interprocess communication you deem to be appropriate for your application - shared memory, window handle, RPC - in short, whatever works.

When to Implement

Implement IMarshal only when you believe that you can realize significant optimizations to COM's default implementation. In practice, this will rarely be the case. However, there are occasions where implementing IMarshal can be preferred:

  • The objects you are writing keep their state in shared memory. In this case, both the original process and the client process uses proxies that refer to the shared memory.
    This type of custom marshaling is possible only if the client process is on the same machine as the original process. COM-provided implementations of IStorage and IStream are examples of this type of custom marshaling.
  • The objects you are writing are immutable, that is, their state does not change after creation. Instead of forwarding method calls to the original objects, you simply create copies of those objects in the client process.
    This technique avoids the cost of switching from one process to another. Some monikers are examples of immutable objects; if you are implementing your own moniker class, you should evaluate the costs and benefits of implementing IMarshal on your moniker objects.
  • Objects that themselves are proxy objects can use custom marshaling to avoid creating proxies to proxies. Instead, the existing proxy can refer new proxies back to the original object.
    This capability is important for the sake of both efficiency and robustness.
  • Your server application wants to manage how calls are made across the network without affecting the interface exposed to clients.
    For example, if a user were making changes to a database record, the server might want to cache the changes until the user has committed them all, at which time the entire transaction would be forwarded in a single packet. Using a custom proxy would enable the caching and batching of changes in this way.

When you choose to implement IMarshal, you must do so for both your original object and the proxy you create for it. When implementing the interface on either object or proxy, you simply return E_NOTIMPL for the methods that are not implemented.

COM uses your implementation of IMarshal in the following manner:

  • When it is necessary to create a remote interface pointer to your object (that is, when a pointer to your object is passed as an argument in a remote function call), COM queries your object for the IMarshal interface.
  • If your object implements it, COM uses your IMarshal implementation to create the proxy object.
  • If your object does not implement IMarshal, COM uses its default implementation.

How you structure the proxy is up to you:

  • You can write the proxy to use whatever mechanisms you deem appropriate for communicating with the original object.
  • You can also create the proxy as either a stand-alone object or as part of a larger aggregation such as a handler.

However you choose to structure the proxy, it must implement IMarshal to work at all. You must also generate a CLSID for the proxy to be returned by your implementation of IMarshal::GetUnmarshalClass on the original object.

When to Use

COM calls this interface as part of system-provided marshaling support. COM's calls are wrapped in calls to CoMarshalInterface and CoUnmarshalInterface.

Your code typically will not need to call this interface. Special circumstances where you might choose to do so are discussed in the Notes to Callers section for each method.

Methods in Vtable Order

IUnknown method

Description

QueryInterface

Returns pointers to supported interfaces.

AddRef

Increments the reference count.

Release

Decrements the reference count.

Method

Description

GetUnmarshalClass

Returns CLSID of unmarshaling code.

GetMarshalSizeMax

Returns size of buffer needed during marshaling.

MarshalInterface

Marshals an interface pointer.

UnmarshalInterface

Unmarshals an interface pointer.

ReleaseMarshalData

Destroys a marshaled data packet.

DisconnectObject

Severs all connections.

Remarks

To determine whether the platform supports this interface, see Determining Supported COM APIs.

Requirements

Header

objidl.h,
objidl.idl

Library

ole32.lib,
uuid.lib

See Also

Reference

COM Interfaces
IMarshal Default Implementation
IStdMarshalInfo