Click here to Skip to main content
11,481,404 members (63,056 online)
Click here to Skip to main content
Add your own
alternative version

Understanding Custom Marshaling Part 1

, 18 Aug 2006 CPOL 132.3K 993 139
Learn the fundamental principles of COM custom marshaling by code examples.
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
#ifndef UTILITIES_H
  #define UTILITIES_H
  
#include <windows.h>
#include <vector>
using namespace std;

typedef vector<HANDLE>		HANDLE_VECTOR;

DWORD ThreadMsgWaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);

DWORD ThreadMsgWaitForMultipleObjects 
(
  DWORD dwCount, 
  LPHANDLE pHandles, 
  BOOL bWaitAll, 
  DWORD dwMilliseconds
);

template <class SmartPtrClass>
bool _CoCreateInstance(LPCTSTR lpszProgID, SmartPtrClass& spSmartPtrReceiver)
{
  HRESULT			hrRetTemp = S_OK;
  _bstr_t			bstProgID(lpszProgID);
  CLSID				clsid;
  bool				bRet = false;
  
  hrRetTemp = CLSIDFromProgID
  (
    (LPCOLESTR)bstProgID,  //Pointer to the ProgID
    (LPCLSID)&clsid         //Pointer to the CLSID
  );

  if (hrRetTemp == S_OK)
  {
    hrRetTemp = spSmartPtrReceiver.CoCreateInstance(clsid);

	if (SUCCEEDED(hrRetTemp))
	{
	  bRet = true;
	}
	else
	{
	  bRet = false;
	}
  }

  return bRet;
}





/* LowLevelInProcMarshalInterface() uses low-level APIs       */
/* CreateStreamOnHGlobal(), CoMarshalInterface(), and IStream */
/* methods to perform interface pointer marshalling across    */
/* apartments in a process.                                   */
/*                                                            */
template <typename T>
LPSTREAM LowLevelInProcMarshalInterface(T* pInterface, REFIID riid)
{
  IUnknown*		pIUnknown = NULL;
  IStream*		pIStreamRet = NULL;

  /* QI the original interface pointer for its IUnknown interface. */
  pInterface -> QueryInterface (IID_IUnknown, (void**)&pIUnknown);

  /* Once we get the IUnknown pointer, we serialize it into a stream of bytes. */
  if (pIUnknown)
  {
    /* Create a Stream Object which will reside in global memory.   */
    /* We set the first parameter to NULL, hence indicating that    */
    /* we want CreateStreamOnHGlobal() to internally allocate       */
    /* a new shared memory block of size zero.                      */
	/* The second parameter is set to TRUE so that when the returned*/
	/* stream object is Release()'d, the global memory will also be */
	/* freed.                                                       */
    ::CreateStreamOnHGlobal
    (
      0,
      TRUE,
      &pIStreamRet
    );

    if (pIStreamRet)
    {
	  LARGE_INTEGER li = { 0 };

      /* We use the new stream object to store the marshalling data */
      /* of spISimpleCOMObject2.                                    */
      /* The use of MSHCTX_INPROC indicates that the unmarshaling   */
      /* of the data in the stream will be done in another apartment*/
      /* in the same process.                                       */
      ::CoMarshalInterface
      (
        pIStreamRet,
        riid,
        (IUnknown*)pIUnknown,
        MSHCTX_INPROC,
        NULL,
        MSHLFLAGS_NORMAL
      );

      /* Always reset the stream to the beginning.*/
	  pIStreamRet -> Seek(li, STREAM_SEEK_SET, NULL);
    }

	pIUnknown -> Release();
	pIUnknown = NULL;
  }

  return pIStreamRet;
}





/* LowLevelInProcUnmarshalInterface() uses low-level APIs     */
/* CoUnmarshalInterface(), CoReleaseMarshalData(), and        */
/* IStream methods to perform interface pointer unmarshalling */
/* for an apartment in a process.                             */
/*                                                            */
template <typename T>
void LowLevelInProcUnmarshalInterface(LPSTREAM pIStream, REFIID riid, T** ppInterfaceReceiver)
{
  /* Deserialize the byte contents of the IStream object */
  /* into an actual interface pointer to be used only    */
  /* within this thread.                                 */
  /*                                                     */
  /* The interface pointer will not be a direct pointer. */
  /* It will be a proxy to the original pointer.         */
  if (pIStream)
  {
	LARGE_INTEGER li = { 0 };
    
    /* Make sure stream pointer is at the beginning of the stream. */
	pIStream -> Seek(li, STREAM_SEEK_SET, NULL);

    if
	(
	  ::CoUnmarshalInterface 
	  (
        pIStream,  //Pointer to the stream
        riid,     //Reference to the identifier of the interface
        (void **)ppInterfaceReceiver      //Address of output variable that receives the 
                   // interface pointer requested in riid
      ) != S_OK
	)
	{
	  /* Since unmarshalling has failed, we call   */
	  /* CoReleaseMarshalData() to destroys the    */
	  /* previously marshaled data packet contained*/
	  /* in pIStream.                              */
	  ::CoReleaseMarshalData(pIStream);
	}

    /* When pIStream is Release()'d the underlying global memory*/
	/* used to store the bytes of the stream is also freed.     */
	pIStream -> Release();
	pIStream = NULL;
  }
}

#endif

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)

Share

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 | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 18 Aug 2006
Article Copyright 2006 by Lim Bio Liong
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid