Source code of Windows XP (NT5)
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

/*++
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;
}