//+------------------------------------------------------------------- // // File: remunkps.cxx // // Contents: IRemoteUnnknown custom proxy/stub implementation // // Classes: CRemUnknownFactory // CRemUnknownSyncP // CRemUnknownAsyncP // // History: 15-Dec-97 MattSmit Created // //-------------------------------------------------------------------- #include #include "remunkps.hxx" #include "..\..\com\dcomrem\sync.hxx" // out internal psclass factory implementation EXTERN_C HRESULT ProxyDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv); //+-------------------------------------------------------------------- // // Function: RemUnkGetClassObject // // Synopsis: Creates a factory object for our custom IRemUnknown proxy. // //--------------------------------------------------------------------- HRESULT RemUnkPSGetClassObject(REFIID riid, LPVOID *ppv) { ComDebOut((DEB_CHANNEL, "RemUnkPSGetClassObject IN riid:%I, ppv:0x%x\n", &riid, ppv)); HRESULT hr = E_OUTOFMEMORY; CRemUnknownFactory *pObj = new CRemUnknownFactory(); if (pObj) { hr = pObj->QueryInterface(riid, ppv); } ComDebOut((DEB_CHANNEL, "RemUnkPSGetClassObject OUT hr:0x%x\n", hr)); return hr; } //+------------------------------------------------------------------- // // Class: CRemUnknownFactory // // Synopsis: Custom factory for the proxy/stub for IRemUnknown. // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Interface: IUnKnown // // Synopsis: Simple IUnknown implementation. QI will support // IPSFactoryBuffer // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownFactory::QueryInterface(REFIID riid, PVOID *pv) { ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::QueryInterface IN riid:%I, pv:0x%x\n", &riid, pv)); if ((riid == IID_IUnknown) || (riid == IID_IPSFactoryBuffer)) { *pv = this; AddRef(); return S_OK; } else { return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) CRemUnknownFactory::AddRef() { return InterlockedIncrement((PLONG) &_cRefs); } STDMETHODIMP_(ULONG) CRemUnknownFactory::Release() { ULONG ret = InterlockedDecrement((PLONG) &_cRefs); if (ret == 0) { delete this; } return ret; } //+------------------------------------------------------------------- // // Interface: IPSFactoryBuffer // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Method: CreateProxy // // Synopsis: Creates a custom synchronous proxy object so we can // implement ICallFactory on the proxy. // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownFactory::CreateProxy(IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) { ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateProxy IN pUnkOuter:0x%x, riid:%I," " ppProxy:0x%x, ppv:0x%x\n", pUnkOuter, &riid, ppProxy, ppv)); HRESULT hr; Win4Assert((riid == IID_IRemUnknown) || (riid == IID_IRemUnknown2) || (riid == IID_IRemUnknownN) || (riid == IID_IRundown)) ; hr = E_OUTOFMEMORY; CRemUnknownSyncP *pObj = new CRemUnknownSyncP(); if (pObj) { hr = pObj->Init(pUnkOuter, riid, ppProxy, ppv); pObj->_IntUnk.Release(); } // Clean up out parameters on error. if (FAILED(hr)) { *ppProxy = NULL; *ppv = NULL; } ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateProxy OUT hr:0x%x\n", hr)); return hr; } //+------------------------------------------------------------------- // // Method: CreateStub // // Synopsis: Create the MIDL generated stub and give it back // because we do not need to get involved on the server // side. // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownFactory::CreateStub(REFIID riid, IUnknown *pUnkServer, IRpcStubBuffer **ppStub) { ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateStub IN riid:%I, pUnkServer:0x%x, ppStub:0x%x\n", &riid, pUnkServer, ppStub)); HRESULT hr; IPSFactoryBuffer *pFac; if (SUCCEEDED(hr = ProxyDllGetClassObject(CLSID_PSOlePrx32, IID_IPSFactoryBuffer, (void **) &pFac))) { hr = pFac->CreateStub(riid, pUnkServer, ppStub); pFac->Release(); } ComDebOut((DEB_CHANNEL, "CRemUnknownFactory::CreateStub OUT hr:0x%x\n", hr)); return hr; } //+------------------------------------------------------------------- // // Class: CRemUnknownSyncP::CRpcProxyBuffer // // Synopsis: Internal Unknown and IRpcProxyBuffer implementation // for CRemUnknownSyncP // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Interface: IUnKnown // // Synopsis: Simple IUnknown implementation. QI will support // IRpcProxyBuffer, ICallFactory and delegate the // rest to the MIDL implementation // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownSyncP::CRpcProxyBuffer::QueryInterface(REFIID riid, PVOID *pv) { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::QueryInterface" " riid:%I, pv:0x%x\n", &riid, pv)); CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk)); if ((riid == IID_IUnknown) || (riid == IID_IRpcProxyBuffer)) { *pv = this; AddRef(); return S_OK; } else if (riid == IID_ICallFactory) { *pv = (ICallFactory * ) This; This->AddRef(); return S_OK; } else { return This->_pPrx->QueryInterface(riid, pv); } } STDMETHODIMP_(ULONG) CRemUnknownSyncP::CRpcProxyBuffer::AddRef() { return InterlockedIncrement((PLONG) &_cRefs); } STDMETHODIMP_(ULONG) CRemUnknownSyncP::CRpcProxyBuffer::Release() { ULONG ret = InterlockedDecrement((PLONG) &_cRefs); if (ret == 0) { CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk)); delete This; } return ret; } //+------------------------------------------------------------------- // // Interface: IRpcProxyBuffer // // Synopsis: Delegates IrpcProxyBuffer calls to the MIDL generated // // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownSyncP::CRpcProxyBuffer::Connect(IRpcChannelBuffer *pRpcChannelBuffer) { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::Connect pRpcChannelBuffer:0x%x\n", pRpcChannelBuffer)); CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk)); return This->_pPrx->Connect(pRpcChannelBuffer); } STDMETHODIMP_(void) CRemUnknownSyncP::CRpcProxyBuffer::Disconnect() { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CRpcProxyBuffer::Disconnect\n" )); CRemUnknownSyncP *This = (CRemUnknownSyncP *) (((BYTE *) this) - offsetof(CRemUnknownSyncP, _IntUnk)); This->_pPrx->Disconnect(); } //+------------------------------------------------------------------- // // Class: CRemUnknownSyncP // // Synopsis: Synchronous proxy for IRemUknown // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Method: Init // // Synopsis: Initializes the proxy wrapper by creating the MIDL // generated proxy and saving the outer unknown. // //-------------------------------------------------------------------- HRESULT CRemUnknownSyncP::Init(IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::Init IN pUnkOuter:0x%x," " riid:%I, ppProxy:0x%x, ppv:0x%x\n", pUnkOuter, &riid, ppProxy, ppv)); HRESULT hr; _pCtrlUnk = pUnkOuter; IPSFactoryBuffer *pFac; if (SUCCEEDED(hr = ProxyDllGetClassObject(CLSID_PSOlePrx32, IID_IPSFactoryBuffer, (void **) &pFac))) { IRpcProxyBuffer *pPrx = 0; if (SUCCEEDED(hr = pFac->CreateProxy(pUnkOuter, riid, &pPrx, ppv))) { _pPrx = pPrx; *ppProxy = &_IntUnk; (*ppProxy)->AddRef(); } pFac->Release(); } ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::Init OUT hr:0x%x\n", hr)); return hr; } //+------------------------------------------------------------------- // // Method: Destructor // // Synopsis: Release the MIDL generated proxy if we aquired it. // //-------------------------------------------------------------------- CRemUnknownSyncP::~CRemUnknownSyncP() { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP~CRemUnknownSyncP \n" )); if (_pPrx) { _pPrx->Release(); _pPrx = NULL; } } //+------------------------------------------------------------------- // // Interface: IUnKnown // // Synopsis: Simple IUnknown implementation. Delegates to outer. // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownSyncP::QueryInterface(REFIID riid, PVOID *pv) { return _pCtrlUnk->QueryInterface(riid, pv); } STDMETHODIMP_(ULONG) CRemUnknownSyncP::AddRef() { return _pCtrlUnk->AddRef(); } STDMETHODIMP_(ULONG) CRemUnknownSyncP::Release() { return _pCtrlUnk->Release(); } //+------------------------------------------------------------------- // // Interface: ICallFactory // // Synopsis: Interface for creating asynchronous call objects // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Method: CreateCall // // Synopsis: create and initialize an async call object // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownSyncP::CreateCall(REFIID riid, IUnknown *pCtrlUnk, REFIID riid2, IUnknown **ppUnk) { ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CreateCall IN " "riid:%I, pCtrlUnk:0x%x, riid2:%I, ppUnk:0x%x\n", &riid, pCtrlUnk, &riid2, ppUnk)); HRESULT hr = E_OUTOFMEMORY; Win4Assert((riid == IID_AsyncIRemUnknown) || (riid == IID_AsyncIRemUnknown2)); CRemUnknownAsyncCallP *pObj = new CRemUnknownAsyncCallP(pCtrlUnk); if (pObj) { hr = pObj->_IntUnk.QueryInterface(riid2, (void **) ppUnk); pObj->_IntUnk.Release(); } ComDebOut((DEB_CHANNEL, "CRemUnknownSyncP::CreateCall OUT hr:0x%x\n", hr)); return hr; } //+------------------------------------------------------------------- // // Class: CRemUnknownAsyncCallP::CRpcProxyBuffer // // Synopsis: Inner unknown and proxy buffer interface // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Interface: IUnKnown // // Synopsis: Simple IUnknown implementation. QI will support // IRpcProxyBuffer and AsyncIRemUnknown // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::CRpcProxyBuffer::QueryInterface(REFIID riid, PVOID *pv) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::CRpcProxyBuffer::QueryInterface " " riid:%I, pv:0x%x\n", &riid, pv)); CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk)); if ((riid == IID_IUnknown) || (riid == IID_IRpcProxyBuffer)) { *pv = this; AddRef(); return S_OK; } else if ((riid == IID_AsyncIRemUnknown) || (riid == IID_AsyncIRemUnknown2) ) { *pv = (AsyncIRemUnknown2 * ) This; This->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::CRpcProxyBuffer::AddRef() { return InterlockedIncrement((PLONG) &_cRefs); } STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::CRpcProxyBuffer::Release() { ULONG ret = InterlockedDecrement((PLONG) &_cRefs); if (ret == 0) { CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk)); delete This; } return ret; } //+------------------------------------------------------------------- // // Interface: IRpcProxyBuffer // // Synopsis: handles logistics of connecting and disconnecting // the proxy call object // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::CRpcProxyBuffer::Connect(IRpcChannelBuffer *pRpcChannelBuffer) { CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk)); Win4Assert(!This->_pChnl); return pRpcChannelBuffer->QueryInterface(IID_IAsyncRpcChannelBuffer, (void **) &(This->_pChnl)); } STDMETHODIMP_(void) CRemUnknownAsyncCallP::CRpcProxyBuffer::Disconnect(void) { CRemUnknownAsyncCallP *This = (CRemUnknownAsyncCallP *) (((BYTE *) this) - offsetof(CRemUnknownAsyncCallP, _IntUnk)); if (This->_pChnl) { This->_pChnl->Release(); This->_pChnl = NULL; } } //+------------------------------------------------------------------- // // Class: CRemUnknownAsyncCallP // // Synopsis: Asynchronous proxy call object for IRemUknown // //-------------------------------------------------------------------- //+------------------------------------------------------------------- // // Interface: IUnKnown // // Synopsis: Simple IUnknown implementation. Delegates to outer. // //-------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::QueryInterface(REFIID riid, PVOID *pv) { return _pCtrlUnk->QueryInterface(riid, pv); } STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::AddRef() { return _pCtrlUnk->AddRef(); } STDMETHODIMP_(ULONG) CRemUnknownAsyncCallP::Release() { return _pCtrlUnk->Release(); } //+------------------------------------------------------------------- // // Interface: AsyncIRemUnknown // // Synopsis: This is the actual async interface which will marshal // the parameters. // //-------------------------------------------------------------------- //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Begin_RemQueryInterface // // Synopsis: Marshal paramenters and save cIids // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemQueryInterface( REFIPID ripid, unsigned long cRefs, unsigned short cIids, IID *iids ) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface IN" " ripid:%I, crefs:0x%d, cIids:0x%d, iids:%I\n", &ripid, cRefs, cIids, iids)); _hr = S_OK; HRESULT hr; // Get the synchronize interface ISynchronize *pSync; if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) )) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface" " FAILED QI for ISyncronize\n")); return hr; } // set up message memset(&_msg, 0, sizeof(RPCOLEMESSAGE)); _msg.cbBuffer = sizeof(IPID) + // ripid sizeof(unsigned long) + // cRefs sizeof(unsigned short) + 2 + // cIids + padding sizeof(unsigned long) + (cIids * sizeof(IID)); // iids _msg.rpcFlags = RPC_BUFFER_ASYNC; _msg.iMethod = 3; // get buffer if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown))) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface " "buffer obtained _msg.cbBuffer:%d, _msg.Buffer:0x%x \n", _msg.cbBuffer, _msg.Buffer)); BYTE * p = (BYTE *)_msg.Buffer; memset(p, 0, _msg.cbBuffer); // marshal the parameters memcpy(p, &ripid, sizeof(IPID)); p += sizeof(IPID); memcpy(p, &cRefs, sizeof(cRefs)); p += sizeof (cRefs); memcpy(p, &cIids, sizeof(unsigned short)); p += sizeof (unsigned short) + 2; memcpy(p, &cIids, sizeof(unsigned short)); p += sizeof (unsigned long); unsigned short i; for (i=0; iSend(&_msg, pSync, &status); } if (FAILED(hr)) { pSync->Signal(); _hr = hr; } pSync->Release(); ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface OUT hr:0x%x\n", hr)); return hr; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Finish_RemQueryInterface // // Synopsis: Unmarshal QI parameters // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemQueryInterface(REMQIRESULT **ppQIResults) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface IN ppQIResults:0x%x\n", ppQIResults)); HRESULT hr; // check state if (FAILED(_hr) ) { return _hr; } // ensure call has completed ISynchronize *pSync; if (SUCCEEDED(_pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) )) { hr = pSync->Wait(0, INFINITE); pSync->Release(); if (FAILED(hr)) { return hr; } } // receive ULONG status; if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status))) { hr = E_OUTOFMEMORY; // unmarshal parameters REMQIRESULT *p = (REMQIRESULT *)CoTaskMemAlloc(_cIids * sizeof(REMQIRESULT)); if (p) { ComDebOut((DEB_CHANNEL, "_cIids = 0x%x, _msg.cbBuffer = 0x%x, _msg.Buffer=0x%x\n", _cIids, _msg.cbBuffer, _msg.Buffer)); ComDebOut((DEB_CHANNEL, "sizeof(REMQIRESULT)=0x%x, offsetof(REMQIRESULT, std)=0x%x\n", sizeof(REMQIRESULT),offsetof(REMQIRESULT, std))); // Win4Assert(_cIids == ((unsigned long *) _msg.Buffer)[1]); BYTE * pBuffer = (BYTE *)_msg.Buffer; pBuffer += sizeof(DWORD)*2; memcpy(p, pBuffer, sizeof(REMQIRESULT) *_cIids); *ppQIResults = p; hr = S_OK; } // free the buffer _pChnl->FreeBuffer(&_msg); } ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface OUT hr:0x%x\n", hr)); return hr; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Begin_RemAddRef // // Synopsis: Not implemented. Never used // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemAddRef(unsigned short cInterfaceRefs, REMINTERFACEREF InterfaceRefs[]) { return E_NOTIMPL; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Finish_RemAddRef // // Synopsis: Not implemented. Never used // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemAddRef(HRESULT *pResults) { return E_NOTIMPL; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Begin_RemRelease // // Synopsis: Marshal parameters. // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemRelease(unsigned short cInterfaceRefs, REMINTERFACEREF InterfaceRefs[]) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemRelease IN cInterfaceRefs:0x%d, ", "InterfaceRefs:0x%x\n", cInterfaceRefs, InterfaceRefs)); _hr = S_OK; HRESULT hr; // Get the synchronize interface ISynchronize *pSync; if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) )) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemRelease FAILED QI for ISyncronize\n")); return hr; } // set up message memset(&_msg, 0, sizeof(RPCOLEMESSAGE)); _msg.cbBuffer = sizeof(unsigned short) + 2 + // cInterfaceRefs sizeof(unsigned long) + (sizeof(REMINTERFACEREF) * cInterfaceRefs); // InterfaceRefs[] _msg.rpcFlags = RPC_BUFFER_ASYNC; _msg.iMethod = 5; // get buffer if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown))) { BYTE * p = (BYTE *)_msg.Buffer; memset(p, 0, _msg.cbBuffer); // marshal the parameters memcpy(p, &cInterfaceRefs, sizeof(unsigned short)); p += sizeof (unsigned short) + 2; memcpy(p, &cInterfaceRefs, sizeof(unsigned short)); p += sizeof (unsigned long); unsigned short i; for (i=0; iSend(&_msg, pSync, &status); } else { pSync->Signal(); } if (FAILED(hr)) { _hr = hr; } pSync->Release(); return hr; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Finish_RemRelease // // Synopsis: Check state and return. // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemRelease() { HRESULT hr; // check state if (FAILED(_hr) ) { return _hr; } // ensure call has completed ISynchronize *pSync; if (SUCCEEDED(_pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) )) { hr = pSync->Wait(0, INFINITE); pSync->Release(); if (FAILED(hr)) { return hr; } } // receive ULONG status; if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status))) { // free the buffer _pChnl->FreeBuffer(&_msg); } return hr; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Begin_RemQueryInterface2 // // Synopsis: Marshal parameters, save count for Finish. // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Begin_RemQueryInterface2 ( REFIPID ripid, unsigned short cIids, IID *iids ) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 IN " "ripid:%I, cIids:0x%d, iids:0x%x\n", &ripid, cIids, iids)); _hr = S_OK; HRESULT hr; // Get the synchronize interface ISynchronize *pSync; if (FAILED(hr = _pCtrlUnk->QueryInterface(IID_ISynchronize, (void **) &pSync) )) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 FAILED QI for ISynchronize\n")); return hr; } // set up message memset(&_msg, 0, sizeof(RPCOLEMESSAGE)); _msg.cbBuffer = sizeof(IPID) + // ripid sizeof(unsigned short) + 2 + // cIids + padding sizeof(unsigned long) + (cIids * sizeof(IID)); // iids _msg.rpcFlags = RPC_BUFFER_ASYNC; _msg.iMethod = 6; // get buffer if (SUCCEEDED(hr = _pChnl->GetBuffer(&_msg, IID_IRemUnknown))) { BYTE * p = (BYTE *)_msg.Buffer; memset(p, 0, _msg.cbBuffer); // marshal the parameters memcpy(p, &ripid, sizeof(IPID)); p += sizeof(IPID); memcpy(p, &cIids, sizeof(unsigned short)); p += sizeof (unsigned short) + 2; memcpy(p, &cIids, sizeof(unsigned short)); p += sizeof (unsigned long); memcpy(p, iids, sizeof(IID) * cIids); ComDebOut((DEB_CHANNEL, "RemQueryInterface2: _msg.Buffer:%x\n", _msg.Buffer)); // save this for later _cIids = cIids; // send ULONG status; hr = _pChnl->Send(&_msg, pSync, &status); } if (FAILED(hr)) { pSync->Signal(); _hr = hr; } pSync->Release(); ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Begin_RemQueryInterface2 OUT hr:0x%x\n", hr)); return hr; } //+---------------------------------------------------------------------------- // // Member: CRemUnknownAsyncCallP::Finish_RemQueryInterface2 // // Synopsis: Unmarshal out parameters. // // History: 23-Jan-98 MattSmit Created // //----------------------------------------------------------------------------- STDMETHODIMP CRemUnknownAsyncCallP::Finish_RemQueryInterface2( HRESULT *phr, MInterfacePointer **ppMIF ) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 IN " "phr:0x%x, ppMIF:0x%x\n", phr, ppMIF)); HRESULT hr; // check state if (FAILED(_hr) ) { return _hr; } // ensure call has completed hr = WaitObject(_pCtrlUnk, 0, INFINITE); if (FAILED(hr)) { return hr; } // receive ULONG status; if (SUCCEEDED(hr = _pChnl->Receive(&_msg, &status))) { ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 \n", "_cIids = 0x%x, _msg.cbBuffer = 0x%x, _msg.Buffer=0x%x\n", _cIids, _msg.cbBuffer, _msg.Buffer)); BYTE * pBuffer = (BYTE *)_msg.Buffer; pBuffer += sizeof(ULONG); // skip the count memcpy(phr, pBuffer, sizeof(HRESULT) *_cIids); // copy the hresults pBuffer += sizeof(HRESULT) *_cIids; // advance past hresults pBuffer += sizeof(ULONG); // skip count pBuffer += sizeof(ULONG) * _cIids; // not sure what this is, but its there. for(int i = 0; i < _cIids; i++) { // allocate memory and transfer to out parameters. ULONG *pulCntData = (PULONG) pBuffer; ULONG cb = sizeof(MInterfacePointer) + *pulCntData; MInterfacePointer *pMIF = (MInterfacePointer *) CoTaskMemAlloc(cb); if (pMIF) { pMIF->ulCntData = *pulCntData; pBuffer += sizeof(ULONG); pBuffer += sizeof(ULONG); // skip count memcpy(pMIF->abData, pBuffer, pMIF->ulCntData); ppMIF[i] = pMIF; pBuffer += pMIF->ulCntData; } else { // no memory, so free up what we have left // an return an error hr = E_OUTOFMEMORY; for (int j = 0; jFreeBuffer(&_msg); } ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 " "phr:%x, ppMIF:%x\n", phr, ppMIF)); ComDebOut((DEB_CHANNEL, "CRemUnknownAsyncCallP::Finish_RemQueryInterface2 OUT hr:0x%x\n", hr)); return hr; }