2888 lines
67 KiB
C++
2888 lines
67 KiB
C++
/*++
|
||
|
||
Microsoft Windows
|
||
Copyright (c) 1994-2000 Microsoft Corporation. All rights reserved.
|
||
|
||
Module Name:
|
||
proxy.c
|
||
|
||
Abstract:
|
||
Implements the IRpcProxyBuffer interface.
|
||
|
||
Author:
|
||
ShannonC 12-Oct-1994
|
||
|
||
Environment:
|
||
Windows NT and Windows 95 and PowerMac.
|
||
We do not support DOS, Win16 and Mac.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#define USE_STUBLESS_PROXY
|
||
#define CINTERFACE
|
||
|
||
#include <ndrp.h>
|
||
#include <ndrole.h>
|
||
#include <rpcproxy.h>
|
||
#include <stddef.h>
|
||
|
||
CStdProxyBuffer * RPC_ENTRY
|
||
NdrGetProxyBuffer(
|
||
void *pThis);
|
||
|
||
const IID * RPC_ENTRY
|
||
NdrGetProxyIID(
|
||
const void *pThis);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_Release(
|
||
IN IRpcProxyBuffer *This);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer2_Release(
|
||
IN IRpcProxyBuffer *This);
|
||
|
||
BOOL NdrpFindInterface(
|
||
IN const ProxyFileInfo ** pProxyFileList,
|
||
IN REFIID riid,
|
||
OUT const ProxyFileInfo ** ppProxyFileInfo,
|
||
OUT long * pIndex );
|
||
|
||
|
||
// The channel wrapper
|
||
//
|
||
|
||
typedef struct tagChannelWrapper
|
||
{
|
||
const IRpcChannelBufferVtbl *lpVtbl;
|
||
long RefCount;
|
||
const IID * pIID;
|
||
struct IRpcChannelBuffer * pChannel;
|
||
} ChannelWrapper;
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CreateChannelWrapper
|
||
(
|
||
const IID * pIID,
|
||
IRpcChannelBuffer * pChannel,
|
||
IRpcChannelBuffer ** pChannelWrapper
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CreateAsyncChannelWrapper
|
||
(
|
||
const IID * pIID,
|
||
IRpcChannelBuffer * pChannel,
|
||
IRpcChannelBuffer ** pChannelWrapper
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_QueryInterface
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
REFIID riid,
|
||
void ** ppvObject
|
||
);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
ChannelWrapper_AddRef
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
ChannelWrapper_Release
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetBuffer
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_SendReceive
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_FreeBuffer
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetDestCtx
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_IsConnected
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetProtocolVersion
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
DWORD * pdwVersion
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Send(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Receive(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG ulSize,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Cancel(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetCallContext(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid,
|
||
void ** pInterface
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetDestCtxEx(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetState(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pState
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_RegisterAsync(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
IAsyncManager * pAsyncMgr
|
||
);
|
||
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_QueryInterface
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
REFIID riid,
|
||
void ** ppvObject
|
||
);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_AddRef
|
||
(
|
||
IAsyncRpcChannelBuffer * This
|
||
);
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Release
|
||
(
|
||
IAsyncRpcChannelBuffer * This
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetBuffer
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_SendReceive
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_FreeBuffer
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetDestCtx
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_IsConnected
|
||
(
|
||
IAsyncRpcChannelBuffer * This
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetProtocolVersion
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
DWORD * pdwVersion
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Send(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ISynchronize * pSynchronize,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Receive(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
);
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetDestCtxEx
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
);
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Global data
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
// ProxyBuffer vtables for non-delegaed and delegated case.
|
||
|
||
extern const IRpcProxyBufferVtbl CStdProxyBufferVtbl = {
|
||
CStdProxyBuffer_QueryInterface,
|
||
CStdProxyBuffer_AddRef,
|
||
CStdProxyBuffer_Release,
|
||
CStdProxyBuffer_Connect,
|
||
CStdProxyBuffer_Disconnect };
|
||
|
||
extern const IRpcProxyBufferVtbl CStdProxyBuffer2Vtbl = {
|
||
CStdProxyBuffer_QueryInterface,
|
||
CStdProxyBuffer_AddRef,
|
||
CStdProxyBuffer2_Release,
|
||
CStdProxyBuffer2_Connect,
|
||
CStdProxyBuffer2_Disconnect };
|
||
|
||
// ICallFactory interface on the ProxyBuffer objects.
|
||
// ICallFactory is an interface on a sync proxy only.
|
||
// It has been introduced for NT5 beta2.
|
||
|
||
extern const ICallFactoryVtbl CStdProxyBuffer_CallFactoryVtbl = {
|
||
CStdProxyBuffer_CF_QueryInterface,
|
||
CStdProxyBuffer_CF_AddRef,
|
||
CStdProxyBuffer_CF_Release,
|
||
CStdProxyBuffer_CF_CreateCall };
|
||
|
||
extern const ICallFactoryVtbl CStdProxyBuffer2_CallFactoryVtbl = {
|
||
CStdProxyBuffer_CF_QueryInterface,
|
||
CStdProxyBuffer_CF_AddRef,
|
||
CStdProxyBuffer_CF_Release,
|
||
CStdProxyBuffer2_CF_CreateCall };
|
||
|
||
extern const IReleaseMarshalBuffersVtbl CStdProxyBuffer_ReleaseMarshalBuffersVtbl = {
|
||
CStdProxyBuffer_RMB_QueryInterface,
|
||
CStdProxyBuffer_RMB_AddRef,
|
||
CStdProxyBuffer_RMB_Release,
|
||
CStdProxyBuffer_RMB_ReleaseMarshalBuffer };
|
||
|
||
extern const IReleaseMarshalBuffersVtbl CStdAsyncProxyBuffer_ReleaseMarshalBuffersVtbl = {
|
||
CStdProxyBuffer_RMB_QueryInterface,
|
||
CStdProxyBuffer_RMB_AddRef,
|
||
CStdProxyBuffer_RMB_Release,
|
||
CStdAsyncProxyBuffer_RMB_ReleaseMarshalBuffer };
|
||
|
||
// Async proxy buffer vtables
|
||
|
||
extern const IRpcProxyBufferVtbl CStdAsyncProxyBufferVtbl = {
|
||
CStdAsyncProxyBuffer_QueryInterface,
|
||
CStdProxyBuffer_AddRef,
|
||
CStdAsyncProxyBuffer_Release,
|
||
CStdAsyncProxyBuffer_Connect,
|
||
CStdProxyBuffer_Disconnect };
|
||
|
||
extern const IRpcProxyBufferVtbl CStdAsyncProxyBuffer2Vtbl = {
|
||
CStdAsyncProxyBuffer_QueryInterface,
|
||
CStdProxyBuffer_AddRef,
|
||
CStdAsyncProxyBuffer2_Release,
|
||
CStdAsyncProxyBuffer2_Connect,
|
||
CStdProxyBuffer2_Disconnect };
|
||
|
||
// Channel wrapper is used for delegetion only.
|
||
|
||
|
||
extern const IRpcChannelBuffer3Vtbl ChannelWrapperVtbl = {
|
||
ChannelWrapper_QueryInterface,
|
||
ChannelWrapper_AddRef,
|
||
ChannelWrapper_Release,
|
||
ChannelWrapper_GetBuffer,
|
||
ChannelWrapper_SendReceive,
|
||
ChannelWrapper_FreeBuffer,
|
||
ChannelWrapper_GetDestCtx,
|
||
ChannelWrapper_IsConnected,
|
||
ChannelWrapper_GetProtocolVersion,
|
||
ChannelWrapper_Send,
|
||
ChannelWrapper_Receive,
|
||
ChannelWrapper_Cancel,
|
||
ChannelWrapper_GetCallContext,
|
||
ChannelWrapper_GetDestCtxEx,
|
||
ChannelWrapper_GetState,
|
||
ChannelWrapper_RegisterAsync
|
||
};
|
||
|
||
extern const IAsyncRpcChannelBufferVtbl AsyncChannelWrapperVtbl = {
|
||
AsyncChannelWrapper_QueryInterface,
|
||
AsyncChannelWrapper_AddRef,
|
||
AsyncChannelWrapper_Release,
|
||
AsyncChannelWrapper_GetBuffer,
|
||
AsyncChannelWrapper_SendReceive,
|
||
AsyncChannelWrapper_FreeBuffer,
|
||
AsyncChannelWrapper_GetDestCtx,
|
||
AsyncChannelWrapper_IsConnected,
|
||
AsyncChannelWrapper_GetProtocolVersion,
|
||
AsyncChannelWrapper_Send,
|
||
AsyncChannelWrapper_Receive,
|
||
AsyncChannelWrapper_GetDestCtxEx
|
||
};
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// End of Global data
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
|
||
#pragma code_seg(".orpc")
|
||
|
||
// __inline
|
||
CStdProxyBuffer * RPC_ENTRY
|
||
NdrGetProxyBuffer(
|
||
IN void *pThis)
|
||
/*++
|
||
|
||
Routine Description:
|
||
The "this" pointer points to the pProxyVtbl field in the
|
||
CStdProxyBuffer structure. The NdrGetProxyBuffer function
|
||
returns a pointer to the top of the CStdProxyBuffer
|
||
structure.
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
|
||
Return Value:
|
||
This function returns a pointer to the proxy buffer.
|
||
|
||
--*/
|
||
{
|
||
unsigned char *pTemp;
|
||
|
||
pTemp = (unsigned char *) pThis;
|
||
pTemp -= offsetof(CStdProxyBuffer, pProxyVtbl);
|
||
|
||
return (CStdProxyBuffer *)pTemp;
|
||
}
|
||
|
||
//__inline
|
||
const IID * RPC_ENTRY
|
||
NdrGetProxyIID(
|
||
IN const void *pThis)
|
||
/*++
|
||
|
||
Routine Description:
|
||
The NDRGetProxyIID function returns a pointer to IID.
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
|
||
Return Value:
|
||
This function returns a pointer to the IID.
|
||
|
||
--*/
|
||
{
|
||
unsigned char ** ppTemp;
|
||
unsigned char * pTemp;
|
||
CInterfaceProxyVtbl *pProxyVtbl;
|
||
|
||
//Get a pointer to the proxy vtbl.
|
||
ppTemp = (unsigned char **) pThis;
|
||
pTemp = *ppTemp;
|
||
pTemp -= sizeof(CInterfaceProxyHeader);
|
||
pProxyVtbl = (CInterfaceProxyVtbl *) pTemp;
|
||
|
||
return pProxyVtbl->header.piid;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_QueryInterface(
|
||
IN IRpcProxyBuffer * This,
|
||
IN REFIID riid,
|
||
OUT void ** ppv)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Query for an interface on the proxy. This function provides access
|
||
to both internal and external interfaces.
|
||
|
||
Arguments:
|
||
riid - Supplies the IID of the requested interface.
|
||
ppv - Returns a pointer to the requested interface.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
HRESULT hr = E_NOINTERFACE;
|
||
const IID * pIID;
|
||
|
||
*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( &pCThis->RefCount);
|
||
*ppv = This;
|
||
hr = S_OK;
|
||
return hr;
|
||
}
|
||
else if ( pCThis->pCallFactoryVtbl != 0 &&
|
||
memcmp(&riid, &IID_ICallFactory, sizeof(IID)) == 0 )
|
||
{
|
||
// This is an exposed interface so go through punkOuter ot addref.
|
||
pCThis->punkOuter->lpVtbl->AddRef(pCThis->punkOuter);
|
||
|
||
*ppv = (void *) & pCThis->pCallFactoryVtbl;
|
||
hr = S_OK;
|
||
return hr;
|
||
}
|
||
else if ( pCThis->pRMBVtbl &&
|
||
(memcmp(&riid, &IID_IReleaseMarshalBuffers,sizeof(IID)) == 0))
|
||
{
|
||
InterlockedIncrement( &pCThis->RefCount);
|
||
|
||
*ppv = (void *) & pCThis->pRMBVtbl;
|
||
hr = S_OK;
|
||
return hr;
|
||
}
|
||
|
||
pIID = NdrGetProxyIID(&pCThis->pProxyVtbl);
|
||
|
||
if( memcmp(&riid, pIID, sizeof(IID)) == 0)
|
||
{
|
||
//Increment the reference count.
|
||
|
||
pCThis->punkOuter->lpVtbl->AddRef(pCThis->punkOuter);
|
||
*ppv = (void *) &pCThis->pProxyVtbl;
|
||
hr = S_OK;
|
||
}
|
||
|
||
return hr;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer_QueryInterface(
|
||
IN IRpcProxyBuffer * This,
|
||
IN REFIID riid,
|
||
OUT void ** ppv)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Query for an interface on the proxy. This function provides access
|
||
to both internal and external interfaces.
|
||
|
||
Used for
|
||
CStdAsyncProxyBuffer2 as well.
|
||
|
||
Arguments:
|
||
riid - Supplies the IID of the requested interface.
|
||
ppv - Returns a pointer to the requested interface.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
HRESULT hr = E_NOINTERFACE;
|
||
const IID * pIID;
|
||
|
||
*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( &pCThis->RefCount);
|
||
*ppv = This;
|
||
hr = S_OK;
|
||
return hr;
|
||
}
|
||
else if ( pCThis->pRMBVtbl &&
|
||
(memcmp(&riid, &IID_IReleaseMarshalBuffers,sizeof(IID)) == 0))
|
||
{
|
||
InterlockedIncrement( &pCThis->RefCount);
|
||
|
||
*ppv = (void *) & pCThis->pRMBVtbl;
|
||
hr = S_OK;
|
||
return hr;
|
||
}
|
||
|
||
if(memcmp(&riid, &IID_ISynchronize, sizeof(IID)) == 0)
|
||
{
|
||
hr = pCThis->punkOuter->lpVtbl->QueryInterface( pCThis->punkOuter,
|
||
IID_ISynchronize,
|
||
ppv);
|
||
}
|
||
|
||
pIID = NdrGetProxyIID(&pCThis->pProxyVtbl);
|
||
|
||
if(memcmp(&riid, pIID, sizeof(IID)) == 0)
|
||
{
|
||
//Increment the reference count.
|
||
pCThis->punkOuter->lpVtbl->AddRef(pCThis->punkOuter);
|
||
|
||
*ppv = (void *) &pCThis->pProxyVtbl;
|
||
hr = S_OK;
|
||
}
|
||
|
||
return hr;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_AddRef(
|
||
IN IRpcProxyBuffer *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Increment reference count.
|
||
|
||
Used for
|
||
CStdProxyBuffer2
|
||
CStdAsyncProxyBuffer
|
||
CStdAsuncProxyBuffer2
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
// We do not need to go through punkOuter for ICallFactory.
|
||
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
|
||
InterlockedIncrement(&pCThis->RefCount);
|
||
|
||
return (ULONG) pCThis->RefCount;
|
||
};
|
||
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_Release(
|
||
IN IRpcProxyBuffer *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Decrement reference count.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
IPSFactoryBuffer *pFactory;
|
||
|
||
NDR_ASSERT(((CStdProxyBuffer *)This)->RefCount > 0, "Invalid reference count");
|
||
|
||
count = (unsigned long) ((CStdProxyBuffer *)This)->RefCount - 1;
|
||
|
||
|
||
if(InterlockedDecrement(&((CStdProxyBuffer *)This)->RefCount) == 0)
|
||
{
|
||
count = 0;
|
||
|
||
pFactory = (IPSFactoryBuffer *) ((CStdProxyBuffer *)This)->pPSFactory;
|
||
|
||
//Decrement the DLL reference count.
|
||
pFactory->lpVtbl->Release(pFactory);
|
||
|
||
#if DBG == 1
|
||
//In debug builds, zero fill the memory.
|
||
memset(This, '\0', sizeof(CStdProxyBuffer));
|
||
#endif
|
||
|
||
//Free the memory
|
||
(*pfnCoTaskMemFree)(This);
|
||
}
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer2_Release(
|
||
IN IRpcProxyBuffer * This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Decrement reference count. This function is used by proxies
|
||
which delegate to the base interface.
|
||
|
||
Arguments:
|
||
This - Points to a CStdProxyBuffer2.
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
IPSFactoryBuffer * pFactory;
|
||
IRpcProxyBuffer * pBaseProxyBuffer;
|
||
IUnknown * pBaseProxy;
|
||
|
||
NDR_ASSERT(((CStdProxyBuffer2 *)This)->RefCount > 0, "Invalid reference count");
|
||
|
||
count = (ULONG) ((CStdProxyBuffer2 *)This)->RefCount - 1;
|
||
|
||
if(InterlockedDecrement(&((CStdProxyBuffer2 *)This)->RefCount) == 0)
|
||
{
|
||
count = 0;
|
||
|
||
//Delegation support.
|
||
pBaseProxy = ((CStdProxyBuffer2 *)This)->pBaseProxy;
|
||
if(pBaseProxy != 0)
|
||
{
|
||
// Shannon - why?
|
||
//This is a weak reference, so we don't release it.
|
||
//pBaseProxy->lpVtbl->Release(pBaseProxy);
|
||
}
|
||
|
||
pBaseProxyBuffer = ((CStdProxyBuffer2 *)This)->pBaseProxyBuffer;
|
||
|
||
if( pBaseProxyBuffer != 0)
|
||
{
|
||
pBaseProxyBuffer->lpVtbl->Release(pBaseProxyBuffer);
|
||
}
|
||
|
||
//Decrement the DLL reference count.
|
||
pFactory = (IPSFactoryBuffer *) ((CStdProxyBuffer2 *)This)->pPSFactory;
|
||
pFactory->lpVtbl->Release(pFactory);
|
||
|
||
#if DBG == 1
|
||
//In debug builds, zero fill the memory.
|
||
memset(This, '\0', sizeof(CStdProxyBuffer2));
|
||
#endif
|
||
|
||
//Free the memory
|
||
(*pfnCoTaskMemFree)(This);
|
||
}
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer_Release(
|
||
IN IRpcProxyBuffer *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Decrement reference count.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
// We do not need to go through punkOuter for ICallFactory
|
||
// and so everything is local.
|
||
|
||
CStdAsyncProxyBuffer * pAsyncPB = (CStdAsyncProxyBuffer *)This;
|
||
ULONG count;
|
||
|
||
|
||
NDR_ASSERT( pAsyncPB->RefCount > 0, "Async proxy Invalid reference count");
|
||
|
||
count = (unsigned long) pAsyncPB->RefCount - 1;
|
||
|
||
|
||
if ( InterlockedDecrement(&pAsyncPB->RefCount) == 0)
|
||
{
|
||
IPSFactoryBuffer * pFactory = pAsyncPB->pPSFactory;
|
||
|
||
count = 0;
|
||
|
||
// Release the pAsyncMsg and the related state
|
||
NdrpAsyncProxyMsgDestructor( pAsyncPB );
|
||
|
||
//Decrement the DLL reference count.
|
||
pFactory->lpVtbl->Release( pFactory );
|
||
|
||
#if DBG == 1
|
||
//In debug builds, zero fill the memory.
|
||
memset( pAsyncPB, '\32', sizeof(CStdAsyncProxyBuffer));
|
||
#endif
|
||
|
||
//Free the memory
|
||
(*pfnCoTaskMemFree)(pAsyncPB);
|
||
}
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer2_Release(
|
||
IN IRpcProxyBuffer * This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Decrement reference count. This function is used by proxies
|
||
which delegate to the base interface.
|
||
|
||
Arguments:
|
||
This - Points to a CStdProxyBuffer2.
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
CStdAsyncProxyBuffer * pAsyncPB = (CStdAsyncProxyBuffer *)This;
|
||
ULONG count;
|
||
|
||
NDR_ASSERT( pAsyncPB->RefCount > 0, "Invalid reference count");
|
||
|
||
count = (ULONG) pAsyncPB->RefCount - 1;
|
||
|
||
if ( InterlockedDecrement(&pAsyncPB->RefCount) == 0)
|
||
{
|
||
IRpcProxyBuffer * pBaseProxyBuffer ;
|
||
IPSFactoryBuffer * pFactory = pAsyncPB->pPSFactory;
|
||
|
||
count = 0;
|
||
|
||
// Delegation support - release the base async proxy.
|
||
|
||
if( pAsyncPB->map.pBaseProxy != 0)
|
||
{
|
||
// Shannon - why?
|
||
//This is a weak reference, so we don't release it.
|
||
//pBaseProxy->lpVtbl->Release(pBaseProxy);
|
||
}
|
||
|
||
pBaseProxyBuffer = pAsyncPB->pBaseProxyBuffer;
|
||
|
||
if( pBaseProxyBuffer != 0)
|
||
pBaseProxyBuffer->lpVtbl->Release(pBaseProxyBuffer);
|
||
|
||
// Release the pAsyncMsg and the related state
|
||
NdrpAsyncProxyMsgDestructor( (CStdAsyncProxyBuffer*)This );
|
||
|
||
// Then clean up the async proxy itself.
|
||
|
||
//Decrement the DLL reference count.
|
||
pFactory->lpVtbl->Release(pFactory);
|
||
|
||
#if DBG == 1
|
||
//In debug builds, zero fill the memory.
|
||
memset(pAsyncPB, '\32', sizeof(CStdAsyncProxyBuffer));
|
||
#endif
|
||
|
||
//Free the memory
|
||
(*pfnCoTaskMemFree)(pAsyncPB);
|
||
}
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_RMB_QueryInterface(
|
||
IN IReleaseMarshalBuffers *This,
|
||
IN REFIID riid,
|
||
OUT void ** ppvObject)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Query for an interface on the interface stub IReleaseMarshalBuffers pointer.
|
||
|
||
Arguments:
|
||
riid - Supplies the IID of the interface being requested.
|
||
ppvObject - Returns a pointer to the requested interface.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
Note:
|
||
Works the same way for ProxyBuffer2 and AsyncProxyBuffer.
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pSyncPB = (CStdProxyBuffer *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer,pRMBVtbl));
|
||
|
||
return pSyncPB->lpVtbl->QueryInterface( (IRpcProxyBuffer *)pSyncPB,
|
||
riid,
|
||
ppvObject );
|
||
}
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_RMB_AddRef(
|
||
IN IReleaseMarshalBuffers *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of AddRef for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
|
||
CStdProxyBuffer * pSyncPB = (CStdProxyBuffer *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer,pRMBVtbl));
|
||
|
||
// It needs to go through punkOuter.
|
||
|
||
count = pSyncPB->lpVtbl->AddRef((IRpcProxyBuffer *) pSyncPB );
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_RMB_Release(
|
||
IN IReleaseMarshalBuffers *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of Release for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
|
||
CStdProxyBuffer2 * pSyncPB = (CStdProxyBuffer2 *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer2,pRMBVtbl));
|
||
|
||
count = pSyncPB->lpVtbl->Release( (IRpcProxyBuffer *)pSyncPB);
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_RMB_ReleaseMarshalBuffer(
|
||
IN IReleaseMarshalBuffers *This,
|
||
IN RPCOLEMESSAGE * pMsg,
|
||
IN DWORD dwFlags,
|
||
IN IUnknown *pChnl)
|
||
{
|
||
CStdProxyBuffer * pSyncPB;
|
||
HRESULT hr;
|
||
if (NULL != pChnl)
|
||
return E_INVALIDARG;
|
||
|
||
// [in] only in client side.
|
||
if (dwFlags)
|
||
return E_INVALIDARG;
|
||
|
||
hr = NdrpClientReleaseMarshalBuffer(This,
|
||
(RPC_MESSAGE *)pMsg,
|
||
dwFlags,
|
||
FALSE ); // SYNC
|
||
|
||
return hr;
|
||
}
|
||
|
||
#define IN_BUFFER 0
|
||
#define OUT_BUFFER 1
|
||
|
||
// the pRMBVtbl member is in the same position is both CStdProxyBuffer(2) and
|
||
// CStdAsyncProxyBuffer so we can cast it anyway.
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer_RMB_ReleaseMarshalBuffer(
|
||
IN IReleaseMarshalBuffers *This,
|
||
IN RPCOLEMESSAGE * pMsg,
|
||
IN DWORD dwIOFlags,
|
||
IN IUnknown *pChnl)
|
||
{
|
||
HRESULT hr;
|
||
if (NULL != pChnl)
|
||
return E_INVALIDARG;
|
||
|
||
// [in] only in client side.
|
||
if (dwIOFlags != IN_BUFFER)
|
||
return E_INVALIDARG;
|
||
|
||
hr = NdrpClientReleaseMarshalBuffer(This,
|
||
(RPC_MESSAGE *)pMsg,
|
||
dwIOFlags,
|
||
TRUE); // is async
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_Connect(
|
||
IN IRpcProxyBuffer * This,
|
||
IN IRpcChannelBuffer * pChannel)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Connect the proxy to the channel.
|
||
|
||
Arguments:
|
||
pChannel - Supplies a pointer to the channel.
|
||
|
||
Return Value:
|
||
S_OK
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pTemp = 0;
|
||
|
||
//
|
||
// Get a pointer to the new channel.
|
||
//
|
||
hr = pChannel->lpVtbl->QueryInterface(
|
||
pChannel, IID_IRpcChannelBuffer, (void **) &pTemp);
|
||
|
||
if(hr == S_OK)
|
||
{
|
||
//
|
||
// Save the pointer to the new channel.
|
||
//
|
||
pTemp = (IRpcChannelBuffer *) InterlockedExchangePointer(
|
||
(PVOID *) &pCThis->pChannel, (PVOID) pTemp);
|
||
|
||
if(pTemp != 0)
|
||
{
|
||
//
|
||
//Release the old channel.
|
||
//
|
||
pTemp->lpVtbl->Release(pTemp);
|
||
pTemp = 0;
|
||
}
|
||
}
|
||
return hr;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer_Connect(
|
||
IN IRpcProxyBuffer * This,
|
||
IN IRpcChannelBuffer * pChannel)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Connect the proxy to the channel.
|
||
|
||
Arguments:
|
||
pChannel - Supplies a pointer to the channel.
|
||
|
||
Return Value:
|
||
S_OK
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pTemp = 0;
|
||
|
||
// Get a pointer to the new channel.
|
||
// Note, the async proxy is not aggregated with the channel,
|
||
// It simply keeps the channel pointer.
|
||
//
|
||
hr = pChannel->lpVtbl->QueryInterface(
|
||
pChannel, IID_IAsyncRpcChannelBuffer, (void **) &pTemp);
|
||
|
||
if(hr == S_OK)
|
||
{
|
||
//
|
||
// Save the pointer to the new channel.
|
||
//
|
||
pTemp = (IRpcChannelBuffer *) InterlockedExchangePointer(
|
||
(PVOID *) &pCThis->pChannel, (PVOID) pTemp);
|
||
|
||
if(pTemp != 0)
|
||
{
|
||
//
|
||
//Release the old channel.
|
||
//
|
||
pTemp->lpVtbl->Release(pTemp);
|
||
pTemp = 0;
|
||
}
|
||
}
|
||
return hr;
|
||
};
|
||
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer2_Connect(
|
||
IN IRpcProxyBuffer * This,
|
||
IN IRpcChannelBuffer * pChannel)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Connect the proxy to the channel. Supports delegation.
|
||
|
||
Arguments:
|
||
pChannel - Supplies a pointer to the channel.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
E_OUTOFMEMORY
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
IRpcProxyBuffer * pBaseProxyBuffer;
|
||
IRpcChannelBuffer * pWrapper;
|
||
const IID * pIID;
|
||
|
||
hr = CStdProxyBuffer_Connect(This, pChannel);
|
||
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
pBaseProxyBuffer = ((CStdProxyBuffer2 *)This)->pBaseProxyBuffer;
|
||
|
||
if(pBaseProxyBuffer != 0)
|
||
{
|
||
pIID = NdrGetProxyIID(&((CStdProxyBuffer2 *)This)->pProxyVtbl);
|
||
|
||
hr = CreateChannelWrapper(pIID,
|
||
pChannel,
|
||
&pWrapper);
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
hr = pBaseProxyBuffer->lpVtbl->Connect(pBaseProxyBuffer, pWrapper);
|
||
// HACKALERT: OleAutomation returns NULL pv in CreateProxy
|
||
// in cases where they don't know whether to return an NDR
|
||
// proxy or a custom-format proxy. So we have to go connect
|
||
// the proxy first then Query for the real interface once that
|
||
// is done.
|
||
if((NULL == ((CStdProxyBuffer2 *)This)->pBaseProxy) &&
|
||
SUCCEEDED(hr))
|
||
{
|
||
IUnknown *pv;
|
||
|
||
hr = pBaseProxyBuffer->lpVtbl->QueryInterface(pBaseProxyBuffer,
|
||
((CStdProxyBuffer2 *)This)->iidBase,
|
||
(void **) &pv);
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
//Release our reference here.
|
||
pv->lpVtbl->Release(pv);
|
||
|
||
//We keep a weak reference to pv.
|
||
((CStdProxyBuffer2 *)This)->pBaseProxy = pv;
|
||
}
|
||
}
|
||
pWrapper->lpVtbl->Release(pWrapper);
|
||
}
|
||
}
|
||
}
|
||
|
||
return hr;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdAsyncProxyBuffer2_Connect(
|
||
IN IRpcProxyBuffer * This,
|
||
IN IRpcChannelBuffer * pChannel)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Connect the proxy to the channel. Supports delegation.
|
||
|
||
Arguments:
|
||
pChannel - Supplies a pointer to the channel.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
E_OUTOFMEMORY
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
IRpcProxyBuffer * pBaseProxyBuffer;
|
||
IRpcChannelBuffer * pWrapper;
|
||
const IID * pIID;
|
||
|
||
hr = CStdAsyncProxyBuffer_Connect(This, pChannel);
|
||
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
// Note that all the fields from CStdProxyBuffer2 that we indicate below
|
||
// have the same offsets in CStdAsyncProxyBuffer that is being handled.
|
||
// So I leave the cast unchanged to make future code merge easier.
|
||
//
|
||
pBaseProxyBuffer = ((CStdProxyBuffer2 *)This)->pBaseProxyBuffer;
|
||
|
||
if(pBaseProxyBuffer != 0)
|
||
{
|
||
pIID = NdrGetProxyIID(&((CStdProxyBuffer2 *)This)->pProxyVtbl);
|
||
|
||
// We need a pChannel that is guaranteed to be IAsyncRpcChannelBuffer -
|
||
// but note, this is exactly what we obtained in the Connect call above.
|
||
|
||
hr = CreateAsyncChannelWrapper( pIID,
|
||
((CStdProxyBuffer2*)This)->pChannel,
|
||
&pWrapper);
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
hr = pBaseProxyBuffer->lpVtbl->Connect(pBaseProxyBuffer, pWrapper);
|
||
|
||
// This hack alert is rather for future.
|
||
// HACKALERT: OleAutomation returns NULL pv in CreateProxy
|
||
// in cases where they don't know whether to return an NDR
|
||
// proxy or a custom-format proxy. So we have to go connect
|
||
// the proxy first then Query for the real interface once that
|
||
// is done.
|
||
if((NULL == ((CStdProxyBuffer2 *)This)->pBaseProxy) &&
|
||
SUCCEEDED(hr))
|
||
{
|
||
IUnknown *pv;
|
||
|
||
hr = pBaseProxyBuffer->lpVtbl->QueryInterface(pBaseProxyBuffer,
|
||
((CStdProxyBuffer2 *)This)->iidBase,
|
||
(void **) &pv);
|
||
if(SUCCEEDED(hr))
|
||
{
|
||
//Release our reference here.
|
||
pv->lpVtbl->Release(pv);
|
||
|
||
//We keep a weak reference to pv.
|
||
((CStdProxyBuffer2 *)This)->pBaseProxy = pv;
|
||
}
|
||
}
|
||
pWrapper->lpVtbl->Release(pWrapper);
|
||
}
|
||
}
|
||
}
|
||
|
||
return hr;
|
||
};
|
||
|
||
|
||
void STDMETHODCALLTYPE
|
||
CStdProxyBuffer_Disconnect(
|
||
IN IRpcProxyBuffer *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Disconnect the proxy from the channel.
|
||
|
||
Also used for:
|
||
CStdAsyncProxyBuffer_Disconnect
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
||
IRpcChannelBuffer * pOldChannel;
|
||
|
||
pOldChannel = (IRpcChannelBuffer *) InterlockedExchangePointer(
|
||
(PVOID *) &pCThis->pChannel, 0);
|
||
|
||
if(pOldChannel != 0)
|
||
{
|
||
//Release the old channel.
|
||
//
|
||
pOldChannel->lpVtbl->Release(pOldChannel);
|
||
}
|
||
};
|
||
|
||
void STDMETHODCALLTYPE
|
||
CStdProxyBuffer2_Disconnect(
|
||
IN IRpcProxyBuffer *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Disconnect the proxy from the channel.
|
||
|
||
Also used for:
|
||
CStdAsyncProxyBuffer2_Disconnect
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
IRpcProxyBuffer *pBaseProxyBuffer;
|
||
|
||
CStdProxyBuffer_Disconnect(This);
|
||
|
||
pBaseProxyBuffer = ((CStdProxyBuffer2 *)This)->pBaseProxyBuffer;
|
||
|
||
if(pBaseProxyBuffer != 0)
|
||
pBaseProxyBuffer->lpVtbl->Disconnect(pBaseProxyBuffer);
|
||
};
|
||
|
||
|
||
HRESULT
|
||
NdrpCreateNonDelegatedAsyncProxy(
|
||
//CStdProxyBuffer_CreateAsyncProxy(
|
||
IN IRpcProxyBuffer *This,
|
||
IN REFIID riid, // async IID
|
||
IN IUnknown * punkOuter, // controlling unknown
|
||
OUT CStdAsyncProxyBuffer ** ppAsyncProxy
|
||
)
|
||
/*
|
||
Creates a call object, i.e. an async proxy object.
|
||
An async proxy doesn't have a pSynchronize, just passes it.
|
||
|
||
Note, because the call comes via a CStdProxyBuffer, not Buffer2,
|
||
we know that we need to create only a non-delegated async proxy.
|
||
This is because CStdProxyBuffer itself is a non-delegated proxy.
|
||
*/
|
||
{
|
||
BOOL fFound;
|
||
long j; // if index
|
||
const ProxyFileInfo * pProxyFileInfo;
|
||
|
||
CStdProxyBuffer * pSyncPB = (CStdProxyBuffer *)This;
|
||
|
||
*ppAsyncProxy = 0;
|
||
|
||
if ( ! pSyncPB->pCallFactoryVtbl || !pSyncPB->pAsyncIID )
|
||
return E_NOINTERFACE;
|
||
|
||
// Check if sync and async iids match.
|
||
|
||
if ( memcmp( &riid, pSyncPB->pAsyncIID, sizeof(IID)) != 0 )
|
||
return E_NOINTERFACE;
|
||
|
||
// same file, so we can use the sync pPSFactory.
|
||
|
||
fFound = NdrpFindInterface( ((CStdPSFactoryBuffer *)pSyncPB->pPSFactory)->pProxyFileList,
|
||
riid,
|
||
&pProxyFileInfo,
|
||
& j);
|
||
if ( !fFound )
|
||
return E_NOINTERFACE;
|
||
|
||
CStdAsyncProxyBuffer *pAsyncPB =
|
||
(CStdAsyncProxyBuffer*)(*pfnCoTaskMemAlloc)(sizeof(CStdAsyncProxyBuffer));
|
||
|
||
if( ! pAsyncPB )
|
||
return E_OUTOFMEMORY;
|
||
|
||
memset( pAsyncPB, 0, sizeof(CStdAsyncProxyBuffer));
|
||
//
|
||
// Everything gets zeroed out regardless of their position
|
||
// when mapping CStdBuffer vs. CstdBuffer2 into CStdAsyncBuffer
|
||
|
||
// Non-delegated case.
|
||
|
||
pAsyncPB->lpVtbl = & CStdAsyncProxyBufferVtbl;
|
||
pAsyncPB->pProxyVtbl = & pProxyFileInfo->pProxyVtblList[j]->Vtbl;
|
||
pAsyncPB->RefCount = 1;
|
||
pAsyncPB->punkOuter = punkOuter ? punkOuter
|
||
: (IUnknown *) pAsyncPB;
|
||
|
||
pAsyncPB->pSyncIID = NdrGetProxyIID( &pSyncPB->pProxyVtbl );
|
||
// Note, no connection to channel yet.
|
||
// Actually we never call create call on the channel.
|
||
|
||
NdrpAsyncProxyMsgConstructor( pAsyncPB );
|
||
|
||
// Increment the DLL reference count for DllCanUnloadNow.
|
||
// Same dll, so we can use the sync pPSFactory.
|
||
//
|
||
pSyncPB->pPSFactory->lpVtbl->AddRef( pSyncPB->pPSFactory );
|
||
// This is in the "map".
|
||
((CStdProxyBuffer *)pAsyncPB)->pPSFactory = pSyncPB->pPSFactory;
|
||
|
||
// Just have it in both places.
|
||
pAsyncPB->pPSFactory = pSyncPB->pPSFactory;
|
||
|
||
*ppAsyncProxy = pAsyncPB;
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
// CStdProxyBuffer2_CreateAsyncProxy(
|
||
NdrpCreateDelegatedAsyncProxy(
|
||
IN IRpcProxyBuffer *This,
|
||
IN REFIID riid, // async IID
|
||
IN IUnknown * punkOuter, // controlling unknown
|
||
OUT CStdAsyncProxyBuffer ** ppAsyncProxy
|
||
)
|
||
/*
|
||
Creates a call object, i.e. an async proxy object.
|
||
|
||
Note, because the call comes via a CStdProxyBuffer2, not Buffer,
|
||
we know that we need to create only a delegated async proxy.
|
||
*/
|
||
{
|
||
HRESULT hr;
|
||
BOOL fFound;
|
||
long j; // if index
|
||
const ProxyFileInfo * pProxyFileInfo;
|
||
|
||
CStdProxyBuffer2 * pSyncPB = (CStdProxyBuffer2 *)This;
|
||
CStdAsyncProxyBuffer *pBaseAsyncPB;
|
||
|
||
ICallFactory * pCallFactory;
|
||
|
||
*ppAsyncProxy = 0;
|
||
|
||
if ( ! pSyncPB->pCallFactoryVtbl || !pSyncPB->pAsyncIID )
|
||
return E_NOINTERFACE;
|
||
|
||
if ( memcmp( &riid, pSyncPB->pAsyncIID, sizeof(IID)) != 0 )
|
||
return E_NOINTERFACE;
|
||
|
||
// same file, so we can use the sync pPSFactory.
|
||
|
||
fFound = NdrpFindInterface( ((CStdPSFactoryBuffer *)pSyncPB->pPSFactory)->pProxyFileList,
|
||
riid,
|
||
&pProxyFileInfo,
|
||
& j);
|
||
if ( !fFound )
|
||
return E_NOINTERFACE;
|
||
|
||
// Create async proxy.
|
||
|
||
CStdAsyncProxyBuffer *pAsyncPB =
|
||
(CStdAsyncProxyBuffer*)(*pfnCoTaskMemAlloc)(sizeof(CStdAsyncProxyBuffer));
|
||
|
||
if( ! pAsyncPB )
|
||
return E_OUTOFMEMORY;
|
||
|
||
memset( pAsyncPB, 0, sizeof(CStdAsyncProxyBuffer));
|
||
//
|
||
// Everything gets zeroed out regardless of their position
|
||
// when mapping CStdBuffer vs. CstdBuffer2 into CStdAsyncBuffer
|
||
|
||
// Fill in for a delegated case.
|
||
|
||
pAsyncPB->lpVtbl = & CStdAsyncProxyBuffer2Vtbl;
|
||
pAsyncPB->pProxyVtbl = & pProxyFileInfo->pProxyVtblList[j]->Vtbl;
|
||
pAsyncPB->RefCount = 1;
|
||
pAsyncPB->punkOuter = punkOuter ? punkOuter
|
||
: (IUnknown *) pAsyncPB;
|
||
pAsyncPB->iidBase = *pProxyFileInfo->pDelegatedIIDs[j];
|
||
pAsyncPB->pPSFactory = pSyncPB->pPSFactory;
|
||
pAsyncPB->pSyncIID = NdrGetProxyIID( &pSyncPB->pProxyVtbl );
|
||
|
||
// Note, no connection to channel yet.
|
||
// So we cannot call create call on the channel.
|
||
|
||
NdrpAsyncProxyMsgConstructor( pAsyncPB );
|
||
|
||
// Create an async proxy for the base interface.
|
||
// We don't know if the base is delegated, so we have to use base call factory.
|
||
// Get the call factory from the base proxy.
|
||
|
||
hr = pSyncPB->pBaseProxyBuffer->lpVtbl->QueryInterface(
|
||
pSyncPB->pBaseProxyBuffer,
|
||
IID_ICallFactory,
|
||
(void**)& pCallFactory );
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
const IID * pBaseAsyncIID;
|
||
|
||
pBaseAsyncIID = *(const IID **)( (uchar*)pSyncPB->pBaseProxyBuffer
|
||
+ offsetof(CStdProxyBuffer, pAsyncIID));
|
||
|
||
// Aggregate the base async proxy with the current async proxy,
|
||
// not with the channel's punkOuter.
|
||
|
||
hr = pCallFactory->lpVtbl->CreateCall( pCallFactory,
|
||
*pBaseAsyncIID,
|
||
(IUnknown*) pAsyncPB,
|
||
IID_IUnknown,
|
||
(IUnknown**)& pBaseAsyncPB );
|
||
pCallFactory->lpVtbl->Release( pCallFactory );
|
||
}
|
||
|
||
|
||
if ( SUCCEEDED(hr) )
|
||
{
|
||
// Increment the DLL reference count for DllCanUnloadNow.
|
||
// Same dll, so we can use the sync pPSFactory.
|
||
//
|
||
pSyncPB->pPSFactory->lpVtbl->AddRef( pSyncPB->pPSFactory );
|
||
|
||
// Hook up the base async proxy.
|
||
|
||
pAsyncPB->pBaseProxyBuffer = (IRpcProxyBuffer*) pBaseAsyncPB;
|
||
pAsyncPB->map.pBaseProxy = (IUnknown *) & pBaseAsyncPB->pProxyVtbl;
|
||
|
||
*ppAsyncProxy = pAsyncPB;
|
||
}
|
||
else
|
||
{
|
||
(*pfnCoTaskMemFree)( pAsyncPB );
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
//
|
||
// ICallFactory interface on the sync ProxyBuffer and ProxyBuffer2 objects.
|
||
//
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_CF_QueryInterface(
|
||
IN ICallFactory *This,
|
||
IN REFIID riid,
|
||
OUT void ** ppvObject)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Query for an interface on the interface stub CallFactory pointer.
|
||
|
||
Arguments:
|
||
riid - Supplies the IID of the interface being requested.
|
||
ppvObject - Returns a pointer to the requested interface.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
Note:
|
||
Works the same way for ProxyBuffer2 and AsyncProxyBuffer.
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pSyncPB = (CStdProxyBuffer *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer,pCallFactoryVtbl));
|
||
|
||
return pSyncPB->punkOuter->lpVtbl->QueryInterface( pSyncPB->punkOuter,
|
||
riid,
|
||
ppvObject );
|
||
}
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_CF_AddRef(
|
||
IN ICallFactory *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of AddRef for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
|
||
CStdProxyBuffer * pSyncPB = (CStdProxyBuffer *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer,pCallFactoryVtbl));
|
||
|
||
// It needs to go through punkOuter.
|
||
|
||
count = pSyncPB->punkOuter->lpVtbl->AddRef( pSyncPB->punkOuter );
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
CStdProxyBuffer_CF_Release(
|
||
IN ICallFactory *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of Release for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
ULONG count;
|
||
|
||
CStdProxyBuffer2 * pSyncPB = (CStdProxyBuffer2 *)
|
||
((uchar *)This - offsetof(CStdProxyBuffer2,pCallFactoryVtbl));
|
||
|
||
count = pSyncPB->punkOuter->lpVtbl->Release( pSyncPB->punkOuter );
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer_CF_CreateCall(
|
||
IN ICallFactory *This,
|
||
IN REFIID riid,
|
||
IN IUnknown * punkOuter, // controlling unknown
|
||
IN REFIID riid2,
|
||
OUT IUnknown ** ppv
|
||
)
|
||
/*
|
||
Creates a call object, i.e. an async proxy object.
|
||
|
||
Note, because the call comes via a CStdProxyBuffer, not Buffer2,
|
||
we know that we need to create only a non-delegated async proxy.
|
||
*/
|
||
{
|
||
CStdProxyBuffer * pSyncPB;
|
||
|
||
if ( memcmp( &riid2, &IID_IUnknown, sizeof(IID)) != 0 )
|
||
return E_INVALIDARG;
|
||
|
||
pSyncPB = (CStdProxyBuffer *)
|
||
(((uchar *)This) - offsetof( CStdProxyBuffer, pCallFactoryVtbl ));
|
||
|
||
return NdrpCreateNonDelegatedAsyncProxy( (IRpcProxyBuffer*) pSyncPB,
|
||
riid,
|
||
punkOuter,
|
||
(CStdAsyncProxyBuffer**) ppv );
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CStdProxyBuffer2_CF_CreateCall(
|
||
IN ICallFactory *This,
|
||
IN REFIID riid,
|
||
IN IUnknown * punkOuter, // controlling unknown
|
||
IN REFIID riid2,
|
||
OUT IUnknown ** ppv
|
||
)
|
||
/*
|
||
Creates a call object, i.e. an async proxy object.
|
||
|
||
Note, because the virtual call comes via a CStdProxyBuffer2,
|
||
we know that we need to create only a delegated async proxy.
|
||
*/
|
||
{
|
||
CStdProxyBuffer2 * pSyncPB;
|
||
|
||
if ( memcmp( &riid2, &IID_IUnknown, sizeof(IID)) != 0 )
|
||
return E_INVALIDARG;
|
||
|
||
pSyncPB = (CStdProxyBuffer2 *)
|
||
(((uchar *)This) - offsetof( CStdProxyBuffer2, pCallFactoryVtbl ));
|
||
|
||
return NdrpCreateDelegatedAsyncProxy( (IRpcProxyBuffer*) pSyncPB,
|
||
riid,
|
||
punkOuter,
|
||
(CStdAsyncProxyBuffer**) ppv );
|
||
}
|
||
/*
|
||
HRESULT STDAPICALLTYPE
|
||
NdrClientReleaseMarshalBuffer(
|
||
IN IRpcProxyBuffer *pProxy,
|
||
IN RPCOLEMESSAGE * pMsg,
|
||
IN DWORD dwFlags,
|
||
IN IUnknown *pChnl)
|
||
{
|
||
CStdProxyBuffer * pSyncPB;
|
||
void * This = NULL;
|
||
HRESULT hr;
|
||
|
||
if (NULL != pChnl)
|
||
return E_INVALIDARG;
|
||
|
||
if (dwFlags)
|
||
return E_INVALIDARG;
|
||
|
||
hr = pProxy->lpVtbl->QueryInterface(pProxy,&IID_IReleaseMarshalBuffers, &This);
|
||
if (FAILED(hr))
|
||
return E_NOTIMPL;
|
||
|
||
pSyncPB = (CStdProxyBuffer *)
|
||
(((uchar *)This) - offsetof( CStdProxyBuffer, lpVtbl ));
|
||
|
||
hr = NdrpClientReleaseMarshalBuffer(pSyncPB,(RPC_MESSAGE *)pMsg, dwFlags);
|
||
((IRpcProxyBuffer *)This)->lpVtbl->Release(This);
|
||
|
||
return hr;
|
||
}
|
||
|
||
*/
|
||
|
||
//
|
||
// IUknown Query, AddRef and Release.
|
||
//
|
||
HRESULT STDMETHODCALLTYPE
|
||
IUnknown_QueryInterface_Proxy(
|
||
IN IUnknown * This,
|
||
IN REFIID riid,
|
||
OUT void ** ppv)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of QueryInterface for interface proxy.
|
||
|
||
Arguments:
|
||
riid - Supplies the IID of the requested interface.
|
||
ppv - Returns a pointer to the requested interface.
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = E_NOINTERFACE;
|
||
CStdProxyBuffer * pProxyBuffer;
|
||
|
||
pProxyBuffer = NdrGetProxyBuffer(This);
|
||
|
||
hr = pProxyBuffer->punkOuter->lpVtbl->QueryInterface(
|
||
pProxyBuffer->punkOuter, riid, ppv);
|
||
|
||
return hr;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
IUnknown_AddRef_Proxy(
|
||
IN IUnknown *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of AddRef for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pProxyBuffer;
|
||
ULONG count;
|
||
|
||
pProxyBuffer = NdrGetProxyBuffer(This);
|
||
count = pProxyBuffer->punkOuter->lpVtbl->AddRef(pProxyBuffer->punkOuter);
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
IUnknown_Release_Proxy(
|
||
IN IUnknown *This)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Implementation of Release for interface proxy.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pProxyBuffer;
|
||
ULONG count;
|
||
|
||
pProxyBuffer = NdrGetProxyBuffer(This);
|
||
count = pProxyBuffer->punkOuter->lpVtbl->Release(pProxyBuffer->punkOuter);
|
||
|
||
return count;
|
||
};
|
||
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrProxyInitialize(
|
||
IN void * pThis,
|
||
IN PRPC_MESSAGE pRpcMsg,
|
||
IN PMIDL_STUB_MESSAGE pStubMsg,
|
||
IN PMIDL_STUB_DESC pStubDescriptor,
|
||
IN unsigned int ProcNum )
|
||
/*++
|
||
|
||
Routine Description:
|
||
Initialize the MIDL_STUB_MESSAGE.
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
pRpcMsg
|
||
pStubMsg
|
||
pStubDescriptor
|
||
ProcNum
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
CStdProxyBuffer * pProxyBuffer;
|
||
HRESULT hr;
|
||
|
||
pProxyBuffer = NdrGetProxyBuffer(pThis);
|
||
|
||
//
|
||
// Initialize the stub message fields.
|
||
//
|
||
NdrClientInitializeNew(
|
||
pRpcMsg,
|
||
pStubMsg,
|
||
pStubDescriptor,
|
||
ProcNum );
|
||
|
||
//Note that NdrClientInitializeNew sets RPC_FLAGS_VALID_BIT in the ProcNum.
|
||
//We don't want to do this for object interfaces, so we clear the flag here.
|
||
pRpcMsg->ProcNum &= ~RPC_FLAGS_VALID_BIT;
|
||
|
||
pStubMsg->pRpcChannelBuffer = pProxyBuffer->pChannel;
|
||
|
||
//Check if we are connected to a channel.
|
||
if(pStubMsg->pRpcChannelBuffer != 0)
|
||
{
|
||
//AddRef the channel.
|
||
//We will release it later in NdrProxyFreeBuffer.
|
||
pStubMsg->pRpcChannelBuffer->lpVtbl->AddRef(pStubMsg->pRpcChannelBuffer);
|
||
|
||
//Get the destination context from the channel
|
||
hr = pStubMsg->pRpcChannelBuffer->lpVtbl->GetDestCtx(
|
||
pStubMsg->pRpcChannelBuffer, &pStubMsg->dwDestContext, &pStubMsg->pvDestContext);
|
||
}
|
||
else
|
||
{
|
||
//We are not connected to a channel.
|
||
RpcRaiseException(CO_E_OBJNOTCONNECTED);
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrProxyGetBuffer(
|
||
IN void * pThis,
|
||
IN PMIDL_STUB_MESSAGE pStubMsg)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Get a message buffer from the channel
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
pStubMsg
|
||
|
||
Return Value:
|
||
None. If an error occurs, this function will raise an exception.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
|
||
const IID * pIID = NdrGetProxyIID(pThis);
|
||
pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;
|
||
pStubMsg->RpcMsg->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION;
|
||
pStubMsg->dwStubPhase = PROXY_GETBUFFER;
|
||
|
||
hr = pStubMsg->pRpcChannelBuffer->lpVtbl->GetBuffer(
|
||
pStubMsg->pRpcChannelBuffer,
|
||
(RPCOLEMESSAGE *) pStubMsg->RpcMsg,
|
||
*pIID);
|
||
|
||
pStubMsg->dwStubPhase = PROXY_MARSHAL;
|
||
|
||
if(FAILED(hr))
|
||
{
|
||
RpcRaiseException(hr);
|
||
}
|
||
else
|
||
{
|
||
NDR_ASSERT( ! ((ULONG_PTR)pStubMsg->RpcMsg->Buffer & 0x7),
|
||
"marshaling buffer misaligned" );
|
||
|
||
pStubMsg->Buffer = (unsigned char *) pStubMsg->RpcMsg->Buffer;
|
||
pStubMsg->fBufferValid = TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrProxySendReceive(
|
||
IN void * pThis,
|
||
IN MIDL_STUB_MESSAGE * pStubMsg)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Send a message to server, then wait for reply message.
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
pStubMsg
|
||
|
||
Return Value:
|
||
None. If an error occurs, this function will raise an exception.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
DWORD dwStatus;
|
||
|
||
//Calculate the number of bytes to send.
|
||
|
||
if ( pStubMsg->RpcMsg->BufferLength <
|
||
(uint)(pStubMsg->Buffer - (uchar *)pStubMsg->RpcMsg->Buffer))
|
||
{
|
||
NDR_ASSERT( 0, "NdrProxySendReceive : buffer overflow" );
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
}
|
||
|
||
pStubMsg->RpcMsg->BufferLength = (ulong)( pStubMsg->Buffer -
|
||
(unsigned char *) pStubMsg->RpcMsg->Buffer );
|
||
|
||
pStubMsg->fBufferValid = FALSE;
|
||
pStubMsg->dwStubPhase = PROXY_SENDRECEIVE;
|
||
|
||
hr = pStubMsg->pRpcChannelBuffer->lpVtbl->SendReceive(
|
||
pStubMsg->pRpcChannelBuffer,
|
||
(RPCOLEMESSAGE *) pStubMsg->RpcMsg, &dwStatus);
|
||
|
||
pStubMsg->dwStubPhase = PROXY_UNMARSHAL;
|
||
|
||
if(FAILED(hr))
|
||
{
|
||
switch(hr)
|
||
{
|
||
case RPC_E_FAULT:
|
||
RpcRaiseException(dwStatus);
|
||
break;
|
||
|
||
default:
|
||
RpcRaiseException(hr);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
NDR_ASSERT( ! ((ULONG_PTR)pStubMsg->RpcMsg->Buffer & 0x7),
|
||
"marshaling buffer misaligned" );
|
||
|
||
pStubMsg->Buffer = (uchar*)pStubMsg->RpcMsg->Buffer;
|
||
pStubMsg->BufferStart = pStubMsg->Buffer;
|
||
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->RpcMsg->BufferLength;
|
||
pStubMsg->fBufferValid = TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrProxyFreeBuffer(
|
||
IN void * pThis,
|
||
IN MIDL_STUB_MESSAGE * pStubMsg)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Free the message buffer.
|
||
|
||
Arguments:
|
||
pThis - Supplies a pointer to the interface proxy.
|
||
pStubMsg
|
||
|
||
Return Value:
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if(pStubMsg->pRpcChannelBuffer != 0)
|
||
{
|
||
//Free the message buffer.
|
||
if(pStubMsg->fBufferValid == TRUE)
|
||
{
|
||
// If pipes, we need to reset the partial bit for some reason.
|
||
|
||
pStubMsg->RpcMsg->RpcFlags &= ~RPC_BUFFER_PARTIAL;
|
||
|
||
pStubMsg->pRpcChannelBuffer->lpVtbl->FreeBuffer(
|
||
pStubMsg->pRpcChannelBuffer, (RPCOLEMESSAGE *) pStubMsg->RpcMsg);
|
||
}
|
||
|
||
//Release the channel.
|
||
pStubMsg->pRpcChannelBuffer->lpVtbl->Release(pStubMsg->pRpcChannelBuffer);
|
||
pStubMsg->pRpcChannelBuffer = 0;
|
||
}
|
||
}
|
||
|
||
HRESULT RPC_ENTRY
|
||
NdrProxyErrorHandler(
|
||
IN DWORD dwExceptionCode)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Maps an exception code into an HRESULT failure code.
|
||
|
||
Arguments:
|
||
dwExceptionCode
|
||
|
||
Return Value:
|
||
This function returns an HRESULT failure code.
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr = dwExceptionCode;
|
||
|
||
if(FAILED((HRESULT) dwExceptionCode))
|
||
hr = (HRESULT) dwExceptionCode;
|
||
else
|
||
hr = HRESULT_FROM_WIN32(dwExceptionCode);
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CreateChannelWrapper
|
||
/*++
|
||
|
||
Routine Description:
|
||
Creates a wrapper for the channel. The wrapper ensures
|
||
that we use the correct IID when the proxy for the base
|
||
interface calls GetBuffer.
|
||
|
||
Arguments:
|
||
pIID
|
||
pChannel
|
||
pChannelWrapper
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_OUTOFMEMORY
|
||
|
||
--*/
|
||
(
|
||
const IID * pIID,
|
||
IRpcChannelBuffer * pChannel,
|
||
IRpcChannelBuffer ** ppChannelWrapper
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
ChannelWrapper *pWrapper =
|
||
(ChannelWrapper*)(*pfnCoTaskMemAlloc)(sizeof(ChannelWrapper));
|
||
|
||
if(pWrapper != 0)
|
||
{
|
||
hr = S_OK;
|
||
pWrapper->lpVtbl = (IRpcChannelBufferVtbl*) &ChannelWrapperVtbl;
|
||
pWrapper->RefCount = 1;
|
||
pWrapper->pIID = pIID;
|
||
pChannel->lpVtbl->AddRef(pChannel);
|
||
pWrapper->pChannel = pChannel;
|
||
*ppChannelWrapper = (IRpcChannelBuffer *) pWrapper;
|
||
}
|
||
else
|
||
{
|
||
hr = E_OUTOFMEMORY;
|
||
*ppChannelWrapper = 0;
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
CreateAsyncChannelWrapper
|
||
/*++
|
||
|
||
Routine Description:
|
||
Creates a wrapper for the channel. The wrapper ensures
|
||
that we use the correct IID when the proxy for the base
|
||
interface calls GetBuffer.
|
||
|
||
Arguments:
|
||
pIID
|
||
pChannel
|
||
pChannelWrapper
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_OUTOFMEMORY
|
||
|
||
--*/
|
||
(
|
||
const IID * pIID,
|
||
IRpcChannelBuffer * pChannel,
|
||
IRpcChannelBuffer ** ppChannelWrapper
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
ChannelWrapper *pWrapper =
|
||
(ChannelWrapper*)(*pfnCoTaskMemAlloc)(sizeof(ChannelWrapper));
|
||
|
||
if(pWrapper != 0)
|
||
{
|
||
hr = S_OK;
|
||
pWrapper->lpVtbl = (IRpcChannelBufferVtbl*) &AsyncChannelWrapperVtbl;
|
||
pWrapper->RefCount = 1;
|
||
pWrapper->pIID = pIID;
|
||
pChannel->lpVtbl->AddRef(pChannel);
|
||
pWrapper->pChannel = pChannel;
|
||
*ppChannelWrapper = (IRpcChannelBuffer *) pWrapper;
|
||
}
|
||
else
|
||
{
|
||
hr = E_OUTOFMEMORY;
|
||
*ppChannelWrapper = 0;
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_QueryInterface
|
||
/*++
|
||
|
||
Routine Description:
|
||
The channel wrapper supports the IUnknown and IRpcChannelBuffer interfaces.
|
||
|
||
Arguments:
|
||
riid
|
||
ppvObject
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
REFIID riid,
|
||
void **ppvObject
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
|
||
if((memcmp(&riid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IRpcChannelBuffer, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IRpcChannelBuffer2, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IRpcChannelBuffer3, sizeof(IID)) == 0))
|
||
{
|
||
hr = S_OK;
|
||
This->lpVtbl->AddRef(This);
|
||
*ppvObject = This;
|
||
}
|
||
else
|
||
{
|
||
hr = E_NOINTERFACE;
|
||
*ppvObject = 0;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_QueryInterface
|
||
/*++
|
||
|
||
Routine Description:
|
||
The channel wrapper supports the IUnknown and IRpcChannelBuffer interfaces.
|
||
|
||
Arguments:
|
||
riid
|
||
ppvObject
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
|
||
--*/
|
||
(
|
||
IAsyncRpcChannelBuffer * This,
|
||
REFIID riid,
|
||
void ** ppvObject
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
|
||
if((memcmp(&riid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IRpcChannelBuffer, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IRpcChannelBuffer2, sizeof(IID)) == 0) ||
|
||
(memcmp(&riid, &IID_IAsyncRpcChannelBuffer, sizeof(IID)) == 0))
|
||
{
|
||
hr = S_OK;
|
||
This->lpVtbl->AddRef(This);
|
||
*ppvObject = This;
|
||
}
|
||
else
|
||
{
|
||
hr = E_NOINTERFACE;
|
||
*ppvObject = 0;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
ChannelWrapper_AddRef
|
||
/*++
|
||
|
||
Routine Description:
|
||
Increment reference count.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
)
|
||
{
|
||
ChannelWrapper *pWrapper = (ChannelWrapper *) This;
|
||
|
||
InterlockedIncrement(&pWrapper->RefCount);
|
||
|
||
return (ULONG) pWrapper->RefCount;
|
||
|
||
}
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_AddRef(
|
||
IAsyncRpcChannelBuffer * This
|
||
)
|
||
{
|
||
return ChannelWrapper_AddRef( (IRpcChannelBuffer3 *) This );
|
||
}
|
||
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
ChannelWrapper_Release
|
||
/*++
|
||
|
||
Routine Description:
|
||
Decrement reference count.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
Reference count.
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
)
|
||
{
|
||
unsigned long count;
|
||
IRpcChannelBuffer * pChannel;
|
||
|
||
NDR_ASSERT(((ChannelWrapper *)This)->RefCount > 0, "Invalid reference count");
|
||
|
||
count = (unsigned long) ((ChannelWrapper *)This)->RefCount - 1;
|
||
|
||
if(InterlockedDecrement(&((ChannelWrapper *)This)->RefCount) == 0)
|
||
{
|
||
count = 0;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
|
||
if(pChannel != 0)
|
||
pChannel->lpVtbl->Release(pChannel);
|
||
|
||
#if DBG == 1
|
||
//In debug builds, zero fill the memory.
|
||
memset(This, '\0', sizeof(ChannelWrapper));
|
||
#endif
|
||
|
||
//Free the memory
|
||
(*pfnCoTaskMemFree)(This);
|
||
}
|
||
|
||
return count;
|
||
}
|
||
|
||
ULONG STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Release(
|
||
IAsyncRpcChannelBuffer * This
|
||
)
|
||
{
|
||
return ChannelWrapper_Release( (IRpcChannelBuffer3 *) This );
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetBuffer
|
||
/*++
|
||
|
||
Routine Description:
|
||
Get a message buffer from the channel.
|
||
|
||
This is the reason we have the ChannelWrapper at all.
|
||
We replace the riid of the current proxy by the one from the Wrapper.
|
||
|
||
Arguments:
|
||
pMessage
|
||
riid
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
const IID * pIID;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
pIID = ((ChannelWrapper *)This)->pIID;
|
||
|
||
hr = pChannel->lpVtbl->GetBuffer(pChannel,
|
||
pMessage,
|
||
*pIID);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetBuffer(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid
|
||
)
|
||
{
|
||
return ChannelWrapper_GetBuffer( (IRpcChannelBuffer3 *) This,
|
||
pMessage,
|
||
riid );
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_SendReceive
|
||
/*++
|
||
|
||
Routine Description:
|
||
Get a message buffer from the channel
|
||
|
||
Arguments:
|
||
pMessage
|
||
pStatus
|
||
|
||
Return Value:
|
||
S_OK
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->SendReceive(pChannel,
|
||
pMessage,
|
||
pStatus);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_SendReceive(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
// This can never happen for an async call stub.
|
||
return E_NOTIMPL;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_FreeBuffer
|
||
/*++
|
||
|
||
Routine Description:
|
||
Free the message buffer.
|
||
|
||
Arguments:
|
||
pMessage
|
||
|
||
Return Value:
|
||
S_OK
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE *pMessage
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->FreeBuffer(pChannel,
|
||
pMessage);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_FreeBuffer(
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage
|
||
)
|
||
{
|
||
return ChannelWrapper_FreeBuffer( (IRpcChannelBuffer3 *) This,
|
||
pMessage );
|
||
}
|
||
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetDestCtx
|
||
/*++
|
||
|
||
Routine Description:
|
||
Get the destination context from the channel
|
||
|
||
Arguments:
|
||
pdwDestContext
|
||
ppvDestContext
|
||
|
||
Return Value:
|
||
S_OK
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->GetDestCtx(pChannel,
|
||
pdwDestContext,
|
||
ppvDestContext);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetDestCtx(
|
||
IAsyncRpcChannelBuffer * This,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
)
|
||
{
|
||
return ChannelWrapper_GetDestCtx( (IRpcChannelBuffer3 *) This,
|
||
pdwDestContext,
|
||
ppvDestContext );
|
||
}
|
||
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_IsConnected
|
||
/*++
|
||
|
||
Routine Description:
|
||
Determines if the channel is connected.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_TRUE
|
||
S_FALSE
|
||
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->IsConnected(pChannel);
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_IsConnected(
|
||
IAsyncRpcChannelBuffer * This
|
||
)
|
||
{
|
||
return ChannelWrapper_IsConnected( (IRpcChannelBuffer3 *) This );
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetProtocolVersion
|
||
/*++
|
||
|
||
Routine Description:
|
||
Returns the protocol version if available.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
DWORD * pdwVersion
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer2 * pChannel2;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer2, (void**)&pChannel2);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel2->lpVtbl->GetProtocolVersion(pChannel2, pdwVersion);
|
||
pChannel2->lpVtbl->Release(pChannel2);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetProtocolVersion(
|
||
IAsyncRpcChannelBuffer * This,
|
||
DWORD * pdwVersion
|
||
)
|
||
{
|
||
return ChannelWrapper_GetProtocolVersion( (IRpcChannelBuffer3 *) This,
|
||
pdwVersion );
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Send
|
||
/*++
|
||
|
||
Routine Description:
|
||
Executes an asynchronous or partial send.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface( pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3 );
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->Send(pChannel3, pMessage, pStatus);
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Send(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Executes an asynchronous or partial send.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ISynchronize * pSynchronize,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IAsyncRpcChannelBuffer * pAsChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface( pChannel,
|
||
IID_IAsyncRpcChannelBuffer,
|
||
(void**)&pAsChannel );
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pAsChannel->lpVtbl->Send( pAsChannel,
|
||
pMessage,
|
||
pSynchronize,
|
||
pStatus);
|
||
pAsChannel->lpVtbl->Release( pAsChannel);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Receive
|
||
/*++
|
||
|
||
Routine Description:
|
||
Executes an asynchronous or partial receive.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
(
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG ulSize,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->Receive( pChannel3, pMessage, ulSize, pStatus );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_Receive(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Executes an asynchronous or partial receive.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
ULONG * pStatus
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IAsyncRpcChannelBuffer *pAsChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface( pChannel,
|
||
IID_IAsyncRpcChannelBuffer,
|
||
(void**)&pAsChannel);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pAsChannel->lpVtbl->Receive( pAsChannel,
|
||
pMessage,
|
||
pStatus );
|
||
pAsChannel->lpVtbl->Release(pAsChannel);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_Cancel(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Executes an asynchronous Cancel.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->Cancel( pChannel3, pMessage );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetCallContext(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Gets an asynchronous call context.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
REFIID riid,
|
||
void ** ppInterface
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->GetCallContext( pChannel3, pMessage, riid, ppInterface );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
AsyncChannelWrapper_GetDestCtxEx(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Gets an asynchronous call context.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IAsyncRpcChannelBuffer * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pdw,
|
||
void ** ppv
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IAsyncRpcChannelBuffer * pAsChannel;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface( pChannel,
|
||
IID_IAsyncRpcChannelBuffer,
|
||
(void**)&pAsChannel);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pAsChannel->lpVtbl->GetDestCtxEx( pAsChannel,
|
||
pMessage,
|
||
pdw,
|
||
ppv );
|
||
pAsChannel->lpVtbl->Release(pAsChannel);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetDestCtxEx(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Gets the new destination context.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pdwDestContext,
|
||
void ** ppvDestContext
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->GetDestCtxEx( pChannel3, pMessage, pdwDestContext, ppvDestContext );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_GetState(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Gets the call state.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
DWORD * pState
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->GetState( pChannel3, pMessage, pState );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT STDMETHODCALLTYPE
|
||
ChannelWrapper_RegisterAsync(
|
||
/*++
|
||
|
||
Routine Description:
|
||
Registers the async manager object and call with the channel.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
S_OK
|
||
E_NOINTERFACE
|
||
--*/
|
||
IRpcChannelBuffer3 * This,
|
||
RPCOLEMESSAGE * pMessage,
|
||
IAsyncManager * pAsyncMgr
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
IRpcChannelBuffer * pChannel;
|
||
IRpcChannelBuffer3 * pChannel3;
|
||
|
||
pChannel = ((ChannelWrapper *)This)->pChannel;
|
||
hr = pChannel->lpVtbl->QueryInterface(pChannel, IID_IRpcChannelBuffer3, (void**)&pChannel3);
|
||
if (S_OK == hr)
|
||
{
|
||
hr = pChannel3->lpVtbl->RegisterAsync( pChannel3, pMessage, pAsyncMgr );
|
||
pChannel3->lpVtbl->Release(pChannel3);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|