mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2912 lines
75 KiB
2912 lines
75 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Copyright (c) 1993-2000 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 :
|
|
|
|
Note:
|
|
Simple types are not checked for buffer over-run since we are
|
|
only reading from the buffer and not writing from it. So if
|
|
a buffer overun actually occures, no real damage is done.
|
|
|
|
---------------------------------------------------------------------*/
|
|
|
|
#include "ndrp.h"
|
|
#include "interp2.h"
|
|
#include "attack.h"
|
|
#include "pointerq.h"
|
|
|
|
unsigned long
|
|
NdrUDTSimpleTypeMemsize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat );
|
|
|
|
extern const
|
|
PMEM_SIZE_ROUTINE MemSizeRoutinesTable[] =
|
|
{
|
|
|
|
// dummies for 64b C compiler workaround
|
|
//
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize, // FC_ZERO - FC_USHORT
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize,
|
|
NdrUDTSimpleTypeMemsize, // FC_LONG - FC_IGNORE
|
|
NdrUDTSimpleTypeMemsize, // FC_ERROR_STATUS_T
|
|
|
|
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, // byte count
|
|
|
|
NdrXmitOrRepAsMemorySize, // transmit as
|
|
NdrXmitOrRepAsMemorySize, // represent as
|
|
|
|
NdrPointerMemorySize,
|
|
|
|
0,
|
|
|
|
// New Post NT 3.5 token serviced from here on.
|
|
|
|
0, // NdrHardStructMemorySize,
|
|
|
|
NdrXmitOrRepAsMemorySize, // transmit as ptr
|
|
NdrXmitOrRepAsMemorySize, // represent as ptr
|
|
|
|
NdrUserMarshalMemorySize,
|
|
|
|
0, // FC_PIPE
|
|
0, // FC_BLK_HOLE
|
|
|
|
NdrpRangeMemorySize,
|
|
|
|
0, // FC_INT3264
|
|
0, // FC_UINT3264
|
|
|
|
0, // NdrCsArrayMemorySize,
|
|
0, // NdrCsTagMemorySize
|
|
};
|
|
|
|
extern const
|
|
PMEM_SIZE_ROUTINE * pfnMemSizeRoutines = MemSizeRoutinesTable;
|
|
|
|
void
|
|
NdrpInterfacePointerMemorySize (
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat );
|
|
|
|
unsigned long
|
|
NdrUDTSimpleTypeMemsize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT(*pFormat) );
|
|
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(*pFormat);
|
|
pStubMsg->MemorySize += SIMPLE_TYPE_MEMSIZE(*pFormat);
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
|
|
unsigned long RPC_ENTRY
|
|
NdrpRangeMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*++
|
|
--*/
|
|
{
|
|
FORMAT_CHARACTER FcType = (FORMAT_CHARACTER)(pFormat[1] & 0x0f);
|
|
|
|
ALIGN(pStubMsg->Buffer,SIMPLE_TYPE_ALIGNMENT(FcType));
|
|
|
|
pStubMsg->Buffer += SIMPLE_TYPE_BUFSIZE(FcType);
|
|
|
|
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(FcType) );
|
|
pStubMsg->MemorySize += SIMPLE_TYPE_MEMSIZE(FcType);
|
|
break;
|
|
}
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
|
|
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 += PTR_WIRE_SIZE;
|
|
}
|
|
else
|
|
pBufferMark = 0;
|
|
|
|
// Else we can leave pBufferMark unitialized.
|
|
|
|
return NdrpPointerMemorySize( pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
}
|
|
|
|
|
|
__forceinline unsigned long
|
|
NdrpPointerMemorySizeInternal(
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
uchar uFlagsSave;
|
|
ulong MemSize;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_RP :
|
|
break;
|
|
|
|
case FC_UP :
|
|
case FC_OP :
|
|
if ( ! *((long *)pBufferMark) )
|
|
return pStubMsg->MemorySize;
|
|
break;
|
|
|
|
case FC_IP:
|
|
if ( IS_BROKEN_INTERFACE_POINTER(pStubMsg->uFlags) )
|
|
{
|
|
// In this case, the whole pointer and pointee are
|
|
// where the pointee should have been.
|
|
// (Treat like toplevel at this point )
|
|
NdrInterfacePointerMemorySize( pStubMsg,
|
|
pFormat );
|
|
}
|
|
else
|
|
{
|
|
if ( ! *((long *)pBufferMark) )
|
|
return pStubMsg->MemorySize;
|
|
NdrpInterfacePointerMemorySize( pStubMsg,
|
|
pFormat );
|
|
}
|
|
return pStubMsg->MemorySize;
|
|
|
|
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_ALIGN );
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
uFlagsSave = pStubMsg->uFlags;
|
|
RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
|
|
|
|
MemSize = (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])
|
|
( pStubMsg,
|
|
pFormat );
|
|
|
|
pStubMsg->uFlags = uFlagsSave;
|
|
|
|
return MemSize;
|
|
}
|
|
|
|
NDR_MEMSIZE_POINTER_QUEUE_ELEMENT::NDR_MEMSIZE_POINTER_QUEUE_ELEMENT(
|
|
MIDL_STUB_MESSAGE *pStubMsg,
|
|
uchar *pBufferMarkNew,
|
|
PFORMAT_STRING pFormatNew ) :
|
|
|
|
pFormat(pFormatNew),
|
|
pBufferMark(pBufferMarkNew),
|
|
Memory(pStubMsg->Memory),
|
|
uFlags(pStubMsg->uFlags)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
NDR_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(
|
|
MIDL_STUB_MESSAGE *pStubMsg)
|
|
{
|
|
SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
|
|
SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
|
|
NDR_ASSERT( !pStubMsg->PointerBufferMark, "PointerBufferMark is not 0!\n");
|
|
NDR_ASSERT( !pStubMsg->PointerLength, "PointerLength is not 0!\n");
|
|
|
|
NdrpPointerMemorySizeInternal( pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
|
|
}
|
|
|
|
#if defined(DBG)
|
|
void
|
|
NDR_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
|
|
{
|
|
DbgPrint("NDR_MRSHL_POINTER_QUEUE_ELEMENT\n");
|
|
DbgPrint("pNext: %p\n", pNext );
|
|
DbgPrint("pFormat: %p\n", pFormat );
|
|
DbgPrint("pBufferMark: %p\n", pBufferMark );
|
|
DbgPrint("Memory: %p\n", Memory );
|
|
DbgPrint("uFlags: %x\n", uFlags );
|
|
}
|
|
#endif
|
|
|
|
void
|
|
NdrpEnquePointerMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pBufferMark,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
|
|
|
|
RpcTryFinally
|
|
{
|
|
|
|
NDR_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
|
|
new(PointerContext.GetActiveState())
|
|
NDR_MEMSIZE_POINTER_QUEUE_ELEMENT(pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
PointerContext.Enque( pElement );
|
|
PointerContext.DispatchIfRequired();
|
|
}
|
|
RpcFinally
|
|
{
|
|
PointerContext.EndContext();
|
|
}
|
|
RpcEndFinally
|
|
}
|
|
|
|
unsigned long
|
|
NdrpPointerMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
uchar * pBufferMark,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
|
|
if ( !NdrIsLowStack(pStubMsg) )
|
|
{
|
|
return
|
|
NdrpPointerMemorySizeInternal( pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
}
|
|
|
|
NdrpEnquePointerMemorySize(
|
|
pStubMsg,
|
|
pBufferMark,
|
|
pFormat );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
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] );
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + Size );
|
|
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;
|
|
uchar Alignment = pFormat[1];
|
|
// set by the outermost embedding complex struct
|
|
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
|
|
Size = *((ushort *)(pFormat + 2));
|
|
|
|
// Get the conformance count.
|
|
if ( fIsEmbeddedStruct )
|
|
{
|
|
// A bogus struct would set the mark.
|
|
pStubMsg->MaxCount = *((long *)pStubMsg->BufferMark);
|
|
}
|
|
else
|
|
{
|
|
// Align for the conformance count.
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
pStubMsg->MaxCount = *((long *&)pStubMsg->Buffer)++;
|
|
}
|
|
|
|
// Increment the format string to the offset to array description.
|
|
pFormat += 4;
|
|
|
|
// Get the array's description.
|
|
pFormatArray = pFormat + *((signed short *)pFormat);
|
|
|
|
// Check bounds.
|
|
CHECK_BOUND( (ulong)pStubMsg->MaxCount, pFormatArray[4] & 0x0f );
|
|
|
|
// check for possible mulitplication overflow attack here.
|
|
Size += MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount, *((ushort *)(pFormatArray + 2) ) );
|
|
|
|
// Increment the format string past the offset to array description.
|
|
pFormat += 2;
|
|
|
|
// Realign for struct
|
|
ALIGN(pStubMsg->Buffer, Alignment);
|
|
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, Alignment );
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, Size );
|
|
pStubMsg->Buffer += Size;
|
|
pStubMsg->MemorySize += Size;
|
|
|
|
if ( *pFormat == FC_PP )
|
|
{
|
|
// Mark the beginning of the struct in the buffer.
|
|
pStubMsg->BufferMark = pStubMsg->Buffer - Size;
|
|
|
|
NdrpEmbeddedPointerMemorySize( pStubMsg,
|
|
pFormat );
|
|
}
|
|
|
|
if ( fIsEmbeddedStruct )
|
|
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
|
|
|
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;
|
|
// set by the outermost embedding complex struct
|
|
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
|
|
Size = *((ushort *)(pFormat + 2));
|
|
|
|
// Get the conformance count.
|
|
if ( fIsEmbeddedStruct )
|
|
{
|
|
pStubMsg->MaxCount = *((long *&)pStubMsg->BufferMark);
|
|
}
|
|
else
|
|
{
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
pStubMsg->MaxCount = *((long *&)pStubMsg->Buffer)++;
|
|
}
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
|
|
|
|
// Remember the start of the struct in the buffer.
|
|
pBufferMark = pStubMsg->Buffer;
|
|
|
|
CHECK_EOB_RAISE_IB( pStubMsg->Buffer + Size );
|
|
pStubMsg->Buffer += Size;
|
|
|
|
pStubMsg->MemorySize += Size;
|
|
|
|
pFormat += 4;
|
|
|
|
// Get array's format string description.
|
|
pFormatArray = pFormat + *((signed short *)pFormat);
|
|
|
|
// We always marshal the array, the outer struct will watch for the done flag.
|
|
|
|
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;
|
|
|
|
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
|
|
|
NdrpEmbeddedPointerMemorySize( pStubMsg,
|
|
pFormat );
|
|
}
|
|
|
|
if ( fIsEmbeddedStruct )
|
|
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
|
|
#if 0
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
ushort CopySize;
|
|
|
|
LENGTH_ALIGN(pStubMsg->MemorySize,pFormat[1]);
|
|
|
|
pStubMsg->MemorySize += *((ushort *)&pFormat[2]);
|
|
|
|
ALIGN(pStubMsg->Buffer,pFormat[1]);
|
|
|
|
CopySize = *((ushort *)&pFormat[10]);
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + CopySize );
|
|
pStubMsg->Buffer += CopySize;
|
|
|
|
if ( *((short *)&pFormat[14]) )
|
|
{
|
|
pFormat += 14;
|
|
pFormat += *((short *)pFormat);
|
|
|
|
(*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
|
pFormat );
|
|
}
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
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.
|
|
|
|
Notes:
|
|
This routine can calculate the memory size with or without pointees.
|
|
When calculating size with pointees at the top level, the routine calls
|
|
itself recursively to find out where pointees would be and then remember
|
|
the context using pStubMsg->MemorySize and pStubMsg->PointerBufferMark.
|
|
|
|
--*/
|
|
{
|
|
uchar * pBufferMark;
|
|
PFORMAT_STRING pFormatPointers;
|
|
PFORMAT_STRING pFormatArray;
|
|
PFORMAT_STRING pFormatComplex;
|
|
long Alignment;
|
|
BOOL fSetPointerBufferMark;
|
|
|
|
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
BOOL fEmbedConfStructContext;
|
|
|
|
//
|
|
// 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) )
|
|
{
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
// This gets clobbered.
|
|
uchar * BufferSave = pStubMsg->Buffer;
|
|
ulong MemorySizeSave = pStubMsg->MemorySize;
|
|
|
|
//
|
|
// Get a buffer pointer to where the struct's pointees are.
|
|
//
|
|
(void) NdrComplexStructMemorySize( pStubMsg,
|
|
pFormat );
|
|
|
|
|
|
// Mark where the pointees begin.
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
pStubMsg->PointerLength = pStubMsg->MemorySize;
|
|
|
|
pStubMsg->IgnoreEmbeddedPointers = FALSE;
|
|
|
|
pStubMsg->MemorySize = MemorySizeSave;
|
|
pStubMsg->Buffer = BufferSave;
|
|
}
|
|
|
|
Alignment = pFormat[1];
|
|
|
|
pFormat += 4;
|
|
|
|
fEmbedConfStructContext = fIsEmbeddedStruct;
|
|
|
|
// Get conformant array description.
|
|
if ( *((ushort *)pFormat) )
|
|
{
|
|
ulong ConformanceSize;
|
|
|
|
pFormatArray = pFormat + *((signed short *)pFormat);
|
|
|
|
if ( FixWireRepForDComVerGTE54( pStubMsg ) )
|
|
fEmbedConfStructContext = TRUE;
|
|
|
|
if ( !fIsEmbeddedStruct )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// conformance count marker
|
|
pStubMsg->BufferMark = pStubMsg->Buffer;
|
|
|
|
// Handle multidimensional arrays.
|
|
ConformanceSize = NdrpArrayDimensions( pStubMsg, pFormatArray, FALSE ) * 4;
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + ConformanceSize );
|
|
pStubMsg->Buffer += ConformanceSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pFormatArray = 0;
|
|
}
|
|
|
|
// BufferMark may be set by an outer bogus struct.
|
|
pBufferMark = pStubMsg->BufferMark;
|
|
RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
|
|
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 :
|
|
#if defined(__RPC_WIN64__)
|
|
case FC_INT3264 :
|
|
case FC_UINT3264 :
|
|
#endif
|
|
case FC_FLOAT :
|
|
case FC_HYPER :
|
|
case FC_DOUBLE :
|
|
case FC_ENUM16 :
|
|
case FC_ENUM32 :
|
|
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);
|
|
uchar *pPointerId = pStubMsg->Buffer;
|
|
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
|
|
|
if ( ! pStubMsg->IgnoreEmbeddedPointers )
|
|
{
|
|
POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );
|
|
NdrpPointerMemorySize( pStubMsg,
|
|
pPointerId,
|
|
pFormatPointers );
|
|
|
|
}
|
|
|
|
//
|
|
// 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_ALIGN );
|
|
|
|
pStubMsg->MemorySize += PTR_MEM_SIZE;
|
|
pFormatPointers += 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);
|
|
|
|
if ( FC_IP == *pFormatComplex )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
uchar *pPointerId = pStubMsg->Buffer;
|
|
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
|
|
|
if ( ! pStubMsg->IgnoreEmbeddedPointers )
|
|
{
|
|
POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );
|
|
NdrpPointerMemorySize( pStubMsg,
|
|
pPointerId,
|
|
pFormatComplex );
|
|
|
|
}
|
|
|
|
pStubMsg->MemorySize += PTR_MEM_SIZE;
|
|
pFormat++;
|
|
break;
|
|
|
|
}
|
|
|
|
// Needed for embedded conf structs
|
|
//
|
|
pStubMsg->BufferMark = pBufferMark;
|
|
if ( fEmbedConfStructContext )
|
|
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
|
|
(void) (*pfnMemSizeRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
|
( pStubMsg,
|
|
pFormatComplex );
|
|
|
|
RESET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
//
|
|
// Increment the main format string one byte. The loop
|
|
// will increment it one more byte past the offset field.
|
|
//
|
|
pFormat++;
|
|
|
|
break;
|
|
|
|
case FC_ALIGNM2 :
|
|
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 :
|
|
pStubMsg->MemorySize += (*pFormat - FC_STRUCTPAD1) + 1;
|
|
break;
|
|
|
|
case FC_STRUCTPADN :
|
|
// FC_STRUCTPADN 0 <unsigned short>
|
|
pStubMsg->MemorySize += *(((unsigned short *)pFormat) + 1);
|
|
pFormat += 3;
|
|
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 && !fIsEmbeddedStruct &&
|
|
! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
|
|
{
|
|
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->MemorySize = pStubMsg->PointerLength;
|
|
pStubMsg->PointerBufferMark = 0;
|
|
pStubMsg->PointerLength = 0;
|
|
}
|
|
|
|
if ( fIsEmbeddedStruct )
|
|
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
|
else
|
|
RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
|
|
|
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)++;
|
|
}
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + Size );
|
|
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;
|
|
|
|
// Check bounds.
|
|
CHECK_BOUND( (ulong)pStubMsg->MaxCount, pFormat[4] & 0x0f );
|
|
|
|
ALIGN(pStubMsg->Buffer, pFormat[1]);
|
|
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, pFormat[1] );
|
|
|
|
// Increment to element size.
|
|
pFormat += 2;
|
|
|
|
// Compute array size.
|
|
// check for possible mulitplication overflow attack here.
|
|
Size = MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount, *((ushort *)pFormat) );
|
|
|
|
pFormat += 6;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, Size );
|
|
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;
|
|
PFORMAT_STRING pFormatVar;
|
|
|
|
//
|
|
// 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)++;
|
|
|
|
// Check bounds.
|
|
CHECK_BOUND( (ulong)pStubMsg->MaxCount, pFormat[4] & 0x0f );
|
|
|
|
pFormatVar = pFormat + 8;
|
|
CORRELATION_DESC_INCREMENT( pFormatVar );
|
|
CHECK_BOUND( pStubMsg->ActualCount, *pFormatVar & 0x0f );
|
|
|
|
if ( (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] );
|
|
|
|
// check for possible mulitplication overflow attack here.
|
|
pStubMsg->MemorySize += MultiplyWithOverflowCheck( (ulong)pStubMsg->MaxCount, *((ushort *)(pFormat + 2)) );
|
|
|
|
if ( ! pStubMsg->ActualCount )
|
|
return pStubMsg->MemorySize;
|
|
|
|
ALIGN(pStubMsg->Buffer, pFormat[1]);
|
|
|
|
// Increment to element size.
|
|
pFormat += 2;
|
|
|
|
BufferSize = pStubMsg->ActualCount * *((ushort *)pFormat);
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
|
|
pStubMsg->Buffer += BufferSize;
|
|
|
|
pFormat += 10;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
|
|
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;
|
|
long Elements;
|
|
|
|
//
|
|
// Get the offset and actual count.
|
|
//
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
|
|
pStubMsg->Offset = *((long *&)pStubMsg->Buffer)++;
|
|
pStubMsg->ActualCount = *((long *&)pStubMsg->Buffer)++;
|
|
|
|
// Check bounds using the old part of correlation descr.
|
|
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(pStubMsg->Buffer, Alignment);
|
|
|
|
// check for possible mulitplication overflow attack here.
|
|
BufferSize = MultiplyWithOverflowCheck( pStubMsg->ActualCount , *((ushort *)pFormat) );
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, BufferSize );
|
|
pStubMsg->Buffer += BufferSize;
|
|
|
|
pFormat += 6;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
|
|
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;
|
|
PFORMAT_STRING pFormatPP;
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
pFormatPP = pFormat + 12;
|
|
CORRELATION_DESC_INCREMENT( pFormatPP );
|
|
CORRELATION_DESC_INCREMENT( pFormatPP );
|
|
|
|
fSetPointerBufferMark = ! pStubMsg->IgnoreEmbeddedPointers &&
|
|
! pStubMsg->PointerBufferMark &&
|
|
*pFormatPP != 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 )
|
|
{
|
|
pStubMsg->IgnoreEmbeddedPointers = TRUE;
|
|
|
|
// Save this since it gets clobbered.
|
|
ulong MemorySizeSave = pStubMsg->MemorySize;
|
|
uchar* pBufferSave = pStubMsg->Buffer;
|
|
|
|
//
|
|
// Get a buffer pointer to where the array's pointees are.
|
|
//
|
|
(void) NdrComplexArrayMemorySize( pStubMsg,
|
|
pFormat );
|
|
|
|
|
|
// This is where the array pointees start.
|
|
pStubMsg->PointerBufferMark = pStubMsg->Buffer;
|
|
pStubMsg->PointerLength = pStubMsg->MemorySize;
|
|
pStubMsg->IgnoreEmbeddedPointers = FALSE;
|
|
|
|
pStubMsg->MemorySize = MemorySizeSave;
|
|
pStubMsg->Buffer = pBufferSave;
|
|
}
|
|
|
|
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( pStubMsg, pFormat, FALSE ) * 4;
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
|
|
|
|
}
|
|
|
|
(void) NdrpComplexArrayMemorySize( pStubMsg,
|
|
pFormat );
|
|
|
|
if ( fSetPointerBufferMark )
|
|
{
|
|
pStubMsg->Buffer = pStubMsg->PointerBufferMark;
|
|
pStubMsg->MemorySize = pStubMsg->PointerLength;
|
|
pStubMsg->PointerLength = 0;
|
|
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;
|
|
uchar * pPointerIdMark;
|
|
|
|
bool IsBrokenInterfacePointerFormat = false;
|
|
//
|
|
// 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];
|
|
|
|
// Check bounds
|
|
CHECK_BOUND( Elements, *pFormat & 0x0f );
|
|
}
|
|
|
|
pFormat += 4;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
|
|
//
|
|
// Check for variance description.
|
|
//
|
|
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
|
{
|
|
long Offset;
|
|
|
|
if ( Dimension == 0 )
|
|
{
|
|
ulong VarianceSize;
|
|
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
|
|
// Mark where the variance counts are.
|
|
pArrayInfo->BufferVarianceMark = (unsigned long *)pStubMsg->Buffer;
|
|
|
|
// Handle multidimensional arrays.
|
|
VarianceSize = NdrpArrayDimensions( pStubMsg, pFormatSave, TRUE ) * 8;
|
|
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + VarianceSize );
|
|
pStubMsg->Buffer += VarianceSize;
|
|
}
|
|
|
|
Count = pArrayInfo->BufferVarianceMark[(Dimension * 2) + 1];
|
|
|
|
// Check bounds
|
|
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;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
|
|
//
|
|
// Only align the buffer if at least one element was shipped.
|
|
//
|
|
if ( Count )
|
|
ALIGN(pStubMsg->Buffer,Alignment);
|
|
|
|
pPointerIdMark = 0;
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_EMBEDDED_COMPLEX :
|
|
pFormat += 2;
|
|
pFormat += *((signed short *)pFormat);
|
|
|
|
pfnMemSize = pfnMemSizeRoutines[ROUTINE_INDEX(*pFormat)];
|
|
|
|
if ( FC_IP == *pFormat ) goto HandleInterfacePointer;
|
|
break;
|
|
|
|
case FC_IP :
|
|
HandleInterfacePointer:
|
|
IsBrokenInterfacePointerFormat = !FixWireRepForDComVerGTE54( pStubMsg );
|
|
pPointerIdMark = pStubMsg->Buffer;
|
|
|
|
// Do not leave any space for the pointer if this is
|
|
// the broken format. But do position the pointee as if the
|
|
// pointer was transmitted.
|
|
if ( pStubMsg->IgnoreEmbeddedPointers ||
|
|
!IsBrokenInterfacePointerFormat )
|
|
{
|
|
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, Count * PTR_WIRE_SIZE );
|
|
pStubMsg->Buffer += MultiplyWithOverflowCheck( Count , PTR_WIRE_SIZE );
|
|
}
|
|
goto HandleRefPointer;
|
|
|
|
case FC_UP :
|
|
case FC_FP :
|
|
case FC_OP :
|
|
pPointerIdMark = pStubMsg->Buffer;
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, Count * PTR_WIRE_SIZE );
|
|
pStubMsg->Buffer += MultiplyWithOverflowCheck( Count , PTR_WIRE_SIZE );
|
|
// Fall through
|
|
case FC_RP :
|
|
HandleRefPointer:
|
|
//
|
|
// Add in the size of the array explicitly.
|
|
//
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_ALIGN );
|
|
pStubMsg->MemorySize += MultiplyWithOverflowCheck( Elements, PTR_MEM_SIZE );
|
|
|
|
if ( pStubMsg->IgnoreEmbeddedPointers )
|
|
goto ComplexArrayMemSizeEnd;
|
|
|
|
pfnMemSize = (PMEM_SIZE_ROUTINE) NdrpPointerMemorySize;
|
|
break;
|
|
|
|
case FC_RANGE:
|
|
{
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, SIMPLE_TYPE_ALIGNMENT( pFormat[1] ) );
|
|
ALIGN( pStubMsg->Buffer, SIMPLE_TYPE_ALIGNMENT( pFormat[1] ) );
|
|
|
|
pStubMsg->Buffer += MultiplyWithOverflowCheck( Count, SIMPLE_TYPE_BUFSIZE( pFormat[1] ) );
|
|
pStubMsg->MemorySize += MultiplyWithOverflowCheck( Elements, SIMPLE_TYPE_MEMSIZE( pFormat[1] ) );
|
|
// not really needed as it's checked after memsize is done
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer );
|
|
goto ComplexArrayMemSizeEnd;
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
ulong ByteCount;
|
|
|
|
NDR_ASSERT( IS_SIMPLE_TYPE(*pFormat),
|
|
"NdrpComplexArrayMemorySize : bad format char" );
|
|
|
|
ByteCount = MultiplyWithOverflowCheck( Count , SIMPLE_TYPE_BUFSIZE(*pFormat) );
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_IB( pStubMsg->Buffer, ByteCount );
|
|
pStubMsg->Buffer += ByteCount;
|
|
|
|
if ( *pFormat == FC_ENUM16 )
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, sizeof(int) - 1 );
|
|
else
|
|
LENGTH_ALIGN( pStubMsg->MemorySize,
|
|
SIMPLE_TYPE_ALIGNMENT(*pFormat) );
|
|
|
|
pStubMsg->MemorySize += MultiplyWithOverflowCheck( Elements, SIMPLE_TYPE_MEMSIZE( * pFormat ) );
|
|
|
|
goto ComplexArrayMemSizeEnd;
|
|
}
|
|
}
|
|
|
|
if ( ! IS_ARRAY_OR_STRING(*pFormat) )
|
|
pStubMsg->pArrayInfo = 0;
|
|
|
|
if ( pfnMemSize == (PMEM_SIZE_ROUTINE) NdrpPointerMemorySize )
|
|
{
|
|
|
|
// If the broken format is used, the pointer and pointee
|
|
// are where the pointee should have been.
|
|
if (IsBrokenInterfacePointerFormat)
|
|
SET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
|
|
|
|
POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );
|
|
|
|
for ( ; Count--; pPointerIdMark += PTR_WIRE_SIZE )
|
|
{
|
|
NdrpPointerMemorySize(
|
|
pStubMsg,
|
|
pPointerIdMark,
|
|
pFormat );
|
|
}
|
|
|
|
if (IsBrokenInterfacePointerFormat)
|
|
RESET_BROKEN_INTERFACE_POINTER( pStubMsg->uFlags );
|
|
|
|
}
|
|
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 ) - (uchar*)0 );
|
|
|
|
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 += MultiplyWithOverflowCheck( (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));
|
|
|
|
if ( MemorySize < BufferSize )
|
|
RpcRaiseException( RPC_X_INVALID_BOUND );
|
|
|
|
switch ( *pFormat )
|
|
{
|
|
case FC_WSTRING :
|
|
// Buffer is already aligned on a 4 byte boundary.
|
|
|
|
// Align memory just in case.
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, 0x1 );
|
|
MemorySize = MultiplyWithOverflowCheck( MemorySize, sizeof(wchar_t) );
|
|
BufferSize = MultiplyWithOverflowCheck( BufferSize, sizeof(wchar_t) );
|
|
break;
|
|
case FC_SSTRING :
|
|
MemorySize = MultiplyWithOverflowCheck( MemorySize, pFormat[1] );
|
|
BufferSize = MultiplyWithOverflowCheck ( BufferSize, pFormat[1] );
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, BufferSize );
|
|
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;
|
|
|
|
ALIGN(pStubMsg->Buffer,3);
|
|
|
|
// Skip the offset.
|
|
pStubMsg->Buffer += 4;
|
|
|
|
BufferSize = *((long *&)pStubMsg->Buffer)++;
|
|
|
|
MemorySize = (ulong)pStubMsg->MaxCount;
|
|
|
|
// Check bounds.
|
|
|
|
if ( (*pFormat != FC_C_SSTRING) && (pFormat[1] == FC_STRING_SIZED) )
|
|
CHECK_BOUND( MemorySize, pFormat[2] & 0xf);
|
|
|
|
//
|
|
// 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 );
|
|
MemorySize = MultiplyWithOverflowCheck( MemorySize, sizeof(wchar_t) );
|
|
BufferSize = MultiplyWithOverflowCheck( BufferSize, sizeof(wchar_t) );
|
|
break;
|
|
|
|
case FC_C_SSTRING :
|
|
MemorySize = MultiplyWithOverflowCheck( MemorySize, pFormat[1] );
|
|
BufferSize = MultiplyWithOverflowCheck( BufferSize, pFormat[1] );
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, BufferSize );
|
|
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]);
|
|
|
|
NO_CORRELATION;
|
|
|
|
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;
|
|
CORRELATION_DESC_INCREMENT( pFormat );
|
|
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 :
|
|
// FC_INT3264 gets mapped to FC_LONG
|
|
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 = pFormat[0];
|
|
|
|
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 ( pStubMsg->IgnoreEmbeddedPointers )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
if ( pStubMsg->PointerBufferMark )
|
|
{
|
|
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
uchar *pPointerId = pStubMsg->Buffer;
|
|
pStubMsg->Buffer += PTR_WIRE_SIZE;
|
|
|
|
if ( !pStubMsg->IgnoreEmbeddedPointers )
|
|
{
|
|
POINTER_MEMSIZE_SWAP_CONTEXT SwapContext(pStubMsg);
|
|
(void) NdrpPointerMemorySize( pStubMsg,
|
|
pPointerId,
|
|
pFormat );
|
|
}
|
|
|
|
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
|
|
{
|
|
uchar *PointerBufferMarkSave = pStubMsg->PointerBufferMark;
|
|
pStubMsg->PointerBufferMark = 0;
|
|
NDR_POINTER_QUEUE *pOldQueue = NULL;
|
|
|
|
if ( pStubMsg->pPointerQueueState)
|
|
{
|
|
pOldQueue = pStubMsg->pPointerQueueState->GetActiveQueue();
|
|
pStubMsg->pPointerQueueState->SetActiveQueue(NULL);
|
|
}
|
|
|
|
RpcTryFinally
|
|
{
|
|
(*pfnMemSizeRoutines[ ROUTINE_INDEX( *pFormat) ])( pStubMsg, pFormat );
|
|
}
|
|
RpcFinally
|
|
{
|
|
pStubMsg->PointerBufferMark = PointerBufferMarkSave;
|
|
if ( pStubMsg->pPointerQueueState)
|
|
{
|
|
pStubMsg->pPointerQueueState->SetActiveQueue(pOldQueue);
|
|
}
|
|
}
|
|
RpcEndFinally
|
|
}
|
|
|
|
return( MemorySize );
|
|
}
|
|
|
|
|
|
|
|
void
|
|
NdrpUserMarshalMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
|
|
unsigned long MemorySizeSave;
|
|
|
|
// Flat type.
|
|
// Optimization: if we know the wire size, don't walk to size it.
|
|
|
|
if ( *(unsigned short *)(pFormat + 6) != 0 )
|
|
{
|
|
CHECK_EOB_RAISE_BSD( pStubMsg->Buffer + *(unsigned short *)(pFormat + 6));
|
|
pStubMsg->Buffer += *(unsigned short *)(pFormat + 6);
|
|
return;
|
|
}
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
void
|
|
NDR_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Dispatch(MIDL_STUB_MESSAGE *pStubMsg)
|
|
{
|
|
NdrpUserMarshalMemorySize( pStubMsg,
|
|
pFormat );
|
|
}
|
|
#if defined(DBG)
|
|
void
|
|
NDR_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT::Print()
|
|
{
|
|
DbgPrint("NDR_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT\n");
|
|
DbgPrint("pFormat: %p\n", pFormat );
|
|
}
|
|
#endif
|
|
|
|
|
|
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.
|
|
|
|
// 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 )
|
|
{
|
|
|
|
ulong PointerMarker = 0;
|
|
|
|
if ( (pFormat[1] & USER_MARSHAL_UNIQUE) ||
|
|
((pFormat[1] & USER_MARSHAL_REF) && pStubMsg->PointerBufferMark) )
|
|
{
|
|
PointerMarker = *((unsigned long * &)pStubMsg->Buffer)++;
|
|
}
|
|
|
|
if ( pStubMsg->IgnoreEmbeddedPointers )
|
|
return pStubMsg->MemorySize;
|
|
|
|
if ( (pFormat[1] & USER_MARSHAL_UNIQUE) &&
|
|
!PointerMarker)
|
|
return pStubMsg->MemorySize;
|
|
|
|
if ( !pStubMsg->pPointerQueueState ||
|
|
!pStubMsg->pPointerQueueState->GetActiveQueue() )
|
|
{
|
|
// If we are embedded, switch to the pointee buffer.
|
|
POINTER_MEMSIZE_SWAP_CONTEXT NewContext(pStubMsg);
|
|
|
|
NdrpUserMarshalMemorySize(
|
|
pStubMsg,
|
|
pFormat );
|
|
}
|
|
else
|
|
{
|
|
NDR_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT*pElement =
|
|
new(pStubMsg->pPointerQueueState)
|
|
NDR_USR_MRSHL_MEMSIZE_POINTER_QUEUE_ELEMENT(pFormat );
|
|
pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
|
|
}
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
NdrpUserMarshalMemorySize(
|
|
pStubMsg,
|
|
pFormat );
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
|
|
void
|
|
NdrpInterfacePointerMemorySize (
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
|
|
ALIGN( pStubMsg->Buffer, 3 );
|
|
// Pick up the conformant size and the count field.
|
|
ulong MaxCount = *((unsigned long *&) pStubMsg->Buffer)++;
|
|
ulong Size = *((unsigned long *&) pStubMsg->Buffer)++;
|
|
|
|
//Check the array bounds
|
|
if ( Size != MaxCount )
|
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|
|
|
IStream* pStream = 0;
|
|
|
|
RpcTryFinally
|
|
{
|
|
if (MaxCount > 0)
|
|
{
|
|
CHECK_EOB_WITH_WRAP_RAISE_BSD( pStubMsg->Buffer, MaxCount );
|
|
if ( IS_WALKIP( pStubMsg->uFlags) )
|
|
{
|
|
|
|
#if defined(DEBUG_WALKIP)
|
|
CHAR AppName[MAX_PATH];
|
|
memset(AppName, 0, sizeof(AppName ) );
|
|
GetModuleFileNameA( NULL, AppName, sizeof(AppName ) );
|
|
DbgPrint("WALKIP32 %s %p\n", AppName, pStubMsg->Buffer );
|
|
#else
|
|
pStream = (*NdrpCreateStreamOnMemory)(pStubMsg->Buffer, MaxCount);
|
|
if(pStream == 0)
|
|
RpcRaiseException(RPC_S_OUT_OF_MEMORY);
|
|
|
|
HRESULT hr = (*pfnCoReleaseMarshalData)(pStream);
|
|
|
|
if(FAILED(hr))
|
|
RpcRaiseException(hr);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
}
|
|
RpcFinally
|
|
{
|
|
if ( pStream ) pStream->Release();
|
|
pStubMsg->Buffer += MaxCount;
|
|
}
|
|
RpcEndFinally
|
|
}
|
|
|
|
unsigned long RPC_ENTRY
|
|
NdrInterfacePointerMemorySize (
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
{
|
|
ALIGN(pStubMsg->Buffer,0x3);
|
|
ulong PtrValue = *((long *&)pStubMsg->Buffer)++;
|
|
|
|
LENGTH_ALIGN( pStubMsg->MemorySize, PTR_MEM_ALIGN );
|
|
pStubMsg->MemorySize += PTR_MEM_SIZE;
|
|
|
|
if ( !PtrValue || pStubMsg->IgnoreEmbeddedPointers )
|
|
return pStubMsg->MemorySize;
|
|
|
|
NdrpInterfacePointerMemorySize( pStubMsg,
|
|
pFormat );
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
if ( pStubMsg->IgnoreEmbeddedPointers )
|
|
return;
|
|
|
|
POINTER_MEMSIZE_SWAP_CONTEXT SwapContext( pStubMsg );
|
|
uchar * pBufPtr;
|
|
uchar * pBufferMark;
|
|
uchar * pBufferSave;
|
|
ULONG_PTR MaxCountSave;
|
|
|
|
MaxCountSave = pStubMsg->MaxCount;
|
|
|
|
pBufferMark = pStubMsg->BufferMark;
|
|
|
|
// Increment past the FC_PP and pad.
|
|
pFormat += 2;
|
|
|
|
for (;;)
|
|
{
|
|
|
|
if ( *pFormat == FC_END )
|
|
{
|
|
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 = (ulong)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;
|
|
}
|
|
|
|
|
|
#ifdef _CS_CHAR
|
|
unsigned long RPC_ENTRY
|
|
NdrCsTagMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Computes the memory size required for a cs tag.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer to FC_CS_TAG in the format string.
|
|
|
|
Return :
|
|
|
|
The computed memory size.
|
|
|
|
--*/
|
|
{
|
|
// We need to set the tag in the stub message so that it can be used
|
|
// later for sizing/unmarshalling arrays
|
|
|
|
NdrpGetSetCSTagUnmarshall(
|
|
pStubMsg,
|
|
(NDR_CS_TAG_FORMAT *) pFormat);
|
|
|
|
pStubMsg->Buffer += sizeof( ulong );
|
|
pStubMsg->MemorySize += sizeof( ulong );
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
|
|
|
|
unsigned long RPC_ENTRY
|
|
NdrCsArrayMemorySize(
|
|
PMIDL_STUB_MESSAGE pStubMsg,
|
|
PFORMAT_STRING pFormat )
|
|
/*++
|
|
|
|
Routine Description :
|
|
|
|
Computes the memory size required for a cs_char array.
|
|
|
|
Arguments :
|
|
|
|
pStubMsg - Pointer to stub message.
|
|
pFormat - Pointer to FC_CS_TAG in the format string.
|
|
|
|
Return :
|
|
|
|
The computed memory size.
|
|
|
|
--*/
|
|
{
|
|
NDR_CS_ARRAY_FORMAT *pCSFormat;
|
|
NDR_CS_SIZE_CONVERT_ROUTINES *CSRoutines;
|
|
CS_TYPE_LOCAL_SIZE_ROUTINE LocalSizeRoutine;
|
|
IDL_CS_CONVERT ConversionType;
|
|
ulong ArraySize;
|
|
ulong WireLength;
|
|
error_status_t status;
|
|
|
|
pCSFormat = (NDR_CS_ARRAY_FORMAT *) pFormat;
|
|
|
|
NDR_ASSERT( NULL != pStubMsg->pCSInfo, "cs_char stub info not set up");
|
|
|
|
// Get all the info out of the FC_CS_ARRAY structure and bump pFormat
|
|
// to point to the underlying data descriptor
|
|
|
|
CSRoutines = pStubMsg->StubDesc->CsRoutineTables->pSizeConvertRoutines;
|
|
LocalSizeRoutine = CSRoutines[ pCSFormat->CSRoutineIndex].pfnLocalSize;
|
|
|
|
pFormat += pCSFormat->DescriptionOffset;
|
|
|
|
// Get the size of the data on the wire
|
|
|
|
WireLength = PtrToUlong( NdrpMemoryIncrement( pStubMsg, 0, pFormat ) );
|
|
|
|
LocalSizeRoutine(
|
|
pStubMsg->RpcMsg->Handle,
|
|
pStubMsg->pCSInfo->WireCodeset,
|
|
WireLength,
|
|
&ConversionType,
|
|
&ArraySize,
|
|
&status);
|
|
|
|
if ( RPC_S_OK != status )
|
|
RpcRaiseException( status );
|
|
|
|
pStubMsg->MemorySize += ArraySize * pCSFormat->UserTypeSize;
|
|
|
|
return pStubMsg->MemorySize;
|
|
}
|
|
#endif
|