953 lines
22 KiB
C
953 lines
22 KiB
C
|
#if !defined(__RPC_DOS__) && !defined(__RPC_WIN16__)
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
||
|
//
|
||
|
// File: rpcproxy.c
|
||
|
//
|
||
|
// Contents: Contains runtime functions for interface proxies and stubs.
|
||
|
//
|
||
|
// Functions:
|
||
|
// DllGetClassObject
|
||
|
// DllCanUnloadNow
|
||
|
// MIDL_user_allocate
|
||
|
// MIDL_user_free
|
||
|
// NdrGetProxyBuffer
|
||
|
// NdrGetProxyIID
|
||
|
// NdrProxyInitialize
|
||
|
// NdrProxyGetBuffer
|
||
|
// NdrProxySendReceive
|
||
|
// NdrProxyFreeBuffer
|
||
|
// NdrProxyErrorHandler
|
||
|
// NdrStubInitialize
|
||
|
// NdrStubGetBuffer
|
||
|
//
|
||
|
// Classes: CStdProxyBuffer
|
||
|
// CStdPSFactoryBuffer
|
||
|
// CStdStubBuffer
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
#include <rpcproxy.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Global data
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
long DllRefCount = 0;
|
||
|
|
||
|
IPSFactoryBufferVtbl CStdPSFactoryBufferVtbl = {
|
||
|
CStdPSFactoryBuffer_QueryInterface,
|
||
|
CStdPSFactoryBuffer_AddRef,
|
||
|
CStdPSFactoryBuffer_Release,
|
||
|
CStdPSFactoryBuffer_CreateProxy,
|
||
|
CStdPSFactoryBuffer_CreateStub };
|
||
|
|
||
|
CStdPSFactoryBuffer gPSFactoryBuffer = {
|
||
|
&CStdPSFactoryBufferVtbl,
|
||
|
0 };
|
||
|
|
||
|
IRpcProxyBufferVtbl CStdProxyBufferVtbl = {
|
||
|
CStdProxyBuffer_QueryInterface,
|
||
|
CStdProxyBuffer_AddRef,
|
||
|
CStdProxyBuffer_Release,
|
||
|
CStdProxyBuffer_Connect,
|
||
|
CStdProxyBuffer_Disconnect };
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllGetClassObject
|
||
|
//
|
||
|
// Synopsis: Standard implementation of entrypoint required by binder.
|
||
|
//
|
||
|
// Arguments: [rclsid] -- class id to find
|
||
|
// [riid] -- interface to return
|
||
|
// [ppv] -- output pointer
|
||
|
//
|
||
|
// Returns: E_UNEXPECTED if class not found
|
||
|
// Otherwise, whatever is returned by the class's QI
|
||
|
//
|
||
|
// Algorithm: Searches the linked list for the required class.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDAPICALLTYPE DllGetClassObject (
|
||
|
REFCLSID rclsid,
|
||
|
REFIID riid,
|
||
|
LPVOID FAR* ppv )
|
||
|
{
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
assert(rclsid);
|
||
|
assert(riid);
|
||
|
assert(ppv);
|
||
|
|
||
|
*ppv = 0;
|
||
|
if(memcmp(rclsid, &CLSID_PSFactoryBuffer, sizeof(IID)) == 0)
|
||
|
hr = gPSFactoryBuffer.lpVtbl->QueryInterface((IPSFactoryBuffer *)&gPSFactoryBuffer, riid, ppv);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DllCanUnloadNow
|
||
|
//
|
||
|
// Synopsis: Standard entrypoint required by binder
|
||
|
//
|
||
|
// Returns: S_OK if DLL reference count is zero
|
||
|
// S_FALSE otherwise
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDAPICALLTYPE DllCanUnloadNow ()
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if(DllRefCount == 0)
|
||
|
hr = S_OK;
|
||
|
else
|
||
|
hr = S_FALSE;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdPSFactoryBuffer_QueryInterface, public
|
||
|
//
|
||
|
// Synopsis: Query for an interface on the class factory.
|
||
|
//
|
||
|
// Derivation: IUnknown
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdPSFactoryBuffer_QueryInterface (
|
||
|
IPSFactoryBuffer *pThis,
|
||
|
REFIID iid,
|
||
|
void **ppv )
|
||
|
{
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(iid);
|
||
|
assert(ppv);
|
||
|
|
||
|
*ppv = 0;
|
||
|
if ((memcmp(iid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
||
|
(memcmp(iid, &IID_IPSFactoryBuffer, sizeof(IID)) == 0))
|
||
|
{
|
||
|
*ppv = pThis;
|
||
|
pThis->lpVtbl->AddRef(pThis);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdPSFactoryBuffer_AddRef, public
|
||
|
//
|
||
|
// Synopsis: Increment DLL reference counts
|
||
|
//
|
||
|
// Derivation: IUnknown
|
||
|
//
|
||
|
// Notes: We have a single instance of the CStdPSFactoryBuffer.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdPSFactoryBuffer_AddRef(
|
||
|
IPSFactoryBuffer *this)
|
||
|
{
|
||
|
assert(this);
|
||
|
|
||
|
InterlockedIncrement(&((CStdPSFactoryBuffer *)this)->RefCount);
|
||
|
InterlockedIncrement(&DllRefCount);
|
||
|
return (unsigned long) ((CStdPSFactoryBuffer *)this)->RefCount;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdPSFactoryBuffer_Release, public
|
||
|
//
|
||
|
// Synopsis: Decrement DLL reference count
|
||
|
//
|
||
|
// Derivation: IUnknown
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdPSFactoryBuffer_Release(
|
||
|
IPSFactoryBuffer *this)
|
||
|
{
|
||
|
long t;
|
||
|
unsigned long count;
|
||
|
|
||
|
assert(this);
|
||
|
|
||
|
t = InterlockedDecrement(&((CStdPSFactoryBuffer *)this)->RefCount);
|
||
|
InterlockedDecrement(&DllRefCount);
|
||
|
|
||
|
if(t == 0)
|
||
|
count = 0;
|
||
|
else
|
||
|
count = (unsigned long) ((CStdPSFactoryBuffer *)this)->RefCount;
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdPSFactoryBuffer_CreateProxy, public
|
||
|
//
|
||
|
// Synopsis: Create a proxy for the specified interface.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdPSFactoryBuffer_CreateProxy
|
||
|
(
|
||
|
IPSFactoryBuffer *this,
|
||
|
IUnknown *punkOuter,
|
||
|
REFIID riid,
|
||
|
IRpcProxyBuffer **ppProxy,
|
||
|
void **ppv
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = E_OUTOFMEMORY;
|
||
|
const IID *pIID;
|
||
|
CStdProxyBuffer *pProxyBuffer = 0;
|
||
|
int i, j;
|
||
|
|
||
|
assert(this);
|
||
|
assert(riid);
|
||
|
assert(ppProxy);
|
||
|
assert(ppv);
|
||
|
|
||
|
*ppProxy = 0;
|
||
|
*ppv = 0;
|
||
|
|
||
|
//Search the list of proxy files.
|
||
|
for(i = 0;
|
||
|
pProxyFileList[i] && !pProxyBuffer;
|
||
|
i++)
|
||
|
{
|
||
|
//Search the interface proxies in the proxy buffer
|
||
|
for(j = 0;
|
||
|
((CStdProxyBuffer *)pProxyFileList[i]->pProxyBuffer)->aProxyVtbl[j] && !pProxyBuffer;
|
||
|
j++)
|
||
|
{
|
||
|
pIID = NdrGetProxyIID(&((CStdProxyBuffer *)pProxyFileList[i]->pProxyBuffer)->aProxyVtbl[j]);
|
||
|
assert(pIID);
|
||
|
|
||
|
if(memcmp(riid, pIID, sizeof(IID)) == 0)
|
||
|
{
|
||
|
//We found the interface!
|
||
|
//Allocate memory for the new proxy buffer.
|
||
|
pProxyBuffer = (CStdProxyBuffer *) CoTaskMemAlloc(pProxyFileList[i]->ProxyBufferSize);
|
||
|
|
||
|
if(pProxyBuffer)
|
||
|
{
|
||
|
//Initialize the new proxy buffer.
|
||
|
memcpy(pProxyBuffer, pProxyFileList[i]->pProxyBuffer, pProxyFileList[i]->ProxyBufferSize);
|
||
|
pProxyBuffer->punkOuter = punkOuter;
|
||
|
|
||
|
//Increment the DLL reference count.
|
||
|
InterlockedIncrement(&DllRefCount);
|
||
|
|
||
|
*ppProxy = (IRpcProxyBuffer *) pProxyBuffer;
|
||
|
*ppv = &pProxyBuffer->aProxyVtbl[j];
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdPSFactoryBuffer_CreateStub, public
|
||
|
//
|
||
|
// Synopsis: Create a stub for the specified interface.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdPSFactoryBuffer_CreateStub
|
||
|
(
|
||
|
IPSFactoryBuffer *this,
|
||
|
REFIID riid,
|
||
|
IUnknown *punkServer,
|
||
|
IRpcStubBuffer **ppStub
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = E_OUTOFMEMORY;
|
||
|
const IID *pIID;
|
||
|
CStdStubBuffer *pStubBuffer = 0;
|
||
|
int i, j;
|
||
|
|
||
|
assert(this);
|
||
|
assert(riid);
|
||
|
assert(ppStub);
|
||
|
|
||
|
*ppStub = 0;
|
||
|
|
||
|
//Search the list of proxy files.
|
||
|
for(i = 0;
|
||
|
pProxyFileList[i] && !pStubBuffer;
|
||
|
i++)
|
||
|
{
|
||
|
//Search the interface stubs in the stub buffer
|
||
|
for(j = 0;
|
||
|
((CStdStubBuffer *)pProxyFileList[i]->pStubBuffer)->aInterfaceStub[j].lpVtbl && !pStubBuffer;
|
||
|
j++)
|
||
|
{
|
||
|
pIID = NdrGetStubIID(&((CStdStubBuffer *)pProxyFileList[i]->pStubBuffer)->aInterfaceStub[j].lpVtbl);
|
||
|
assert(pIID);
|
||
|
|
||
|
if(memcmp(riid, pIID, sizeof(IID)) == 0)
|
||
|
{
|
||
|
//We found the interface!
|
||
|
//Allocate memory for the new proxy buffer.
|
||
|
pStubBuffer = (CStdStubBuffer *) CoTaskMemAlloc(pProxyFileList[i]->StubBufferSize);
|
||
|
|
||
|
if(pStubBuffer)
|
||
|
{
|
||
|
//Initialize the new stub buffer.
|
||
|
memcpy(pStubBuffer, pProxyFileList[i]->pStubBuffer, pProxyFileList[i]->StubBufferSize);
|
||
|
|
||
|
if(punkServer)
|
||
|
{
|
||
|
punkServer->lpVtbl->AddRef(punkServer);
|
||
|
pStubBuffer->punkObject = punkServer;
|
||
|
hr = punkServer->lpVtbl->QueryInterface(punkServer, riid, &pStubBuffer->aInterfaceStub[j].pvServerObject);
|
||
|
}
|
||
|
else
|
||
|
hr = S_OK;
|
||
|
|
||
|
if(FAILED(hr))
|
||
|
CoTaskMemFree(pStubBuffer);
|
||
|
else
|
||
|
{
|
||
|
*ppStub = (IRpcStubBuffer *) &pStubBuffer->aInterfaceStub[j].lpVtbl;
|
||
|
|
||
|
//Increment the DLL reference count.
|
||
|
InterlockedIncrement(&DllRefCount);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdProxyBuffer_QueryInterface, public
|
||
|
//
|
||
|
// Synopsis: Query for an interface on the proxy. This provides access
|
||
|
// to both internal and external interfaces.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdProxyBuffer_QueryInterface(IRpcProxyBuffer *pThis, REFIID riid, void **ppv)
|
||
|
{
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
CStdProxyBuffer *pProxyBuffer = (CStdProxyBuffer *) pThis;
|
||
|
void *pInterfaceProxy = 0;
|
||
|
int j;
|
||
|
const IID *pIID;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(riid);
|
||
|
assert(ppv);
|
||
|
|
||
|
*ppv = 0;
|
||
|
|
||
|
if((memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
||
|
(memcmp(riid, &IID_IRpcProxyBuffer, sizeof(IID)) == 0))
|
||
|
{
|
||
|
//This is an internal interface. Increment the internal reference count.
|
||
|
InterlockedIncrement( &((CStdProxyBuffer *)pThis)->RefCount);
|
||
|
*ppv = pThis;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
//Search the interface proxies in the proxy buffer
|
||
|
for(j = 0;
|
||
|
pProxyBuffer->aProxyVtbl[j] && !pInterfaceProxy;
|
||
|
j++)
|
||
|
{
|
||
|
pIID = NdrGetProxyIID(&pProxyBuffer->aProxyVtbl[j]);
|
||
|
assert(pIID);
|
||
|
|
||
|
if(memcmp(riid, pIID, sizeof(IID)) == 0)
|
||
|
{
|
||
|
//We found the interface!
|
||
|
pInterfaceProxy = &pProxyBuffer->aProxyVtbl[j];
|
||
|
|
||
|
//Increment the reference count.
|
||
|
if(pProxyBuffer->punkOuter)
|
||
|
{
|
||
|
pProxyBuffer->punkOuter->lpVtbl->AddRef(pProxyBuffer->punkOuter);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InterlockedIncrement(&pProxyBuffer->RefCount);
|
||
|
}
|
||
|
|
||
|
*ppv = pInterfaceProxy;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdProxyBuffer_AddRef, public
|
||
|
//
|
||
|
// Synopsis: Increment reference count.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdProxyBuffer_AddRef(IRpcProxyBuffer *pThis)
|
||
|
{
|
||
|
InterlockedIncrement(&((CStdProxyBuffer *)pThis)->RefCount);
|
||
|
return (ULONG) ((CStdProxyBuffer *)pThis)->RefCount;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdProxyBuffer_Release, public
|
||
|
//
|
||
|
// Synopsis: Decrement reference count.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdProxyBuffer_Release(IRpcProxyBuffer *pThis)
|
||
|
{
|
||
|
long RefCount;
|
||
|
unsigned long count;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
RefCount = InterlockedDecrement(&((CStdProxyBuffer *)pThis)->RefCount);
|
||
|
assert(RefCount >= 0);
|
||
|
|
||
|
if(RefCount == 0)
|
||
|
{
|
||
|
count = 0;
|
||
|
|
||
|
//Decrement the DLL reference count.
|
||
|
InterlockedDecrement(&DllRefCount);
|
||
|
|
||
|
//Free the memory
|
||
|
MIDL_user_free(pThis);
|
||
|
}
|
||
|
else
|
||
|
count = (unsigned long) ((CStdProxyBuffer *)pThis)->RefCount;
|
||
|
|
||
|
return count;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdProxyBuffer_Connect, public
|
||
|
//
|
||
|
// Synopsis: Connect the proxy to the channel.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdProxyBuffer_Connect(IRpcProxyBuffer *pThis, IRpcChannelBuffer *pChannel)
|
||
|
{
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pThis->lpVtbl->Disconnect(pThis);
|
||
|
if(pChannel)
|
||
|
hr = pChannel->lpVtbl->QueryInterface(pChannel, &IID_IRpcChannelBuffer, &((CStdProxyBuffer *)pThis)->pChannel);
|
||
|
|
||
|
return hr;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdProxyBuffer_Disconnect, public
|
||
|
//
|
||
|
// Synopsis: Disconnect the proxy from the channel.
|
||
|
//
|
||
|
// Derivation: IRpcProxyBuffer
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
void STDMETHODCALLTYPE
|
||
|
CStdProxyBuffer_Disconnect(IRpcProxyBuffer *pThis)
|
||
|
{
|
||
|
assert(pThis);
|
||
|
|
||
|
if(((CStdProxyBuffer *)pThis)->pChannel)
|
||
|
{
|
||
|
((CStdProxyBuffer *)pThis)->pChannel->lpVtbl->Release(((CStdProxyBuffer *)pThis)->pChannel);
|
||
|
((CStdProxyBuffer *)pThis)->pChannel = 0;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdStubBuffer_QueryInterface, public
|
||
|
//
|
||
|
// Synopsis: Query for an interface on the stub buffer.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_QueryInterface(IRpcStubBuffer *pThis, REFIID riid, void **ppvObject)
|
||
|
{
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(riid);
|
||
|
assert(ppvObject);
|
||
|
|
||
|
*ppvObject = 0;
|
||
|
if ((memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
||
|
(memcmp(riid, &IID_IRpcStubBuffer, sizeof(IID)) == 0))
|
||
|
{
|
||
|
*ppvObject = (IRpcStubBuffer *) pThis;
|
||
|
pThis->lpVtbl->AddRef(pThis);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdStubBuffer_AddRef, public
|
||
|
//
|
||
|
// Synopsis: Increment reference count.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_AddRef(IRpcStubBuffer *pThis)
|
||
|
{
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
InterlockedIncrement(&pStubBuffer->RefCount);
|
||
|
return (ULONG) pStubBuffer->RefCount;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CStdStubBuffer_Release, public
|
||
|
//
|
||
|
// Synopsis: Decrement reference count.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_Release(IRpcStubBuffer *pThis)
|
||
|
{
|
||
|
long RefCount;
|
||
|
unsigned long count;
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
RefCount = InterlockedDecrement(&pStubBuffer->RefCount);
|
||
|
assert(RefCount >= 0);
|
||
|
|
||
|
if(RefCount == 0)
|
||
|
{
|
||
|
count = 0;
|
||
|
|
||
|
//Decrement the DLL reference count.
|
||
|
InterlockedDecrement(&DllRefCount);
|
||
|
|
||
|
//Free the stub buffer
|
||
|
MIDL_user_free(pStubBuffer);
|
||
|
}
|
||
|
else
|
||
|
count = (unsigned long) pStubBuffer->RefCount;
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_Connect(IRpcStubBuffer *pThis, IUnknown *pUnkServer)
|
||
|
{
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
pThis->lpVtbl->Disconnect(pThis);
|
||
|
|
||
|
if(pUnkServer)
|
||
|
{
|
||
|
hr = pUnkServer->lpVtbl->QueryInterface(pUnkServer, &IID_IUnknown, &pStubBuffer->punkObject);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_Disconnect(IRpcStubBuffer *pThis)
|
||
|
{
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
long temp;
|
||
|
int j;
|
||
|
IUnknown *punkObject;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
punkObject = pStubBuffer->punkObject;
|
||
|
|
||
|
//Free the interface pointers held by the stub buffer
|
||
|
if(punkObject)
|
||
|
{
|
||
|
for(j = 0;
|
||
|
pStubBuffer->aInterfaceStub[j].lpVtbl;
|
||
|
j++)
|
||
|
{
|
||
|
temp = InterlockedExchange((long *) &pStubBuffer->aInterfaceStub[j].pvServerObject, 0);
|
||
|
|
||
|
if(temp)
|
||
|
punkObject->lpVtbl->Release(punkObject);
|
||
|
}
|
||
|
temp = InterlockedExchange((long *) &pStubBuffer->punkObject, 0);
|
||
|
|
||
|
if(temp)
|
||
|
punkObject->lpVtbl->Release(punkObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_Invoke(
|
||
|
IRpcStubBuffer *pThis,
|
||
|
RPCOLEMESSAGE *prpcmsg,
|
||
|
IRpcChannelBuffer *pRpcChannelBuffer)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
unsigned char **ppTemp;
|
||
|
unsigned char *pTemp;
|
||
|
CInterfaceStubVtbl *pStubVtbl;
|
||
|
CInterfaceStub *pInterfaceStub;
|
||
|
DWORD dwExceptionCode;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(prpcmsg);
|
||
|
assert(pRpcChannelBuffer);
|
||
|
|
||
|
pInterfaceStub = (CInterfaceStub *) pThis;
|
||
|
|
||
|
//Get a pointer to the stub vtbl.
|
||
|
ppTemp = (unsigned char **) pThis;
|
||
|
pTemp = *ppTemp;
|
||
|
pTemp -= sizeof(CInterfaceStubHeader);
|
||
|
pStubVtbl = (CInterfaceStubVtbl *) pTemp;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
//Check the data rep
|
||
|
|
||
|
//Check if we are connected to the server object.
|
||
|
if(pInterfaceStub->pvServerObject == 0)
|
||
|
{
|
||
|
CStdStubBuffer *pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
if(pStubBuffer->punkObject)
|
||
|
{
|
||
|
const IID *piid = NdrGetStubIID(pThis);
|
||
|
|
||
|
assert(piid);
|
||
|
|
||
|
hr = pStubBuffer->punkObject->lpVtbl->QueryInterface(pStubBuffer->punkObject, piid, &pInterfaceStub->pvServerObject);
|
||
|
if(FAILED(hr))
|
||
|
{
|
||
|
SetLastError(hr);
|
||
|
RpcRaiseException(RPC_E_FAULT);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//We are not connected to the server object.
|
||
|
SetLastError((unsigned long) CO_E_OBJNOTCONNECTED);
|
||
|
RpcRaiseException(RPC_E_FAULT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Check if procnum is valid.
|
||
|
if(prpcmsg->iMethod >= pStubVtbl->header.DispatchTableCount)
|
||
|
RpcRaiseException(RPC_S_PROCNUM_OUT_OF_RANGE);
|
||
|
|
||
|
(*pStubVtbl->header.pDispatchTable[prpcmsg->iMethod])(
|
||
|
pRpcChannelBuffer,
|
||
|
(PRPC_MESSAGE) prpcmsg,
|
||
|
pInterfaceStub->pvServerObject);
|
||
|
}
|
||
|
except(EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
dwExceptionCode = GetExceptionCode();
|
||
|
|
||
|
switch(dwExceptionCode)
|
||
|
{
|
||
|
case RPC_E_FAULT:
|
||
|
hr = GetLastError();
|
||
|
break;
|
||
|
case RPC_E_SERVERFAULT:
|
||
|
//Pass the server's exception to the channel.
|
||
|
dwExceptionCode = GetLastError();
|
||
|
RpcRaiseException(dwExceptionCode);
|
||
|
break;
|
||
|
default:
|
||
|
//Assume this is a win32 error code.
|
||
|
hr = HRESULT_FROM_WIN32(dwExceptionCode);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
IRpcStubBuffer * STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_IsIIDSupported(IRpcStubBuffer *pThis, REFIID riid)
|
||
|
{
|
||
|
int j;
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
IRpcStubBuffer *pInterfaceStub = 0;
|
||
|
const IID *pIID;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(riid);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
//Search the interface stubs in the stub buffer
|
||
|
for(j = 0;
|
||
|
pStubBuffer->aInterfaceStub[j].lpVtbl && !pInterfaceStub;
|
||
|
j++)
|
||
|
{
|
||
|
pIID = NdrGetStubIID(&pStubBuffer->aInterfaceStub[j].lpVtbl);
|
||
|
assert(pIID);
|
||
|
|
||
|
if(memcmp(riid, pIID, sizeof(IID)) == 0)
|
||
|
{
|
||
|
//We found the interface!
|
||
|
if(pStubBuffer->aInterfaceStub[j].pvServerObject == 0)
|
||
|
{
|
||
|
//Check if the server object supports the interface.
|
||
|
if(pStubBuffer->punkObject)
|
||
|
{
|
||
|
pStubBuffer->punkObject->lpVtbl->QueryInterface(
|
||
|
pStubBuffer->punkObject,
|
||
|
riid,
|
||
|
&pStubBuffer->aInterfaceStub[j].pvServerObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(pStubBuffer->aInterfaceStub[j].pvServerObject)
|
||
|
{
|
||
|
pInterfaceStub = (IRpcStubBuffer *)&pStubBuffer->aInterfaceStub[j].lpVtbl;
|
||
|
pInterfaceStub->lpVtbl->AddRef(pInterfaceStub);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pInterfaceStub;
|
||
|
}
|
||
|
|
||
|
ULONG STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_CountRefs(IRpcStubBuffer *pThis)
|
||
|
{
|
||
|
ULONG count = 0;
|
||
|
int j;
|
||
|
CStdStubBuffer *pStubBuffer;
|
||
|
|
||
|
assert(pThis);
|
||
|
|
||
|
pStubBuffer = NdrGetStubBuffer(pThis);
|
||
|
assert(pStubBuffer);
|
||
|
|
||
|
if(pStubBuffer->punkObject != 0)
|
||
|
count++;
|
||
|
|
||
|
//Search the interface stubs in the stub buffer
|
||
|
for(j = 0;
|
||
|
pStubBuffer->aInterfaceStub[j].lpVtbl;
|
||
|
j++)
|
||
|
{
|
||
|
//We found the interface!
|
||
|
if(pStubBuffer->aInterfaceStub[j].pvServerObject != 0)
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
HRESULT STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_DebugServerQueryInterface(IRpcStubBuffer *pThis, void **ppv)
|
||
|
{
|
||
|
HRESULT hr = E_UNEXPECTED;
|
||
|
|
||
|
assert(pThis);
|
||
|
assert(ppv);
|
||
|
|
||
|
*ppv = ((CInterfaceStub *)pThis)->pvServerObject;
|
||
|
if(*ppv)
|
||
|
hr = S_OK;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void STDMETHODCALLTYPE
|
||
|
CStdStubBuffer_DebugServerRelease(IRpcStubBuffer *pthis, void *pv)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: IUnknown_QueryInterface_Proxy
|
||
|
//
|
||
|
// Synopsis: Implementation of QueryInterface for interface proxy.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
HRESULT __stdcall
|
||
|
IUnknown_QueryInterface_Proxy(
|
||
|
IUnknown *pThis,
|
||
|
REFIID riid,
|
||
|
void **ppv)
|
||
|
{
|
||
|
HRESULT hr = E_NOINTERFACE;
|
||
|
CStdProxyBuffer *pProxyBuffer = NdrGetProxyBuffer(pThis);
|
||
|
|
||
|
assert(pProxyBuffer);
|
||
|
|
||
|
hr = pProxyBuffer->punkOuter->lpVtbl->QueryInterface(pProxyBuffer->punkOuter, riid, ppv);
|
||
|
|
||
|
return hr;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: IUnknown_AddRef_Proxy
|
||
|
//
|
||
|
// Synopsis: Implementation of AddRef for interface proxy.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG __stdcall
|
||
|
IUnknown_AddRef_Proxy(IUnknown *pThis)
|
||
|
{
|
||
|
CStdProxyBuffer *pProxyBuffer = NdrGetProxyBuffer(pThis);
|
||
|
ULONG count;
|
||
|
|
||
|
|
||
|
count = pProxyBuffer->punkOuter->lpVtbl->AddRef(pProxyBuffer->punkOuter);
|
||
|
|
||
|
return count;
|
||
|
};
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: IUnknown_Release_Proxy
|
||
|
//
|
||
|
// Synopsis: Implementation of Release for interface proxy.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
ULONG __stdcall
|
||
|
IUnknown_Release_Proxy(IUnknown *pThis)
|
||
|
{
|
||
|
CStdProxyBuffer *pProxyBuffer = NdrGetProxyBuffer(pThis);
|
||
|
ULONG count;
|
||
|
|
||
|
count = pProxyBuffer->punkOuter->lpVtbl->Release(pProxyBuffer->punkOuter);
|
||
|
|
||
|
return count;
|
||
|
};
|
||
|
|
||
|
void __RPC_STUB
|
||
|
IUnknown_QueryInterface_Stub(
|
||
|
IRpcChannelBuffer * _pRpcChannelBuffer,
|
||
|
PRPC_MESSAGE _pRpcMessage,
|
||
|
void * _pvServerObject )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void __RPC_STUB
|
||
|
IUnknown_AddRef_Stub(
|
||
|
IRpcChannelBuffer * _pRpcChannelBuffer,
|
||
|
PRPC_MESSAGE _pRpcMessage,
|
||
|
void * _pvServerObject )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void __RPC_STUB
|
||
|
IUnknown_Release_Stub(
|
||
|
IRpcChannelBuffer * _pRpcChannelBuffer,
|
||
|
PRPC_MESSAGE _pRpcMessage,
|
||
|
void * _pvServerObject )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MIDL_user_allocate
|
||
|
//
|
||
|
// Synopsis: Allocate memory via OLE task allocator.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
void * __stdcall MIDL_user_allocate(size_t size)
|
||
|
{
|
||
|
void *pMemory;
|
||
|
|
||
|
pMemory = CoTaskMemAlloc(size);
|
||
|
|
||
|
if(0 == pMemory)
|
||
|
{
|
||
|
SetLastError((unsigned long) E_OUTOFMEMORY);
|
||
|
RpcRaiseException(RPC_E_FAULT);
|
||
|
}
|
||
|
|
||
|
return pMemory;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MIDL_user_free
|
||
|
//
|
||
|
// Synopsis: Free memory using OLE task allocator.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
void __stdcall MIDL_user_free(void *pMemory)
|
||
|
{
|
||
|
CoTaskMemFree(pMemory);
|
||
|
}
|
||
|
|
||
|
#endif // !defined(__RPC_DOS__) && !defined(__RPC_WIN16__)
|