mirror of https://github.com/lianthony/NT4.0
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.
2959 lines
74 KiB
2959 lines
74 KiB
/************************************************************************
|
|
|
|
Copyright (c) 1993 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"
|
|
|
|
//
|
|
// Function table of marshalling routines.
|
|
//
|
|
const PMARSHALL_ROUTINE MarshallRoutinesTable[] =
|
|
{
|
|
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
|
|
|
|
NdrInterfacePointerMarshall,
|
|
|
|
NdrMarshallHandle,
|
|
|
|
// New Post NT 3.5 token serviced from here on.
|
|
|
|
NdrHardStructMarshall,
|
|
|
|
NdrXmitOrRepAsMarshall, // transmit as ptr
|
|
NdrXmitOrRepAsMarshall, // represent as ptr
|
|
|
|
NdrUserMarshalMarshall
|
|
|
|
};
|
|
|
|
const PMARSHALL_ROUTINE * pfnMarshallRoutines = &MarshallRoutinesTable[-FC_RP];
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_3" )
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
#if defined(__RPC_MAC__)
|
|
pMemory += 2;
|
|
#endif
|
|
|
|
// 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 :
|
|
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
|
|
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 += 4;
|
|
}
|
|
else
|
|
pBufferMark = 0;
|
|
|
|
//
|
|
// For ref pointers pBufferMark will not be used and can be left
|
|
// unitialized.
|
|
//
|
|
|
|
NdrpPointerMarshall( pStubMsg,
|
|
pBufferMark,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined( DOS ) || defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
void
|
|
NdrpPointerMarshall(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pBufferMark,
|
|
uchar * pMemory,
|
|
PFORMAT_STRING pFormat )
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Private routine for marshalling a pointer to anything. 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's node id 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.
|
|
|
|
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)++ = (ulong) pMemory;
|
|
|
|
if ( ! pMemory )
|
|
return;
|
|
|
|
break;
|
|
|
|
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]) )
|
|
{
|
|
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.
|
|
//
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
PFORMAT_STRING pFormatArray;
|
|
uint StructSize;
|
|
uchar Alignment;
|
|
|
|
// Align the buffer for conformance count marshalling.
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// 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 );
|
|
|
|
// Marshall conformance count.
|
|
*((ulong *)pStubMsg->Buffer)++ = pStubMsg->MaxCount;
|
|
|
|
// Re-align buffer only if struct is aligned on an 8 byte boundary.
|
|
if ( Alignment == 7 )
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
// Increment array format string to array element size field.
|
|
pFormatArray += 2;
|
|
|
|
// Add the size of the conformant array to the structure size.
|
|
StructSize += 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.
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
// Mark the start of the structure in the buffer.
|
|
pStubMsg->BufferMark = pStubMsg->Buffer - StructSize;
|
|
|
|
NdrpEmbeddedPointerMarshall( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined( DOS ) || defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
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;
|
|
|
|
// 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;
|
|
|
|
// 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);
|
|
|
|
// Increment buffer pointer past where conformance will be marshalled.
|
|
pStubMsg->Buffer += 4;
|
|
|
|
// Align buffer if needed on 8 byte boundary.
|
|
if ( Alignment == 7 )
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
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 = pStubMsg->Buffer - StructSize;
|
|
|
|
NdrpEmbeddedPointerMarshall( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
return 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;
|
|
}
|
|
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferSave;
|
|
uchar * pBufferMark;
|
|
uchar * pMemorySave;
|
|
PFORMAT_STRING pFormatPointers;
|
|
PFORMAT_STRING pFormatArray;
|
|
PFORMAT_STRING pFormatSave;
|
|
PFORMAT_STRING pFormatComplex;
|
|
long Alignment;
|
|
long Align8Mod;
|
|
uchar fSetPointerBufferMark;
|
|
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
long Align4Mod;
|
|
#endif
|
|
|
|
// Get struct's wire alignment.
|
|
Alignment = pFormat[1];
|
|
|
|
//
|
|
// This is used for support of structs with doubles passed on an
|
|
// i386 stack.
|
|
//
|
|
Align8Mod = (long) pMemory % 8;
|
|
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
Align4Mod = (long) pMemory % 4;
|
|
#endif
|
|
|
|
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);
|
|
|
|
// Align for conformance marshalling.
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Remember where the conformance count(s) will be marshalled.
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
// Increment the buffer pointer 4 bytes for every array dimension.
|
|
pStubMsg->Buffer += NdrpArrayDimensions( pFormatArray, FALSE ) * 4;
|
|
}
|
|
else
|
|
{
|
|
pFormatArray = 0;
|
|
pBufferMark = 0;
|
|
}
|
|
|
|
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;
|
|
|
|
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 = (ulong) pBufferSave;
|
|
|
|
NdrComplexStructBufferSize( pStubMsg,
|
|
pMemory,
|
|
pFormatSave );
|
|
|
|
// Set the location in the buffer where pointees will be marshalled.
|
|
pStubMsg->PointerBufferMark = (uchar *) pStubMsg->BufferLength;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
}
|
|
|
|
//
|
|
// 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 :
|
|
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 += 4;
|
|
break;
|
|
|
|
case FC_POINTER :
|
|
{
|
|
uchar * pBuffer;
|
|
|
|
ALIGN( pStubMsg->Buffer, 0x3 );
|
|
|
|
// Save current buffer pointer.
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
//
|
|
// Set the buffer pointer to where the pointees are being
|
|
// marshalled in the buffer.
|
|
//
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
|
|
NdrpPointerMarshall( pStubMsg,
|
|
pBuffer,
|
|
*((uchar **)pMemory),
|
|
pFormatPointers );
|
|
|
|
// Update.
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
//
|
|
// Increment buffer and memory pointers past the pointer.
|
|
//
|
|
|
|
pStubMsg->Buffer = pBuffer + 4;
|
|
|
|
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);
|
|
|
|
// Marshall complex type.
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
|
( pStubMsg,
|
|
(*pFormatComplex == FC_IP) ? *(uchar **)pMemory : pMemory,
|
|
pFormatComplex );
|
|
|
|
//
|
|
// Increment the memory pointer.
|
|
//
|
|
pMemory = NdrpMemoryIncrement( pStubMsg,
|
|
pMemory,
|
|
pFormatComplex );
|
|
|
|
//
|
|
// 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 :
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
//
|
|
// We have to play some tricks for the dos and win16
|
|
// to handle the case when an 4 byte aligned structure
|
|
// is passed by value. The alignment of the struct on
|
|
// the stack is not guaranteed to be on an 4 byte boundary.
|
|
//
|
|
pMemory -= Align4Mod;
|
|
ALIGN( pMemory, 0x3 );
|
|
pMemory += Align4Mod;
|
|
#else
|
|
ALIGN( pMemory, 0x3 );
|
|
#endif
|
|
|
|
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_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.
|
|
//
|
|
if ( pFormatArray )
|
|
{
|
|
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;
|
|
|
|
goto MarshallConfArray;
|
|
}
|
|
|
|
MarshallConfArray:
|
|
|
|
//
|
|
// 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;
|
|
|
|
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 = MIDL_wchar_strlen((wchar_t *)pMemory) + 1;
|
|
CopySize = Count * 2;
|
|
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;
|
|
}
|
|
|
|
#if defined( DOS ) || defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
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 = MIDL_wchar_strlen((wchar_t *)pMemory) + 1;
|
|
CopySize = ActualCount * 2;
|
|
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 = 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;
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
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 = 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;
|
|
|
|
// 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;
|
|
}
|
|
#if defined( DOS ) || defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
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) = 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 the buffer if needed on an 8 byte boundary.
|
|
if ( pFormat[1] == 7 )
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
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;
|
|
|
|
// 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 );
|
|
}
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
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 the buffer if needed on an 8 byte boundary.
|
|
if ( pFormat[1] == 7 )
|
|
ALIGN(pStubMsg->Buffer,7);
|
|
|
|
// 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;
|
|
|
|
// 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;
|
|
|
|
//
|
|
// Setting this flag means that the array is not embedded inside of
|
|
// another complex struct or array.
|
|
//
|
|
fSetPointerBufferMark = (! pStubMsg->PointerBufferMark) &&
|
|
(pFormat[12] != FC_RP);
|
|
|
|
if ( fSetPointerBufferMark )
|
|
{
|
|
BOOL fOldIgnore;
|
|
ulong MaxCount, Offset, ActualCount;
|
|
|
|
//
|
|
// Save the current conformance and variance fields. The sizing
|
|
// routine can overwrite them.
|
|
//
|
|
MaxCount = 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.
|
|
//
|
|
pStubMsg->BufferLength = (ulong) pStubMsg->Buffer;
|
|
|
|
NdrComplexArrayBufferSize( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
//
|
|
// This is the buffer pointer to the position where embedded pointers
|
|
// will be marshalled.
|
|
//
|
|
pStubMsg->PointerBufferMark = (uchar *) pStubMsg->BufferLength;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = fOldIgnore;
|
|
|
|
// Restore conformance and variance fields.
|
|
pStubMsg->MaxCount = MaxCount;
|
|
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( 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;
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
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.
|
|
|
|
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;
|
|
|
|
//
|
|
// 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 = (unsigned long *) pStubMsg->MaxCount;
|
|
ArrayInfo.OffsetArray = (unsigned long *) pStubMsg->Offset;
|
|
ArrayInfo.ActualCountArray = (unsigned long *) 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 = NdrpComputeConformance( pStubMsg,
|
|
pMemory,
|
|
pFormatStart );
|
|
|
|
// Marshall this dimension's conformance count.
|
|
pArrayInfo->BufferConformanceMark[Dimension] = Elements;
|
|
}
|
|
|
|
pFormat += 4;
|
|
|
|
//
|
|
// 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( 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;
|
|
|
|
//
|
|
// 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);
|
|
|
|
// Get the proper marshalling routine.
|
|
pfnMarshall = pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)];
|
|
|
|
pArrayInfo->Dimension = Dimension + 1;
|
|
|
|
// Compute the size of an array element.
|
|
MemoryElementSize = 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 :
|
|
pfnMarshall = NdrInterfacePointerMarshall;
|
|
|
|
// 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;
|
|
|
|
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.
|
|
//
|
|
if ( ! pfnMarshall )
|
|
{
|
|
for ( ; Count--; )
|
|
{
|
|
if ( *((int *)pMemory) & ~((int)0x7fff) )
|
|
RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
|
|
|
|
*((ushort *)pStubMsg->Buffer)++ = (ushort) *((int *)pMemory)++;
|
|
}
|
|
|
|
goto ComplexArrayMarshallEnd;
|
|
}
|
|
|
|
//
|
|
// Array of ref or interface pointers.
|
|
//
|
|
if ( (pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall) ||
|
|
(pfnMarshall == NdrInterfacePointerMarshall) )
|
|
{
|
|
uchar * pBuffer;
|
|
|
|
pStubMsg->pArrayInfo = 0;
|
|
|
|
//
|
|
// If PointerBufferMark is set then we must set the buffer pointer
|
|
// here before marshalling.
|
|
//
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
pBuffer = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
}
|
|
else
|
|
pBuffer = 0;
|
|
|
|
if ( pfnMarshall == (PMARSHALL_ROUTINE) NdrpPointerMarshall )
|
|
{
|
|
for ( ; Count--; )
|
|
{
|
|
NdrpPointerMarshall( pStubMsg,
|
|
0,
|
|
*((uchar **)pMemory)++,
|
|
pFormat );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( ; Count--; )
|
|
{
|
|
NdrInterfacePointerMarshall( pStubMsg,
|
|
*((uchar **)pMemory)++,
|
|
pFormat );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fix up the stub message buffer fields if needed.
|
|
//
|
|
if ( pBuffer )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
pStubMsg->Buffer = pBuffer;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
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;
|
|
|
|
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 :
|
|
#if defined(__RPC_MAC__)
|
|
SwitchIs = (long) *((short *)(pMemory+2));
|
|
break;
|
|
#endif
|
|
// non-Mac: fall to short
|
|
|
|
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 :
|
|
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 = NdrpComputeSwitchIs( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
//
|
|
// Set the format string to the memory size and arm description.
|
|
//
|
|
pFormat += 6;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
NdrpUnionMarshall( pStubMsg,
|
|
pMemory,
|
|
pFormat,
|
|
SwitchIs,
|
|
SwitchType );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg( "NDR20_9" )
|
|
#endif
|
|
|
|
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;
|
|
|
|
#if defined(__RPC_MAC__)
|
|
long SavedSwitchIs;
|
|
|
|
SavedSwitchIs = SwitchIs;
|
|
|
|
if ( (FC_BYTE <= SwitchType) && (SwitchType <= FC_USMALL) )
|
|
SwitchIs <<= 24;
|
|
else if ( (FC_WCHAR <= SwitchType) && (SwitchType <= FC_USHORT) )
|
|
SwitchIs <<= 16;
|
|
#endif
|
|
|
|
// Marshall the switch is value.
|
|
NdrSimpleTypeMarshall( pStubMsg,
|
|
(uchar *)&SwitchIs,
|
|
SwitchType );
|
|
|
|
#if defined(__RPC_MAC__)
|
|
SwitchIs = SavedSwitchIs;
|
|
#endif
|
|
|
|
// 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,
|
|
#if defined(__RPC_MAC__)
|
|
pFormat[1] );
|
|
#else
|
|
pFormat[0] );
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
//
|
|
// Non-interface pointers only.
|
|
//
|
|
if ( IS_BASIC_POINTER(*pFormat) )
|
|
{
|
|
//
|
|
// If we're embedded in a struct or array we have do some extra stuff.
|
|
//
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
uchar * pBufferSave;
|
|
|
|
pBufferSave = pStubMsg->Buffer;
|
|
|
|
// We have to align pBufferSave as well.
|
|
ALIGN(pBufferSave,3);
|
|
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
pStubMsg->PointerBufferMark = 0;
|
|
|
|
//
|
|
// We must call the private pointer marshalling routine.
|
|
//
|
|
NdrpPointerMarshall( pStubMsg,
|
|
pBufferSave,
|
|
pMemory,
|
|
pFormat );
|
|
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
|
|
// Increment past the pointer in the buffer.
|
|
pStubMsg->Buffer = pBufferSave + 4;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Union arm of a non-simple type.
|
|
//
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
|
|
( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
|
|
#if defined( DOS ) && !defined( WIN )
|
|
#pragma code_seg()
|
|
#endif
|
|
|
|
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;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pMemory,
|
|
pFormat );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
#pragma optimize( "", off )
|
|
#endif
|
|
|
|
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
|
|
{
|
|
(*pfnMarshallRoutines[ROUTINE_INDEX(*pFormat)])
|
|
( pStubMsg,
|
|
fXmitByPtr ? *(uchar **)pTransmittedType
|
|
: pTransmittedType,
|
|
pFormat );
|
|
}
|
|
pStubMsg->pTransmitType = pTransmittedType;
|
|
|
|
// Free the temporary transmitted object (it was allocated by the user).
|
|
|
|
pQuintuple[ QIndex ].pfnFreeXmit( pStubMsg );
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(__RPC_DOS__) || defined(__RPC_WIN16__)
|
|
#pragma optimize( "", on )
|
|
#endif
|
|
|
|
|
|
unsigned char * RPC_ENTRY
|
|
NdrUserMarshalMarshall(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pMemory,
|
|
PFORMAT_STRING pFormat )
|
|
/*++
|
|
|
|
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 long * pWireMarkerPtr = 0;
|
|
unsigned char * pUserBufferSaved;
|
|
|
|
// Align for the object or a pointer to it.
|
|
|
|
ALIGN( pStubMsg->Buffer, LOW_NIBBLE(pFormat[1]) );
|
|
|
|
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;
|
|
}
|
|
|
|
// Check if the object is embedded.
|
|
// Pointer buffer mark is set only when in a complex struct or array.
|
|
// For unions, when the union is embedded in a complex struct or array.
|
|
// If the union is top level, it's the same like a top level object.
|
|
|
|
if ( (pFormat[1] & USER_MARSHAL_POINTER) && pStubMsg->PointerBufferMark )
|
|
{
|
|
// Embedded: User object among pointees.
|
|
|
|
pUserBuffer = pStubMsg->PointerBufferMark;
|
|
}
|
|
else
|
|
pUserBuffer = pStubMsg->Buffer;
|
|
|
|
pUserBufferSaved = pUserBuffer;
|
|
|
|
// We always call user's routine to marshall.
|
|
|
|
UserMarshalCB.Flags = USER_CALL_CTXT_MASK( pStubMsg->dwDestContext );
|
|
UserMarshalCB.pStubMsg = pStubMsg;
|
|
if ( pFormat[1] & USER_MARSHAL_IID )
|
|
{
|
|
UserMarshalCB.pReserve = pFormat + 10;
|
|
}
|
|
else
|
|
{
|
|
UserMarshalCB.pReserve = 0;
|
|
}
|
|
|
|
QIndex = *(unsigned short *)(pFormat + 2);
|
|
pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
|
|
|
|
pUserBuffer = pQuadruple[ QIndex ].pfnMarshall( (ulong*) &UserMarshalCB,
|
|
pUserBuffer,
|
|
pMemory );
|
|
|
|
if ( (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 0;
|
|
}
|
|
else
|
|
RpcRaiseException( RPC_X_NULL_REF_POINTER );
|
|
}
|
|
|
|
// Advance the appropriate buffer pointer.
|
|
|
|
if ( (pFormat[1] & USER_MARSHAL_POINTER) && pStubMsg->PointerBufferMark )
|
|
pStubMsg->PointerBufferMark = pUserBuffer;
|
|
else
|
|
pStubMsg->Buffer = pUserBuffer;
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
unsigned char * RPC_ENTRY
|
|
NdrInterfacePointerMarshall (
|
|
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;
|
|
|
|
--*/
|
|
{
|
|
#if !defined( NDR_OLE_SUPPORT )
|
|
|
|
NDR_ASSERT(0, "Unimplemented");
|
|
|
|
#else //NT or Chicago
|
|
|
|
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;
|
|
uchar * pBufferSave;
|
|
|
|
// Always put the pointer itself on wire, it behaves like a unique.
|
|
//
|
|
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
*((long *)pStubMsg->Buffer)++ = (long) pMemory;
|
|
|
|
// If the pointer is null, it's done.
|
|
|
|
if ( pMemory == 0 )
|
|
return 0;
|
|
|
|
// Check if the pointer is embedded, to put the pointee
|
|
// in the right place.
|
|
//
|
|
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
pBufferSave = pStubMsg->Buffer;
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
|
|
//Align the buffer on a 4 byte boundary
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
}
|
|
else
|
|
pBufferSave = 0;
|
|
|
|
|
|
//
|
|
// 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 an 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 = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
|
|
cbMax = pStubMsg->BufferLength - position;
|
|
|
|
#if DBG == 1
|
|
//In the debug build, we call CoGetMarshalSizeMax to get
|
|
//upper bound for the size of the marshalled interface pointer.
|
|
hr = (*pfnCoGetMarshalSizeMax)(&cbMax, piid, (IUnknown *)pMemory, pStubMsg->dwDestContext, pStubMsg->pvDestContext, 0);
|
|
#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->lpVtbl->Release(pStream);
|
|
pStream = 0;
|
|
RpcRaiseException(hr);
|
|
}
|
|
|
|
//Calculate the size of the data written
|
|
|
|
libMove.LowPart = 0;
|
|
libMove.HighPart = 0;
|
|
pStream->lpVtbl->Seek(pStream, libMove, STREAM_SEEK_CUR, &libPosition);
|
|
pStream->lpVtbl->Release(pStream);
|
|
pStream = 0;
|
|
cbData = libPosition.LowPart;
|
|
}
|
|
|
|
//Update the array bounds.
|
|
|
|
*pMaxCount = cbData;
|
|
*pSize = cbData;
|
|
|
|
//Advance the stub message buffer pointer.
|
|
pStubMsg->Buffer += cbData;
|
|
|
|
//
|
|
// End of MAGIC.
|
|
//
|
|
if ( pBufferSave )
|
|
{
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
pStubMsg->Buffer = pBufferSave;
|
|
}
|
|
#endif// NT or Chicago
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// 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.
|
|
|
|
--*/
|
|
{
|
|
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 += 20;
|
|
}
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
#if defined( NDR_SERVER_SUPPORT )
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
NDRSContextMarshall( ContextHandle,
|
|
pStubMsg->Buffer,
|
|
RundownRoutine );
|
|
|
|
pStubMsg->Buffer += 20;
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|