windows-nt/Source/XPSP1/NT/com/rpc/ndr20/relmrl.cxx
2020-09-26 16:20:57 +08:00

388 lines
11 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1998 - 1999 Microsoft Corporation
Module Name :
relmrl.c
Abstract :
This file contains release of Marshaled Data (called before unmarshal).
Author :
Yong Qu (yongqu@microsoft.com) Nov 1998
Revision History :
---------------------------------------------------------------------*/
#define USE_STUBLESS_PROXY
#define CINTERFACE
#include "ndrp.h"
#include "ndrole.h"
#include "rpcproxy.h"
#include "hndl.h"
#include "interp2.h"
#include "pipendr.h"
#include "attack.h"
#include "mulsyntx.h"
#include <stddef.h>
#include <stdarg.h>
/* client side: we only care about the [in] part.
it's basically like unmarshal on the server side, just that
we immediately free the buffer (virtual stack) after unmarshalling.
The call it not necessary always OLE call: one side raw RPC and
the other side OLE call is possible: do we support this?
mostly code from NdrStubCall2, remove irrelavant code.
*/
#define IN_BUFFER 0
#define OUT_BUFFER 1
#define IsSameDir(dwFlags,param) ((dwFlags == IN_BUFFER)? param.IsIn :param.IsOut)
HRESULT NdrpReleaseMarshalBuffer(
RPC_MESSAGE *pRpcMsg,
PFORMAT_STRING pFormat,
PMIDL_STUB_DESC pStubDesc,
DWORD dwFlags,
BOOLEAN fServer)
{
ushort StackSize;
MIDL_STUB_MESSAGE StubMsg;
PPARAM_DESCRIPTION Params;
INTERPRETER_FLAGS InterpreterFlags;
INTERPRETER_OPT_FLAGS OptFlags;
long NumberParams;
long n;
PNDR_PROC_HEADER_EXTS pHeaderExts = 0;
HRESULT hr = S_OK;
uchar * pBuffer;
PFORMAT_STRING pFormatComplex;
PFORMAT_STRING pFormatTypes;
NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
"marshaling buffer misaligned at server" );
// must be auto handle.
if (FC_AUTO_HANDLE != pFormat[0])
return E_NOTIMPL;
InterpreterFlags = *((PINTERPRETER_FLAGS)&pFormat[1]);
pFormat += InterpreterFlags.HasRpcFlags ? 8 : 4;
StackSize = *((ushort * &)pFormat)++;
memset(&StubMsg,0,sizeof(MIDL_STUB_MESSAGE));
StubMsg.FullPtrXlatTables = 0;
//
// Get new interpreter info.
//
NdrServerInitialize(pRpcMsg,&StubMsg,pStubDesc);
SET_WALKIP( StubMsg.uFlags );
OptFlags = *((PINTERPRETER_OPT_FLAGS)&pFormat[4]);
NumberParams = (long) pFormat[5];
Params = (PPARAM_DESCRIPTION) &pFormat[6];
// Proc header extentions, from NDR ver. 5.2.
// Params must be set correctly here because of exceptions.
// need to setup correlation information.
if ( OptFlags.HasExtensions )
{
pHeaderExts = (NDR_PROC_HEADER_EXTS *)Params;
Params = (PPARAM_DESCRIPTION)((uchar*)Params + pHeaderExts->Size);
StubMsg.fHasExtensions = 1;
StubMsg.fHasNewCorrDesc = pHeaderExts->Flags2.HasNewCorrDesc;
}
if ( InterpreterFlags.FullPtrUsed )
StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit( 0, XLAT_SERVER );
//
// context handle is not supported in object
//
pFormatTypes = pStubDesc->pFormatTypes;
// Save the original buffer pointer to restore later.
pBuffer = StubMsg.Buffer;
// Get the type format string.
RpcTryFinally
{
RpcTryExcept
{
//
// Check if we need to do any walking .
//
if ( (fServer && dwFlags == OUT_BUFFER)
&&
(pRpcMsg->DataRepresentation & 0X0000FFFFUL) !=
NDR_LOCAL_DATA_REPRESENTATION )
{
NdrConvert2( &StubMsg,
(PFORMAT_STRING) Params,
NumberParams );
}
for ( n = 0; n < NumberParams; n++ )
{
if ( (dwFlags == IN_BUFFER ) &&
Params[n].ParamAttr.IsPartialIgnore )
{
PMIDL_STUB_MESSAGE pStubMsg = &StubMsg;
ALIGN( StubMsg.Buffer, 0x3 );
StubMsg.Buffer += PTR_WIRE_SIZE;
CHECK_EOB_RAISE_BSD( StubMsg.Buffer );
continue;
}
if ( ! IsSameDir(dwFlags,Params[n].ParamAttr) ||
Params[n].ParamAttr.IsPipe)
continue;
if ( Params[n].ParamAttr.IsBasetype )
{
ALIGN(StubMsg.Buffer, SIMPLE_TYPE_ALIGNMENT( Params[n].SimpleType.Type ));
StubMsg.Buffer += SIMPLE_TYPE_BUFSIZE( Params[n].SimpleType.Type );
}
else
{
//
// Complex type or pointer to complex type.
//
pFormatComplex = pFormatTypes + Params[n].TypeOffset;
(*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
( &StubMsg,
pFormatComplex);
};
}
}
RpcExcept( EXCEPTION_EXECUTE_HANDLER )
{
hr = HRESULT_FROM_WIN32(RpcExceptionCode());
}
RpcEndExcept
}
RpcFinally
{
NdrFullPointerXlatFree( StubMsg.FullPtrXlatTables );
StubMsg.Buffer = pBuffer;
}
RpcEndFinally
return hr;
}
HRESULT NdrpClientReleaseMarshalBuffer(
IReleaseMarshalBuffers *pRMB,
RPC_MESSAGE *pRpcMsg,
DWORD dwIOFlags,
BOOLEAN fAsync )
{
CStdProxyBuffer * pProxyBuffer;
PMIDL_STUBLESS_PROXY_INFO pProxyInfo;
CInterfaceProxyHeader * ProxyHeader;
long ParamSize;
ushort ProcNum;
ushort FormatOffset;
PFORMAT_STRING pFormat;
PMIDL_STUB_DESC pStubDesc;
void * This;
HRESULT hr;
pProxyBuffer = (CStdProxyBuffer *)
(((uchar *)pRMB) - offsetof( CStdProxyBuffer, pRMBVtbl ));
// The channel queries for IReleaseMarshalBuffers interface and gets the interface pointer
// only when proxy is the new proxy with bigger header, with ProxyInfo.
// Just in case, check this condition again.
if ( pRMB == 0 )
return E_NOTIMPL;
// quite often OLE pass in NULL buffer. Do an additional check here.
if ( NULL == pRpcMsg->Buffer )
return E_INVALIDARG;
This = (void *)pProxyBuffer->pProxyVtbl;
ProxyHeader = (CInterfaceProxyHeader *)
( (char *)This - sizeof(CInterfaceProxyHeader));
pProxyInfo = (PMIDL_STUBLESS_PROXY_INFO) (ProxyHeader->pStublessProxyInfo);
// Hack just in case, the bit should not be set up, actually.
ProcNum = pRpcMsg->ProcNum & ~RPC_FLAGS_VALID_BIT;
// RPCMSG always has the synchronous proc number;
if ( fAsync )
ProcNum = 2 * ProcNum - 3; // Begin method #
if ( dwIOFlags != IN_BUFFER )
return E_NOTIMPL;
pStubDesc = pProxyInfo->pStubDesc;
#if defined(BUILD_NDR64)
// check out ndr64
if ( pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES )
{
SYNTAX_TYPE SyntaxType;
long i;
MIDL_SYNTAX_INFO * pSyntaxInfo;
SyntaxType = NdrpGetSyntaxType( pRpcMsg->TransferSyntax );
// branch into ndr64 if SyntaxType is NDR64. fall through otherwise
if ( XFER_SYNTAX_NDR64 == SyntaxType )
{
for ( i = 0; i < (long)pProxyInfo->nCount; i++ )
{
if ( SyntaxType == NdrpGetSyntaxType( &pProxyInfo->pSyntaxInfo[i].TransferSyntax ) )
{
pSyntaxInfo = &pProxyInfo->pSyntaxInfo[i];
break;
}
}
return Ndr64pReleaseMarshalBuffer( pRpcMsg, pSyntaxInfo, ProcNum, pStubDesc, dwIOFlags, FALSE );
}
}
#endif
FormatOffset = pProxyInfo->FormatStringOffset[ProcNum];
pFormat = &((pProxyInfo->ProcFormatString)[FormatOffset]);
// only support Oicf mode
if ( (MIDL_VERSION_3_0_39 > pStubDesc->MIDLVersion ) ||
!(pFormat[1] & Oi_OBJ_USE_V2_INTERPRETER ))
return E_NOTIMPL;
hr = NdrpReleaseMarshalBuffer( pRpcMsg,
pFormat,
pStubDesc,
dwIOFlags,
FALSE ); // client
return hr;
}
HRESULT NdrpServerReleaseMarshalBuffer(
IReleaseMarshalBuffers *pRMB,
RPC_MESSAGE *pRpcMsg,
DWORD dwIOFlags,
BOOLEAN fAsync)
{
CStdStubBuffer * pStubBuffer ;
PRPC_SERVER_INTERFACE pServerIfInfo;
PMIDL_SERVER_INFO pServerInfo;
ushort ProcNum;
IUnknown * pSrvObj;
CInterfaceStubVtbl * pStubVTable;
ushort FormatOffset;
PFORMAT_STRING pFormat;
PMIDL_STUB_DESC pStubDesc;
HRESULT hr;
pStubBuffer = (CStdStubBuffer *) (((uchar *)pRMB) -
offsetof(CStdStubBuffer, pRMBVtbl));
// The channel queries for IReleaseMarshalBuffers interface and gets the interface pointer
// only when proxy is the new proxy with bigger header, with ProxyInfo.
// Just in case, check this condition again.
if ( pRMB == 0 )
return E_NOTIMPL;
if ( NULL == pRpcMsg->Buffer )
return E_INVALIDARG;
pSrvObj = (IUnknown * )((CStdStubBuffer *)pStubBuffer)->pvServerObject;
pStubVTable = (CInterfaceStubVtbl *)
((uchar *)pStubBuffer->lpVtbl - sizeof(CInterfaceStubHeader));
pServerInfo = (PMIDL_SERVER_INFO) pStubVTable->header.pServerInfo;
// Hack just in case, this should not be set up, actually.
ProcNum = pRpcMsg->ProcNum & ~RPC_FLAGS_VALID_BIT;
// RPCMSG always has the synchronous proc number;
if ( fAsync )
{
ProcNum = 2 * ProcNum - 3; // Begin method #
if ( dwIOFlags != IN_BUFFER )
ProcNum++; // Finish method
}
pStubDesc = pServerInfo->pStubDesc;
#if defined(BUILD_NDR64)
if ( pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES )
{
SYNTAX_TYPE SyntaxType;
long i;
MIDL_SYNTAX_INFO * pSyntaxInfo;
SyntaxType = NdrpGetSyntaxType( pRpcMsg->TransferSyntax );
if ( XFER_SYNTAX_NDR64 == SyntaxType )
{
for ( i = 0; i < (long)pServerInfo->nCount; i++ )
{
if ( SyntaxType == NdrpGetSyntaxType( &pServerInfo->pSyntaxInfo[i].TransferSyntax ) )
{
pSyntaxInfo = &pServerInfo->pSyntaxInfo[i];
break;
}
}
return Ndr64pReleaseMarshalBuffer( pRpcMsg, pSyntaxInfo, ProcNum, pStubDesc, dwIOFlags, TRUE );
}
}
#endif
FormatOffset = pServerInfo->FmtStringOffset[ProcNum];
pFormat = &((pServerInfo->ProcString)[FormatOffset]);
// only support Oicf mode
if ( (MIDL_VERSION_3_0_39 > pStubDesc->MIDLVersion ) ||
!(pFormat[1] & Oi_OBJ_USE_V2_INTERPRETER ))
return E_NOTIMPL;
hr = NdrpReleaseMarshalBuffer(pRpcMsg,pFormat,pStubDesc,dwIOFlags,TRUE);
return hr;
}