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