388 lines
11 KiB
C++
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;
|
|
|
|
}
|
|
|