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