1.3 Overview
The IManagedObject interface is a COM interface used by the common language runtime (CLR) to identify managed objects (objects created by the CLR) that are exported for interoperability with the Component Object Model (COM). The IManagedObject interface allows these objects to be identified when they reenter the CLR.
The IManagedObject interface is used specifically for scenarios in which managed code uses COM and interacts with a managed object. This interface is an optimization that allows managed code to avoid going through COM to interact with the managed object. There are two different scenarios in which this can occur: Either the managed object is within the same process division, the same application domain, or the managed object is in a different process division (application domain). In either case, this document discusses what is done instead of using DCOM [MS-DCOM] to interact between the CLR and managed objects.
When using COM, the COM Callable Wrapper (CCW) is the view of the object to COM, as defined in [MSDN-CCW]. When the CLR identifies a COM object that includes a CCW, a Runtime Callable Wrapper (RCW) is required in order to interact with the COM object, as defined in [MSDN-RCW]. If an RCW doesn't exist, the CLR attempts to create an RCW. If the object implements IManagedObject, the CLR determines that it is a .NET object. For more information on CCW and RCW, see [MSDN-CCW] and [MSDN-RCW].
In cases in which the .NET object is in the same process division, the CLR interacts directly with the .NET object.

Figure 1: CLR interacts directly with .NET object
The steps describing the CLR and the .NET object interaction are as follows:
A COM object, which is a CCW wrapping a local CLR object, reenters the CLR through a COM call. The CLR calls the QueryInterface method on the CCW for the IManagedObject interface in order to determine whether this COM object is a CCW or not.
Since the COM object is a CCW, it returns the IManagedObject call with S_OK and a pointer to its IManagedObject interface.
The CLR calls IManagedObject::GetObjectIdentity on the IManagedObject interface obtained in step 2 in order to determine if the object is local to the current process and application domain.
The CCW responds back with its ID, and the CLR notes that this ID is local to the current process and application domain.
As established in step 4, the wrapped object belongs to this instance of the CLR, and the CLR can interact with the object directly instead of going through an RCW / CCW pair and communicating over a COM channel.
In cases in which the .NET object is in a different process division (different application domain or process), a remoting proxy is used to interact with the .NET object. In such a case, the CCW implementing IManagedObject returns a Server Object Identity / AppDomainID from IManagedObject::GetObjectIdentity that does not correspond to the current process. The CLR will then ask for the remoting ID for the object (IManagedObject::GetSerializedBuffer). This can be used to generate a transparent remoting proxy to communicate to the original object. At this point, the communication endpoints are now remoting .NET objects, and CCWs / RCWs are not used:

Figure 2: CLR interacts via remoting proxy
The steps describing the CLR interaction via remoting proxy are as follows:
A COM object, which is a CCW wrapping a CLR object, from a different application domain or process enters the CLR through a COM call. The CLR calls the QueryInterface method on the CCW for the IManagedObject interface in order to determine whether this COM object is a CCW or not.
Because the COM object is a CCW, it responds to the QueryInterface call with S_OK and a pointer to its IManagedObject interface.
The CLR calls IManagedObject::GetObjectIdentity on the IManagedObject interface obtained in step 2 in order to determine whether the object is local to the current process and application domain.
The CCW responds back with its ID, and the CLR notes that this ID is not local to the current process and application domain.
The CLR calls IManagedObject::GetSerializedBuffer to get information to set up a .NET Remoting connection to the remote CLR object.
The CCW responds back with the remoting information.
The CLR uses the remoting information obtained in step 6 to create a remoting proxy that communicates with the .NET object via .NET Remoting, rather than using an RCW/CCW pair and communicating over a COM channel.
CLR-managed objects can be exposed to COM clients as COM objects. They can implement any number of COM interfaces, but all such exported objects implement IManagedObject.
The CLR also allows COM objects to be imported and used as managed objects. In this case, IManagedObject is used to determine if an object is truly a COM object or if it is actually originated as a CLR-managed object.
When a COM object enters the CLR, the CLR uses the standard COM interface querying mechanism (QueryInterface) to determine if the given object implements IManagedObject. If the object supports IManagedObject, IManagedObject::GetObjectIdentity is called.
At CLR instantiation, the CLR creates a unique GUID to identify a specific CLR instance within a given process. This GUID is formatted as a string ([MS-DTYP] section 2.3.4.3) and is saved. All CLR-managed objects originating from this specific instance of the CLR will return this unique identifier as the first parameter of the call to IManagedObject::GetObjectIdentity. This GUID is used to recognize that an imported managed object originated in this runtime.
The CLR can support even finer-grained levels of grouping than the process. Objects exported from a given process division are tagged and return the identifier used for process division in their second parameter to IManagedObject::GetObjectIdentity. This identifier is also used to indicate whether or not the given object originated in the correct process division. If the process identifier and process division match, the last parameter of IManagedObject::GetObjectIdentity is a pointer to the implementation-specific representation of the managed object.
If the given object does not match the current CLR instance and process division, IManagedObject::GetSerializedBuffer is called to return a binary representation of a managed object, as specified by the .NET Remoting: Binary Format Data Structure [MS-NRBF]. It is the responsibility of the caller on the client CLR to interpret the deserialized opaque object reference.

Figure 3: IManagedObject request-response