mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3677 lines
98 KiB
3677 lines
98 KiB
/************************************************************************
|
|
|
|
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;
|
|
}
|