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

1320 lines
41 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 <midles.h>
#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( 1 )
{
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( 1 )
{
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:
// <version:1><endian:1><header_size:2><endian info: 4>
// addtional header:
// <reserved: 16> <transfer_syntax><iid>
//
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;
}
// Next decoding needs to start at aligned to 8.
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;
}