- custommarshaling01_src.zip
- BasicSample01
- Clients
- VCConsoleClient01
- VCConsoleClient02
- VCConsoleClient03
- Implementations
- BasicSample01InterfacesImpl
- Interfaces
- BasicSample01Interfaces
- utilities
|
// VCConsoleClient03.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// Global event object handle that will be signalled when
// an interface of a custom marshaled object has been
// marshaled into a stream. This will signal a receiving
// thread that unmarshaling can now be performed.
HANDLE g_hInterfaceMarshaled = NULL;
DWORD WINAPI ThreadFunc_CustomMarshaledObject(LPVOID lpvParameter)
{
MSG msg;
long lLong = 0;
IGlobalInterfaceTable* pIGlobalInterfaceTable = NULL;
DWORD dwGITCookie = 0;
DWORD* pdwGITCookieReceiver = (DWORD*)lpvParameter;
// This thread will be thread of an STA.
::CoInitialize(NULL);
// There is a single instance of the global interface
// table per process.
// Hence all calls in a process to create it will
// return the same instance.
CoCreateInstance
(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pIGlobalInterfaceTable
);
if (pIGlobalInterfaceTable)
{
IImmutableObjectFactoryPtr spIImmutableObjectFactory = NULL;
IImmutablePtr spIImmutable = NULL;
IUnknown* pIUnknown = NULL;
// Create an instance of the COM object which has ProgID
// "BasicSample01InterfacesImpl.ImmutableObjectFactoryImpl" and manage it
// via its IImmutableObjectFactory interface.
// Now, because the resultant object (spIImmutableObjectFactory) is an STA object,
// and this thread is an STA thread, spIImmutableObjectFactory will live in the
// same STA as this thread.
_CoCreateInstance("BasicSample01InterfacesImpl.ImmutableObjectFactoryImpl", spIImmutableObjectFactory);
// Get the IImmutable object from spIImmutableObjectFactory.
// Now because spIImmutable is also an STA object, it will live in the
// same STA as this thread.
spIImmutableObjectFactory -> CreateObject(101, (IImmutable**)&spIImmutable);
// QI the original interface pointer for its IUnknown interface.
spIImmutable -> QueryInterface (IID_IUnknown, (void**)&pIUnknown);
if (pIUnknown)
{
// Register this interface pointer in the GIT.
//
// No need to call pIUnknown -> AddRef().
// Another thread can retrieve the pIUnknown
// using the cookie.
//
// When RegisterInterfaceInGlobal() is called on
// the IImmutable interface, COM will attempt to
// get a marshal data packet from the underlying object
// and then store it into the GIT. An associated
// cookie will be returned.
//
// The following sequence of function calls will take place :
//
// CImmutableImpl::GetUnmarshalClass()
// CImmutableImpl::GetUnmarshalClass()
// CImmutableImpl::GetMarshalSizeMax()
// CImmutableImpl::MarshalInterface()
//
pIGlobalInterfaceTable -> RegisterInterfaceInGlobal
(
pIUnknown,
__uuidof(IImmutablePtr),
&dwGITCookie
);
*pdwGITCookieReceiver = dwGITCookie;
pIUnknown -> Release();
pIUnknown = NULL;
if (g_hInterfaceMarshaled)
{
SetEvent(g_hInterfaceMarshaled);
}
}
// Dispatch all windows messages in queue.
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage(&msg);
}
pIGlobalInterfaceTable -> RevokeInterfaceFromGlobal(dwGITCookie);
pIGlobalInterfaceTable -> Release();
pIGlobalInterfaceTable = NULL;
}
::CoUninitialize();
return 0;
}
void Demonstrate_Cross_Apartment_Call_Via_GIT()
{
HANDLE hThread = NULL;
DWORD dwThreadId = 0;
DWORD dwGITCookie = 0;
long lLongValue = 0;
IGlobalInterfaceTable* pIGlobalInterfaceTable = NULL;
// There is a single instance of the global interface
// table per process.
// Hence all calls in a process to create it will
// return the same instance.
CoCreateInstance
(
CLSID_StdGlobalInterfaceTable,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable,
(void **)&pIGlobalInterfaceTable
);
if (pIGlobalInterfaceTable)
{
IImmutablePtr spIImmutable = NULL;
hThread = CreateThread
(
(LPSECURITY_ATTRIBUTES)NULL,
(SIZE_T)0,
(LPTHREAD_START_ROUTINE)ThreadFunc_CustomMarshaledObject,
(LPVOID)(&dwGITCookie),
(DWORD)0,
(LPDWORD)&dwThreadId
);
ThreadMsgWaitForSingleObject(g_hInterfaceMarshaled, INFINITE);
ResetEvent(g_hInterfaceMarshaled);
// Retrieve the interface pointer from the GIT.
// What is returned is actually a proxy to the
// original interface pointer created in the
// ThreadFunc_CustomMarshaledObject() function.
//
// The Marshal Data Packet is already in the GIT.
// All COM needs is a new Proxy object to which it passes
// the Marshal Data Packet (in the UnmarshalInterface()
// method call).
//
// When GetInterfaceFromGlobal() is called on dwGITCookie,
// COM will attempt to create a proxy for the IImmutable
// object, get its marshal data packet from the GIT
// and then pass the packet to the proxy in order
// for the proxy to initialize itself.
//
// These actions have the collective effect of importing
// the IImmutable interface pointer from the STA,
// in which ThreadFunc_CustomMarshaledObject() runs,
// to the current STA.
//
// The following sequence of function calls will take place :
//
// CImmutableImpl() (part of proxy construction)
// CImmutableImpl::FinalConstruct() (part of proxy construction)
// CImmutableImpl::UnmarshalInterface()
//
pIGlobalInterfaceTable -> GetInterfaceFromGlobal
(
dwGITCookie,
__uuidof(IImmutablePtr),
(void**)&spIImmutable
);
if (spIImmutable)
{
spIImmutable -> get_LongValue(&lLongValue);
}
}
PostThreadMessage(dwThreadId, WM_QUIT, 0, 0);
ThreadMsgWaitForSingleObject(hThread, INFINITE);
CloseHandle (hThread);
hThread = NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
g_hInterfaceMarshaled = CreateEvent(NULL, TRUE, FALSE, NULL);
Demonstrate_Cross_Apartment_Call_Via_GIT();
if (g_hInterfaceMarshaled)
{
CloseHandle(g_hInterfaceMarshaled);
g_hInterfaceMarshaled = NULL;
}
::CoUninitialize();
return 0;
}
|
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.
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.