mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2887 lines
67 KiB
2887 lines
67 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|