Windows NT 4.0 source code leak
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

/************************************************************************
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
}