windows-nt/Source/XPSP1/NT/com/ole32/oleprx32/proxy/remunkps.cxx
2020-09-26 16:20:57 +08:00

1023 lines
28 KiB
C++

//+-------------------------------------------------------------------
//
// File: remunkps.cxx
//
// Contents: IRemoteUnnknown custom proxy/stub implementation
//
// Classes: CRemUnknownFactory
// CRemUnknownSyncP
// CRemUnknownAsyncP
//
// History: 15-Dec-97 MattSmit Created
//
//--------------------------------------------------------------------
#include <ole2int.h>
#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; i<cIids; i++)
{
memcpy(p, iids+i, sizeof(IID));
p += sizeof (IID);
}
// 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_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; i<cInterfaceRefs; i++)
{
memcpy(p, InterfaceRefs+i, sizeof(REMINTERFACEREF));
p += sizeof (REMINTERFACEREF);
}
// send
ULONG status;
hr = _pChnl->Send(&_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; j<i; j++)
{
CoTaskMemFree(ppMIF[j]);
ppMIF[j] = NULL;
}
break;
}
}
// free the buffer
_pChnl->FreeBuffer(&_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;
}