mirror of https://github.com/lianthony/NT4.0
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.
1198 lines
25 KiB
1198 lines
25 KiB
/*++
|
|
|
|
Microsoft Windows
|
|
Copyright (c) 1994 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
|
|
|
|
#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);
|
|
|
|
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
|
|
ChannelWrapper_QueryInterface
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
REFIID riid,
|
|
void ** ppvObject
|
|
);
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
ChannelWrapper_AddRef
|
|
(
|
|
IRpcChannelBuffer * This
|
|
);
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
ChannelWrapper_Release
|
|
(
|
|
IRpcChannelBuffer * This
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_GetBuffer
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
RPCOLEMESSAGE * pMessage,
|
|
REFIID riid
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_SendReceive
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
RPCOLEMESSAGE * pMessage,
|
|
ULONG * pStatus
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_FreeBuffer
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
RPCOLEMESSAGE * pMessage
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_GetDestCtx
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
DWORD * pdwDestContext,
|
|
void ** ppvDestContext
|
|
);
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_IsConnected
|
|
(
|
|
IRpcChannelBuffer * This
|
|
);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Global data
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
const IRpcProxyBufferVtbl CStdProxyBufferVtbl = {
|
|
#if defined(_MPPC_)
|
|
0, // a dummy for PowerMac
|
|
#endif
|
|
CStdProxyBuffer_QueryInterface,
|
|
CStdProxyBuffer_AddRef,
|
|
CStdProxyBuffer_Release,
|
|
CStdProxyBuffer_Connect,
|
|
CStdProxyBuffer_Disconnect };
|
|
|
|
const IRpcProxyBufferVtbl CStdProxyBuffer2Vtbl = {
|
|
#if defined(_MPPC_)
|
|
0, // a dummy for PowerMac
|
|
#endif
|
|
CStdProxyBuffer_QueryInterface,
|
|
CStdProxyBuffer_AddRef,
|
|
CStdProxyBuffer2_Release,
|
|
CStdProxyBuffer2_Connect,
|
|
CStdProxyBuffer2_Disconnect };
|
|
|
|
const IRpcChannelBufferVtbl ChannelWrapperVtbl = {
|
|
#if defined(_MPPC_)
|
|
0, // a dummy for PowerMac
|
|
#endif
|
|
ChannelWrapper_QueryInterface,
|
|
ChannelWrapper_AddRef,
|
|
ChannelWrapper_Release,
|
|
ChannelWrapper_GetBuffer,
|
|
ChannelWrapper_SendReceive,
|
|
ChannelWrapper_FreeBuffer,
|
|
ChannelWrapper_GetDestCtx,
|
|
ChannelWrapper_IsConnected};
|
|
|
|
#pragma code_seg(".orpc")
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
Reference count.
|
|
|
|
--*/
|
|
{
|
|
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)
|
|
{
|
|
//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;
|
|
};
|
|
|
|
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 *) InterlockedExchange(
|
|
(long *) &pCThis->pChannel, (long) 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;
|
|
};
|
|
|
|
void STDMETHODCALLTYPE
|
|
CStdProxyBuffer_Disconnect(
|
|
IN IRpcProxyBuffer *This)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Disconnect the proxy from the channel.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CStdProxyBuffer * pCThis = (CStdProxyBuffer *) This;
|
|
IRpcChannelBuffer * pOldChannel;
|
|
|
|
pOldChannel = (IRpcChannelBuffer *) InterlockedExchange(
|
|
(long *) &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.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
IRpcProxyBuffer *pBaseProxyBuffer;
|
|
|
|
CStdProxyBuffer_Disconnect(This);
|
|
|
|
pBaseProxyBuffer = ((CStdProxyBuffer2 *)This)->pBaseProxyBuffer;
|
|
|
|
if(pBaseProxyBuffer != 0)
|
|
pBaseProxyBuffer->lpVtbl->Disconnect(pBaseProxyBuffer);
|
|
};
|
|
|
|
|
|
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;
|
|
};
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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.
|
|
//
|
|
pStubMsg->dwStubPhase = PROXY_CALCSIZE;
|
|
|
|
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;
|
|
|
|
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( ! ((unsigned long)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 = 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( ! ((unsigned long)pStubMsg->RpcMsg->Buffer & 0x7),
|
|
"marshaling buffer misaligned" );
|
|
|
|
pStubMsg->fBufferValid = TRUE;
|
|
pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
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;
|
|
|
|
pWrapper = (*pfnCoTaskMemAlloc)(sizeof(ChannelWrapper));
|
|
|
|
if(pWrapper != 0)
|
|
{
|
|
hr = S_OK;
|
|
pWrapper->lpVtbl = &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
|
|
ChannelWrapper_QueryInterface
|
|
/*++
|
|
|
|
Routine Description:
|
|
The channel wrapper supports the IUnknown and IRpcChannelBuffer interfaces.
|
|
|
|
Arguments:
|
|
riid
|
|
ppvObject
|
|
|
|
Return Value:
|
|
S_OK
|
|
E_NOINTERFACE
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
REFIID riid,
|
|
void *__RPC_FAR *ppvObject
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if((memcmp(riid, &IID_IUnknown, sizeof(IID)) == 0) ||
|
|
(memcmp(riid, &IID_IRpcChannelBuffer, 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.
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This
|
|
)
|
|
{
|
|
ChannelWrapper *pWrapper = (ChannelWrapper *) This;
|
|
|
|
InterlockedIncrement(&pWrapper->RefCount);
|
|
|
|
return (ULONG) pWrapper->RefCount;
|
|
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
ChannelWrapper_Release
|
|
/*++
|
|
|
|
Routine Description:
|
|
Decrement reference count.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
Reference count.
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * 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;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_GetBuffer
|
|
/*++
|
|
|
|
Routine Description:
|
|
Get a message buffer from the channel
|
|
|
|
Arguments:
|
|
pMessage
|
|
riid
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * 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
|
|
ChannelWrapper_SendReceive
|
|
/*++
|
|
|
|
Routine Description:
|
|
Get a message buffer from the channel
|
|
|
|
Arguments:
|
|
pMessage
|
|
pStatus
|
|
|
|
Return Value:
|
|
S_OK
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
RPCOLEMESSAGE * pMessage,
|
|
ULONG * pStatus
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRpcChannelBuffer * pChannel;
|
|
|
|
pChannel = ((ChannelWrapper *)This)->pChannel;
|
|
hr = pChannel->lpVtbl->SendReceive(pChannel,
|
|
pMessage,
|
|
pStatus);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_FreeBuffer
|
|
/*++
|
|
|
|
Routine Description:
|
|
Free the message buffer.
|
|
|
|
Arguments:
|
|
pMessage
|
|
|
|
Return Value:
|
|
S_OK
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
RPCOLEMESSAGE *pMessage
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRpcChannelBuffer * pChannel;
|
|
|
|
pChannel = ((ChannelWrapper *)This)->pChannel;
|
|
hr = pChannel->lpVtbl->FreeBuffer(pChannel,
|
|
pMessage);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_GetDestCtx
|
|
/*++
|
|
|
|
Routine Description:
|
|
Get the destination context from the channel
|
|
|
|
Arguments:
|
|
pdwDestContext
|
|
ppvDestContext
|
|
|
|
Return Value:
|
|
S_OK
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This,
|
|
DWORD *pdwDestContext,
|
|
void *__RPC_FAR *ppvDestContext
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRpcChannelBuffer * pChannel;
|
|
|
|
pChannel = ((ChannelWrapper *)This)->pChannel;
|
|
hr = pChannel->lpVtbl->GetDestCtx(pChannel,
|
|
pdwDestContext,
|
|
ppvDestContext);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
ChannelWrapper_IsConnected
|
|
/*++
|
|
|
|
Routine Description:
|
|
Determines if the channel is connected.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
S_TRUE
|
|
S_FALSE
|
|
|
|
--*/
|
|
(
|
|
IRpcChannelBuffer * This
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRpcChannelBuffer * pChannel;
|
|
|
|
pChannel = ((ChannelWrapper *)This)->pChannel;
|
|
hr = pChannel->lpVtbl->IsConnected(pChannel);
|
|
return hr;
|
|
}
|
|
|
|
|