Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Understanding Custom Marshaling Part 1

, 18 Aug 2006
Learn the fundamental principles of COM custom marshaling by code examples.
Prize winner in Competition "MFC/C++ Jul 2006"
custommarshaling01_src.zip
utilities
BasicSample01
Interfaces
Implementations
Clients
BasicSample01Interfaces
BasicSample01Interfaces.aps
BasicSample01Interfaces.def
BasicSample01Interfaces.ncb
BasicSample01Interfaces.rgs
BasicSample01Interfacesps.def
Immutable.rgs
ImmutableObjectFactory.rgs
BasicSample01Interfaces.vcproj.vspscc
BasicSample01InterfacesPS.vcproj.vspscc
BasicSample01InterfacesImpl
BasicSample01InterfacesImpl.aps
BasicSample01InterfacesImpl.def
BasicSample01InterfacesImpl.rgs
BasicSample01InterfacesImplps.def
ImmutableImpl.rgs
ImmutableObjectFactoryImpl.rgs
BasicSample01InterfacesImpl.ncb
BasicSample01InterfacesImpl.vcproj.vspscc
BasicSample01InterfacesImplPS.vcproj.vspscc
VCConsoleClient01
VCConsoleClient03
VCConsoleClient02
VCConsoleClient01.ncb
VCConsoleClient03.ncb
VCConsoleClient02.ncb
// ImmutableImpl.h : Declaration of the CImmutableImpl

#pragma once
#include "resource.h"       // main symbols

#include "BasicSample01InterfacesImpl.h"


// CImmutableImpl

class ATL_NO_VTABLE CImmutableImpl : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CImmutableImpl, &CLSID_ImmutableImpl>,
	public IDispatchImpl<IImmutableImpl, &IID_IImmutableImpl, &LIBID_BasicSample01InterfacesImplLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public IDispatchImpl<IImmutable, &__uuidof(IImmutable), &LIBID_BasicSample01InterfacesLib, /* wMajor = */ 1, /* wMinor = */ 0>,
	public IMarshal
{
public:
	CImmutableImpl() :
	  m_lLongValue(0)
	{
	}
	
	~CImmutableImpl()
	{
	}	

	DECLARE_REGISTRY_RESOURCEID(IDR_IMMUTABLEIMPL)


	BEGIN_COM_MAP(CImmutableImpl)
	    COM_INTERFACE_ENTRY(IMarshal)
		COM_INTERFACE_ENTRY(IImmutableImpl)
		COM_INTERFACE_ENTRY2(IDispatch, IImmutable)
		COM_INTERFACE_ENTRY(IImmutable)
	END_COM_MAP()


	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease() 
	{
	}

public:


	// IImmutable Methods
public:
	STDMETHOD(get_LongValue)(long * pVal)
	{
	    *pVal = m_lLongValue;
	    
		return S_OK;
	}
	
	// IMarshal Methods.
	/*! IMarshal implementation.
	The CoMarshalInterface() API will call GetUnmarshalClass()
	Here, we will indicate to CoMarshalInterface() the CLSID
	of the object that will take charge of unmarshaling
	the interface pointers of this current object.
	*/
	STDMETHOD(GetUnmarshalClass) (REFIID riid, void * pv, DWORD dwDestContext, void * pvDestContext, DWORD mshlFlags, CLSID* pCid )
	{
	    // The class that will perform the unmarshaling will be
	    // this class itslf.
	    *pCid = GetObjectCLSID();

		return S_OK;
	}
	
	/*!
	The CoMarshalInterface() API will call GetMarshalSizeMax().
	Here, we will indicate to CoMarshalInterface() the total 
	size of the marshaled object reference.\n
	
	The marshaled object reference will end up being serialized
	and marshaled across to a target apartment.\n
	
	It should contain information that will help the proxy 
	to uniquely identify and establish connection with this object
	in order to invoke its properties and methods.\n
	
	*/
	STDMETHOD(GetMarshalSizeMax) (REFIID riid, void * pv, DWORD dwDestContext, void * pvDestContext, DWORD mshlFlags, ULONG* pSize )
	{
		HRESULT hr = S_OK;

		*pSize = sizeof(CImmutableMarshaledObjectReferenceStruct);

		return hr;
	}

	STDMETHOD(MarshalInterface)  (IStream* pStm, REFIID riid, void *pv, DWORD dwDestContext, void * pvDestContext, DWORD mshlFlags)
	{		    
	    if (dwDestContext != MSHCTX_INPROC)
	    {
	      return E_FAIL;
	    }
	    
	    CImmutableMarshaledObjectReferenceStruct ImmutableMarshaledObjectReferenceStruct;
	    
	    ImmutableMarshaledObjectReferenceStruct.lLongValue = m_lLongValue;
	    
	    *pStm << ImmutableMarshaledObjectReferenceStruct;
	    
	    return S_OK;
	}

	// It is the Proxy which will perform the UnmarshalInterface().
	// The object itself is the proxy and so during UnmarshalInterface(),
	// it is re-constructed from the input marshaling object reference
	// contained inside pStm.
	STDMETHOD(UnmarshalInterface)(IStream* pStm, REFIID riid, void ** ppv )
	{
	    CImmutableMarshaledObjectReferenceStruct	ImmutableMarshaledObjectReferenceStruct;
		
		*pStm >> (CImmutableMarshaledObjectReferenceStruct&)ImmutableMarshaledObjectReferenceStruct;

		m_lLongValue = ImmutableMarshaledObjectReferenceStruct.lLongValue;
		
		return QueryInterface(riid, ppv);
	}

    // This method is COM's way of indicating to an object (which has been marshaled) 
    // that a marshaled object packet is being destroyed. 
    // A marshaled object reference can be considered an additional reference
    // to an object. Hence, a call to ReleaseMarshalData() should signal 
    // an object to perform reference count state management.
    //
    // However it is not significant in our basic example, as will be the case for most 
    // "Marshal-by-value" proxies. This is because a "Marshal-by-value" proxy is independent
    // of its original object.
	STDMETHOD (ReleaseMarshalData)(IStream *pStm)
	{
		return S_OK;
	}
    
    // The usual case in which this method is called occurs when an end user 
    // forcibly closes a COM server (usually an EXE server) that has one or 
    // more running objects that implement IMarshal. 
    //
    // Under normal circumstances too, prior to shutting down, the server 
    // needs to call the CoDisconnectObject() helper function to release 
    // external connections to all its running objects. 
    // For each object that implements IMarshal, however, this function calls 
    // IMarshal::DisconnectObject() so that each object that manages its own 
    // marshaling can take steps to notify its proxy that it is about to 
    // shut down.
    //
    // The outcome of any implementation of this method should be to enable 
    // a proxy to respond to all subsequent calls from its client by returning 
    // RPC_E_DISCONNECTED or CO_E_OBJECTNOTCONNECTED rather than attempting 
    // to forward the calls on to the original object. Note that it is up to 
    // the client to destroy the proxy.
    //
    // Because CImmutableImpl is an immutable object, its implementation doesn't 
    // need to do anything because its instances will be copied whole into the 
    // client's address space. Therefore, they have neither a proxy nor a connection 
    // to the original object.
    // 
    STDMETHOD (DisconnectObject)(DWORD dwReserved)
	{
		return S_OK;
	}			

protected :
	long			m_lLongValue;

// Non-COM public methods.
public :
	void			SetLongValue(long lLongValue)
	{
	  m_lLongValue = lLongValue;
	}	
};

OBJECT_ENTRY_AUTO(__uuidof(ImmutableImpl), CImmutableImpl)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Lim Bio Liong
Web Developer
Singapore Singapore
Lim Bio Liong is a Specialist at a leading Software House in Singapore.
 
Bio has been in software development for over 10 years. He specialises in C/C++ programming and Windows software development.
 
Bio has also done device-driver development and enjoys low-level programming. Bio has recently picked up C# programming and has been researching in this area.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 18 Aug 2006
Article Copyright 2006 by Lim Bio Liong
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid