1023 lines
28 KiB
C++
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;
|
|
|
|
}
|
|
|