3678 lines
98 KiB
C++
3678 lines
98 KiB
C++
/************************************************************************
|
||
|
||
Copyright (c) 1993-2000 Microsoft Corporation
|
||
|
||
Module Name :
|
||
|
||
mrshl.c
|
||
|
||
Abstract :
|
||
|
||
This file contains the marshalling routines called by MIDL generated
|
||
stubs and the interpreter.
|
||
|
||
Author :
|
||
|
||
David Kays dkays September 1993.
|
||
|
||
Revision History :
|
||
|
||
***********************************************************************/
|
||
|
||
#include "ndrp.h"
|
||
#include "hndl.h"
|
||
#include "ndrole.h"
|
||
#include "attack.h"
|
||
#include "pointerq.h"
|
||
|
||
unsigned char *RPC_ENTRY
|
||
NdrUDTSimpleTypeMarshall1(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
unsigned char * pMemory,
|
||
PFORMAT_STRING pFormat
|
||
);
|
||
|
||
//
|
||
// Function table of marshalling routines.
|
||
//
|
||
extern const PMARSHALL_ROUTINE MarshallRoutinesTable[] =
|
||
{
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
NdrUDTSimpleTypeMarshall1,
|
||
|
||
NdrPointerMarshall,
|
||
NdrPointerMarshall,
|
||
NdrPointerMarshall,
|
||
NdrPointerMarshall,
|
||
|
||
NdrSimpleStructMarshall,
|
||
NdrSimpleStructMarshall,
|
||
NdrConformantStructMarshall,
|
||
NdrConformantStructMarshall,
|
||
NdrConformantVaryingStructMarshall,
|
||
|
||
NdrComplexStructMarshall,
|
||
|
||
NdrConformantArrayMarshall,
|
||
NdrConformantVaryingArrayMarshall,
|
||
NdrFixedArrayMarshall,
|
||
NdrFixedArrayMarshall,
|
||
NdrVaryingArrayMarshall,
|
||
NdrVaryingArrayMarshall,
|
||
|
||
NdrComplexArrayMarshall,
|
||
|
||
NdrConformantStringMarshall,
|
||
NdrConformantStringMarshall,
|
||
NdrConformantStringMarshall,
|
||
NdrConformantStringMarshall,
|
||
|
||
NdrNonConformantStringMarshall,
|
||
NdrNonConformantStringMarshall,
|
||
NdrNonConformantStringMarshall,
|
||
NdrNonConformantStringMarshall,
|
||
|
||
NdrEncapsulatedUnionMarshall,
|
||
NdrNonEncapsulatedUnionMarshall,
|
||
|
||
NdrByteCountPointerMarshall,
|
||
|
||
NdrXmitOrRepAsMarshall, // transmit as
|
||
NdrXmitOrRepAsMarshall, // represent as
|
||
|
||
NdrPointerMarshall,
|
||
|
||
NdrMarshallHandle,
|
||
|
||
// New Post NT 3.5 token serviced from here on.
|
||
|
||
0, // NdrHardStructMarshall,
|
||
|
||
NdrXmitOrRepAsMarshall, // transmit as ptr
|
||
NdrXmitOrRepAsMarshall, // represent as ptr
|
||
|
||
NdrUserMarshalMarshall,
|
||
|
||
0, // FC_PIPE
|
||
0, // FC_BLK_HOLE
|
||
|
||
NdrpRangeMarshall,
|
||
|
||
0, // FC_INT3264
|
||
0, // FC_UINT3264
|
||
|
||
0, // NdrCsArrayMarshall,
|
||
0, // NdrCsTagMarshall
|
||
};
|
||
|
||
extern const PMARSHALL_ROUTINE * pfnMarshallRoutines = MarshallRoutinesTable;
|
||
|
||
unsigned char *
|
||
NdrpInterfacePointerMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat );
|
||
|
||
RPCRTAPI
|
||
unsigned char *RPC_ENTRY
|
||
NdrTypeMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
return
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
|
||
__inline unsigned char *RPC_ENTRY
|
||
NdrUDTSimpleTypeMarshall1(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING FormatString )
|
||
{
|
||
NdrSimpleTypeMarshall(pStubMsg,pMemory,*FormatString);
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrSimpleTypeMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
uchar FormatChar )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a simple type.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the data to be marshalled.
|
||
FormatChar - Simple type format character.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
switch ( FormatChar )
|
||
{
|
||
case FC_CHAR :
|
||
case FC_BYTE :
|
||
case FC_SMALL :
|
||
case FC_USMALL :
|
||
*(pStubMsg->Buffer)++ = *pMemory;
|
||
break;
|
||
|
||
case FC_ENUM16 :
|
||
if ( *((int *)pMemory) & ~((int)0x7fff) )
|
||
{
|
||
RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
|
||
}
|
||
// fall through...
|
||
|
||
case FC_WCHAR :
|
||
case FC_SHORT :
|
||
case FC_USHORT :
|
||
ALIGN(pStubMsg->Buffer,1);
|
||
|
||
*((ushort *&)pStubMsg->Buffer)++ = *((ushort *)pMemory);
|
||
break;
|
||
|
||
case FC_LONG :
|
||
case FC_ULONG :
|
||
#if defined(__RPC_WIN64__)
|
||
case FC_INT3264:
|
||
case FC_UINT3264:
|
||
#endif
|
||
case FC_FLOAT :
|
||
case FC_ENUM32 :
|
||
case FC_ERROR_STATUS_T:
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
*((ulong *&)pStubMsg->Buffer)++ = *((ulong *)pMemory);
|
||
break;
|
||
|
||
case FC_HYPER :
|
||
case FC_DOUBLE :
|
||
ALIGN(pStubMsg->Buffer,7);
|
||
|
||
//
|
||
// Let's stay away from casts to double.
|
||
//
|
||
*((ulong *&)pStubMsg->Buffer)++ = *((ulong *)pMemory);
|
||
*((ulong *&)pStubMsg->Buffer)++ = *((ulong *)(pMemory + 4));
|
||
break;
|
||
|
||
case FC_IGNORE:
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrSimpleTypeMarshall : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrpRangeMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
--*/
|
||
{
|
||
uchar FcType = pFormat[1] & 0x0f;
|
||
|
||
NdrSimpleTypeMarshall( pStubMsg, pMemory, FcType );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrPointerMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a top level pointer to anything. Pointers embedded in
|
||
structures, arrays, or unions call NdrpPointerMarshall directly.
|
||
|
||
Used for FC_RP, FC_UP, FC_FP, FC_OP.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the data to be marshalled.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uchar * pBufferMark;
|
||
|
||
//
|
||
// If this is not a ref pointer then set buffer mark and increment the
|
||
// stub message buffer pointer.
|
||
//
|
||
if ( *pFormat != FC_RP )
|
||
{
|
||
ALIGN( pStubMsg->Buffer, 3 );
|
||
|
||
// This is where we marshall the node id.
|
||
pBufferMark = pStubMsg->Buffer;
|
||
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
}
|
||
else
|
||
pBufferMark = 0;
|
||
|
||
//
|
||
// For ref pointers pBufferMark will not be used and can be left
|
||
// unitialized.
|
||
//
|
||
|
||
NdrpPointerMarshall( pStubMsg,
|
||
pBufferMark,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
__forceinline void
|
||
NdrpPointerMarshallInternal(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pBufferMark,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine for marshalling a pointer and its pointee. This is the
|
||
entry point for pointers embedded in structures, arrays, and unions.
|
||
|
||
Used for FC_RP, FC_UP, FC_FP, FC_OP.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pBufferMark - The location in the buffer where the pointer itself is
|
||
marshalled. Important for full pointers, unfortunately it's
|
||
overkill for unique pointers.
|
||
pMemory - Pointer to the data to be marshalled.
|
||
pFormat - Pointer format string description.
|
||
|
||
pStubMsg->Buffer - the place for the pointee.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Check the pointer type.
|
||
//
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_RP :
|
||
if ( ! pMemory )
|
||
RpcRaiseException( RPC_X_NULL_REF_POINTER );
|
||
|
||
break;
|
||
|
||
case FC_UP :
|
||
case FC_OP :
|
||
// Put the pointer in the buffer.
|
||
*((ulong*&)pBufferMark)++ = PTR_WIRE_REP(pMemory);
|
||
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
break;
|
||
|
||
case FC_IP :
|
||
|
||
if ( IS_BROKEN_INTERFACE_POINTER(pStubMsg->uFlags) )
|
||
{
|
||
// The pointee is effectivly both the pointer
|
||
// and the pointee.
|
||
|
||
NdrInterfacePointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
return;
|
||
}
|
||
|
||
// Interface pointers behave like unique pointers
|
||
*((ulong*&)pBufferMark)++ = PTR_WIRE_REP(pMemory);
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
NdrpInterfacePointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
return;
|
||
|
||
case FC_FP :
|
||
//
|
||
// Marshall the pointer's ref id and see if we've already
|
||
// marshalled the pointer's data.
|
||
//
|
||
if ( NdrFullPointerQueryPointer( pStubMsg->FullPtrXlatTables,
|
||
pMemory,
|
||
FULL_POINTER_MARSHALLED,
|
||
(ulong *) pBufferMark ) )
|
||
return;
|
||
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrpPointerMarshall : bad pointer type");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Check for a pointer to a complex type.
|
||
//
|
||
if ( ! SIMPLE_POINTER(pFormat[1]) )
|
||
{
|
||
uchar uFlagsSave;
|
||
|
||
if ( POINTER_DEREF(pFormat[1]) )
|
||
pMemory = *((uchar **)pMemory);
|
||
|
||
// Increment to offset_to_complex_description<2> field.
|
||
pFormat += 2;
|
||
|
||
//
|
||
// Set format string to complex type description.
|
||
// Cast must be to a signed short since some offsets are negative.
|
||
//
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
//
|
||
// Look up the proper marshalling routine in the marshalling function
|
||
// table.
|
||
//
|
||
uFlagsSave = pStubMsg->uFlags;
|
||
RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
|
||
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
pStubMsg->uFlags = uFlagsSave;
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Else it's a pointer to a simple type or a string pointer.
|
||
//
|
||
|
||
switch ( pFormat[2] )
|
||
{
|
||
case FC_C_CSTRING :
|
||
case FC_C_BSTRING :
|
||
case FC_C_WSTRING :
|
||
case FC_C_SSTRING :
|
||
NdrConformantStringMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat + 2 );
|
||
break;
|
||
|
||
default :
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat[2] );
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
NDR_MRSHL_POINTER_QUEUE_ELEMENT::NDR_MRSHL_POINTER_QUEUE_ELEMENT(
|
||
MIDL_STUB_MESSAGE *pStubMsg,
|
||
uchar * const pBufferMarkNew,
|
||
uchar * const pMemoryNew,
|
||
const PFORMAT_STRING pFormatNew) :
|
||
|
||
pBufferMark(pBufferMarkNew),
|
||
pMemory(pMemoryNew),
|
||
pFormat(pFormatNew),
|
||
Memory(pStubMsg->Memory),
|
||
uFlags(pStubMsg->uFlags)
|
||
{
|
||
|
||
}
|
||
|
||
void
|
||
NDR_MRSHL_POINTER_QUEUE_ELEMENT::Dispatch(
|
||
MIDL_STUB_MESSAGE *pStubMsg)
|
||
{
|
||
SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
|
||
SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
|
||
NDR_ASSERT( !pStubMsg->PointerBufferMark, "PointerBufferMark is not 0\n");
|
||
|
||
NdrpPointerMarshallInternal( pStubMsg,
|
||
pBufferMark,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
#if defined(DBG)
|
||
void
|
||
NDR_MRSHL_POINTER_QUEUE_ELEMENT::Print()
|
||
{
|
||
DbgPrint("NDR_MRSHL_POINTER_QUEUE_ELEMENT\n");
|
||
DbgPrint("pNext: %p\n", pNext );
|
||
DbgPrint("pBufferMark: %p\n", pBufferMark );
|
||
DbgPrint("pMemory: %p\n", pMemory );
|
||
DbgPrint("pFormat: %p\n", pFormat );
|
||
DbgPrint("Memory: %p\n", Memory );
|
||
DbgPrint("uFlags: %x\n", uFlags );
|
||
}
|
||
#endif
|
||
|
||
void
|
||
NdrpEnquePointerMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pBufferMark,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
|
||
|
||
RpcTryFinally
|
||
{
|
||
NDR_MRSHL_POINTER_QUEUE_ELEMENT*pElement =
|
||
new(PointerContext.GetActiveState())
|
||
NDR_MRSHL_POINTER_QUEUE_ELEMENT(pStubMsg,
|
||
pBufferMark,
|
||
pMemory,
|
||
pFormat);
|
||
PointerContext.Enque( pElement );
|
||
PointerContext.DispatchIfRequired();
|
||
}
|
||
RpcFinally
|
||
{
|
||
PointerContext.EndContext();
|
||
}
|
||
RpcEndFinally
|
||
}
|
||
|
||
void
|
||
NdrpPointerMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pBufferMark,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
|
||
if ( !NdrIsLowStack(pStubMsg) )
|
||
{
|
||
NdrpPointerMarshallInternal( pStubMsg,
|
||
pBufferMark,
|
||
pMemory,
|
||
pFormat );
|
||
return;
|
||
}
|
||
|
||
NdrpEnquePointerMarshall( pStubMsg,
|
||
pBufferMark,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
}
|
||
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrSimpleStructMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a simple structure.
|
||
|
||
Used for FC_STRUCT and FC_PSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the structure to be marshalled.
|
||
pFormat - Structure's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uint StructSize;
|
||
|
||
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
||
|
||
StructSize = (uint) *((ushort *)(pFormat + 2));
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
StructSize );
|
||
|
||
// Mark the start of the structure in the buffer.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
pStubMsg->Buffer += StructSize;
|
||
|
||
// Marshall embedded pointers.
|
||
if ( *pFormat == FC_PSTRUCT )
|
||
{
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat + 4 );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrConformantStructMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a conformant structure.
|
||
|
||
Used for FC_CSTRUCT and FC_CPSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the structure to be marshalled.
|
||
pFormat - Structure's format string description.
|
||
|
||
Return :
|
||
|
||
None. - may set the CONF_ARRAY_DONE flag.
|
||
|
||
Note
|
||
|
||
Due to problems with MIDL generated code, the ConformantStruct routine always
|
||
marshals the conformant array. Only a bogus struct can embed a conf struct,
|
||
and there is a flag that bogus struct watches in order not to marshal the array
|
||
second time.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatArray;
|
||
uint StructSize;
|
||
uchar Alignment;
|
||
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
|
||
// Save structure's alignment.
|
||
Alignment = pFormat[1];
|
||
|
||
// Increment format string to struct size field.
|
||
pFormat += 2;
|
||
|
||
// Get flat struct size and increment format string.
|
||
StructSize = (uint) *((ushort *&)pFormat)++;
|
||
|
||
// Set conformant array format string description.
|
||
pFormatArray = pFormat + *((signed short *)pFormat);
|
||
|
||
//
|
||
// Compute conformance information. Pass a memory pointer to the
|
||
// end of the non-conformant part of the structure.
|
||
//
|
||
NdrpComputeConformance( pStubMsg,
|
||
pMemory + StructSize,
|
||
pFormatArray );
|
||
|
||
// Only a bogus struct can embed a conf struct.
|
||
|
||
if ( fIsEmbeddedStruct )
|
||
*(ulong *)pStubMsg->BufferMark = (ulong)pStubMsg->MaxCount;
|
||
else
|
||
{
|
||
// Align the buffer for conformance count marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Marshall conformance count.
|
||
*((ulong *&)pStubMsg->Buffer)++ = (ulong)pStubMsg->MaxCount;
|
||
}
|
||
|
||
|
||
// Re-align buffer
|
||
ALIGN(pStubMsg->Buffer,Alignment);
|
||
|
||
// Increment array format string to array element size field.
|
||
pFormatArray += 2;
|
||
|
||
// Add the size of the conformant array to the structure size.
|
||
StructSize += (ulong)pStubMsg->MaxCount * *((ushort *)pFormatArray);
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
StructSize );
|
||
|
||
// Update the buffer pointer.
|
||
pStubMsg->Buffer += StructSize;
|
||
|
||
// Increment format string past offset to array description field.
|
||
pFormat += 2;
|
||
|
||
// Marshall embedded pointers. This covers the struct and the conf array.
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
// Mark the start of the structure in the buffer.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer - StructSize;
|
||
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
// Only a complex struct may set up this flag for embedding.
|
||
// Set the reverse flag to signal that array has been marshaled.
|
||
|
||
if ( fIsEmbeddedStruct )
|
||
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrConformantVaryingStructMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a structure which contains a conformant varying array.
|
||
|
||
Used for FC_CVSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the structure to be marshalled.
|
||
pFormat - Structure's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatArray;
|
||
uint StructSize;
|
||
uchar Alignment;
|
||
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
uchar* pBuffer;
|
||
|
||
if ( !fIsEmbeddedStruct )
|
||
{
|
||
// Align the buffer for marshalling conformance info.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Mark the location in the buffer where the conformance will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment buffer pointer past where conformance will be marshalled.
|
||
pStubMsg->Buffer += 4;
|
||
}
|
||
// else BufferMark is set by the ComplexStruct code.
|
||
|
||
// Save the structure's alignment.
|
||
Alignment = pFormat[1];
|
||
|
||
// Increment format string to struct size field.
|
||
pFormat += 2;
|
||
|
||
// Get non-conformance struct size and increment format string.
|
||
StructSize = (uint) *((ushort *&)pFormat)++;
|
||
|
||
// Get conformant array's description.
|
||
pFormatArray = pFormat + *((signed short *)pFormat);
|
||
|
||
// Align buffer for struct
|
||
ALIGN(pStubMsg->Buffer, Alignment);
|
||
pBuffer = pStubMsg->Buffer;
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
StructSize );
|
||
// Set stub message buffer pointer past non-conformant part of struct.
|
||
pStubMsg->Buffer += StructSize;
|
||
|
||
//
|
||
// Call the correct private array or string marshalling routine.
|
||
// We must pass a memory pointer to the beginning of the array/string.
|
||
//
|
||
if ( *pFormatArray == FC_CVARRAY )
|
||
{
|
||
NdrpConformantVaryingArrayMarshall( pStubMsg,
|
||
pMemory + StructSize,
|
||
pFormatArray );
|
||
}
|
||
else
|
||
{
|
||
NdrpConformantStringMarshall( pStubMsg,
|
||
pMemory + StructSize,
|
||
pFormatArray );
|
||
}
|
||
|
||
// Increment format string past the offset_to_array_description<2> field.
|
||
pFormat += 2;
|
||
|
||
//
|
||
// Marshall embedded pointers.
|
||
//
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
// Mark the start of the structure in the buffer.
|
||
pStubMsg->BufferMark = pBuffer;
|
||
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
// Only a complex struct may set up this flag for embedding.
|
||
// Set the reverse flag to signal that array has been marshaled.
|
||
|
||
if ( fIsEmbeddedStruct )
|
||
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
#if 0
|
||
unsigned char * RPC_ENTRY
|
||
NdrHardStructMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a hard structure.
|
||
|
||
Used for FC_HARD_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the structure being marshalled.
|
||
pFormat - Structure's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
||
|
||
pFormat += 8;
|
||
|
||
//
|
||
// Do any needed enum16 exception check.
|
||
//
|
||
if ( *((short *)pFormat) != (short) -1 )
|
||
{
|
||
if ( *((int *)(pMemory + *((ushort *)pFormat))) & ~((int)0x7fff) )
|
||
{
|
||
RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
|
||
}
|
||
}
|
||
|
||
pFormat += 2;
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
*((ushort *)pFormat) );
|
||
|
||
pStubMsg->Buffer += *((ushort *)pFormat)++;
|
||
|
||
//
|
||
// See if we have a union.
|
||
//
|
||
if ( *((short *)&pFormat[2]) )
|
||
{
|
||
pMemory += *((ushort *)pFormat)++;
|
||
|
||
pFormat += *((short *)pFormat);
|
||
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
#endif // 0
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrComplexStructMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a complex structure.
|
||
|
||
Used for FC_BOGUS_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the structure being marshalled.
|
||
pFormat - Structure's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
Notes :
|
||
|
||
pStubMsg->BufferMark is set to a place where conformance would be marhaled.
|
||
pStubMsg->pPointerBufferMark is a pointee buffer mark a usual.
|
||
|
||
--*/
|
||
{
|
||
uchar * pBufferSave;
|
||
uchar * pBufferMark;
|
||
uchar * pMemorySave;
|
||
PFORMAT_STRING pFormatPointers;
|
||
PFORMAT_STRING pFormatArray;
|
||
PFORMAT_STRING pFormatSave;
|
||
PFORMAT_STRING pFormatComplex;
|
||
long Alignment;
|
||
long Align8Mod;
|
||
uchar fSetPointerBufferMark;
|
||
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
BOOL fEmbedConfStructContext;
|
||
|
||
// Get struct's wire alignment.
|
||
Alignment = pFormat[1];
|
||
|
||
//
|
||
// This is used for support of structs with doubles passed on an
|
||
// i386 stack.
|
||
//
|
||
// A cast to long is what we need.
|
||
Align8Mod = 0x7 & PtrToLong( pMemory );
|
||
|
||
pFormatSave = pFormat;
|
||
pBufferSave = pStubMsg->Buffer;
|
||
pMemorySave = pStubMsg->Memory;
|
||
|
||
pStubMsg->Memory = pMemory;
|
||
|
||
// Increment to conformant array offset field.
|
||
pFormat += 4;
|
||
|
||
// Get conformant array description.
|
||
if ( *((ushort *)pFormat) )
|
||
{
|
||
pFormatArray = pFormat + *((signed short *)pFormat);
|
||
|
||
if ( !fIsEmbeddedStruct )
|
||
{
|
||
// Align for conformance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Remember where the conformance count(s) will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment the buffer pointer 4 bytes for every array dimension.
|
||
pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormatArray, FALSE ) * 4;
|
||
}
|
||
}
|
||
else
|
||
pFormatArray = 0;
|
||
|
||
// Mark the place to marshal conformant size(s), this may come from upper levels.
|
||
pBufferMark = pStubMsg->BufferMark;
|
||
|
||
pFormat += 2;
|
||
|
||
// Get pointer layout description.
|
||
if ( *((ushort *)pFormat) )
|
||
pFormatPointers = pFormat + *((ushort *)pFormat);
|
||
else
|
||
pFormatPointers = 0;
|
||
|
||
pFormat += 2;
|
||
|
||
// Align buffer on struct's alignment.
|
||
ALIGN(pStubMsg->Buffer,Alignment);
|
||
|
||
//
|
||
// If the the stub message PointerBufferMark field is 0, then determine
|
||
// the position in the buffer where pointees will be marshalled.
|
||
//
|
||
// We have to do this to handle embedded pointers.
|
||
//
|
||
if ( fSetPointerBufferMark = ! pStubMsg->PointerBufferMark )
|
||
{
|
||
BOOL fOldIgnore;
|
||
ulong BufferLenOffset;
|
||
|
||
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
||
|
||
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
||
|
||
//
|
||
// Set BufferLength equal to the current buffer pointer, and then
|
||
// when we return from NdrComplexStructBufferSize it will pointer to
|
||
// the location in the buffer where the pointees should be marshalled.
|
||
// pStubMsg->BufferLength = pBufferSave;
|
||
// Instead of pointer, we now calculate pointer increment explicitly.
|
||
|
||
// Set the pointer alignment as a base.
|
||
// We use pBufferSave as the sizing routine accounts for the conf sizes.
|
||
//
|
||
BufferLenOffset = 0xf & PtrToUlong( pBufferSave );
|
||
ulong BufferLengthSave = pStubMsg->BufferLength;
|
||
pStubMsg->BufferLength = BufferLenOffset;
|
||
|
||
NdrComplexStructBufferSize( pStubMsg,
|
||
pMemory,
|
||
pFormatSave );
|
||
|
||
// Pointer increment including alignments.
|
||
BufferLenOffset = pStubMsg->BufferLength - BufferLenOffset;
|
||
|
||
// Set the location in the buffer where pointees will be marshalled.
|
||
pStubMsg->PointerBufferMark = pBufferSave + BufferLenOffset;
|
||
pStubMsg->BufferLength = BufferLengthSave;
|
||
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
||
}
|
||
|
||
fEmbedConfStructContext = fIsEmbeddedStruct ||
|
||
pFormatArray && FixWireRepForDComVerGTE54( pStubMsg );
|
||
|
||
RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
//
|
||
// Marshall the structure member by member.
|
||
//
|
||
for ( ; ; pFormat++ )
|
||
{
|
||
switch ( *pFormat )
|
||
{
|
||
//
|
||
// Simple types.
|
||
//
|
||
case FC_CHAR :
|
||
case FC_BYTE :
|
||
case FC_SMALL :
|
||
case FC_WCHAR :
|
||
case FC_SHORT :
|
||
case FC_LONG :
|
||
#if defined(__RPC_WIN64__)
|
||
case FC_INT3264 :
|
||
case FC_UINT3264 :
|
||
#endif
|
||
case FC_FLOAT :
|
||
case FC_HYPER :
|
||
case FC_DOUBLE :
|
||
case FC_ENUM16 :
|
||
case FC_ENUM32 :
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
pMemory,
|
||
*pFormat );
|
||
|
||
pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
|
||
break;
|
||
|
||
case FC_IGNORE :
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
pMemory += PTR_MEM_SIZE;
|
||
break;
|
||
|
||
case FC_POINTER :
|
||
{
|
||
|
||
ALIGN( pStubMsg->Buffer, 0x3 );
|
||
uchar *pPointerId = pStubMsg->Buffer;
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
NDR_ASSERT(pFormatPointers, "NdrComplexStructMarshall: pointer field but no pointer layout");
|
||
|
||
{
|
||
POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
|
||
NdrpPointerMarshall( pStubMsg,
|
||
pPointerId,
|
||
*((uchar **)pMemory),
|
||
pFormatPointers );
|
||
|
||
}
|
||
|
||
//
|
||
// Increment memory pointers past the pointer.
|
||
//
|
||
|
||
pMemory += PTR_MEM_SIZE;
|
||
|
||
pFormatPointers += 4;
|
||
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Embedded complex types.
|
||
//
|
||
case FC_EMBEDDED_COMPLEX :
|
||
// Increment memory pointer by padding.
|
||
pMemory += pFormat[1];
|
||
|
||
pFormat += 2;
|
||
|
||
// Get the type's description.
|
||
pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
|
||
|
||
if ( FC_IP == *pFormatComplex )
|
||
{
|
||
|
||
// Treat the same as an embedded pointer
|
||
ALIGN( pStubMsg->Buffer, 0x3 );
|
||
uchar *pPointerId = pStubMsg->Buffer;
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
|
||
{
|
||
POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
|
||
NdrpPointerMarshall( pStubMsg,
|
||
pPointerId,
|
||
*((uchar **)pMemory),
|
||
pFormatComplex );
|
||
|
||
}
|
||
pMemory += PTR_MEM_SIZE;
|
||
pFormat++;
|
||
break;
|
||
|
||
}
|
||
|
||
// Context needed for the embedded conf struct.
|
||
//
|
||
pStubMsg->BufferMark = pBufferMark;
|
||
if ( fEmbedConfStructContext )
|
||
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
|
||
// Marshall complex type.
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
||
( pStubMsg,
|
||
pMemory,
|
||
pFormatComplex );
|
||
|
||
//
|
||
// Increment the memory pointer.
|
||
//
|
||
pMemory = NdrpMemoryIncrement( pStubMsg,
|
||
pMemory,
|
||
pFormatComplex );
|
||
|
||
RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
|
||
//
|
||
// Increment the main format string one byte. The loop
|
||
// will increment it one more byte past the offset field.
|
||
//
|
||
pFormat++;
|
||
|
||
break;
|
||
|
||
case FC_ALIGNM2 :
|
||
ALIGN( pMemory, 0x1 );
|
||
break;
|
||
|
||
case FC_ALIGNM4 :
|
||
ALIGN( pMemory, 0x3 );
|
||
break;
|
||
|
||
case FC_ALIGNM8 :
|
||
//
|
||
// We have to play some tricks for the i386 to handle the case
|
||
// when an 8 byte aligned structure is passed by value. The
|
||
// alignment of the struct on the stack is not guaranteed to be
|
||
// on an 8 byte boundary.
|
||
//
|
||
pMemory -= Align8Mod;
|
||
ALIGN( pMemory, 0x7 );
|
||
pMemory += Align8Mod;
|
||
|
||
break;
|
||
|
||
case FC_STRUCTPAD1 :
|
||
case FC_STRUCTPAD2 :
|
||
case FC_STRUCTPAD3 :
|
||
case FC_STRUCTPAD4 :
|
||
case FC_STRUCTPAD5 :
|
||
case FC_STRUCTPAD6 :
|
||
case FC_STRUCTPAD7 :
|
||
//
|
||
// Increment memory pointer by amount of padding.
|
||
//
|
||
pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
|
||
break;
|
||
|
||
case FC_STRUCTPADN :
|
||
// FC_STRUCTPADN 0 <unsigned short>
|
||
pMemory += *(((unsigned short *)pFormat) + 1);
|
||
pFormat += 3;
|
||
break;
|
||
|
||
case FC_PAD :
|
||
break;
|
||
|
||
//
|
||
// Done with layout.
|
||
//
|
||
case FC_END :
|
||
goto ComplexMarshallEnd;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrComplexStructMarshall : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return 0;
|
||
} // switch
|
||
} // for
|
||
|
||
ComplexMarshallEnd:
|
||
|
||
//
|
||
// Marshall conformant array if we have one.
|
||
// .. but not when embedded and not when it had been marshaled by conf struct.
|
||
//
|
||
if ( pFormatArray && !fIsEmbeddedStruct &&
|
||
! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
|
||
{
|
||
// Normal case: top level marshaling.
|
||
|
||
PPRIVATE_MARSHALL_ROUTINE pfnPMarshall;
|
||
|
||
|
||
switch ( *pFormatArray )
|
||
{
|
||
case FC_CARRAY :
|
||
pfnPMarshall = NdrpConformantArrayMarshall;
|
||
break;
|
||
|
||
case FC_CVARRAY :
|
||
pfnPMarshall = NdrpConformantVaryingArrayMarshall;
|
||
break;
|
||
|
||
case FC_BOGUS_ARRAY :
|
||
pfnPMarshall = NdrpComplexArrayMarshall;
|
||
break;
|
||
|
||
case FC_C_WSTRING :
|
||
ALIGN(pMemory,1);
|
||
// fall through
|
||
|
||
// case FC_C_CSTRING :
|
||
// case FC_C_BSTRING :
|
||
// case FC_C_SSTRING :
|
||
|
||
default :
|
||
pfnPMarshall = NdrpConformantStringMarshall;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Mark where the conformance count(s) will be marshalled.
|
||
//
|
||
pStubMsg->BufferMark = pBufferMark;
|
||
|
||
// Marshall the array.
|
||
(*pfnPMarshall)( pStubMsg,
|
||
pMemory,
|
||
pFormatArray );
|
||
}
|
||
|
||
//
|
||
// Now fix up the stub message Buffer field if we set the PointerBufferMark
|
||
// field.
|
||
//
|
||
if ( fSetPointerBufferMark )
|
||
{
|
||
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
||
|
||
pStubMsg->PointerBufferMark = 0;
|
||
}
|
||
|
||
pStubMsg->Memory = pMemorySave;
|
||
|
||
if ( fIsEmbeddedStruct )
|
||
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
else
|
||
RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrNonConformantStringMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a non conformant string.
|
||
|
||
Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
|
||
compatability only).
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the string to be marshalled.
|
||
pFormat - String's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uint Count;
|
||
uint CopySize;
|
||
|
||
// Align the buffer for offset and count marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_CSTRING :
|
||
case FC_BSTRING :
|
||
CopySize = Count = MIDL_ascii_strlen((char *)pMemory) + 1;
|
||
break;
|
||
|
||
case FC_WSTRING :
|
||
Count = wcslen((wchar_t *)pMemory) + 1;
|
||
CopySize = Count * sizeof(wchar_t);
|
||
break;
|
||
|
||
case FC_SSTRING :
|
||
Count = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
|
||
CopySize = Count * pFormat[1];
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrNonConformantStringMarshall : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return 0;
|
||
}
|
||
|
||
// Marshall variance.
|
||
*((ulong *&)pStubMsg->Buffer)++ = 0;
|
||
*((ulong *&)pStubMsg->Buffer)++ = Count;
|
||
|
||
// Copy the string.
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
CopySize );
|
||
|
||
// Update buffer pointer.
|
||
pStubMsg->Buffer += CopySize;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrConformantStringMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Marshalls a top level conformant string.
|
||
|
||
Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
|
||
(NT Beta2 compatability only).
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the string to be marshalled.
|
||
pFormat - String's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if ( pStubMsg->pArrayInfo != 0 )
|
||
{
|
||
//
|
||
// If this is part of a multidimensional array then we get the location
|
||
// where the conformance is marshalled from a special place.
|
||
//
|
||
pStubMsg->BufferMark = ( uchar * )
|
||
&(pStubMsg->pArrayInfo->
|
||
BufferConformanceMark[pStubMsg->pArrayInfo->Dimension]);
|
||
}
|
||
else
|
||
{
|
||
// Align the buffer for max count marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Mark where the max count will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment the buffer past where the max count will be marshalled.
|
||
pStubMsg->Buffer += 4;
|
||
}
|
||
|
||
// Call the private marshalling routine.
|
||
NdrpConformantStringMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpConformantStringMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine description :
|
||
|
||
Private routine for marshalling a conformant string. This is the
|
||
entry point for marshalling an embedded conformant strings.
|
||
|
||
Used for FC_C_CSTRING, FC_C_WSTRING, FC_C_SSTRING, and FC_C_BSTRING
|
||
(NT Beta2 compatability only).
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the string to be marshalled.
|
||
pFormat - String's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ulong MaxCount;
|
||
uint ActualCount, CopySize;
|
||
BOOL IsSized;
|
||
|
||
IsSized = (pFormat[1] == FC_STRING_SIZED);
|
||
|
||
// Compute the element count of the string and the total copy size.
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_C_CSTRING :
|
||
case FC_C_BSTRING :
|
||
CopySize = ActualCount = MIDL_ascii_strlen((char *)pMemory) + 1;
|
||
break;
|
||
|
||
case FC_C_WSTRING :
|
||
ActualCount = wcslen((wchar_t *)pMemory) + 1;
|
||
CopySize = ActualCount * sizeof(wchar_t);
|
||
break;
|
||
|
||
case FC_C_SSTRING :
|
||
ActualCount = NdrpStringStructLen( pMemory, pFormat[1] ) + 1;
|
||
CopySize = ActualCount * pFormat[1];
|
||
|
||
// Redo this check correctly.
|
||
IsSized = (pFormat[2] == FC_STRING_SIZED);
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrpConformantStringMarshall : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return;
|
||
}
|
||
|
||
//
|
||
// If the string is sized then compute the max count, otherwise the
|
||
// max count is equal to the actual count.
|
||
//
|
||
if ( IsSized )
|
||
{
|
||
MaxCount = (ulong) NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
else
|
||
{
|
||
MaxCount = ActualCount;
|
||
}
|
||
|
||
// Marshall the max count.
|
||
*((ulong *)pStubMsg->BufferMark) = MaxCount;
|
||
|
||
// Align the buffer for variance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Marshall variance.
|
||
*((ulong *&)pStubMsg->Buffer)++ = 0;
|
||
*((ulong *&)pStubMsg->Buffer)++ = ActualCount;
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
CopySize );
|
||
|
||
// Update the Buffer pointer.
|
||
pStubMsg->Buffer += CopySize;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrFixedArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a fixed array of any number of dimensions.
|
||
|
||
Used for FC_SMFARRAY and FC_LGFARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array to be marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uint Size;
|
||
|
||
// Align the buffer.
|
||
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
||
|
||
// Get total array size.
|
||
if ( *pFormat == FC_SMFARRAY )
|
||
{
|
||
pFormat += 2;
|
||
Size = (ulong) *((ushort *&)pFormat)++;
|
||
}
|
||
else // *pFormat == FC_LGFARRAY
|
||
{
|
||
pFormat += 2;
|
||
Size = *((ulong UNALIGNED *&)pFormat)++;
|
||
}
|
||
|
||
// Copy the array.
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
Size );
|
||
|
||
// Increment stub message buffer pointer.
|
||
pStubMsg->Buffer += Size;
|
||
|
||
// Marshall embedded pointers.
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
// Mark the start of the array in the buffer.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
|
||
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrConformantArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a top level one dimensional conformant array.
|
||
|
||
Used for FC_CARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
// Align the buffer for conformance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Mark where the conformance will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment past where the conformance will go.
|
||
pStubMsg->Buffer += 4;
|
||
|
||
// Call the private marshalling routine to do the work.
|
||
NdrpConformantArrayMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpConformantArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine for marshalling a one dimensional conformant array.
|
||
This is the entry point for marshalling an embedded conformant array.
|
||
|
||
Used for FC_CARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ulong Count;
|
||
uint CopySize;
|
||
|
||
// Compute conformance information.
|
||
Count = (ulong) NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Marshall the conformance.
|
||
*((ulong *)pStubMsg->BufferMark) = Count;
|
||
|
||
//
|
||
// Return if size is 0.
|
||
//
|
||
if ( ! Count )
|
||
return;
|
||
|
||
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
||
|
||
// Compute the total array size in bytes.
|
||
CopySize = Count * *((ushort *)(pFormat + 2));
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
CopySize );
|
||
|
||
// Update buffer pointer.
|
||
pStubMsg->Buffer += CopySize;
|
||
|
||
// Increment to possible pointer layout.
|
||
pFormat += 8;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
// Marshall embedded pointers.
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
//
|
||
// Mark the start of the array in the buffer.
|
||
//
|
||
pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
|
||
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrConformantVaryingArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a top level one dimensional conformant varying array.
|
||
|
||
Used for FC_CVARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
// Align the buffer for conformance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Mark where the conformance will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment past where the conformance will go.
|
||
pStubMsg->Buffer += 4;
|
||
|
||
// Call the private marshalling routine to do the work.
|
||
NdrpConformantVaryingArrayMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpConformantVaryingArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine for marshalling a one dimensional conformant varying array.
|
||
This is the entry point for marshalling an embedded conformant varying
|
||
array.
|
||
|
||
Used for FC_CVARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array to be marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uint CopyOffset, CopySize;
|
||
ushort ElemSize;
|
||
|
||
// Compute and marshall the conformant size.
|
||
*((ulong *)pStubMsg->BufferMark) = (ulong) NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Compute variance offset and count.
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Align the buffer for variance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Marshall variance.
|
||
*((ulong *&)pStubMsg->Buffer)++ = pStubMsg->Offset;
|
||
*((ulong *&)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
|
||
|
||
//
|
||
// Return if length is 0.
|
||
//
|
||
if ( ! pStubMsg->ActualCount )
|
||
return;
|
||
|
||
ALIGN(pStubMsg->Buffer, pFormat[1]);
|
||
|
||
ElemSize = *((ushort *)(pFormat + 2));
|
||
|
||
// Compute byte offset and size for the array copy.
|
||
CopyOffset = pStubMsg->Offset * ElemSize;
|
||
CopySize = pStubMsg->ActualCount * ElemSize;
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory + CopyOffset,
|
||
CopySize );
|
||
|
||
pStubMsg->Buffer += CopySize;
|
||
|
||
// Increment to a possible pointer layout.
|
||
pFormat += 12;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
// Marshall embedded pointers.
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
//
|
||
// Set the MaxCount field equal to the ActualCount field. The pointer
|
||
// marshalling routine uses the MaxCount field to determine the number
|
||
// of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
|
||
// of variance the correct number of time is the ActualCount, not the
|
||
// the MaxCount.
|
||
//
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
//
|
||
// Mark the start of the array in the buffer.
|
||
//
|
||
pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
|
||
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrVaryingArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a top level or embedded one dimensional varying array.
|
||
|
||
Used for FC_SMVARRAY and FC_LGVARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uint CopyOffset, CopySize;
|
||
ushort ElemSize;
|
||
|
||
// Compute the variance offset and count.
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Align the buffer for variance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Marshall variance.
|
||
*((ulong *&)pStubMsg->Buffer)++ = pStubMsg->Offset;
|
||
*((ulong *&)pStubMsg->Buffer)++ = pStubMsg->ActualCount;
|
||
|
||
//
|
||
// Return if length is 0.
|
||
//
|
||
if ( ! pStubMsg->ActualCount )
|
||
return 0;
|
||
|
||
ALIGN(pStubMsg->Buffer, pFormat[1]);
|
||
|
||
// Increment the format string to the element_size field.
|
||
if ( *pFormat == FC_SMVARRAY )
|
||
pFormat += 6;
|
||
else // *pFormat == FC_LGVARRAY
|
||
pFormat += 10;
|
||
|
||
// Get element size.
|
||
ElemSize = *((ushort *)pFormat);
|
||
|
||
//
|
||
// Compute the byte offset from the beginning of the array for the copy
|
||
// and the number of bytes to copy.
|
||
//
|
||
CopyOffset = pStubMsg->Offset * ElemSize;
|
||
CopySize = pStubMsg->ActualCount * ElemSize;
|
||
|
||
// Copy the array.
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory + CopyOffset,
|
||
CopySize );
|
||
|
||
// Update buffer pointer.
|
||
pStubMsg->Buffer += CopySize;
|
||
|
||
// Increment format string to possible pointer layout.
|
||
pFormat += 6;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
// Marshall embedded pointers.
|
||
if ( *pFormat == FC_PP )
|
||
{
|
||
// Mark the start of the array in the buffer.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer - CopySize;
|
||
|
||
//
|
||
// Set the MaxCount field equal to the ActualCount field. The pointer
|
||
// marshalling routine uses the MaxCount field to determine the number
|
||
// of times an FC_VARIABLE_REPEAT pointer is marshalled. In the face
|
||
// of variance the correct number of time is the ActualCount, not the
|
||
// the MaxCount.
|
||
//
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
//
|
||
// Marshall the embedded pointers.
|
||
// Make sure to pass a memory pointer to the first array element
|
||
// which is actually being marshalled.
|
||
//
|
||
NdrpEmbeddedPointerMarshall( pStubMsg,
|
||
pMemory + CopyOffset,
|
||
pFormat );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrComplexArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a top level complex array.
|
||
|
||
Used for FC_BOGUS_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
BOOL fSetPointerBufferMark;
|
||
PFORMAT_STRING pFormatPP;
|
||
|
||
//
|
||
// Setting this flag means that the array is not embedded inside of
|
||
// another complex struct or array.
|
||
//
|
||
pFormatPP = pFormat + 12;
|
||
CORRELATION_DESC_INCREMENT( pFormatPP );
|
||
CORRELATION_DESC_INCREMENT( pFormatPP );
|
||
|
||
fSetPointerBufferMark = (! pStubMsg->PointerBufferMark) &&
|
||
(*pFormatPP != FC_RP);
|
||
|
||
if ( fSetPointerBufferMark )
|
||
{
|
||
BOOL fOldIgnore;
|
||
ULONG_PTR MaxCountSave;
|
||
ulong Offset, ActualCount;
|
||
ulong BufferLenOffset;
|
||
|
||
//
|
||
// Save the current conformance and variance fields. The sizing
|
||
// routine can overwrite them.
|
||
//
|
||
MaxCountSave = pStubMsg->MaxCount;
|
||
Offset = pStubMsg->Offset;
|
||
ActualCount = pStubMsg->ActualCount;
|
||
|
||
fOldIgnore = pStubMsg->IgnoreEmbeddedPointers;
|
||
|
||
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
||
|
||
//
|
||
// Set BufferLength equal to the current buffer pointer, and then
|
||
// when we return from NdrComplexArrayBufferSize it will point to
|
||
// the location in the buffer where the pointers should be marshalled
|
||
// into.
|
||
// Instead of pointer, we now calculate pointer increment explicitly.
|
||
//
|
||
// Set the pointer alignment as a base.
|
||
|
||
BufferLenOffset = 0xf & PtrToUlong( pStubMsg->Buffer );
|
||
ulong BufferLengthSave = pStubMsg->BufferLength;
|
||
pStubMsg->BufferLength = BufferLenOffset;
|
||
|
||
NdrComplexArrayBufferSize( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Pointer increment including alignments.
|
||
BufferLenOffset = pStubMsg->BufferLength - BufferLenOffset;
|
||
|
||
//
|
||
// This is the buffer pointer to the position where embedded pointers
|
||
// will be marshalled.
|
||
//
|
||
pStubMsg->PointerBufferMark = pStubMsg->Buffer + BufferLenOffset;
|
||
pStubMsg->BufferLength = BufferLengthSave;
|
||
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
||
|
||
// Restore conformance and variance fields.
|
||
pStubMsg->MaxCount = MaxCountSave;
|
||
pStubMsg->Offset = Offset;
|
||
pStubMsg->ActualCount = ActualCount;
|
||
}
|
||
|
||
if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
|
||
( pStubMsg->pArrayInfo == 0 ) )
|
||
{
|
||
//
|
||
// Outer most dimension sets the conformance marker.
|
||
//
|
||
|
||
// Align the buffer for conformance marshalling.
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// Mark where the conformance count(s) will be marshalled.
|
||
pStubMsg->BufferMark = pStubMsg->Buffer;
|
||
|
||
// Increment past where the conformance will go.
|
||
pStubMsg->Buffer += NdrpArrayDimensions( pStubMsg, pFormat, FALSE ) * 4;
|
||
}
|
||
|
||
// Call the private marshalling routine to do all the work.
|
||
NdrpComplexArrayMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
if ( fSetPointerBufferMark )
|
||
{
|
||
//
|
||
// This will set the buffer pointer to end of all of the array's
|
||
// unmarshalled data in the buffer.
|
||
//
|
||
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
||
|
||
pStubMsg->PointerBufferMark = 0;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpComplexArrayMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine for marshalling a complex array. This is the entry
|
||
point for marshalling an embedded complex array.
|
||
|
||
Used for FC_BOGUS_ARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the array being marshalled.
|
||
pFormat - Array's format string description.
|
||
|
||
pStubMsg->Buffer - array pointer
|
||
pStubMsg->BufferMark - a place to marshal the conformant size
|
||
pStubMsg->BufferPointerMark - a place to marshal the pointees
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ARRAY_INFO ArrayInfo;
|
||
PARRAY_INFO pArrayInfo;
|
||
PMARSHALL_ROUTINE pfnMarshall;
|
||
PFORMAT_STRING pFormatStart;
|
||
uint Elements;
|
||
uint Offset, Count;
|
||
uint MemoryElementSize;
|
||
long Dimension;
|
||
uchar Alignment;
|
||
bool UseBrokenInterfacePointerRep = false;
|
||
|
||
//
|
||
// Lots of setup if we are the outer dimension. All this is for
|
||
// multidimensional array support. If we didn't have to worry about
|
||
// Beta2 stub compatability we could this much better.
|
||
//
|
||
//
|
||
if ( ! pStubMsg->pArrayInfo )
|
||
{
|
||
pStubMsg->pArrayInfo = &ArrayInfo;
|
||
|
||
ArrayInfo.Dimension = 0;
|
||
ArrayInfo.BufferConformanceMark = (unsigned long *) pStubMsg->BufferMark;
|
||
ArrayInfo.BufferVarianceMark = 0;
|
||
ArrayInfo.MaxCountArray = (ulong *) pStubMsg->MaxCount;
|
||
ArrayInfo.OffsetArray = (ulong *) UlongToPtr( pStubMsg->Offset );
|
||
ArrayInfo.ActualCountArray = (ulong *) UlongToPtr( pStubMsg->ActualCount );
|
||
}
|
||
|
||
pFormatStart = pFormat;
|
||
|
||
pArrayInfo = pStubMsg->pArrayInfo;
|
||
|
||
Dimension = pArrayInfo->Dimension;
|
||
|
||
// Get the array's alignment.
|
||
Alignment = pFormat[1];
|
||
|
||
pFormat += 2;
|
||
|
||
// Get number of elements (0 if the array has conformance).
|
||
Elements = *((ushort *&)pFormat)++;
|
||
|
||
//
|
||
// Check for conformance description.
|
||
//
|
||
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
||
{
|
||
Elements = (ulong) NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormatStart );
|
||
|
||
// Marshall this dimension's conformance count.
|
||
pArrayInfo->BufferConformanceMark[Dimension] = Elements;
|
||
}
|
||
|
||
pFormat += 4;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
//
|
||
// Check for variance description.
|
||
//
|
||
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
||
{
|
||
if ( Dimension == 0 )
|
||
{
|
||
//
|
||
// Set the variance marker.
|
||
//
|
||
|
||
ALIGN(pStubMsg->Buffer,0x3);
|
||
|
||
// Mark where the variance count(s) will be marshalled.
|
||
pArrayInfo->BufferVarianceMark = (unsigned long *) pStubMsg->Buffer;
|
||
|
||
// Increment past where the variance will go.
|
||
pStubMsg->Buffer +=
|
||
NdrpArrayDimensions( pStubMsg, pFormatStart, TRUE ) * 8;
|
||
}
|
||
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormatStart );
|
||
|
||
Offset = pStubMsg->Offset;
|
||
Count = pStubMsg->ActualCount;
|
||
|
||
//
|
||
// Marshall the outer dimension's variance.
|
||
//
|
||
pArrayInfo->BufferVarianceMark[Dimension * 2] = Offset;
|
||
pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1] = Count;
|
||
}
|
||
else
|
||
{
|
||
Offset = 0;
|
||
Count = Elements;
|
||
}
|
||
|
||
pFormat += 4;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
//
|
||
// Return if count is 0.
|
||
//
|
||
if ( ! Count )
|
||
goto ComplexArrayMarshallEnd;
|
||
|
||
// Align on array's alignment.
|
||
ALIGN(pStubMsg->Buffer,Alignment);
|
||
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_EMBEDDED_COMPLEX :
|
||
pFormat += 2;
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
if ( FC_IP == *pFormat )
|
||
goto HandleInterfacePointer;
|
||
|
||
// Get the proper marshalling routine.
|
||
pfnMarshall = pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)];
|
||
|
||
pArrayInfo->Dimension = Dimension + 1;
|
||
|
||
// Compute the size of an array element.
|
||
MemoryElementSize = (uint) (NdrpMemoryIncrement( pStubMsg,
|
||
pMemory,
|
||
pFormat ) - pMemory);
|
||
break;
|
||
|
||
case FC_RP :
|
||
case FC_UP :
|
||
case FC_FP :
|
||
case FC_OP :
|
||
pfnMarshall = (PMARSHALL_ROUTINE) NdrpPointerMarshall;
|
||
|
||
// Need this in case we have a variant offset.
|
||
MemoryElementSize = PTR_MEM_SIZE;
|
||
break;
|
||
|
||
case FC_IP :
|
||
HandleInterfacePointer:
|
||
UseBrokenInterfacePointerRep = !FixWireRepForDComVerGTE54( pStubMsg );
|
||
|
||
// Probably does not exercise this code path, for IP the compiler
|
||
// generates embedded complex as an array element.
|
||
//
|
||
pfnMarshall = (PMARSHALL_ROUTINE) NdrpPointerMarshall;
|
||
|
||
// Need this in case we have a variant offset.
|
||
MemoryElementSize = PTR_MEM_SIZE;
|
||
break;
|
||
|
||
case FC_ENUM16 :
|
||
pfnMarshall = 0;
|
||
|
||
// Need this in case we have a variant offset.
|
||
MemoryElementSize = sizeof(int);
|
||
break;
|
||
|
||
#if defined(__RPC_WIN64__)
|
||
case FC_INT3264:
|
||
case FC_UINT3264:
|
||
pfnMarshall = 0;
|
||
MemoryElementSize = sizeof(__int64);
|
||
break;
|
||
#endif
|
||
case FC_RANGE:
|
||
// let's just memcpy in marshalling phase: don't need to check value here.
|
||
Count *= SIMPLE_TYPE_BUFSIZE( pFormat[1] );
|
||
pMemory += Offset * SIMPLE_TYPE_MEMSIZE( pFormat[1] );
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
Count );
|
||
|
||
pStubMsg->Buffer += Count;
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
|
||
"NdrpComplexArrayMarshall : bad format char" );
|
||
|
||
Count *= SIMPLE_TYPE_BUFSIZE(*pFormat);
|
||
|
||
pMemory += Offset * SIMPLE_TYPE_MEMSIZE(*pFormat);
|
||
|
||
RpcpMemoryCopy( pStubMsg->Buffer,
|
||
pMemory,
|
||
Count );
|
||
|
||
pStubMsg->Buffer += Count;
|
||
|
||
goto ComplexArrayMarshallEnd;
|
||
}
|
||
|
||
//
|
||
// If there is variance then increment the memory pointer to the first
|
||
// element actually being marshalled.
|
||
//
|
||
if ( Offset )
|
||
pMemory += Offset * MemoryElementSize;
|
||
|
||
//
|
||
// Array of enum16 or int3264.
|
||
//
|
||
if ( ! pfnMarshall )
|
||
{
|
||
#if defined(__RPC_WIN64__)
|
||
if ( *pFormat != FC_ENUM16 )
|
||
{
|
||
for ( ; Count--; )
|
||
*((long * &)pStubMsg->Buffer)++ = (long)*((INT64 * &)pMemory)++;
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
for ( ; Count--; )
|
||
{
|
||
if ( *((int *)pMemory) & ~((int)0x7fff) )
|
||
RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
|
||
|
||
*((ushort *&)pStubMsg->Buffer)++ = (ushort) *((int *&)pMemory)++;
|
||
}
|
||
}
|
||
|
||
goto ComplexArrayMarshallEnd;
|
||
}
|
||
|
||
//
|
||
// For 32b, an array of ref or interface pointers.
|
||
// For 64b, an array of any pointers.
|
||
//
|
||
if ( pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall )
|
||
{
|
||
pStubMsg->pArrayInfo = 0;
|
||
|
||
uchar * pPointerId = (*pFormat == FC_RP) ? 0 : pStubMsg->Buffer;
|
||
|
||
if ( UseBrokenInterfacePointerRep )
|
||
{
|
||
// If were using the broken array format, do no increment the
|
||
// buffer pointer for the flat part, and throw everything
|
||
// where the pointee should go.
|
||
SET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
|
||
|
||
POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
|
||
for ( ; Count--; )
|
||
{
|
||
|
||
// This effectively calls NdrInterfacePointerMarshall. Doinging
|
||
// this so another queue structure/callback isn't needed just for
|
||
// this rare code.
|
||
NdrpPointerMarshall(
|
||
pStubMsg,
|
||
pPointerId,
|
||
*((uchar **&)pMemory)++,
|
||
pFormat );
|
||
pPointerId += PTR_WIRE_SIZE;
|
||
}
|
||
RESET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
|
||
}
|
||
|
||
else
|
||
{
|
||
{
|
||
POINTER_BUFFER_SWAP_CONTEXT NewContext(pStubMsg);
|
||
for ( ; Count--; )
|
||
{
|
||
|
||
NdrpPointerMarshall(
|
||
pStubMsg,
|
||
pPointerId,
|
||
*((uchar **&)pMemory)++,
|
||
pFormat );
|
||
//
|
||
// Needed only for non ref pointers, but pPointerIds is not used for refs.
|
||
//
|
||
pPointerId += PTR_WIRE_SIZE;
|
||
}
|
||
}
|
||
|
||
// Increment buffer pointer past the flat part of the array.
|
||
if ( *pFormat != FC_RP )
|
||
pStubMsg->Buffer = pPointerId;
|
||
|
||
}
|
||
|
||
|
||
goto ComplexArrayMarshallEnd;
|
||
}
|
||
|
||
//
|
||
// It's an array of complex types.
|
||
//
|
||
|
||
if ( ! IS_ARRAY_OR_STRING(*pFormat) )
|
||
pStubMsg->pArrayInfo = 0;
|
||
|
||
// Marshall the array elements.
|
||
for ( ; Count--; )
|
||
{
|
||
// Keep track of multidimensional array dimension.
|
||
if ( IS_ARRAY_OR_STRING(*pFormat) )
|
||
pArrayInfo->Dimension = Dimension + 1;
|
||
|
||
(*pfnMarshall)( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Increment the memory pointer by the element size.
|
||
pMemory += MemoryElementSize;
|
||
}
|
||
|
||
ComplexArrayMarshallEnd:
|
||
|
||
// pArrayInfo must be zero when not valid.
|
||
pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrEncapsulatedUnionMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls an encapsulated union.
|
||
|
||
Used for FC_ENCAPSULATED_UNION.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the union being marshalled.
|
||
pFormat - Union's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long SwitchIs;
|
||
uchar SwitchType;
|
||
|
||
NO_CORRELATION;
|
||
|
||
SwitchType = LOW_NIBBLE(pFormat[1]);
|
||
|
||
switch ( SwitchType )
|
||
{
|
||
case FC_SMALL :
|
||
case FC_CHAR :
|
||
SwitchIs = (long) *((char *)pMemory);
|
||
break;
|
||
case FC_USMALL :
|
||
SwitchIs = (long) *((uchar *)pMemory);
|
||
break;
|
||
|
||
case FC_ENUM16 :
|
||
case FC_SHORT :
|
||
SwitchIs = (long) *((short *)pMemory);
|
||
break;
|
||
|
||
case FC_USHORT :
|
||
case FC_WCHAR :
|
||
SwitchIs = (long) *((ushort *)pMemory);
|
||
break;
|
||
case FC_LONG :
|
||
case FC_ULONG :
|
||
case FC_ENUM32 :
|
||
// FC_INT3264 gets mapped to FC_LONG
|
||
SwitchIs = *((long *)pMemory);
|
||
break;
|
||
default :
|
||
NDR_ASSERT(0,"NdrEncapsulatedUnionMarshall : bad swith type");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return 0;
|
||
}
|
||
|
||
// Increment the memory pointer to the union.
|
||
pMemory += HIGH_NIBBLE(pFormat[1]);
|
||
|
||
NdrpUnionMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat + 2,
|
||
SwitchIs,
|
||
SwitchType );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrNonEncapsulatedUnionMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a non encapsulated union.
|
||
|
||
Used for FC_NON_ENCAPSULATED_UNION.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the union being marshalled.
|
||
pFormat - Union's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long SwitchIs;
|
||
uchar SwitchType;
|
||
|
||
SwitchType = pFormat[1];
|
||
|
||
SwitchIs = (ulong) NdrpComputeSwitchIs( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
//
|
||
// Set the format string to the memory size and arm description.
|
||
//
|
||
pFormat += 6;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
NdrpUnionMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
SwitchIs,
|
||
SwitchType );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpUnionMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat,
|
||
long SwitchIs,
|
||
uchar SwitchType )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine for marshalling a union. This routine is shared for
|
||
both encapsulated and non-encapsulated unions and handles the actual
|
||
marshalling of the proper union arm.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the union being marshalled.
|
||
pFormat - The memory size and arm description portion of the format
|
||
string for the union.
|
||
SwitchIs - Union's switch is.
|
||
SwitchType - Union's switch is type.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long Arms;
|
||
uchar Alignment;
|
||
|
||
// Marshall the switch is value.
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
(uchar *)&SwitchIs,
|
||
SwitchType );
|
||
|
||
// Skip the memory size field.
|
||
pFormat += 2;
|
||
|
||
//
|
||
// We're at the union_arms<2> field now, which contains both the
|
||
// Microsoft union aligment value and the number of union arms.
|
||
//
|
||
|
||
//
|
||
// Get the union alignment (0 if this is a DCE union).
|
||
//
|
||
Alignment = (uchar) ( *((ushort *)pFormat) >> 12 );
|
||
|
||
ALIGN(pStubMsg->Buffer,Alignment);
|
||
|
||
//
|
||
// Number of arms is the lower 12 bits.
|
||
//
|
||
Arms = (long) ( *((ushort *&)pFormat)++ & 0x0fff);
|
||
|
||
//
|
||
// Search for the correct arm.
|
||
//
|
||
for ( ; Arms; Arms-- )
|
||
{
|
||
if ( *((long UNALIGNED *&)pFormat)++ == SwitchIs )
|
||
{
|
||
//
|
||
// Found the right arm, break out.
|
||
//
|
||
break;
|
||
}
|
||
|
||
// Else increment format string.
|
||
pFormat += 2;
|
||
}
|
||
|
||
//
|
||
// Check if we took the default arm and no default arm is specified.
|
||
//
|
||
if ( ! Arms && (*((ushort *)pFormat) == (ushort) 0xffff) )
|
||
{
|
||
RpcRaiseException( RPC_S_INVALID_TAG );
|
||
}
|
||
|
||
//
|
||
// Return if the arm is empty.
|
||
//
|
||
if ( ! *((ushort *)pFormat) )
|
||
return;
|
||
|
||
//
|
||
// Get the arm's description.
|
||
//
|
||
// We need a real solution after beta for simple type arms. This could
|
||
// break if we have a format string larger than about 32K.
|
||
//
|
||
if ( IS_MAGIC_UNION_BYTE(pFormat) )
|
||
{
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat[0] );
|
||
|
||
return;
|
||
}
|
||
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
//
|
||
// If the union arm we take is a pointer, we have to dereference the
|
||
// current memory pointer since we're passed a pointer to the union
|
||
// (regardless of whether the actual parameter was a by-value union
|
||
// or a pointer to a union).
|
||
//
|
||
// We also have to do a bunch of other special stuff to handle unions
|
||
// embedded inside of strutures.
|
||
//
|
||
if ( IS_POINTER_TYPE(*pFormat) )
|
||
{
|
||
pMemory = *((uchar **)pMemory);
|
||
|
||
//
|
||
// If we're embedded in a struct or array we have do some extra stuff.
|
||
//
|
||
if ( pStubMsg->PointerBufferMark )
|
||
{
|
||
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
uchar *pPointerId = pStubMsg->Buffer;
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
|
||
POINTER_BUFFER_SWAP_CONTEXT SwapContext( pStubMsg );
|
||
|
||
NdrpPointerMarshall( pStubMsg,
|
||
pPointerId,
|
||
pMemory,
|
||
pFormat );
|
||
return;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Union arm of a non-simple type.
|
||
//
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
|
||
( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrByteCountPointerMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a pointer with the byte count attribute applied to it.
|
||
|
||
Used for FC_BYTE_COUNT_POINTER.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the byte count pointer being marshalled.
|
||
pFormat - Byte count pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// We don't do anything special here. Just pass things on to the
|
||
// right marshalling routine.
|
||
//
|
||
if ( pFormat[1] != FC_PAD )
|
||
{
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat[1] );
|
||
}
|
||
else
|
||
{
|
||
pFormat += 6;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrXmitOrRepAsMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a transmit as or represent as argument:
|
||
- translate the presented object into a transmitted object
|
||
- marshall the transmitted object
|
||
- free the transmitted object
|
||
|
||
Format string layout:
|
||
|
||
0 FC_TRANSMIT_AS or FC_REPRESENT_AS
|
||
Oi array flag/alignment<1>
|
||
+2 quintuple index<2>
|
||
+4 pres type mem size<2>
|
||
+6 tran type buf size<2>
|
||
+8 offset<2>
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - a pointer to the stub message
|
||
pMemory - presented type translated into transmitted type
|
||
and than to be marshalled
|
||
pFormat - format string description
|
||
|
||
--*/
|
||
{
|
||
unsigned char * pTransmittedType;
|
||
const XMIT_ROUTINE_QUINTUPLE * pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
|
||
unsigned short QIndex;
|
||
BOOL fXmitByPtr = *pFormat == FC_TRANSMIT_AS_PTR ||
|
||
*pFormat == FC_REPRESENT_AS_PTR;
|
||
|
||
// Skip the token itself and Oi flag. Fetch the QuintupleIndex.
|
||
|
||
QIndex = *(unsigned short *)(pFormat + 2);
|
||
|
||
// First translate the presented type into the transmitted type.
|
||
// This includes an allocation of a transmitted type object.
|
||
|
||
pStubMsg->pPresentedType = pMemory;
|
||
pStubMsg->pTransmitType = NULL;
|
||
pQuintuple[ QIndex ].pfnTranslateToXmit( pStubMsg );
|
||
|
||
// Marshall the transmitted type.
|
||
|
||
pFormat += 8;
|
||
pFormat = pFormat + *(short *) pFormat;
|
||
|
||
pTransmittedType = pStubMsg->pTransmitType;
|
||
if ( IS_SIMPLE_TYPE( *pFormat ))
|
||
{
|
||
NdrSimpleTypeMarshall( pStubMsg,
|
||
pTransmittedType,
|
||
*pFormat );
|
||
}
|
||
else
|
||
{
|
||
uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
|
||
pStubMsg->PointerBufferMark = 0;
|
||
NDR_POINTER_QUEUE *pOldQueue = NULL;
|
||
|
||
// Reset the current queue to NULL so that all the pointers
|
||
// in the transmitted type will be queued and marshalled togother.
|
||
if ( pStubMsg->pPointerQueueState )
|
||
{
|
||
pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
|
||
pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
|
||
}
|
||
|
||
RpcTryFinally
|
||
{
|
||
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
|
||
( pStubMsg,
|
||
fXmitByPtr ? *(uchar **)pTransmittedType
|
||
: pTransmittedType,
|
||
pFormat );
|
||
}
|
||
RpcFinally
|
||
{
|
||
pStubMsg->PointerBufferMark = PointerBufferMarkSave;
|
||
if ( pStubMsg->pPointerQueueState )
|
||
{
|
||
pStubMsg->pPointerQueueState->SetActiveQueue( pOldQueue );
|
||
}
|
||
}
|
||
RpcEndFinally
|
||
}
|
||
pStubMsg->pTransmitType = pTransmittedType;
|
||
|
||
// Free the temporary transmitted object (it was allocated by the user).
|
||
|
||
pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpUserMarshalMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat,
|
||
unsigned long * pWireMarkerPtr )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshals a usr_marshall object.
|
||
|
||
The format string layout is as follows:
|
||
|
||
FC_USER_MARSHAL
|
||
flags & alignment<1>
|
||
quadruple index<2>
|
||
memory size<2>
|
||
wire size<2>
|
||
type offset<2>
|
||
|
||
The wire layout description is at the type offset.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the usr_marshall object to marshall.
|
||
pFormat - Object's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
|
||
unsigned short QIndex;
|
||
unsigned char * pUserBuffer;
|
||
USER_MARSHAL_CB UserMarshalCB;
|
||
unsigned char * pUserBufferSaved;
|
||
|
||
pUserBufferSaved = pUserBuffer = pStubMsg->Buffer;
|
||
|
||
// We always call user's routine to marshall.
|
||
NdrpInitUserMarshalCB( pStubMsg,
|
||
pFormat,
|
||
USER_MARSHAL_CB_MARSHALL,
|
||
& UserMarshalCB );
|
||
|
||
QIndex = *(unsigned short *)(pFormat + 2);
|
||
pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
|
||
|
||
if ((pUserBufferSaved < (uchar *) pStubMsg->RpcMsg->Buffer) ||
|
||
((unsigned long) (pUserBufferSaved - (uchar *) pStubMsg->RpcMsg->Buffer)
|
||
> pStubMsg->RpcMsg->BufferLength))
|
||
{
|
||
RpcRaiseException( RPC_X_INVALID_BUFFER );
|
||
}
|
||
|
||
pUserBuffer = pQuadruple[ QIndex ].pfnMarshall( (ulong*) &UserMarshalCB,
|
||
pUserBuffer,
|
||
pMemory );
|
||
|
||
if ((pUserBufferSaved > pUserBuffer) ||
|
||
((unsigned long) (pUserBuffer - (uchar *) pStubMsg->RpcMsg->Buffer)
|
||
> pStubMsg->RpcMsg->BufferLength ))
|
||
{
|
||
RpcRaiseException( RPC_X_INVALID_BUFFER );
|
||
}
|
||
|
||
if ( pUserBuffer == pUserBufferSaved )
|
||
{
|
||
// This is valid only if the wire type was a unique type.
|
||
|
||
if ( (pFormat[1] & USER_MARSHAL_UNIQUE) )
|
||
{
|
||
*pWireMarkerPtr = 0;
|
||
return;
|
||
}
|
||
else
|
||
RpcRaiseException( RPC_X_NULL_REF_POINTER );
|
||
}
|
||
|
||
pStubMsg->Buffer = pUserBuffer;
|
||
return;
|
||
}
|
||
|
||
void
|
||
NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
|
||
{
|
||
NdrpUserMarshalMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
pWireMarkerPtr );
|
||
}
|
||
|
||
#if defined(DBG)
|
||
void
|
||
NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT::Print()
|
||
{
|
||
DbgPrint("NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT\n");
|
||
DbgPrint("pMemory: %p\n", pMemory );
|
||
DbgPrint("pFormat: %p\n", pFormat );
|
||
DbgPrint("pWireMarkerPtr: %p\n", pWireMarkerPtr );
|
||
}
|
||
#endif
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrUserMarshalMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
|
||
unsigned long * pWireMarkerPtr = 0;
|
||
// Align for the object or a pointer to it.
|
||
|
||
ALIGN( pStubMsg->Buffer, LOW_NIBBLE(pFormat[1]) );
|
||
|
||
if ( pFormat[1] & USER_MARSHAL_POINTER )
|
||
{
|
||
|
||
if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
|
||
((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
|
||
{
|
||
pWireMarkerPtr = (unsigned long *) pStubMsg->Buffer;
|
||
*((unsigned long *&)pStubMsg->Buffer)++ = USER_MARSHAL_MARKER;
|
||
}
|
||
|
||
if ( !pStubMsg->pPointerQueueState ||
|
||
!pStubMsg->pPointerQueueState->GetActiveQueue() )
|
||
{
|
||
// If we are embedded, switch to the pointee buffer.
|
||
POINTER_BUFFER_SWAP_CONTEXT SwapContext(pStubMsg);
|
||
|
||
NdrpUserMarshalMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
pWireMarkerPtr );
|
||
}
|
||
else
|
||
{
|
||
NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT*pElement =
|
||
new(pStubMsg->pPointerQueueState)
|
||
NDR_USR_MRSHL_MRSHL_POINTER_QUEUE_ELEMENT(pMemory,
|
||
pFormat,
|
||
pWireMarkerPtr);
|
||
pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
NdrpUserMarshalMarshall( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
pWireMarkerPtr );
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
unsigned char *
|
||
NdrpInterfacePointerMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls an interface pointer.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the interface pointer being marshalled.
|
||
pFormat - Interface pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
Notes : There is now one representation of a marshalled interface pointer.
|
||
The format string contains FC_IP followed by either
|
||
FC_CONSTANT_IID or FC_PAD.
|
||
|
||
typedef struct
|
||
{
|
||
unsigned long size;
|
||
[size_is(size)] byte data[];
|
||
}MarshalledInterface;
|
||
|
||
--*/
|
||
{
|
||
HRESULT hr;
|
||
IID iid;
|
||
IID * piid;
|
||
unsigned long * pSize;
|
||
unsigned long * pMaxCount;
|
||
unsigned long cbData = 0;
|
||
unsigned long cbMax;
|
||
unsigned long position;
|
||
IStream * pStream;
|
||
LARGE_INTEGER libMove;
|
||
ULARGE_INTEGER libPosition;
|
||
|
||
ALIGN(pStubMsg->Buffer,0x3);
|
||
//
|
||
// Get an IID pointer.
|
||
//
|
||
if ( pFormat[1] != FC_CONSTANT_IID )
|
||
{
|
||
//
|
||
// This is like computing a variance with a long.
|
||
//
|
||
|
||
piid = (IID *) NdrpComputeIIDPointer( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
if(piid == 0)
|
||
RpcRaiseException( RPC_S_INVALID_ARG );
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// The IID may not be aligned properly in the format string,
|
||
// so we copy it to a local variable.
|
||
//
|
||
|
||
piid = &iid;
|
||
RpcpMemoryCopy( &iid, &pFormat[2], sizeof(iid) );
|
||
}
|
||
|
||
// Leave space in the buffer for the conformant size and the size field.
|
||
|
||
pMaxCount = (unsigned long *) pStubMsg->Buffer;
|
||
pStubMsg->Buffer += sizeof(unsigned long);
|
||
|
||
pSize = (unsigned long *) pStubMsg->Buffer;
|
||
pStubMsg->Buffer += sizeof(unsigned long);
|
||
|
||
if(pMemory)
|
||
{
|
||
|
||
//Calculate the maximum size of the stream.
|
||
|
||
position = (ulong)( pStubMsg->Buffer - (uchar *)pStubMsg->RpcMsg->Buffer);
|
||
cbMax = pStubMsg->RpcMsg->BufferLength - position;
|
||
|
||
#if defined(DEBUG_WALKIP)
|
||
{
|
||
CHAR AppName[MAX_PATH];
|
||
memset(AppName, 0, sizeof(AppName ) );
|
||
GetModuleFileNameA( NULL, AppName, sizeof(AppName ) );
|
||
DbgPrint("MRSHL32 %s %p\n", AppName, pStubMsg->Buffer );
|
||
}
|
||
#endif
|
||
|
||
//Create a stream on memory.
|
||
|
||
pStream = NdrpCreateStreamOnMemory(pStubMsg->Buffer, cbMax);
|
||
if(pStream == 0)
|
||
RpcRaiseException(RPC_S_OUT_OF_MEMORY);
|
||
|
||
hr = (*pfnCoMarshalInterface)(pStream, *piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
|
||
if(FAILED(hr))
|
||
{
|
||
pStream->Release();
|
||
pStream = 0;
|
||
RpcRaiseException(hr);
|
||
}
|
||
|
||
//Calculate the size of the data written
|
||
|
||
libMove.LowPart = 0;
|
||
libMove.HighPart = 0;
|
||
pStream->Seek(libMove, STREAM_SEEK_CUR, &libPosition);
|
||
pStream->Release();
|
||
pStream = 0;
|
||
cbData = libPosition.LowPart;
|
||
}
|
||
|
||
//Update the array bounds.
|
||
|
||
*pMaxCount = cbData;
|
||
*pSize = cbData;
|
||
|
||
//Advance the stub message buffer pointer.
|
||
pStubMsg->Buffer += cbData;
|
||
|
||
return 0;
|
||
}
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrInterfacePointerMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
|
||
// Always put the pointer itself on wire, it behaves like a unique.
|
||
//
|
||
|
||
// This function is only called for toplevel interface pointers with Os mode,
|
||
// or when being backward compatible with the incorrect wire format.
|
||
// Oicf uses NdrPointerMarshall.
|
||
|
||
ALIGN(pStubMsg->Buffer,0x3);
|
||
*((ulong *&)pStubMsg->Buffer)++ = PTR_WIRE_REP(pMemory);
|
||
|
||
// If the pointer is null, it's done.
|
||
|
||
if ( pMemory == 0 )
|
||
return 0;
|
||
|
||
|
||
return
|
||
NdrpInterfacePointerMarshall(
|
||
pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
|
||
//
|
||
// Context handle marshalling routines.
|
||
//
|
||
|
||
void RPC_ENTRY
|
||
NdrClientContextMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
NDR_CCONTEXT ContextHandle,
|
||
int fCheck )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a context handle on the client side.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to stub message.
|
||
ContextHandle - Context handle to marshall.
|
||
fCheck - TRUE if an exception check should be made on the handle,
|
||
FALSE otherwise.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
// Note, this is a routine called directly from -Os stubs.
|
||
// The routine called by interpreter is called NdrMarshallHandle
|
||
// and can be found in hndl.c
|
||
|
||
if ( fCheck && ! ContextHandle )
|
||
RpcRaiseException( RPC_X_SS_IN_NULL_CONTEXT );
|
||
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
// This call will check for bogus handles now and will raise
|
||
// an exception when necessary.
|
||
|
||
NDRCContextMarshall( ContextHandle, pStubMsg->Buffer );
|
||
|
||
pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
|
||
}
|
||
|
||
void RPC_ENTRY
|
||
NdrServerContextMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
NDR_SCONTEXT ContextHandle,
|
||
NDR_RUNDOWN RundownRoutine )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a context handle on the server side.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to stub message.
|
||
ContextHandle - Context handle to marshall.
|
||
RundownRoutine - The context rundown routine.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
// Note, this is a routine called directly from -Os stubs.
|
||
// The routine called by interpreter is called NdrMarshallHandle
|
||
// and can be found in hndl.c
|
||
|
||
ALIGN(pStubMsg->Buffer,3);
|
||
|
||
NDRSContextMarshall2(pStubMsg->RpcMsg->Handle,
|
||
ContextHandle,
|
||
pStubMsg->Buffer,
|
||
RundownRoutine,
|
||
RPC_CONTEXT_HANDLE_DEFAULT_GUARD,
|
||
RPC_CONTEXT_HANDLE_DEFAULT_FLAGS );
|
||
|
||
pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
|
||
}
|
||
|
||
void RPC_ENTRY
|
||
NdrServerContextNewMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
NDR_SCONTEXT ContextHandle,
|
||
NDR_RUNDOWN RundownRoutine,
|
||
PFORMAT_STRING pFormat )
|
||
/*
|
||
This is a non-optimized NDR engine entry for context handle marshaling.
|
||
In particular it is able to handle all the new NT5 context handle flavors.
|
||
The optimized routine follows below.
|
||
|
||
ContextHandle - note, this is not the user's handle but a
|
||
NDR_SCONTEXT pointer from the stub local stack.
|
||
User's handle is a field in that object.
|
||
|
||
Note that intepreter calls NdrMarshallHandle. However, we can't use it
|
||
as it assumes a helper array of saved context handles that we don't need.
|
||
|
||
*/
|
||
{
|
||
void * pGuard = RPC_CONTEXT_HANDLE_DEFAULT_GUARD;
|
||
DWORD Flags = RPC_CONTEXT_HANDLE_DEFAULT_FLAGS;
|
||
|
||
// NT5 beta2 features: strict context handle, serialize and noserialize.
|
||
|
||
if ( pFormat[1] & NDR_STRICT_CONTEXT_HANDLE )
|
||
{
|
||
pGuard = pStubMsg->StubDesc->RpcInterfaceInformation;
|
||
pGuard = & ((PRPC_SERVER_INTERFACE)pGuard)->InterfaceId;
|
||
}
|
||
if ( pFormat[1] & NDR_CONTEXT_HANDLE_NOSERIALIZE )
|
||
{
|
||
Flags = RPC_CONTEXT_HANDLE_DONT_SERIALIZE;
|
||
}
|
||
else if ( pFormat[1] & NDR_CONTEXT_HANDLE_SERIALIZE )
|
||
{
|
||
Flags = RPC_CONTEXT_HANDLE_SERIALIZE;
|
||
}
|
||
|
||
ALIGN( pStubMsg->Buffer, 0x3 );
|
||
|
||
NDRSContextMarshall2(
|
||
pStubMsg->RpcMsg->Handle,
|
||
ContextHandle,
|
||
pStubMsg->Buffer,
|
||
RundownRoutine,
|
||
pGuard,
|
||
Flags );
|
||
|
||
pStubMsg->Buffer += CONTEXT_HANDLE_WIRE_SIZE;
|
||
}
|
||
|
||
|
||
void
|
||
NdrpGetArraySizeLength (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat,
|
||
long ElementSize,
|
||
long * pSize,
|
||
long * pLength,
|
||
long * pWireSize )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Return the size and length of an array.
|
||
|
||
We need to have this routine rather than just calling BufferSize since
|
||
we need the actual length of the array, not the length plus whatever
|
||
goop the NDR format puts in from of it.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the local array.
|
||
pFormat - Pointer to the array to get the size of.
|
||
|
||
Return :
|
||
|
||
The size and length.
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
{
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_SMFARRAY:
|
||
*pWireSize = * (short *) ( pFormat + 2 );
|
||
*pSize = *pWireSize;
|
||
*pLength = *pSize;
|
||
return;
|
||
|
||
case FC_LGFARRAY:
|
||
*pWireSize = * (int *) ( pFormat + 2 );
|
||
*pSize = *pWireSize;
|
||
*pLength = *pSize;
|
||
return;
|
||
|
||
case FC_CARRAY:
|
||
*pSize = (long) NdrpComputeConformance( pStubMsg, pMemory, pFormat );
|
||
*pWireSize = *pLength * ElementSize;
|
||
*pLength = *pSize;
|
||
return;
|
||
|
||
case FC_LGVARRAY:
|
||
*pWireSize = * (long *) ( pFormat + 2 );
|
||
*pSize = * (short *) ( pFormat + 6 );
|
||
NdrpComputeVariance( pStubMsg, pMemory, pFormat );
|
||
*pLength = pStubMsg->ActualCount;
|
||
return;
|
||
|
||
case FC_SMVARRAY:
|
||
*pWireSize = * (short *) ( pFormat + 2 );
|
||
*pSize = * (short *) ( pFormat + 4 );
|
||
NdrpComputeVariance( pStubMsg, pMemory, pFormat );
|
||
*pLength = pStubMsg->ActualCount;
|
||
return;
|
||
|
||
case FC_CVARRAY:
|
||
*pSize = (long) NdrpComputeConformance( pStubMsg, pMemory, pFormat );
|
||
*pWireSize = *pSize * ElementSize;
|
||
NdrpComputeVariance( pStubMsg, pMemory, pFormat );
|
||
*pLength = pStubMsg->ActualCount;
|
||
return;
|
||
|
||
case FC_CSTRING:
|
||
*pSize = strlen( (char*)pMemory ) + 1;
|
||
*pWireSize = *pSize;
|
||
*pLength = *pSize;
|
||
return;
|
||
|
||
case FC_WSTRING:
|
||
*pSize = wcslen( (wchar_t *) pMemory ) + 1;
|
||
*pWireSize = *pSize * 2;
|
||
*pLength = *pSize;
|
||
return;
|
||
}
|
||
|
||
NDR_ASSERT( 0, "NdrpGetArraySizeLength: Unhandled type" );
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
*pSize = 0;
|
||
*pWireSize = 0;
|
||
*pLength = 0;
|
||
}
|
||
|
||
|
||
#ifdef _CS_CHAR_
|
||
unsigned char * RPC_ENTRY
|
||
NdrCsTagMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a cs tag (i.e. a parameter marked with [cs_stag], [cs_drtag],
|
||
or [cs_rtag].
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the value on the stack.
|
||
pFormat - Pointer to the FC_CS_TAG entry in the format string.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ulong Codeset = NdrpGetSetCSTagMarshall(
|
||
pStubMsg,
|
||
pMemory,
|
||
(NDR_CS_TAG_FORMAT *) pFormat);
|
||
|
||
* (ulong *) pStubMsg->Buffer = Codeset;
|
||
pStubMsg->Buffer += sizeof( ulong );
|
||
|
||
return 0;
|
||
}
|
||
|
||
extern const byte NdrpArrayMarshallFlags[] =
|
||
{
|
||
MARSHALL_CONFORMANCE, // Conformant array
|
||
MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant varying
|
||
0, // Small fixed
|
||
0, // Large fixed
|
||
MARSHALL_VARIANCE, // Small varying
|
||
MARSHALL_VARIANCE, // Large varying
|
||
MARSHALL_BOGUS, // Bogus array
|
||
MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant C string
|
||
MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant byte string
|
||
MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant struct string
|
||
MARSHALL_CONFORMANCE | MARSHALL_VARIANCE, // Conformant Unicode string
|
||
MARSHALL_VARIANCE, // C string
|
||
MARSHALL_VARIANCE, // byte string
|
||
MARSHALL_VARIANCE, // struct string
|
||
MARSHALL_VARIANCE // Unicode string
|
||
};
|
||
|
||
|
||
|
||
void
|
||
NdrpUpdateArrayProlog(
|
||
PFORMAT_STRING pFormat,
|
||
uchar * BufferMark,
|
||
ulong WireSize,
|
||
ulong Offset,
|
||
ulong WireLength )
|
||
{
|
||
int flags;
|
||
|
||
NDR_ASSERT( *pFormat >= FC_CARRAY, "Invalid array descriptor" );
|
||
NDR_ASSERT( *pFormat <= FC_WSTRING, "Invalid array descriptor" );
|
||
|
||
// We don't support bogus arrays for now
|
||
NDR_ASSERT( *pFormat != FC_BOGUS_ARRAY, "Bogus arrays are not supported" );
|
||
|
||
flags = NdrpArrayMarshallFlags[ *pFormat - FC_CARRAY ];
|
||
|
||
if ( flags & MARSHALL_CONFORMANCE )
|
||
{
|
||
* (ulong *) BufferMark = WireSize;
|
||
BufferMark += 4;
|
||
}
|
||
|
||
if ( flags & MARSHALL_VARIANCE )
|
||
{
|
||
* (ulong *) BufferMark = Offset;
|
||
BufferMark += 4;
|
||
* (ulong *) BufferMark = WireLength;
|
||
}
|
||
}
|
||
|
||
|
||
unsigned char * RPC_ENTRY
|
||
NdrCsArrayMarshall (
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Marshalls a [cs_char] array.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to the local array.
|
||
pFormat - Pointer to the FC_CSARRAY entry in the format string.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
Notes :
|
||
|
||
Arrays of [cs_char] are defined as arrays of bytes on the wire so
|
||
marshalling is pretty simple once you know which bytes to marshall and
|
||
how many of them. Since the existing array marshalling routines are not
|
||
very general (they don't take size/length parameters) and since the
|
||
overhead of a call to memcpy isn't very high we do the marshalling
|
||
ourselves.
|
||
|
||
--*/
|
||
{
|
||
ulong SendingCodeset;
|
||
ulong ReceivingCodeset;
|
||
ulong ArraySize;
|
||
ulong ArrayLength;
|
||
ulong WireSize;
|
||
ulong WireLength;
|
||
uchar *BufferMark;
|
||
error_status_t status;
|
||
|
||
NDR_CS_ARRAY_FORMAT *pCSFormat;
|
||
NDR_CS_SIZE_CONVERT_ROUTINES *CSRoutines;
|
||
CS_TYPE_NET_SIZE_ROUTINE NetSizeRoutine;
|
||
CS_TYPE_TO_NETCS_ROUTINE ToNetCSRoutine;
|
||
IDL_CS_CONVERT ConversionType;
|
||
|
||
pCSFormat = (NDR_CS_ARRAY_FORMAT *) pFormat;
|
||
|
||
// Get all the info out of the FC_CS_ARRAY structure and bump pFormat
|
||
// to point to the underlying data descriptor
|
||
|
||
NDR_ASSERT( NULL != pStubMsg->pCSInfo, "cs_char info is not set up");
|
||
|
||
if ( pStubMsg->IsClient )
|
||
SendingCodeset = pStubMsg->pCSInfo->WireCodeset;
|
||
else
|
||
SendingCodeset = pStubMsg->pCSInfo->DesiredReceivingCodeset;
|
||
|
||
CSRoutines = pStubMsg->StubDesc->CsRoutineTables->pSizeConvertRoutines;
|
||
|
||
NetSizeRoutine = CSRoutines[pCSFormat->CSRoutineIndex].pfnNetSize;
|
||
ToNetCSRoutine = CSRoutines[pCSFormat->CSRoutineIndex].pfnToNetCs;
|
||
|
||
pFormat += pCSFormat->DescriptionOffset;
|
||
|
||
// Get the size and length of the unconverted array.
|
||
|
||
NdrpGetArraySizeLength( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
pCSFormat->UserTypeSize,
|
||
(long*)&ArraySize,
|
||
(long*)&ArrayLength,
|
||
(long*)&WireSize );
|
||
|
||
// Figure out whether we need to convert the data
|
||
|
||
WireSize = ArraySize;
|
||
|
||
NetSizeRoutine(
|
||
pStubMsg->RpcMsg->Handle,
|
||
SendingCodeset,
|
||
ArraySize,
|
||
&ConversionType,
|
||
NdrpIsConformantArray( pFormat ) ? &WireSize : NULL,
|
||
&status);
|
||
|
||
if ( RPC_S_OK != status )
|
||
RpcRaiseException( status );
|
||
|
||
// Skip the buffer ahead to where the actual bits will go. We'll patch
|
||
// up the array prolog later.
|
||
|
||
ALIGN( pStubMsg->Buffer, 3 );
|
||
|
||
BufferMark = pStubMsg->Buffer;
|
||
pStubMsg->Buffer += NdrpArrayPrologLength( pFormat );
|
||
|
||
// If we need to convert do so, otherwise just memcpy
|
||
|
||
// WireLength = WireSize;
|
||
WireLength = ArrayLength * pCSFormat->UserTypeSize;
|
||
|
||
if ( IDL_CS_NO_CONVERT == ConversionType )
|
||
{
|
||
CopyMemory( pStubMsg->Buffer, pMemory, WireLength );
|
||
pStubMsg->Buffer += WireLength;
|
||
}
|
||
else
|
||
{
|
||
ToNetCSRoutine(
|
||
pStubMsg->RpcMsg->Handle,
|
||
SendingCodeset,
|
||
pMemory,
|
||
ArrayLength,
|
||
pStubMsg->Buffer,
|
||
// ! NdrpIsVaryingArray( pFormat ) ? NULL : &WireLength,
|
||
NdrpIsFixedArray( pFormat ) ? NULL : &WireLength,
|
||
&status);
|
||
|
||
if ( RPC_S_OK != status )
|
||
RpcRaiseException( status );
|
||
|
||
NDR_ASSERT(
|
||
WireLength <= WireSize,
|
||
"Buffer overflow during [cs_char] conversion");
|
||
|
||
pStubMsg->Buffer += WireLength;
|
||
/*
|
||
// For conformant or fixed arrays we must have WireSize bytes on the
|
||
// wire so pad it out if necessary
|
||
|
||
if ( ! NdrpIsVaryingArray( pFormat ) && WireLength < WireSize )
|
||
{
|
||
// REVIEW: Is zero'ing necessary?
|
||
ZeroMemory( pStubMsg->Buffer, WireSize - WireLength );
|
||
pStubMsg->Buffer += WireSize - WireLength;
|
||
}
|
||
*/
|
||
if ( ! NdrpIsVaryingArray( pFormat ) )
|
||
WireSize = WireLength;
|
||
}
|
||
|
||
NdrpUpdateArrayProlog(
|
||
pFormat,
|
||
BufferMark,
|
||
WireSize,
|
||
pStubMsg->Offset,
|
||
WireLength );
|
||
|
||
return 0;
|
||
}
|
||
#endif // _CS_CHAR
|
||
|
||
|
||
void
|
||
RPC_ENTRY
|
||
NdrPartialIgnoreClientMarshall(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
void * pMemory
|
||
)
|
||
{
|
||
ALIGN( pStubMsg->Buffer, 0x3 );
|
||
*(ulong *)pStubMsg->Buffer = pMemory ? 1 : 0;
|
||
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
||
}
|