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.
 
 
 
 
 
 

2361 lines
51 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1993 Microsoft Corporation
Module Name :
memsize.c
Abstract :
This file contains the routines called by MIDL 2.0 stubs and the
intepreter for computing the memory size needed to hold a parameter being
unmarshalled.
Author :
David Kays dkays November 1993.
Revision History :
---------------------------------------------------------------------*/
#include "ndrp.h"
const
PMEM_SIZE_ROUTINE MemSizeRoutinesTable[] =
{
NdrPointerMemorySize,
NdrPointerMemorySize,
NdrPointerMemorySize,
NdrPointerMemorySize,
NdrSimpleStructMemorySize,
NdrSimpleStructMemorySize,
NdrConformantStructMemorySize,
NdrConformantStructMemorySize,
NdrConformantVaryingStructMemorySize,
NdrComplexStructMemorySize,
NdrConformantArrayMemorySize,
NdrConformantVaryingArrayMemorySize,
NdrFixedArrayMemorySize,
NdrFixedArrayMemorySize,
NdrVaryingArrayMemorySize,
NdrVaryingArrayMemorySize,
NdrComplexArrayMemorySize,
NdrConformantStringMemorySize,
NdrConformantStringMemorySize,
NdrConformantStringMemorySize,
NdrConformantStringMemorySize,
NdrNonConformantStringMemorySize,
NdrNonConformantStringMemorySize,
NdrNonConformantStringMemorySize,
NdrNonConformantStringMemorySize,
NdrEncapsulatedUnionMemorySize,
NdrNonEncapsulatedUnionMemorySize,
0,
NdrXmitOrRepAsMemorySize, // transmit as
NdrXmitOrRepAsMemorySize, // represent as
NdrInterfacePointerMemorySize,
0,
// New Post NT 3.5 token serviced from here on.
NdrHardStructMemorySize,
NdrXmitOrRepAsMemorySize, // transmit as ptr
NdrXmitOrRepAsMemorySize, // represent as ptr
NdrUserMarshalMemorySize
};
const
PMEM_SIZE_ROUTINE * pfnMemSizeRoutines = &MemSizeRoutinesTable[-FC_RP];
#if defined( DOS ) || defined( WIN )
#pragma code_seg( "NDR20_10" )
#endif
unsigned long RPC_ENTRY
NdrPointerMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a top level pointer to anything.
Pointers embedded in structures, arrays, or unions call
NdrpPointerMemorySize directly.
Used for FC_RP, FC_UP, FC_FP, FC_OP.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar * pBufferMark;
//
// If this is not a ref pointer then mark where the pointer's id is in
// the buffer and increment the stub message buffer pointer.
//
if ( *pFormat != FC_RP )
{
ALIGN(pStubMsg->Buffer,0x3);
pBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer += 4;
}
else
pBufferMark = 0;
// Else we can leave pBufferMark unitialized.
return NdrpPointerMemorySize( pStubMsg,
pBufferMark,
pFormat );
}
unsigned long
NdrpPointerMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
uchar * pBufferMark,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Private routine for computing the memory size required for a pointer to
anything. This is the entry point for pointers embedded in structures
arrays, or unions.
Used for FC_RP, FC_UP, FC_FP, FC_OP.
Arguments :
pStubMsg - Pointer to stub message.
pBufferMark - Location in the buffer where a unique or full pointer's id is.
Unused for ref pointers.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
switch ( *pFormat )
{
case FC_RP :
break;
case FC_UP :
case FC_OP :
if ( ! *((long *)pBufferMark) )
return pStubMsg->MemorySize;
break;
case FC_FP :
//
// Check if we've already mem sized this full pointer.
//
if ( NdrFullPointerQueryRefId( pStubMsg->FullPtrXlatTables,
*((ulong *)pBufferMark),
FULL_POINTER_MEM_SIZED,
0 ) )
return pStubMsg->MemorySize;
break;
default :
NDR_ASSERT(0,"NdrpPointerMemorySize : bad format char");
RpcRaiseException( RPC_S_INTERNAL_ERROR );
return 0;
}
//
// We align all memory pointers on at least a void * boundary.
//
LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_SIZE - 1 );
if ( ! SIMPLE_POINTER(pFormat[1]) )
{
// Pointer to complex type.
if ( POINTER_DEREF(pFormat[1]) )
pStubMsg->MemorySize += PTR_MEM_SIZE;
pFormat += 2;
pFormat += *((signed short *)pFormat);
}
else
{
switch ( pFormat[2] )
{
case FC_C_CSTRING :
case FC_C_BSTRING :
case FC_C_WSTRING :
case FC_C_SSTRING :
// Increment to string's description.
pFormat += 2;
break;
default :
// Simple type.
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(pFormat[2]));
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(pFormat[2]);
switch ( pFormat[2] )
{
case FC_ENUM16 :
//
// We can't use the simple type tables for enum16.
//
LENGTH_ALIGN( pStubMsg->MemorySize, sizeof(int) - 1 );
pStubMsg->MemorySize += sizeof(int);
break;
default :
LENGTH_ALIGN( pStubMsg->MemorySize,
SIMPLE_TYPE_ALIGNMENT(pFormat[2]) );
pStubMsg->MemorySize += SIMPLE_TYPE_MEMSIZE(pFormat[2]);
break;
}
return pStubMsg->MemorySize;
}
}
return (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])
( pStubMsg,
pFormat );
}
unsigned long RPC_ENTRY
NdrSimpleStructMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a simple structure.
Used for FC_STRUCT and FC_PSTRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Structure's format string description.
Return :
The computed memory size.
--*/
{
ulong Size;
Size = *((ushort *)(pFormat + 2));
ALIGN(pStubMsg->Buffer,pFormat[1]);
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
pStubMsg->Buffer += Size;
pStubMsg->MemorySize += Size;
if ( *pFormat == FC_PSTRUCT )
{
// Mark where the structure starts in the buffer.
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat + 4 );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrConformantStructMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a conformant structure.
Used for FC_CSTRUCT and FC_CPSTRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
PFORMAT_STRING pFormatArray;
ulong Size;
Size = *((ushort *)(pFormat + 2));
// Align for the conformance count.
ALIGN(pStubMsg->Buffer,0x3);
// Get the conformance count.
pStubMsg->MaxCount = *((long *)pStubMsg->Buffer)++;
// Realign on 8 byte boundary only.
if ( pFormat[1] == 7 )
ALIGN(pStubMsg->Buffer,0x7);
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
// Increment the format string to the offset to array description.
pFormat += 4;
// Get the array's description.
pFormatArray = pFormat + *((signed short *)pFormat);
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
CHECK_BOUND( pStubMsg->MaxCount, pFormatArray[4] & 0x0f );
// Add array size.
Size += pStubMsg->MaxCount * *((ushort *)(pFormatArray + 2));
pStubMsg->Buffer += Size;
pStubMsg->MemorySize += Size;
pFormat += 2;
if ( *pFormat == FC_PP )
{
// Mark the beginning of the struct in the buffer.
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrConformantVaryingStructMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a conformant varying structure.
Used for FC_CVSTRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
PFORMAT_STRING pFormatArray;
uchar * pBufferMark;
ulong Size;
Size = *((ushort *)(pFormat + 2));
// Align for conformance count.
ALIGN(pStubMsg->Buffer,0x3);
// Get the conformance count.
pStubMsg->MaxCount = *((long *)pStubMsg->Buffer)++;
// Realign on 8 byte boundary only.
if ( pFormat[1] == 7 )
ALIGN(pStubMsg->Buffer,7);
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
// Remember the start of the struct in the buffer.
pBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer += Size;
pStubMsg->MemorySize += Size;
pFormat += 4;
// Get array's format string description.
pFormatArray = pFormat + *((signed short *)pFormat);
if ( *pFormatArray == FC_CVARRAY )
{
NdrpConformantVaryingArrayMemorySize( pStubMsg,
pFormatArray );
}
else
{
NdrpConformantStringMemorySize( pStubMsg,
pFormatArray );
}
pFormat += 2;
if ( *pFormat == FC_PP )
{
// Mark the start of the structure in the buffer.
pStubMsg->Buffer = pBufferMark;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrHardStructMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a hard structure.
Used for FC_HARD_STRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
LENGTH_ALIGN(pStubMsg->MemorySize,pFormat[1]);
pStubMsg->MemorySize += *((ushort *)&pFormat[2]);
ALIGN(pStubMsg->Buffer,pFormat[1]);
pStubMsg->Buffer += *((ushort *)&pFormat[10]);
if ( *((short *)&pFormat[14]) )
{
pFormat += 14;
pFormat += *((short *)pFormat);
(*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrComplexStructMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a complex structure.
Used for FC_BOGUS_STRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar * pBufferMark;
PFORMAT_STRING pFormatPointers;
PFORMAT_STRING pFormatArray;
PFORMAT_STRING pFormatComplex;
long Alignment;
BOOL fSetPointerBufferMark;
//
// This is fun. If we're not ignoring embedded pointers and this structure
// is not embedded inside of another struct or array then we make a
// recursive call to get a pointer to where the flat part of the structure
// ends in the buffer. Then we can properly get to any embedded pointer's
// pointees.
//
if ( fSetPointerBufferMark =
(! pStubMsg->IgnoreEmbeddedPointers && ! pStubMsg->PointerBufferMark) )
{
uchar * pBuffer;
ulong MemorySize;
pBuffer = pStubMsg->Buffer;
pStubMsg->IgnoreEmbeddedPointers = TRUE;
// This gets clobbered.
MemorySize = pStubMsg->MemorySize;
//
// Get a buffer pointer to where the struct's pointees are.
//
(void) NdrComplexStructMemorySize( pStubMsg,
pFormat );
pStubMsg->MemorySize = MemorySize;
// Mark where the pointees begin.
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->IgnoreEmbeddedPointers = FALSE;
pStubMsg->Buffer = pBuffer;
}
Alignment = pFormat[1];
pFormat += 4;
// Get conformant array description.
if ( *((ushort *)pFormat) )
{
pFormatArray = pFormat + *((signed short *)pFormat);
ALIGN(pStubMsg->Buffer,3);
pBufferMark = pStubMsg->Buffer;
// Handle multidimensional arrays.
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(pStubMsg->Buffer,Alignment);
//
// Size 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 :
case FC_IGNORE :
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(*pFormat));
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(*pFormat);
pStubMsg->MemorySize += SIMPLE_TYPE_MEMSIZE(*pFormat);
break;
case FC_POINTER :
ALIGN(pStubMsg->Buffer,0x3);
if ( ! pStubMsg->IgnoreEmbeddedPointers )
{
uchar * pBuffer;
pBuffer = pStubMsg->Buffer;
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
NdrpPointerMemorySize( pStubMsg,
pBuffer,
pFormatPointers );
pFormatPointers += 4;
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer = pBuffer;
}
//
// We actually do a post alignment of the memory size.
// Do this to prevent some under-allocations when pointers
// to strings, or char or short are involved.
//
LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_SIZE - 1 );
pStubMsg->MemorySize += PTR_MEM_SIZE;
pStubMsg->Buffer += 4;
break;
//
// Embedded complex types.
//
case FC_EMBEDDED_COMPLEX :
// Add padding.
pStubMsg->MemorySize += pFormat[1];
pFormat += 2;
// Get the type's description.
pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
(void) (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
( pStubMsg,
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 :
LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
break;
case FC_ALIGNM4 :
LENGTH_ALIGN( pStubMsg->MemorySize, 0x3 );
break;
case FC_ALIGNM8 :
LENGTH_ALIGN( pStubMsg->MemorySize, 0x7 );
break;
case FC_STRUCTPAD1 :
case FC_STRUCTPAD2 :
case FC_STRUCTPAD3 :
case FC_STRUCTPAD4 :
case FC_STRUCTPAD5 :
case FC_STRUCTPAD6 :
case FC_STRUCTPAD7 :
//
// Increment memory size by amount of padding.
//
pStubMsg->MemorySize += (*pFormat - FC_STRUCTPAD1) + 1;
break;
case FC_PAD :
break;
//
// Done with layout.
//
case FC_END :
goto ComplexMemorySizeEnd;
default :
NDR_ASSERT(0,"NdrComplexStructMemorySize : bad format char");
RpcRaiseException( RPC_S_INTERNAL_ERROR );
return 0;
}
}
ComplexMemorySizeEnd :
if ( pFormatArray )
{
PPRIVATE_MEM_SIZE_ROUTINE pfnMemSize;
switch ( *pFormatArray )
{
case FC_CARRAY :
pfnMemSize = NdrpConformantArrayMemorySize;
break;
case FC_CVARRAY :
pfnMemSize = NdrpConformantVaryingArrayMemorySize;
break;
case FC_BOGUS_ARRAY :
pfnMemSize = NdrpComplexArrayMemorySize;
break;
// case FC_C_CSTRING :
// case FC_C_BSTRING :
// case FC_C_WSTRING :
// case FC_C_SSTRING :
default :
pfnMemSize = NdrpConformantStringMemorySize;
break;
}
// Set the max count for non-complex conformant arrays.
pStubMsg->MaxCount = *((ulong *)pBufferMark);
// Mark where conformance count(s) are.
pStubMsg->BufferMark = pBufferMark;
(void) (*pfnMemSize)( pStubMsg,
pFormatArray );
}
if ( fSetPointerBufferMark )
{
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrFixedArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a fixed array of any number of dimensions.
Used for FC_SMFARRAY and FC_LGFARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong Size;
ALIGN(pStubMsg->Buffer,pFormat[1]);
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
if ( *pFormat == FC_SMFARRAY )
{
pFormat += 2;
Size = *((ushort *)pFormat)++;
}
else
{
pFormat += 2;
Size = *((ulong UNALIGNED *)pFormat)++;
}
pStubMsg->Buffer += Size;
pStubMsg->MemorySize += Size;
if ( *pFormat == FC_PP )
{
// Mark the location in the buffer where the array starts.
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrConformantArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a top level one dimensional conformant array.
Used for FC_CARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
//
// Get the conformance count.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->MaxCount = *((long *)pStubMsg->Buffer)++;
return NdrpConformantArrayMemorySize( pStubMsg,
pFormat );
}
unsigned long
NdrpConformantArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Private routine for computing the memory size of a one dimensional
conformant array. This is the entry point for an embedded conformant
array.
Used for FC_CARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong Size;
if ( ! pStubMsg->MaxCount )
return pStubMsg->MemorySize;
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
CHECK_BOUND( pStubMsg->MaxCount, pFormat[4] & 0x0f );
// Align on 8 byte boundary if needed.
if ( pFormat[1] == 0x7 )
ALIGN(pStubMsg->Buffer,0x7);
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
// Increment to element size.
pFormat += 2;
// Compute array size.
Size = pStubMsg->MaxCount * *((ushort *)pFormat);
pFormat += 6;
pStubMsg->Buffer += Size;
pStubMsg->MemorySize += Size;
if ( *pFormat == FC_PP )
{
// Mark the location in the buffer where the array starts.
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrConformantVaryingArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a one dimensional top level conformant
varying array.
Used for FC_CVARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
//
// Get the conformance count.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->MaxCount = *((long *)pStubMsg->Buffer)++;
return NdrpConformantVaryingArrayMemorySize( pStubMsg,
pFormat );
}
unsigned long
NdrpConformantVaryingArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Private routine for computing the memory size of a one dimensional
conformant varying array. This is the entry point for memory sizing an
embedded conformant varying array.
Used for FC_CVARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong BufferSize;
//
// Get the offset and actual count in case needed for pointer sizing.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->Offset = *((long *)pStubMsg->Buffer)++;
pStubMsg->ActualCount = *((long *)pStubMsg->Buffer)++;
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
{
CHECK_BOUND( pStubMsg->MaxCount, pFormat[4] & 0x0f );
CHECK_BOUND( pStubMsg->ActualCount, pFormat[8] & 0x0f );
if ( (pStubMsg->Offset < 0) ||
(pStubMsg->MaxCount < (pStubMsg->Offset + pStubMsg->ActualCount)) )
RpcRaiseException( RPC_X_INVALID_BOUND );
}
//
// Do the memory size increment now in case the actual count is 0.
//
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
pStubMsg->MemorySize += pStubMsg->MaxCount * *((ushort *)(pFormat + 2));
if ( ! pStubMsg->ActualCount )
return pStubMsg->MemorySize;
// Align if needed on an 8 byte boundary.
if ( pFormat[1] == 0x7 )
ALIGN(pStubMsg->Buffer,0x7);
// Increment to element size.
pFormat += 2;
BufferSize = pStubMsg->ActualCount * *((ushort *)pFormat);
pStubMsg->Buffer += BufferSize;
pFormat += 10;
if ( *pFormat == FC_PP )
{
// Mark the location in the buffer where the array starts.
pStubMsg->BufferMark = pStubMsg->Buffer - BufferSize;
pStubMsg->MaxCount = pStubMsg->ActualCount;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrVaryingArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a top level or embedded varying array.
Used for FC_SMVARRAY and FC_LGVARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong MemorySize;
ulong BufferSize;
uchar Alignment;
//
// Get the offset and actual count.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->Offset = *((long *)pStubMsg->Buffer)++;
pStubMsg->ActualCount = *((long *)pStubMsg->Buffer)++;
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
{
long Elements;
CHECK_BOUND( pStubMsg->ActualCount,
pFormat[(*pFormat == FC_SMVARRAY) ? 8 : 12] & 0x0f );
Elements =
(*pFormat == FC_SMVARRAY) ?
*((ushort *)(pFormat + 4)) : *((ulong UNALIGNED *)(pFormat + 6));
if ( (((long)pStubMsg->Offset) < 0) ||
(Elements < (long)(pStubMsg->ActualCount + pStubMsg->Offset)) )
RpcRaiseException( RPC_X_INVALID_BOUND );
}
Alignment = pFormat[1];
if ( *pFormat == FC_SMVARRAY )
{
pFormat += 2;
MemorySize = (ulong) *((ushort *)pFormat);
pFormat += 4;
}
else
{
pFormat += 2;
MemorySize = *((ulong UNALIGNED *)pFormat);
pFormat += 8;
}
//
// Do the memory size increment now in case the actual count is 0 and
// we have return.
//
LENGTH_ALIGN( pStubMsg->MemorySize, Alignment );
pStubMsg->MemorySize += MemorySize;
if ( ! pStubMsg->ActualCount )
return pStubMsg->MemorySize;
//
// Align on an 8 byte boundary if needed.
//
if ( Alignment == 0x7 )
ALIGN(pStubMsg->Buffer,0x7);
BufferSize = pStubMsg->ActualCount * *((ushort *)pFormat);
pStubMsg->Buffer += BufferSize;
pFormat += 6;
if ( *pFormat == FC_PP )
{
// Mark the start of the array in the buffer.
pStubMsg->BufferMark = pStubMsg->Buffer - BufferSize;
pStubMsg->MaxCount = pStubMsg->ActualCount;
NdrpEmbeddedPointerMemorySize( pStubMsg,
pFormat );
}
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrComplexArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a top level complex array.
Used for FC_BOGUS_STRUCT.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
BOOL fSetPointerBufferMark;
//
// We set this if we're doing a real 'all nodes' sizing, this array
// is not embedded in another structure or array, and this is not an
// array of ref pointers.
//
fSetPointerBufferMark = ! pStubMsg->IgnoreEmbeddedPointers &&
! pStubMsg->PointerBufferMark &&
pFormat[12] != FC_RP;
//
// More fun. Make a recursive call so that we have a pointer to the end
// of the array's flat stuff in the buffer. Then we can properly get to
// any embedded pointer members. We have no way of knowing if there are
// any embedded pointers so we're stuck doing this all the time.
//
if ( fSetPointerBufferMark )
{
uchar * pBuffer;
ulong MemorySize;
pBuffer = pStubMsg->Buffer;
pStubMsg->IgnoreEmbeddedPointers = TRUE;
// Save this since it gets clobbered.
MemorySize = pStubMsg->MemorySize;
//
// Get a buffer pointer to where the array's pointees are.
//
(void) NdrComplexArrayMemorySize( pStubMsg,
pFormat );
pStubMsg->MemorySize = MemorySize;
// This is where the array pointees start.
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->IgnoreEmbeddedPointers = FALSE;
pStubMsg->Buffer = pBuffer;
}
if ( ( *((long UNALIGNED *)(pFormat + 4)) != 0xffffffff ) &&
( pStubMsg->pArrayInfo == 0 ) )
{
//
// The outer most array dimension sets the conformance marker.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->BufferMark = pStubMsg->Buffer;
// Increment past conformance count(s).
pStubMsg->Buffer += NdrpArrayDimensions( pFormat, FALSE ) * 4;
}
(void) NdrpComplexArrayMemorySize( pStubMsg,
pFormat );
if ( fSetPointerBufferMark )
{
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
return pStubMsg->MemorySize;
}
unsigned long
NdrpComplexArrayMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Private routine for computing the memory size of a complex array. This
is the entry point for memory sizing an embedded complex array.
Used for FC_BOGUS_ARRAY.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ARRAY_INFO ArrayInfo;
PARRAY_INFO pArrayInfo;
PMEM_SIZE_ROUTINE pfnMemSize;
uchar * pBufferSave;
PFORMAT_STRING pFormatSave;
ulong Elements;
ulong Count, CountSave;
long Dimension;
uchar Alignment;
//
// Setup if we are the outer dimension.
//
if ( ! pStubMsg->pArrayInfo )
{
pStubMsg->pArrayInfo = &ArrayInfo;
ArrayInfo.Dimension = 0;
ArrayInfo.BufferConformanceMark = (unsigned long *)pStubMsg->BufferMark;
ArrayInfo.BufferVarianceMark = 0;
}
// Used for array of ref pointers only.
pBufferSave = 0;
pFormatSave = pFormat;
pArrayInfo = pStubMsg->pArrayInfo;
Dimension = pArrayInfo->Dimension;
// Get the array alignment.
Alignment = pFormat[1];
pFormat += 2;
// Get number of elements (0 if conformance present).
Elements = *((ushort *)pFormat)++;
//
// Check for conformance description.
//
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
{
Elements = pArrayInfo->BufferConformanceMark[Dimension];
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
CHECK_BOUND( Elements, *pFormat & 0x0f );
}
pFormat += 4;
//
// Check for variance description.
//
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
{
if ( Dimension == 0 )
{
ALIGN(pStubMsg->Buffer,0x3);
// Mark where the variance counts are.
pArrayInfo->BufferVarianceMark = (unsigned long *)pStubMsg->Buffer;
// Handle multidimensional arrays.
pStubMsg->Buffer += NdrpArrayDimensions( pFormatSave, TRUE ) * 8;
}
Count = pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1];
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
{
long Offset;
CHECK_BOUND( Count, *pFormat & 0x0f );
Offset = pArrayInfo->BufferVarianceMark[(Dimension * 2)];
if ( (Offset < 0) || (Elements < (Offset + Count)) )
RpcRaiseException( RPC_X_INVALID_BOUND );
}
}
else
{
Count = Elements;
}
CountSave = Count;
pFormat += 4;
//
// Only align the buffer if at least one element was shipped.
//
if ( Count )
ALIGN(pStubMsg->Buffer,Alignment);
switch ( *pFormat )
{
case FC_EMBEDDED_COMPLEX :
pFormat += 2;
pFormat += *((signed short *)pFormat);
pfnMemSize = pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)];
break;
case FC_RP :
case FC_UP :
case FC_FP :
case FC_OP :
case FC_IP :
//
// Add in the size of the array explicitly.
//
LENGTH_ALIGN(pStubMsg->MemorySize,0x3);
pStubMsg->MemorySize += Elements * PTR_MEM_SIZE;
if ( pStubMsg->IgnoreEmbeddedPointers )
goto ComplexArrayMemSizeEnd;
if ( pStubMsg->PointerBufferMark )
{
pBufferSave = pStubMsg->Buffer;
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
pfnMemSize = (*pFormat == FC_RP) ?
(PMEM_SIZE_ROUTINE) NdrpPointerMemorySize :
NdrInterfacePointerMemorySize;
break;
default :
NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
"NdrpComplexArrayMemorySize : bad format char" );
pStubMsg->Buffer += Count * SIMPLE_TYPE_BUFSIZE(*pFormat);
if ( *pFormat == FC_ENUM16 )
LENGTH_ALIGN( pStubMsg->MemorySize, sizeof(int) - 1 );
else
LENGTH_ALIGN( pStubMsg->MemorySize,
SIMPLE_TYPE_ALIGNMENT(*pFormat) );
pStubMsg->MemorySize += Elements * SIMPLE_TYPE_MEMSIZE(*pFormat);
goto ComplexArrayMemSizeEnd;
}
if ( ! IS_ARRAY_OR_STRING(*pFormat) )
pStubMsg->pArrayInfo = 0;
if ( pfnMemSize == (PMEM_SIZE_ROUTINE) NdrpPointerMemorySize )
{
for ( ; Count--; )
{
NdrpPointerMemorySize( pStubMsg,
0,
pFormat );
}
}
else
{
for ( ; Count--; )
{
// Keep track of multidimensional array dimension.
if ( IS_ARRAY_OR_STRING(*pFormat) )
pArrayInfo->Dimension = Dimension + 1;
(*pfnMemSize)( pStubMsg,
pFormat );
}
}
if ( pBufferSave )
{
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer = pBufferSave;
}
//
// If we had variance then we have to make sure and add in the node size
// of any members that were not shipped.
//
if ( (CountSave < Elements) && (*pFormat != FC_RP) )
{
long ElementSize;
pArrayInfo->Dimension = Dimension + 1;
pArrayInfo->MaxCountArray = pArrayInfo->BufferConformanceMark;
pStubMsg->pArrayInfo = pArrayInfo;
ElementSize = (long) NdrpMemoryIncrement( pStubMsg,
0,
pFormat );
pArrayInfo->MaxCountArray = 0;
//
// We don't have the memory alignment anywhere, so align the memory
// size to 8. At worse we'll allocate a few extra bytes.
//
LENGTH_ALIGN(pStubMsg->MemorySize,0x7);
pStubMsg->MemorySize += (Elements - CountSave) * ElementSize;
}
ComplexArrayMemSizeEnd:
// pArrayInfo must be zero when not valid.
pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrNonConformantStringMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a non conformant string.
Used for FC_CSTRING, FC_WSTRING, FC_SSTRING, and FC_BSTRING (NT Beta2
compatability only).
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong BufferSize;
ulong MemorySize;
ALIGN(pStubMsg->Buffer,0x3);
// Skip the offset.
pStubMsg->Buffer += 4;
BufferSize = *((long *)pStubMsg->Buffer)++;
MemorySize = *((ushort *)(pFormat + 2));
switch ( *pFormat )
{
case FC_WSTRING :
// Buffer is already aligned on a 4 byte boundary.
// Align memory just in case.
LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
BufferSize *= 2;
MemorySize *= 2;
break;
case FC_SSTRING :
BufferSize *= pFormat[1];
MemorySize *= pFormat[1];
break;
default :
break;
}
pStubMsg->Buffer += BufferSize;
pStubMsg->MemorySize += MemorySize;
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrConformantStringMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of 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 stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
//
// Get string size.
//
if ( pStubMsg->pArrayInfo != 0 )
{
//
// If this is part of a multidimensional array then we get the location
// where the conformance is from a special place.
//
pStubMsg->MaxCount =
pStubMsg->pArrayInfo->
BufferConformanceMark[pStubMsg->pArrayInfo->Dimension];
}
else
{
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->MaxCount = *((long *)pStubMsg->Buffer)++;
}
return NdrpConformantStringMemorySize( pStubMsg,
pFormat );
}
unsigned long
NdrpConformantStringMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Private routine for determing the memory size of a conformant string.
This is the entry point for an embedded 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 stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
ulong MemorySize;
ulong BufferSize;
// Skip the offset.
pStubMsg->Buffer += 4;
BufferSize = *((long *)pStubMsg->Buffer)++;
MemorySize = pStubMsg->MaxCount;
if ( pStubMsg->fCheckBounds && ! pStubMsg->IsClient )
{
if ( (*pFormat != FC_C_SSTRING) && (pFormat[1] == FC_STRING_SIZED) )
CHECK_BOUND( MemorySize, pFormat[2] );
//
// Make sure the offset is 0 and the memory size is at least as
// large as the buffer size.
//
if ( *((long *)(pStubMsg->Buffer - 8)) != 0 ||
(MemorySize < BufferSize) )
RpcRaiseException( RPC_X_INVALID_BOUND );
}
switch ( *pFormat )
{
case FC_C_WSTRING :
// Buffer is already aligned on a 4 byte boundary.
// Align memory just in case.
LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
BufferSize *= 2;
MemorySize *= 2;
break;
case FC_C_SSTRING :
BufferSize *= pFormat[1];
MemorySize *= pFormat[1];
break;
default :
break;
}
pStubMsg->Buffer += BufferSize;
pStubMsg->MemorySize += MemorySize;
return pStubMsg->MemorySize;
}
unsigned long RPC_ENTRY
NdrEncapsulatedUnionMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of an encapsulated union.
Used for FC_ENCAPSULATED_UNION.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar SwitchType;
SwitchType = LOW_NIBBLE(pFormat[1]);
//
// No alignment needed. Add number of bytes to the union.
//
pStubMsg->MemorySize += HIGH_NIBBLE(pFormat[1]);
return NdrpUnionMemorySize( pStubMsg,
pFormat + 2,
SwitchType );
}
unsigned long RPC_ENTRY
NdrNonEncapsulatedUnionMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size of a non-encapsulated union.
Used for FC_NON_ENCAPSULATED_UNION.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar SwitchType;
SwitchType = pFormat[1];
//
// Set the format string to the memory size and arm description.
//
pFormat += 6;
pFormat += *((signed short *)pFormat);
return NdrpUnionMemorySize( pStubMsg,
pFormat,
SwitchType );
}
unsigned long
NdrpUnionMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat,
uchar SwitchType )
/*++
Routine Description :
Private routine for computing the memory size needed for a union. This
routine is used for sizing both encapsulated and non-encapsulated unions.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
SwitchType - Union's switch type.
Return :
The computed memory size.
--*/
{
long UnionSize;
long SwitchIs;
long Arms;
uchar Alignment;
switch ( SwitchType )
{
case FC_SMALL :
case FC_CHAR :
SwitchIs = (long) *((char *)pStubMsg->Buffer)++;
break;
case FC_USMALL :
SwitchIs = (long) *((uchar *)pStubMsg->Buffer)++;
break;
case FC_SHORT :
case FC_ENUM16 :
ALIGN(pStubMsg->Buffer,0x1);
SwitchIs = (long) *((short *)pStubMsg->Buffer)++;
break;
case FC_USHORT :
case FC_WCHAR :
ALIGN(pStubMsg->Buffer,0x1);
SwitchIs = (long) *((ushort *)pStubMsg->Buffer)++;
break;
case FC_LONG :
case FC_ULONG :
case FC_ENUM32 :
ALIGN(pStubMsg->Buffer,0x3);
SwitchIs = *((long *)pStubMsg->Buffer)++;
break;
default :
NDR_ASSERT(0,"NdrpUnionMemorySize : bad switch type");
RpcRaiseException( RPC_S_INTERNAL_ERROR );
return 0;
}
//
// Get the max flat union memory size.
//
UnionSize = *((ushort *)pFormat)++;
//
// 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);
pStubMsg->MemorySize += UnionSize;
//
// Get number of union arms.
//
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) )
{
//
// Raise an exception here.
//
RpcRaiseException( RPC_S_INVALID_TAG );
}
//
// Return if the arm is emtpy.
//
if ( ! *((ushort *)pFormat) )
return pStubMsg->MemorySize;
//
// Ok we've got the correct arm now. The only goal now is to increment
// the buffer pointer by the correct amount, and possibly add the size
// of embedded pointers in the chosen union arm to the memory size.
//
//
// 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) )
{
unsigned char FcType;
#if defined(__RPC_MAC__)
FcType = pFormat[1];
#else
FcType = pFormat[0];
#endif
ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT( FcType ));
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( FcType );
return pStubMsg->MemorySize;
}
pFormat += *((signed short *)pFormat);
if ( IS_POINTER_TYPE(*pFormat) )
{
//
// If we're ignoring pointers then just add in the size of a pointer
// here and return.
//
if ( pStubMsg->IgnoreEmbeddedPointers )
{
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->Buffer += 4;
return pStubMsg->MemorySize;
}
}
//
// Non-interface pointer only.
//
if ( IS_BASIC_POINTER(*pFormat) )
{
if ( pStubMsg->PointerBufferMark )
{
uchar * pBufferSave;
pBufferSave = pStubMsg->Buffer;
// We have to align pBufferSave as well.
ALIGN(pBufferSave,0x3);
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
(void) NdrpPointerMemorySize( pStubMsg,
pBufferSave,
pFormat );
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer = pBufferSave + 4;
return pStubMsg->MemorySize;
}
}
//
// Add in the size of arm. We end up adding the size of the flat part
// of the arm a second time here.
// We do have to call this however, so that the buffer pointer is properly
// updated.
//
return (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])
( pStubMsg,
pFormat );
}
unsigned long RPC_ENTRY
NdrXmitOrRepAsMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for the presented type of a
transmit as or represent as.
See mrshl.c for the description of the FC layout.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size of the presented type object.
--*/
{
unsigned long MemorySize;
unsigned short QIndex;
// Fetch the QuintupleIndex.
QIndex = *(unsigned short *)(pFormat + 2);
// Memsize the presented object.
MemorySize = *(unsigned short *)(pFormat + 4);
// Update our current count in the stub message.
pStubMsg->MemorySize += MemorySize;
// Move the pointer in the buffer behind the transmitted object
// for the next field to be memsized correctly.
pFormat += 8;
pFormat = pFormat + *(short *)pFormat;
if ( IS_SIMPLE_TYPE( *pFormat ))
{
// Simple type.
ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT( *pFormat) );
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( *pFormat );
}
else
{
(*pfnMemSizeRoutines[ ROUTINE_INDEX( *pFormat) ])( pStubMsg, pFormat );
}
return( MemorySize );
}
unsigned long RPC_ENTRY
NdrUserMarshalMemorySize(
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for a usr_marshal type.
See mrshl.c for the description of the layouts.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The memory size of the usr_marshall object.
--*/
{
unsigned long MemorySize;
// The memory sizing routine can be called only when sizing a complex
// struct for memory allocation.
// Hence, IgnoreEmbeddedPointer in this case has to be on.
NDR_ASSERT( pStubMsg->IgnoreEmbeddedPointers, "non-embedded call?" );
// Memsize the presented object.
MemorySize = *(unsigned short *)(pFormat + 4);
// Update our current count in the stub message.
pStubMsg->MemorySize += MemorySize;
// Move the pointer in the buffer behind the transmitted object
// for the next field to be memsized correctly.
ALIGN( pStubMsg->Buffer, LOW_NIBBLE( pFormat[1] ) );
if ( pFormat[1] & USER_MARSHAL_POINTER )
{
// it's embedded: unique or ref.
pStubMsg->Buffer += 4;
}
else
{
unsigned long MemorySizeSave;
// Flat type.
// Optimization: if we know the wire size, don't walk to size it.
if ( *(unsigned short *)(pFormat + 6) != 0 )
{
pStubMsg->Buffer += *(unsigned short *)(pFormat + 6);
return MemorySize;
}
// Unknown wire size: we need to step through the buffer.
// However, the memory size may have nothing to do with
// the wire type description..
// so, we need to remember what the current memory size is.
MemorySizeSave = pStubMsg->MemorySize;
pFormat += 8;
pFormat = pFormat + *(short *)pFormat;
if ( IS_SIMPLE_TYPE( *pFormat ))
{
// Simple type.
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE( *pFormat );
}
else
{
(*pfnMemSizeRoutines[ ROUTINE_INDEX( *pFormat) ])( pStubMsg, pFormat );
}
pStubMsg->MemorySize = MemorySizeSave;
}
return( MemorySize );
}
unsigned long RPC_ENTRY
NdrInterfacePointerMemorySize (
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size needed for an interface pointer.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The current memory size.
--*/
{
//
// Always do both of these.
//
ALIGN(pStubMsg->Buffer,0x3);
pStubMsg->Buffer += sizeof(void *);
LENGTH_ALIGN(pStubMsg->MemorySize,0x3);
pStubMsg->MemorySize += sizeof(void *);
return pStubMsg->MemorySize;
}
void
NdrpEmbeddedPointerMemorySize (
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat )
/*++
Routine Description :
Computes the memory size required for all embedded pointers in an
array or a structure.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar * pBufPtr;
uchar * pBufferMark;
uchar * pBufferSave;
long MaxCountSave;
MaxCountSave = pStubMsg->MaxCount;
if ( pStubMsg->IgnoreEmbeddedPointers )
return;
//
// Check if we're handling pointers in a complex struct or array, and
// re-set the Buffer pointer if so.
//
if ( pStubMsg->PointerBufferMark )
{
pBufferSave = pStubMsg->Buffer;
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
pStubMsg->PointerBufferMark = 0;
}
else
pBufferSave = 0;
pBufferMark = pStubMsg->BufferMark;
// Increment past the FC_PP and pad.
pFormat += 2;
for (;;)
{
if ( *pFormat == FC_END )
{
if ( pBufferSave )
{
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
pStubMsg->Buffer = pBufferSave;
}
return;
}
//
// Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT.
//
if ( *pFormat != FC_NO_REPEAT )
{
pStubMsg->MaxCount = MaxCountSave;
pStubMsg->BufferMark = pBufferMark;
NdrpEmbeddedRepeatPointerMemorySize( pStubMsg,
&pFormat );
// Continue to the next pointer.
continue;
}
// Compute the pointer to the pointer id in the buffer to size.
pBufPtr = (pBufferMark + *((signed short *)(pFormat + 4)));
// Increment to the pointer description.
pFormat += 6;
NdrpPointerMemorySize( pStubMsg,
pBufPtr,
pFormat );
// Increment to next pointer description.
pFormat += 4;
} // for
}
void
NdrpEmbeddedRepeatPointerMemorySize (
PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING * ppFormat )
/*++
Routine Description :
Computes the memory size required for all embedded pointers in an
array.
Arguments :
pStubMsg - Pointer to stub message.
pFormat - Pointer's format string description.
Return :
The computed memory size.
--*/
{
uchar * pBufPtr;
uchar * pBufferMark;
PFORMAT_STRING pFormat;
PFORMAT_STRING pFormatSave;
ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
pBufferMark = pStubMsg->BufferMark;
pFormat = *ppFormat;
switch ( *pFormat )
{
case FC_FIXED_REPEAT :
// Increment past the FC_FIXED_REPEAT and FC_PAD.
pFormat += 2;
// Get the total number of times to repeat the pointer marshall.
RepeatCount = *((ushort *)pFormat)++;
break;
case FC_VARIABLE_REPEAT :
// Get the total number of times to repeat the pointer marshall.
RepeatCount = pStubMsg->MaxCount;
pFormat += 2;
break;
default :
NDR_ASSERT(0,"NdrpEmbeddedRepeatPointerMemorySize : bad format");
RpcRaiseException( RPC_S_INTERNAL_ERROR );
return;
}
// Get the increment amount between successive pointers.
RepeatIncrement = *((ushort *)pFormat)++;
// Offset to array is ignored.
pFormat += 2;
// Get number of pointers.
PointersSave = Pointers = *((ushort *)pFormat)++;
pFormatSave = pFormat;
//
// Loop for the number of shipped array elements.
//
for ( ; RepeatCount--;
pBufferMark += RepeatIncrement )
{
pFormat = pFormatSave;
Pointers = PointersSave;
//
// Loop for the number of pointer in each array element (which could
// be greater than 0 for an array of structures).
//
for ( ; Pointers--; )
{
pFormat += 2;
// Get the buffer pointer where the pointer id is.
pBufPtr = pBufferMark + *((signed short *)pFormat)++;
NdrpPointerMemorySize( pStubMsg,
pBufPtr,
pFormat );
// Increment to the next the pointer description.
pFormat += 4;
}
}
// Get the format string pointer past this repeat pointer description.
*ppFormat = pFormatSave + PointersSave * 8;
}