WritePtr ReadPtr , CoMarshalInterface . (wrapper functions), CoMarshalInterface CoUnmarshalInterface. API- CoMarshalInterThreadInterfaceInStream
HRESULT CoMarshalInterThreadInterfaceInStream( [in] REFIID riid, [in, iid_is(riid)] IUnknown *pItf, [out] IStream **ppStm );
CreateStreamOnHGlobal CoMarshalInterface, :
// from OLE32.DLL (approx.) // OLE32.DLL ( ) HRESULT CoMarshalInterThreadInterfaceInStream( REFIID riid, IUnknown *pItf, IStream **ppStm) { HRESULT hr = CreateStreamOnHGlobal(0, TRUE, ppStm); if (SUCCEEDED(hr)) hr = CoMarshalInterface(*ppStm, riid, pItf, MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL); return hr; }
CoUnmarshalInterface:
HRESULT CoGetInterfaceAndReleaseStream( [in] IStream *pStm, [in] REFIID riid, [out, iid_is(riid)] void **ppv );CoUnmarshalInterface:
// from OLE32.DLL (approx.) // OLE32.DLL ( ) HRESULT CoGetInterfaceAndReleaseStream( IStream *pStm, REFIID riid, void **ppv) { HRESULT hr = CoUnmarshalInterface(pStm, riid, ppv); pStm->Release(); return hr; }
- , , .
:
HRESULT WritePtrToGlobalVarable(IRacer *pRacer) { // where to write the marshaled ptr // extern IStream *g_pStmPtr; // thread synchronization for read/write // / extern HANDLE g_heventWritten; // write marshaled object reference to global variable // // HRESULT hr = CoMarshalInterThreadInterfaceInStream( IID_IRacer, pRacer, &g_pStmPtr); // signal other thread that ptr is now available // , // SetEvent (g_heventWritten); return hr; }
, :
HRESULT ReadPtrFromGlobalVariable(IRacer * &rpRacer) { // where to write the marshaled ptr // extern IStream *g_pStmPtr; // thread synchronization for read/write // / extern HANDLE g_heventWritten; // wait for other thread to signal that ptr is available // , . // WaitForSingleObject(g_heventWritten, INFINITE); // read marshaled object reference from global variable // HRESULT hr = CoGetInterfaceAndReleaseStream( g_pStmPtr, IID_IRacer. (void**) &rpRacer); // MSHLFLAGS_NORMAL means no more unmarshals are legal // MSHLFLAGS_NORMAL , // g_pStmPtr = 0; return hr; }
1. , , RTA, , , . , (writer) AddRef (reader). , , , Release.
, g_pStmPtr . , MSHLFLAGS_NORMAL . . , , , . , , , . , , , , . MSHLFLAGS_TABLESTRONG, , ( ). , ( ) , , , . Service Pack 3 Windows NT 4.0 (Global Interface Table - GIT).
GIT CoMarshalInterface / CoUnmarshalInterface, . GIT . GIT , . , GIT , . GIT IGlobalInterfaceTable:
[uuid(00000146-0000-0000-C000-000000000046), object, local ] interface IGlobalInterfaceTable : IUnknown { // marshal an Interface into the GIT // GIT HRESULT RegisterInterfaceInGlobal ( [in, iid_is(riid)] IUnknown *pItf, [in] REFIID riid, [out] DWORD *pdwCookie); // destroy the marshaled object reference // HRESULT RevokeInterfaceFromGlobal ( [in] DWORD dwCookle); // unmarshal an interface from the GIT // GIT HRESULT GetInterfaceFromGlobal ( [in] DWORD dwCookie, [in] REFIID riid, [out, iid_is(riid)] void **ppv); }
GIT , CocreateInstance CLSID_StdGlobalInterfaceTable. CoCreateInstance CLSID GIT . IStream, CoMarshalInterThreadInterfaceInStream, GIT .
, , , GIT RegisterInterfaceInGlobal. GIT DWORD, . DWORD GetInterfaceFromGlobal. DWORD , RevokeInterfaceFromGlobal . , (GIT), :
IGlobalInterfaceTable *g_pGIT = 0; HRESULT Init0nce(void) { assert(g_pGIT == 0); return CoCreateInstance(CLSID_StdGlobalInterfaceTable, 0, CLSCDX_INPROC_5ERVER, IID_IGlobalInterfaceTable, (void**)&g_pGIT); }
, :
HRESULT WritePtrToGlobalVariable(IRacer *pRacer) { // where to write the marshaled ptr // extern DWORD g_dwCookie; // thread synchronization // extern HANDLE g_heventWritten; // write marshaled object reference to global variable // HRESULT hr = g_pGIT->RegisterInterfaceInGlobal( pRacer, IID_IRacer, &g_dwCookie); // signal other thread that ptr is now available // SetEvent(g_heventWritten); return hr; }
:
HRESULT ReadPtrFromGlobalVariable(IRacer * &rpRacer, bool bLastUnmarshal) { // where to write the marshaled ptr // extern DWORD g_dwCookie; // thread synchronization // extern HANDLE g_heventWritten; // wait for other thread to signal that ptr is available // , WaitForSingleObject(g_heventWritten, INFINITE); // read marshaled object reference from global variable // HRESULT hr = g_pGIT->GetInterfaceFromGlobal( g_dwCookie, IID_IRacer, (void**)&rpRacer); // if we are the last to unmarshal, revoke the pointer // , // if (bLastUnmarshal) g_pGIT->RevokeInterfaceFromGlobal(g_dwCookie); return hr; }
CoMarshalInterThreadInterfaceInStream. , , GIT, .
1 , , , . CoMarshalInterThreadInterfaceInStream, , IStream .