/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 2000 Microsoft Corporation Module Name: pickle64.cxx Abstract: This module contains ndr64 related pickling ndr library routines. Notes: Author: Yong Qu Nov, 1993 Revision History: ------------------------------------------------------------------------*/ #include "precomp.hxx" #include #include "endianp.h" #include "picklep.hxx" extern "C" { void RPC_ENTRY NdrpPicklingClientFinally( PMIDL_STUB_MESSAGE pStubMsg, void * pThis ); void RPC_ENTRY Ndr64pPicklingClientFinally( PMIDL_STUB_MESSAGE pStubMsg, void * pThis ); } const SYNTAX_DISPATCH_TABLE SyncDcePicklingClient = { NdrpClientInit, NdrpSizing, NdrpClientMarshal, NdrpClientUnMarshal, NdrpClientExceptionHandling, NdrpPicklingClientFinally }; const SYNTAX_DISPATCH_TABLE SyncNdr64PicklingClient = { Ndr64pClientInit, Ndr64pSizing, Ndr64pClientMarshal, Ndr64pClientUnMarshal, Ndr64pClientExceptionHandling, Ndr64pPicklingClientFinally }; extern const MIDL_FORMAT_STRING __MIDLFormatString; __inline void Ndr64pMesTypeInit( PMIDL_STUB_MESSAGE pStubMsg, NDR_PROC_CONTEXT * pContext, PMIDL_STUB_DESC pStubDesc ) { // we need this for correlation cache. NdrpInitializeProcContext( pContext ); pStubMsg->pContext = pContext; pStubMsg->fHasExtensions = 1; pStubMsg->StubDesc = pStubDesc; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; pStubMsg->pCorrInfo = NULL; } #define NdrpSetupMesTypeCommon( pfnName, pfnDCE, pfnNDR64 ) \ \ if ( pMesMsg->Operation == MES_ENCODE || pMesMsg->Operation == MES_DECODE ) \ { \ SyntaxType = XFER_SYNTAX_DCE; \ pfnName = &pfnDCE; \ } \ else \ { \ SyntaxType = XFER_SYNTAX_NDR64; \ pfnName = &pfnNDR64; \ } \ \ for ( long i = 0; i < (long) pProxyInfo->nCount; i ++ ) \ if ( NdrpGetSyntaxType( &pProxyInfo->pSyntaxInfo[i].TransferSyntax ) == SyntaxType ) \ { \ pSyntaxInfo = &pProxyInfo->pSyntaxInfo[i]; \ break; \ } \ \ if (NULL == pSyntaxInfo ) \ RpcRaiseException( RPC_S_UNSUPPORTED_TRANS_SYN ); \ \ if ( XFER_SYNTAX_DCE == SyntaxType ) \ { \ ulong nFormatOffset = ArrTypeOffset[i][nTypeIndex]; \ pTypeFormat = &pSyntaxInfo->TypeString[nFormatOffset]; \ } \ else \ { \ if ( SyntaxType == XFER_SYNTAX_NDR64 ) \ Ndr64pMesTypeInit( &pMesMsg->StubMsg, &ProcContext, pProxyInfo->pStubDesc ); \ \ pTypeFormat = (PFORMAT_STRING)(((const FormatInfoRef **) ArrTypeOffset)[i][nTypeIndex]); \ } \ \ ProcContext.pSyntaxInfo = pSyntaxInfo; void Ndr64pValidateMesHandle( PMIDL_ES_MESSAGE_EX pMesMsgEx ) { RpcTryExcept { if ( pMesMsgEx == 0 || pMesMsgEx->Signature != MIDL_ES_SIGNATURE || ( pMesMsgEx->MesMsg.MesVersion != MIDL_NDR64_ES_VERSION && pMesMsgEx->MesMsg.MesVersion != MIDL_ES_VERSION ) ) RpcRaiseException( RPC_S_INVALID_ARG ); } RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) ) { RpcRaiseException( RPC_S_INVALID_ARG ); } RpcEndExcept } RPC_STATUS Ndr64pValidateMesHandleReturnStatus( PMIDL_ES_MESSAGE_EX pMesMsgEx ) { RPC_STATUS Status = RPC_S_OK; RpcTryExcept { if ( pMesMsgEx == 0 || pMesMsgEx->Signature != MIDL_NDR64_ES_SIGNATURE || pMesMsgEx->MesMsg.MesVersion != MIDL_NDR64_ES_VERSION ) Status = RPC_S_INVALID_ARG; } RpcExcept( NdrServerUnmarshallExceptionFlag(GetExceptionInformation()) ) { Status = RPC_S_INVALID_ARG; } RpcEndExcept return Status; } void Ndr64pCommonTypeHeaderSize( PMIDL_ES_MESSAGE pMesMsg ) { // This check is to prevent a decoding handle from being used // for both encoding and sizing of types. if ( pMesMsg->Operation != MES_ENCODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); if ( ! GET_COMMON_TYPE_HEADER_SIZED( pMesMsg ) ) { pMesMsg->StubMsg.BufferLength += MES_NDR64_CTYPE_HEADER_SIZE; SET_COMMON_TYPE_HEADER_SIZED( pMesMsg ); } } size_t RPC_ENTRY Ndr64MesTypeAlignSize( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, const void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = ( PMIDL_ES_MESSAGE )Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; size_t OldLength = pStubMsg->BufferLength; PMIDL_TYPE_PICKLING_INFOp pPicklingInfo; Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); if ( ! pObject ) RpcRaiseException( RPC_X_NULL_REF_POINTER ); if( (long)pStubMsg->BufferLength & 0xf ) RpcRaiseException( RPC_X_INVALID_BUFFER ); pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo; NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" ); // See if we need to size the common type header. Ndr64pCommonTypeHeaderSize( (PMIDL_ES_MESSAGE)Handle ); // Now the individual type object. pStubMsg->BufferLength += MES_NDR64_HEADER_SIZE; if ( NDR64_IS_POINTER_TYPE(*pFormat) ) { // We have to dereference the pointer once. pObject = *(void __RPC_FAR * __RPC_FAR *)pObject; } (Ndr64SizeRoutinesTable[ NDR64_ROUTINE_INDEX(*pFormat) ]) ( pStubMsg, (uchar __RPC_FAR *)pObject, pFormat ); LENGTH_ALIGN( pStubMsg->BufferLength, 0xf ); Ndr64pPicklingClientFinally( pStubMsg, NULL ); // object return( pStubMsg->BufferLength - OldLength ); } // ndr64 entries. size_t RPC_ENTRY NdrMesTypeAlignSize3( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pPicklingInfo, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, const unsigned long ** ArrTypeOffset, unsigned long nTypeIndex, const void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PFORMAT_STRING pTypeFormat; MIDL_SYNTAX_INFO * pSyntaxInfo = NULL; PFNMESTYPEALIGNSIZE pfnSize; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; SYNTAX_TYPE SyntaxType; NDR_PROC_CONTEXT ProcContext; if ( (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE && (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); NdrpSetupMesTypeCommon( pfnSize, NdrMesTypeAlignSize2, Ndr64MesTypeAlignSize ); return ( *pfnSize )( Handle, pPicklingInfo, pProxyInfo->pStubDesc, pTypeFormat, pObject ); } // common type header for type pickling is longer than before: // if version is 1, the header size is 8, // if version is higher than 1, the header size is 24+2*sizeof(RPC_SYNTAX_IDENTIFIER) // starting 8 bytes is still the same as old one: // // addtional header: // // size_t Ndr64pCommonTypeHeaderMarshall( PMIDL_ES_MESSAGE pMesMsg ) /*++ Returns the space used by the common header. --*/ { if ( ! GET_COMMON_TYPE_HEADER_IN( pMesMsg ) ) { PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; if ( (ULONG_PTR)pStubMsg->Buffer & 15 ) RpcRaiseException( RPC_X_INVALID_BUFFER ); MIDL_memset( pStubMsg->Buffer, 0xcc, MES_NDR64_CTYPE_HEADER_SIZE ); *pStubMsg->Buffer++ = MIDL_NDR64_ES_VERSION; *pStubMsg->Buffer++ = NDR_LOCAL_ENDIAN; * PSHORT_CAST pStubMsg->Buffer = MES_NDR64_CTYPE_HEADER_SIZE; pStubMsg->Buffer += MES_CTYPE_HEADER_SIZE + 16 -2 ; // skip over reserved, make header size 64bytes RpcpMemoryCopy( pStubMsg->Buffer, & NDR64_TRANSFER_SYNTAX, sizeof(RPC_SYNTAX_IDENTIFIER) ); pStubMsg->Buffer += sizeof( RPC_SYNTAX_IDENTIFIER ); RpcpMemoryCopy( pStubMsg->Buffer , & pMesMsg->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER) + sizeof(long) ); pStubMsg->Buffer += sizeof( RPC_SYNTAX_IDENTIFIER ); SET_COMMON_TYPE_HEADER_IN( pMesMsg ); return( MES_NDR64_CTYPE_HEADER_SIZE ); } return( 0 ); } void RPC_ENTRY Ndr64MesTypeEncode( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, const void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; PMIDL_TYPE_PICKLING_INFOp pPicklingInfo; uchar __RPC_FAR * pBufferSaved, *pTypeHeader; size_t RequiredLen, CommonHeaderSize, LengthSaved; pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo; NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" ) Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); if ( ! pObject ) RpcRaiseException( RPC_X_NULL_REF_POINTER ); if( (LONG_PTR)pStubMsg->Buffer & 0xf ) RpcRaiseException( RPC_X_INVALID_BUFFER ); pStubMsg->BufferLength = 0xf & PtrToUlong( pStubMsg->Buffer ); RequiredLen = Ndr64MesTypeAlignSize( Handle, pxPicklingInfo, pStubDesc, pFormat, pObject ); NdrpAllocPicklingBuffer( pMesMsg, RequiredLen ); pBufferSaved = pStubMsg->Buffer; LengthSaved = RequiredLen; // See if we need to marshall the common type header CommonHeaderSize = Ndr64pCommonTypeHeaderMarshall( pMesMsg ); // Marshall the header and the object. memset( pStubMsg->Buffer, 0, MES_NDR64_HEADER_SIZE ); pStubMsg->Buffer += MES_NDR64_HEADER_SIZE; if ( NDR64_IS_POINTER_TYPE(*pFormat) ) { // We have to dereference the pointer once. pObject = *(void __RPC_FAR * __RPC_FAR *)pObject; } RpcTryFinally { ALIGN( pStubMsg->Buffer, 0xf ); (Ndr64MarshallRoutinesTable[ NDR64_ROUTINE_INDEX(*pFormat) ]) ( pStubMsg, (uchar __RPC_FAR *)pObject, pFormat ); // We adjust the buffer to the next align by 16 and // so, we tell the user that we've written out till next mod 16. // cleanup possible leaks before raising exception. } RpcFinally { Ndr64pPicklingClientFinally( pStubMsg, NULL ); // object } RpcEndFinally ALIGN( pStubMsg->Buffer, 0xf ); size_t WriteLength = (size_t)(pStubMsg->Buffer - pBufferSaved); // We always save the rounded up object length in the type header. *(unsigned long __RPC_FAR *)(pBufferSaved + CommonHeaderSize) = WriteLength - CommonHeaderSize - MES_NDR64_HEADER_SIZE; if ( LengthSaved < WriteLength ) { NDR_ASSERT( 0, "NdrMesTypeEncode: encode buffer overflow" ); RpcRaiseException( RPC_S_INTERNAL_ERROR ); } NdrpWritePicklingBuffer( pMesMsg, pBufferSaved, WriteLength ); } void RPC_ENTRY NdrMesTypeEncode3( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pPicklingInfo, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, const unsigned long ** ArrTypeOffset, unsigned long nTypeIndex, const void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PFORMAT_STRING pTypeFormat; MIDL_SYNTAX_INFO * pSyntaxInfo = NULL; PFNMESTYPEENCODE pfnEncode; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; SYNTAX_TYPE SyntaxType; NDR_PROC_CONTEXT ProcContext; if ( (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE && (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); NdrpSetupMesTypeCommon( pfnEncode, NdrMesTypeEncode2, Ndr64MesTypeEncode ); ( *pfnEncode )( Handle, pPicklingInfo, pProxyInfo->pStubDesc, pTypeFormat, pObject ); } // read the type header, and determine if the buffer is marshalled // using ndr or ndr64 // for future extension, we can allow other transfer syntaxes. void RPC_ENTRY Ndr64pCommonTypeHeaderUnmarshall( PMIDL_ES_MESSAGE pMesMsg ) { BOOL IsNewPickling = FALSE; if ( pMesMsg->Operation != MES_DECODE && pMesMsg->Operation != MES_DECODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); if ( ! GET_COMMON_TYPE_HEADER_IN( pMesMsg ) ) { PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; // read the common header first. NdrpReadPicklingBuffer( pMesMsg, MES_CTYPE_HEADER_SIZE ); // Check the version number, endianness. if ( *pStubMsg->Buffer == MIDL_ES_VERSION ) { IsNewPickling = FALSE; pMesMsg->Operation = MES_DECODE; } else { IsNewPickling = TRUE; } if ( pStubMsg->Buffer[1] == NDR_LOCAL_ENDIAN ) { // Read the note about endianess at NdrMesTypeDecode. // pMesMsg->AlienDataRep = NDR_LOCAL_DATA_REPRESENTATION; } else { NDR_ASSERT( pMesMsg->Operation != MES_DECODE_NDR64, "endian convertion is not supported in ndr64" ); unsigned char temp = pStubMsg->Buffer[2]; pStubMsg->Buffer[2] = pStubMsg->Buffer[3]; pStubMsg->Buffer[3] = temp; pMesMsg->AlienDataRep = ( NDR_ASCII_CHAR | // chars pStubMsg->Buffer[1] | // endianness NDR_IEEE_FLOAT ); // float } pStubMsg->Buffer += MES_CTYPE_HEADER_SIZE; if ( IsNewPickling ) { SYNTAX_TYPE SyntaxType; // read the remaining header. NdrpReadPicklingBuffer( pMesMsg, MES_NDR64_CTYPE_HEADER_SIZE - MES_CTYPE_HEADER_SIZE ); pStubMsg->Buffer += 16; // skip over Reserved; SyntaxType = NdrpGetSyntaxType( (RPC_SYNTAX_IDENTIFIER *)pStubMsg->Buffer ); if ( SyntaxType == XFER_SYNTAX_DCE ) { pMesMsg->Operation = MES_DECODE; } else if ( SyntaxType == XFER_SYNTAX_NDR64 ) { pMesMsg->Operation = ( MIDL_ES_CODE )MES_DECODE_NDR64; } else { RpcRaiseException( RPC_S_UNSUPPORTED_TRANS_SYN ); } // skip over iid: we don't need it for now. might be used for verification. pStubMsg->Buffer += 2*sizeof( RPC_SYNTAX_IDENTIFIER ); } SET_COMMON_TYPE_HEADER_IN( pMesMsg ); } } void RPC_ENTRY Ndr64MesTypeDecode( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; PMIDL_TYPE_PICKLING_INFOp pPicklingInfo; uchar __RPC_FAR * pBufferSaved, pTypeHeader; size_t RequiredLen, CommonHeaderSize, LengthSaved; pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo; NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" ) Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); if( (LONG_PTR)pStubMsg->Buffer & 0xf ) RpcRaiseException( RPC_X_INVALID_BUFFER ); pStubMsg->BufferLength = 0xf & PtrToUlong( pStubMsg->Buffer ); NdrpReadPicklingBuffer( pMesMsg, MES_NDR64_HEADER_SIZE ); RequiredLen = (size_t) *(unsigned long __RPC_FAR *)pStubMsg->Buffer; pStubMsg->Buffer += MES_NDR64_HEADER_SIZE; NdrpReadPicklingBuffer( pMesMsg, RequiredLen ); void * pArg = pObject; if ( NDR64_IS_POINTER_TYPE(*pFormat) ) { // We have to dereference the pointer once. // pArg = *(void **)pArg; } RpcTryFinally { (Ndr64UnmarshallRoutinesTable[ NDR64_ROUTINE_INDEX( *pFormat )]) ( pStubMsg, (uchar __RPC_FAR * __RPC_FAR *)&pArg, pFormat, FALSE ); if ( NDR64_IS_POINTER_TYPE(*pFormat) ) { // Don't drop the pointee, if it was allocated. *(void **)pObject = pArg; } if ( pStubMsg->pCorrInfo ) Ndr64CorrelationPass( pStubMsg ); // Next decoding needs to start at aligned to 16. ALIGN( pStubMsg->Buffer, 15 ); } RpcFinally { Ndr64pPicklingClientFinally( pStubMsg, NULL ); // object } RpcEndFinally } void RPC_ENTRY NdrMesTypeDecode3( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pPicklingInfo, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, const unsigned long ** ArrTypeOffset, unsigned long nTypeIndex, void __RPC_FAR * pObject ) { size_t RequiredLen; PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; uchar * BufferSaved; PFNMESDECODE pfnDecode; MIDL_SYNTAX_INFO * pSyntaxInfo; PFORMAT_STRING pTypeFormat; SYNTAX_TYPE SyntaxType; NDR_PROC_CONTEXT ProcContext; if ( ! pObject ) RpcRaiseException( RPC_X_NULL_REF_POINTER ); Ndr64pCommonTypeHeaderUnmarshall( pMesMsg ); NdrpSetupMesTypeCommon( pfnDecode, NdrMesTypeDecode2, Ndr64MesTypeDecode ); (* pfnDecode )( Handle, pPicklingInfo, pProxyInfo->pStubDesc, pTypeFormat, pObject ); } void RPC_ENTRY Ndr64MesTypeFree( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, const MIDL_STUB_DESC * pStubDesc, PFORMAT_STRING pFormat, void __RPC_FAR * pObject ) /*++ Routine description: Free the object. Arguments: Handle - a pickling handle, pStubDesc - a pointer to the stub descriptor, pFormat - a pointer to the format code describing the object type pObject - a pointer to the object being freed. Returns: Note: The pickling header is included in the sizing. --*/ { NDR_PROC_CONTEXT ProcContext; PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; PMIDL_TYPE_PICKLING_INFOp pPicklingInfo; Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo; NDR_ASSERT( pPicklingInfo->Flags.Oicf, "Oicf should always be on" ) if ( ! pObject ) RpcRaiseException( RPC_X_NULL_REF_POINTER ); if( (LONG_PTR)pStubMsg->Buffer & 0xf ) RpcRaiseException( RPC_X_INVALID_BUFFER ); // Now the individual type object. if ( NDR64_IS_POINTER_TYPE(*pFormat) ) { // We have to dereference the pointer once. pObject = *(void __RPC_FAR * __RPC_FAR *)pObject; } (Ndr64FreeRoutinesTable[ NDR64_ROUTINE_INDEX(*pFormat) ]) ( pStubMsg, (uchar __RPC_FAR *)pObject, pFormat ); Ndr64pPicklingClientFinally( pStubMsg, NULL ); // object } void RPC_ENTRY NdrMesTypeFree3( handle_t Handle, const MIDL_TYPE_PICKLING_INFO * pxPicklingInfo, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, const unsigned long ** ArrTypeOffset, unsigned long nTypeIndex, void __RPC_FAR * pObject ) { PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; PMIDL_TYPE_PICKLING_INFOp pPicklingInfo; PFNMESFREE pfnFree; MIDL_SYNTAX_INFO * pSyntaxInfo; PFORMAT_STRING pTypeFormat; SYNTAX_TYPE SyntaxType; NDR_PROC_CONTEXT ProcContext; pPicklingInfo = (PMIDL_TYPE_PICKLING_INFOp) pxPicklingInfo; NdrpSetupMesTypeCommon( pfnFree, NdrMesTypeFree2, Ndr64MesTypeFree ); (*pfnFree)(Handle, pxPicklingInfo, pProxyInfo->pStubDesc, pTypeFormat, pObject ); } void Ndr64pMesProcEncodeInit( PMIDL_ES_MESSAGE pMesMsg, const MIDL_STUBLESS_PROXY_INFO * pProxyInfo, unsigned long nProcNum, MIDL_ES_CODE Operation, NDR_PROC_CONTEXT * pContext, uchar * StartofStack) { PMIDL_STUB_DESC pStubDesc = pProxyInfo->pStubDesc; SYNTAX_TYPE syntaxType; BOOL fUseEncode, fIsSupported = FALSE; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; RPC_STATUS res; // TODO: verify stub version. if ( Operation == MES_ENCODE ) { syntaxType = XFER_SYNTAX_DCE; memcpy( &( (PMIDL_ES_MESSAGE_EX)pMesMsg )->TransferSyntax, &NDR_TRANSFER_SYNTAX , sizeof( RPC_SYNTAX_IDENTIFIER ) ); } else { syntaxType = XFER_SYNTAX_NDR64; memcpy( &( (PMIDL_ES_MESSAGE_EX)pMesMsg )->TransferSyntax, &NDR64_TRANSFER_SYNTAX , sizeof( RPC_SYNTAX_IDENTIFIER ) ); } Ndr64ClientInitializeContext( syntaxType, pProxyInfo, nProcNum, pContext, StartofStack ); pStubMsg->pContext = pContext; pStubMsg->StubDesc = pStubDesc; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; // varify proc header if ( syntaxType == XFER_SYNTAX_DCE ) { uchar InterpreterFlag = * ((uchar *)&pContext->NdrInfo.InterpreterFlags ); fUseEncode = InterpreterFlag & ENCODE_IS_USED; memcpy( & (pContext->pfnInit), &SyncDcePicklingClient, sizeof( SYNTAX_DISPATCH_TABLE ) ); } else { fUseEncode = ( ( (NDR64_PROC_FLAGS *) & pContext->Ndr64Header->Flags)->IsEncode ); memcpy( & (pContext->pfnInit), &SyncNdr64PicklingClient, sizeof( SYNTAX_DISPATCH_TABLE ) ); } if (!fUseEncode ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); } CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrMesProcEncode3( PMIDL_ES_MESSAGE pMesMsg, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, unsigned long nProcNum, uchar * StartofStack ) { PMIDL_STUB_MESSAGE pStubMsg = & pMesMsg->StubMsg; NDR_PROC_CONTEXT ProcContext; unsigned long ulAlignment; unsigned char * BufferSaved; size_t WriteLength; CLIENT_CALL_RETURN Ret; Ret.Simple = NULL; pMesMsg->ProcNumber = nProcNum; Ndr64pMesProcEncodeInit( pMesMsg, pProxyInfo, nProcNum, pMesMsg->Operation, &ProcContext, StartofStack ); RpcTryFinally { ProcContext.pfnInit( pStubMsg, NULL ); // return value ProcContext.pfnSizing( pStubMsg, TRUE ); if ( pMesMsg->Operation == MES_ENCODE ) ulAlignment = 0x7; else ulAlignment = 0xf; // we are not changing the proc header, but we need to overestimate because // proc header is marshalled first. LENGTH_ALIGN( pStubMsg->BufferLength, ulAlignment ); pStubMsg->BufferLength += MES_PROC_HEADER_SIZE ; LENGTH_ALIGN( pStubMsg->BufferLength, ulAlignment ); size_t LengthSaved; NdrpAllocPicklingBuffer( pMesMsg, pStubMsg->BufferLength ); BufferSaved = pStubMsg->Buffer; LengthSaved = pStubMsg->BufferLength; NDR_ASSERT( ( (ULONG_PTR)pStubMsg->Buffer & ulAlignment ) == 0, "pickling buffer is not aligned" ); NdrpProcHeaderMarshallAll( pMesMsg ); ALIGN( pStubMsg->Buffer, ulAlignment ); ProcContext.pfnMarshal( pStubMsg, FALSE ); ALIGN( pStubMsg->Buffer, ulAlignment ); WriteLength = (size_t)(pStubMsg->Buffer - BufferSaved); * (unsigned long __RPC_FAR *) ( BufferSaved + MES_PROC_HEADER_SIZE - 4) = WriteLength - MES_PROC_HEADER_SIZE; if ( LengthSaved < WriteLength ) { NDR_ASSERT( 0, "NdrMesProcEncodeDecode: encode buffer overflow" ); RpcRaiseException( RPC_S_INTERNAL_ERROR ); } NdrpWritePicklingBuffer( pMesMsg, BufferSaved, WriteLength ); } RpcFinally { ( *ProcContext.pfnClientFinally)( pStubMsg, NULL ); // not object } RpcEndFinally return Ret; } // both encode and decode acts like the client side. void Ndr64pMesProcDecodeInit( PMIDL_ES_MESSAGE pMesMsg, const MIDL_STUBLESS_PROXY_INFO * pProxyInfo, SYNTAX_TYPE SyntaxType, unsigned long nProcNum, NDR_PROC_CONTEXT * pContext, uchar * StartofStack ) { RPC_STATUS res; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; unsigned long nFormatOffset; PMIDL_STUB_DESC pStubDesc = pProxyInfo->pStubDesc; BOOL fUseDecode; // REVIEW: Calling the "Client" init for decode seems weird but it does // the right thing and NdrServerSetupMultipleTransferSyntax assumes // ndr64. Ndr64ClientInitializeContext( SyntaxType, pProxyInfo, nProcNum, pContext, StartofStack ); pStubMsg->pContext = pContext; pStubMsg->StubDesc = pStubDesc; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; NdrpDataBufferInit( pMesMsg, pContext->pProcFormat ); if ( SyntaxType == XFER_SYNTAX_DCE ) { uchar InterpreterFlag = * ((uchar *)&pContext->NdrInfo.InterpreterFlags ); fUseDecode = InterpreterFlag & DECODE_IS_USED; memcpy( & (pContext->pfnInit), &SyncDcePicklingClient, sizeof( SYNTAX_DISPATCH_TABLE ) ); } else { fUseDecode = ( ( (NDR64_PROC_FLAGS *) & pContext->Ndr64Header->Flags)->IsDecode ); memcpy( & (pContext->pfnInit), &SyncNdr64PicklingClient, sizeof( SYNTAX_DISPATCH_TABLE ) ); } if (!fUseDecode ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); } CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrMesProcDecode3( PMIDL_ES_MESSAGE pMesMsg, const MIDL_STUBLESS_PROXY_INFO *pProxyInfo, unsigned long nProcNum, uchar * StartofStack, void * pReturnValue ) { CLIENT_CALL_RETURN RetVal; NDR_PROC_CONTEXT ProcContext; SYNTAX_TYPE SyntaxType; PMIDL_STUB_MESSAGE pStubMsg = & pMesMsg->StubMsg; NDR64_PROC_FLAGS *ProcFlags; unsigned long ulAlign; long HasComplexReturn; RetVal.Simple = NULL; if (NULL == pReturnValue ) pReturnValue = &RetVal; if ( GET_MES_HEADER_PEEKED( pMesMsg ) ) { // This makes it possible to encode/decode several procs one after // another with the same pickling handle (using the same buffer). CLEAR_MES_HEADER_PEEKED( pMesMsg ); } else NdrpProcHeaderUnmarshallAll( pMesMsg ); SyntaxType = NdrpGetSyntaxType( &((PMIDL_ES_MESSAGE_EX)pMesMsg)->TransferSyntax ); if ( SyntaxType == XFER_SYNTAX_DCE ) { pMesMsg->Operation = MES_DECODE; ulAlign = 0x7; } else if ( SyntaxType == XFER_SYNTAX_NDR64 ) { pMesMsg->Operation = ( MIDL_ES_CODE )MES_DECODE_NDR64; ulAlign = 0xf; } else RpcRaiseException( RPC_S_UNSUPPORTED_TRANS_SYN ); if ( (LONG_PTR)pStubMsg->BufferStart & ulAlign ) RpcRaiseException( RPC_X_INVALID_BUFFER ); Ndr64pMesProcDecodeInit( pMesMsg, pProxyInfo, SyntaxType, nProcNum, &ProcContext, StartofStack ); RpcTryFinally { ProcContext.pfnInit( pStubMsg, NULL ); // return value ALIGN( pStubMsg->Buffer, ulAlign ); ProcContext.pfnUnMarshal( pStubMsg, ProcContext.HasComplexReturn ? &pReturnValue : pReturnValue ); // prepare for new decoding. ALIGN( pStubMsg->Buffer, ulAlign ); } RpcFinally { ( *ProcContext.pfnClientFinally)( pStubMsg, NULL ); // object } RpcEndFinally return *(CLIENT_CALL_RETURN *)pReturnValue; } CLIENT_CALL_RETURN RPC_VAR_ENTRY NdrMesProcEncodeDecode3( handle_t Handle, const MIDL_STUBLESS_PROXY_INFO* pProxyInfo, unsigned long nProcNum, void *pReturnValue, ... ) { BOOL fMoreParams; PFORMAT_STRING pProcFormat; void __RPC_FAR * pArg; va_list ArgList; unsigned char * BufferSaved; size_t WriteLength; uchar * StartofStack; Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; INIT_ARG( ArgList, pReturnValue ); GET_FIRST_IN_ARG(ArgList); StartofStack = (uchar *)GET_STACK_START(ArgList); if ( pMesMsg->Operation == MES_ENCODE || pMesMsg->Operation == MES_ENCODE_NDR64 ) return NdrMesProcEncode3( (PMIDL_ES_MESSAGE)Handle, pProxyInfo, nProcNum, StartofStack ); else return NdrMesProcDecode3( (PMIDL_ES_MESSAGE)Handle, pProxyInfo, nProcNum, StartofStack, pReturnValue ); } void RPC_ENTRY NdrpPicklingClientFinally( PMIDL_STUB_MESSAGE pStubMsg, void * pThis ) { NDR_PROC_CONTEXT * pContext = (NDR_PROC_CONTEXT *) pStubMsg->pContext; PMIDL_STUB_DESC pStubDesc = pStubMsg->StubDesc; NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); NdrCorrelationFree( pStubMsg ); NdrpAllocaDestroy( & pContext->AllocateContext ); } void RPC_ENTRY Ndr64pPicklingClientFinally( PMIDL_STUB_MESSAGE pStubMsg, void * pThis ) { NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables); NdrpAllocaDestroy( & ( (NDR_PROC_CONTEXT *)pStubMsg->pContext )->AllocateContext ); } // ======================================================================= // // Ready to use AlignSize routines for simple types // // ======================================================================= void ValidateMesSimpleTypeAll( const MIDL_STUBLESS_PROXY_INFO * pProxyInfo, MIDL_ES_CODE Operation ) { ulong i; SYNTAX_TYPE SyntaxType; if ( Operation == MES_ENCODE || Operation == MES_DECODE ) SyntaxType = XFER_SYNTAX_DCE; else SyntaxType = XFER_SYNTAX_NDR64; for ( i = 0; i < ( ulong )pProxyInfo->nCount; i++ ) { if ( NdrpGetSyntaxType( &pProxyInfo->pSyntaxInfo[i].TransferSyntax ) == SyntaxType ) break; } // Raise exception if we didn't find the supported syntax in proxyinfo. if ( i >= pProxyInfo->nCount ) RpcRaiseException( RPC_S_UNSUPPORTED_TRANS_SYN ); } size_t RPC_ENTRY NdrMesSimpleTypeAlignSizeAll( handle_t Handle, const MIDL_STUBLESS_PROXY_INFO * pProxyInfo ) /*++ Size is always 8 bytes for data and there is no header here per data. However, the common header gets included for the first object. --*/ { if ( (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE && (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); PMIDL_STUB_MESSAGE pStubMsg = &((PMIDL_ES_MESSAGE) Handle)->StubMsg; ValidateMesSimpleTypeAll( pProxyInfo, ((PMIDL_ES_MESSAGE)Handle)->Operation ); unsigned long OldLength = pStubMsg->BufferLength; if ( ((PMIDL_ES_MESSAGE)Handle)->Operation == MES_ENCODE ) { if( (long)( pStubMsg->BufferLength & 0x7 ) ) RpcRaiseException( RPC_X_INVALID_BUFFER ); NdrpCommonTypeHeaderSize( (PMIDL_ES_MESSAGE)Handle ); pStubMsg->BufferLength += 8; } else { if( (long)( pStubMsg->BufferLength & 0xf ) ) RpcRaiseException( RPC_X_INVALID_BUFFER ); Ndr64pCommonTypeHeaderSize( (PMIDL_ES_MESSAGE)Handle ); LENGTH_ALIGN( pStubMsg->BufferLength, 0xf ); pStubMsg->BufferLength += 16; } return( (size_t)(pStubMsg->BufferLength - OldLength) ); } // ======================================================================= // // Ready to use Encode routines for simple types // // ======================================================================= void RPC_ENTRY NdrMesSimpleTypeEncodeAll( handle_t Handle, const MIDL_STUBLESS_PROXY_INFO * pProxyInfo, const void __RPC_FAR * pData, short Size ) /*++ Marshall a simple type entity. There is no header here per data. However, the common header gets included for the first object. --*/ { if ( (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE && (( PMIDL_ES_MESSAGE)Handle )->Operation != MES_ENCODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &pMesMsg->StubMsg; PMIDL_STUB_DESC pStubDesc = pProxyInfo->pStubDesc; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; unsigned long ulAlignment; size_t RequiredLen; // Size and allocate the buffer. // The req len includes: (the common header) and the data // Take the pointer alignment to come up with the right size. pStubMsg->BufferLength = 0xf & PtrToUlong( pStubMsg->Buffer ); RequiredLen = NdrMesSimpleTypeAlignSizeAll( Handle, pProxyInfo ); NdrpAllocPicklingBuffer( pMesMsg, RequiredLen ); // See if we need to marshall the common type header uchar __RPC_FAR * pBufferSaved = pStubMsg->Buffer; if ( pMesMsg->Operation == MES_ENCODE ) { NdrpCommonTypeHeaderMarshall( pMesMsg ); ulAlignment = 0x7; } else if ( pMesMsg->Operation == MES_ENCODE_NDR64 ) { Ndr64pCommonTypeHeaderMarshall( pMesMsg ); ulAlignment = 0xf; } else RpcRaiseException( RPC_X_INVALID_ES_ACTION ); ALIGN( pStubMsg->Buffer, ulAlignment ); switch ( Size ) { case 1: * PCHAR_CAST pStubMsg->Buffer = * PCHAR_CAST pData; break; case 2: * PSHORT_CAST pStubMsg->Buffer = * PSHORT_CAST pData; break; case 4: * PLONG_CAST pStubMsg->Buffer = * PLONG_CAST pData; break; case 8: * PHYPER_CAST pStubMsg->Buffer = * PHYPER_CAST pData; break; default: NDR_ASSERT( 0, " Size generation problem" ); } pStubMsg->Buffer += ulAlignment+1; NdrpWritePicklingBuffer( pMesMsg, pBufferSaved, RequiredLen ); } // ======================================================================= // // Ready to use Decode routines for simple types // // ======================================================================= void RPC_ENTRY NdrMesSimpleTypeDecodeAll( handle_t Handle, const MIDL_STUBLESS_PROXY_INFO * pProxyInfo, void __RPC_FAR * pData, short FormatChar ) /*++ Does not include the header for the data. However, the common header gets included for the first object. Note. Endianness and other conversions for decode. This has been deemed as not worthy doing in the Daytona time frame. However, to be able to add it in future without backward compatibility problems, we have the last argument to be the format character as opposed to the size. This makes it possible to call NdrSimpleTypeConvert, if needed. Note that the compiler uses the 32bit tokens for this since this routine is common to both formats. --*/ { if ( ( (PMIDL_ES_MESSAGE)Handle )->Operation != MES_DECODE && ( (PMIDL_ES_MESSAGE)Handle )->Operation != MES_DECODE_NDR64 ) RpcRaiseException( RPC_X_INVALID_ES_ACTION ); Ndr64pValidateMesHandle( (PMIDL_ES_MESSAGE_EX)Handle ); PMIDL_ES_MESSAGE pMesMsg = (PMIDL_ES_MESSAGE) Handle; PMIDL_STUB_MESSAGE pStubMsg = &((PMIDL_ES_MESSAGE)Handle)->StubMsg; uchar * BufferSaved; unsigned long ulAlignment; // See if we need to unmarshall the common type header. Ndr64pCommonTypeHeaderUnmarshall( pMesMsg ); // Now the data. if ( pMesMsg->Operation == MES_DECODE ) { NdrpReadPicklingBuffer( (PMIDL_ES_MESSAGE) Handle, 8); ulAlignment = 0x7; } else { NdrpReadPicklingBuffer( (PMIDL_ES_MESSAGE) Handle, 16); ulAlignment = 0xf; } NDR_ASSERT( ( (ULONG_PTR)pStubMsg->Buffer & ulAlignment ) == 0, "invalid buffer alignment in simple type pickling" ); ValidateMesSimpleTypeAll( pProxyInfo, ((PMIDL_ES_MESSAGE)Handle)->Operation ); if ( pMesMsg->AlienDataRep != NDR_LOCAL_DATA_REPRESENTATION ) { pStubMsg->RpcMsg->DataRepresentation = pMesMsg->AlienDataRep; BufferSaved = pStubMsg->Buffer; NdrSimpleTypeConvert( pStubMsg, (unsigned char)FormatChar ); pStubMsg->Buffer = BufferSaved; } switch ( FormatChar ) { case FC_BYTE: case FC_CHAR: case FC_SMALL: case FC_USMALL: * PCHAR_CAST pData = * PCHAR_CAST pStubMsg->Buffer; break; case FC_WCHAR: case FC_SHORT: case FC_USHORT: * PSHORT_CAST pData = * PSHORT_CAST pStubMsg->Buffer; break; case FC_LONG: case FC_ULONG: case FC_FLOAT: case FC_ENUM32: case FC_ERROR_STATUS_T: * PLONG_CAST pData = * PLONG_CAST pStubMsg->Buffer; break; case FC_HYPER: case FC_DOUBLE: * PHYPER_CAST pData = * PHYPER_CAST pStubMsg->Buffer; break; #if defined(__RPC_WIN64__) case FC_INT3264: if (pMesMsg->Operation == MES_DECODE ) *((INT64 *)pData) = *((long *) pStubMsg->Buffer); else *((INT64 *)pData) = *((INT64 *) pStubMsg->Buffer); break; case FC_UINT3264: if (pMesMsg->Operation == MES_DECODE ) *((UINT64 *)pData) = *((ulong *)pStubMsg->Buffer); else *((UINT64 *)pData) = *((UINT64 *)pStubMsg->Buffer); break; #endif default: NDR_ASSERT( 0, " Size generation problem for simple types" ); } pStubMsg->Buffer += ulAlignment+1; }