1864 lines
46 KiB
C++
1864 lines
46 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Copyright (c) 1993-2000 Microsoft Corporation
|
||
|
||
Module Name :
|
||
|
||
free.c
|
||
|
||
Abstract :
|
||
|
||
This file contains the routines called by MIDL 2.0 stubs and the
|
||
interpreter for freeing unmarshalled data on the server.
|
||
|
||
Author :
|
||
|
||
David Kays dkays September 1993.
|
||
|
||
Revision History :
|
||
|
||
---------------------------------------------------------------------*/
|
||
|
||
#include "ndrp.h"
|
||
#include "ndrole.h"
|
||
#include "attack.h"
|
||
#include "pointerq.h"
|
||
|
||
RPCRTAPI
|
||
void
|
||
RPC_ENTRY
|
||
NdrpNoopFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
unsigned char * pMemory,
|
||
PFORMAT_STRING pFormat
|
||
);
|
||
|
||
|
||
//
|
||
// Free routine table.
|
||
//
|
||
extern const
|
||
PFREE_ROUTINE FreeRoutinesTable[] =
|
||
{
|
||
NdrpNoopFree, // 0x00
|
||
NdrpNoopFree, // 0x01
|
||
NdrpNoopFree, // 0x02
|
||
NdrpNoopFree, // 0x03
|
||
NdrpNoopFree, // 0x04
|
||
NdrpNoopFree, // 0x05
|
||
NdrpNoopFree, // 0x06
|
||
NdrpNoopFree, // 0x07
|
||
NdrpNoopFree, // 0x08
|
||
NdrpNoopFree, // 0x09
|
||
NdrpNoopFree, // 0x0A
|
||
NdrpNoopFree, // 0x0B
|
||
NdrpNoopFree, // 0x0C
|
||
NdrpNoopFree, // 0x0D
|
||
NdrpNoopFree, // 0x0E
|
||
NdrpNoopFree, // 0x0F
|
||
NdrpNoopFree, // 0x10
|
||
|
||
NdrPointerFree, // 0x11
|
||
NdrPointerFree, // 0x12
|
||
NdrPointerFree, // 0x13
|
||
NdrPointerFree, // 0x14
|
||
|
||
NdrpNoopFree, // 0x15 Simple struct
|
||
NdrSimpleStructFree, // 0x16
|
||
NdrpNoopFree, // 0x17 Conformant struct
|
||
NdrConformantStructFree, // 0x18
|
||
NdrConformantVaryingStructFree, // 0x19
|
||
|
||
NdrComplexStructFree, // 0x1A
|
||
|
||
NdrConformantArrayFree, // 0x1B
|
||
NdrConformantVaryingArrayFree, // 0x1C
|
||
|
||
NdrFixedArrayFree, // 0x1D
|
||
NdrFixedArrayFree, // 0x1E
|
||
NdrVaryingArrayFree, // 0x1F Small varying array
|
||
NdrVaryingArrayFree, // 0x20 Large varying array
|
||
|
||
NdrComplexArrayFree, // 0x21
|
||
|
||
NdrpNoopFree, // 0x22 Conformant string
|
||
NdrpNoopFree, // 0x23 Conformant string
|
||
NdrpNoopFree, // 0x24 Conformant string
|
||
NdrpNoopFree, // 0x25 Conformant string
|
||
|
||
NdrpNoopFree, // 0x26 NonConformant string
|
||
NdrpNoopFree, // 0x27 NonConformant string
|
||
NdrpNoopFree, // 0x28 NonConformant string
|
||
NdrpNoopFree, // 0x29 NonConformant string
|
||
|
||
NdrEncapsulatedUnionFree, // 0x2A
|
||
NdrNonEncapsulatedUnionFree, // 0x2B
|
||
|
||
NdrByteCountPointerFree, // 0x2C
|
||
|
||
NdrXmitOrRepAsFree, // 0x2D transmit as
|
||
NdrXmitOrRepAsFree, // 0x2E represent as
|
||
|
||
NdrPointerFree, // 0x2F
|
||
|
||
NdrpNoopFree, // 0x30 Context handle
|
||
|
||
// New Post NT 3.5 token serviced from here on.
|
||
|
||
NdrpNoopFree, // 0x31 NdrHardStructFree,
|
||
|
||
NdrXmitOrRepAsFree, // 0x32 transmit as ptr
|
||
NdrXmitOrRepAsFree, // 0x33 represent as ptr
|
||
|
||
NdrUserMarshalFree, // 0x34
|
||
|
||
NdrpNoopFree, // 0x35 FC_PIPE
|
||
NdrpNoopFree, // 0x36 FC_BLK_HOLE
|
||
|
||
NdrpRangeFree, // 0x37
|
||
|
||
NdrpNoopFree, // 0x38
|
||
NdrpNoopFree, // 0x39
|
||
NdrpNoopFree, // 0x3A
|
||
NdrpNoopFree, // 0x3B
|
||
NdrpNoopFree, // 0x3C
|
||
NdrpNoopFree, // 0x3D
|
||
NdrpNoopFree, // 0x3E
|
||
NdrpNoopFree, // 0x3F
|
||
|
||
};
|
||
|
||
extern const
|
||
PFREE_ROUTINE * pfnFreeRoutines = FreeRoutinesTable;
|
||
|
||
RPCRTAPI
|
||
void RPC_ENTRY
|
||
NdrTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
|
||
unsigned char __RPC_FAR * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
if (pfnFreeRoutines[ROUTINE_INDEX(*pFormat)])
|
||
{
|
||
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrpNoopFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a top level or embedded simple type.
|
||
|
||
Used for VT_USERDEFINED but in fact simple types,
|
||
like TKIND_ENUM and TKIND_ALIAS
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
return;
|
||
}
|
||
|
||
inline void
|
||
NdrFreeTypeMemory(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory )
|
||
{
|
||
|
||
if ( !pStubMsg->pPointerQueueState ||
|
||
!pStubMsg->pPointerQueueState->GetActiveQueue() )
|
||
{
|
||
(*pStubMsg->pfnFree)(pMemory);
|
||
}
|
||
else
|
||
{
|
||
NDR_PFNFREE_POINTER_QUEUE_ELEMENT*pElement =
|
||
new(pStubMsg->pPointerQueueState)
|
||
NDR_PFNFREE_POINTER_QUEUE_ELEMENT(pStubMsg->pfnFree,
|
||
pMemory );
|
||
pStubMsg->pPointerQueueState->GetActiveQueue()->Enque( pElement );
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
__forceinline void
|
||
NdrPointerFreeInternal(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a top level or embedded pointer to anything.
|
||
|
||
Used for FC_RP, FC_UP, FC_FP, FC_OP.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatPointee;
|
||
uchar * pMemoryPointee;
|
||
|
||
pMemoryPointee = pMemory;
|
||
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
switch( *pFormat )
|
||
{
|
||
case FC_FP:
|
||
//
|
||
// Check if we've already freed this full pointer.
|
||
//
|
||
if ( ! NdrFullPointerFree( pStubMsg->FullPtrXlatTables,
|
||
pMemory ) )
|
||
return;
|
||
break;
|
||
|
||
case FC_IP:
|
||
if(pMemory != 0)
|
||
{
|
||
((IUnknown *)pMemory)->Release();
|
||
pMemory = 0;
|
||
}
|
||
return;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if ( pFormat[1] == 0 )
|
||
goto FreeEmbeddedPointers;
|
||
|
||
//
|
||
// Check if this pointer and any possible embedded pointers should not
|
||
// be freed.
|
||
//
|
||
if ( DONT_FREE(pFormat[1]) )
|
||
return;
|
||
|
||
//
|
||
// Just go free a pointer to a simple type.
|
||
//
|
||
if ( SIMPLE_POINTER(pFormat[1]) )
|
||
goto FreeTopPointer;
|
||
|
||
//
|
||
// Check if this is an allocate all nodes pointer.
|
||
// IDL symantics say that we only free the top most allocate all nodes
|
||
// pointer on the server even in the [out] only case. So jump to the
|
||
// check for the pointer free at the end of the routine.
|
||
//
|
||
if ( ALLOCATE_ALL_NODES(pFormat[1]) )
|
||
goto FreeTopPointer;
|
||
|
||
if ( POINTER_DEREF(pFormat[1]) )
|
||
pMemoryPointee = *((uchar **)pMemory);
|
||
|
||
FreeEmbeddedPointers:
|
||
|
||
pFormatPointee = pFormat + 2;
|
||
pFormatPointee += *((signed short *)pFormatPointee);
|
||
|
||
//
|
||
// Call the correct free routine if one exists for this type.
|
||
//
|
||
if ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatPointee)] )
|
||
{
|
||
uchar uFlagsSave = pStubMsg->uFlags;
|
||
|
||
RESET_CONF_FLAGS_TO_STANDALONE(pStubMsg->uFlags);
|
||
|
||
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormatPointee)])
|
||
( pStubMsg,
|
||
pMemoryPointee,
|
||
pFormatPointee );
|
||
|
||
pStubMsg->uFlags = uFlagsSave;
|
||
}
|
||
|
||
FreeTopPointer:
|
||
|
||
//
|
||
// Now free the pointer. Pointer guaranteed to be non-null here.
|
||
//
|
||
// We only free the pointer if it lies outside of the message buffer
|
||
// that the server stub received from the RPC runtime. Otherwise we
|
||
// used the RPC buffer to hold the pointer's data and should not free it.
|
||
//
|
||
if ( (pMemory < pStubMsg->BufferStart) || (pMemory > pStubMsg->BufferEnd) )
|
||
{
|
||
//
|
||
// Also check to make sure that the pointer was not allocated on the
|
||
// server stub's stack (this may happen for ref pointers).
|
||
//
|
||
// full pointer can't be allocated on stack (it's possible that
|
||
// an embedded FP points to the stack slot and got free first, and
|
||
// it will try to free the stack memory ). But currently MIDL still
|
||
// generate allocated_on_stack flag for FC_FP. The workaround is
|
||
// that in unmarshall, we always allocate new, and in free, we should
|
||
// free despite the flag.
|
||
if ( ! ALLOCED_ON_STACK(pFormat[1]) || ( *pFormat == FC_FP ))
|
||
{
|
||
|
||
NdrFreeTypeMemory(
|
||
pStubMsg,
|
||
pMemory );
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
NDR_FREE_POINTER_QUEUE_ELEMENT::NDR_FREE_POINTER_QUEUE_ELEMENT(
|
||
MIDL_STUB_MESSAGE *pStubMsg,
|
||
uchar * const pMemoryNew,
|
||
const PFORMAT_STRING pFormatNew) :
|
||
pMemory(pMemoryNew),
|
||
pFormat(pFormatNew),
|
||
Memory(pStubMsg->Memory),
|
||
uFlags(pStubMsg->uFlags)
|
||
{
|
||
|
||
}
|
||
|
||
void
|
||
NDR_FREE_POINTER_QUEUE_ELEMENT::Dispatch(
|
||
MIDL_STUB_MESSAGE *pStubMsg)
|
||
{
|
||
SAVE_CONTEXT<uchar*> MemorySave( pStubMsg->Memory, Memory );
|
||
SAVE_CONTEXT<uchar> uFlagsSave( pStubMsg->uFlags, uFlags );
|
||
|
||
NdrPointerFreeInternal( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
#if defined(DBG)
|
||
void
|
||
NDR_FREE_POINTER_QUEUE_ELEMENT::Print()
|
||
{
|
||
DbgPrint("NDR_FREE_POINTER_QUEUE_ELEMENT\n");
|
||
DbgPrint("pNext: %p\n", pNext );
|
||
DbgPrint("pMemory: %p\n", pMemory );
|
||
DbgPrint("pFormat: %p\n", pFormat );
|
||
DbgPrint("Memory: %p\n", Memory );
|
||
DbgPrint("uFlags: %x\n", uFlags );
|
||
|
||
}
|
||
#endif
|
||
|
||
void
|
||
NdrpEnquePointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
NDR32_POINTER_CONTEXT PointerContext( pStubMsg );
|
||
|
||
RpcTryFinally
|
||
{
|
||
NDR_FREE_POINTER_QUEUE_ELEMENT*pElement =
|
||
new(PointerContext.GetActiveState())
|
||
NDR_FREE_POINTER_QUEUE_ELEMENT(pStubMsg,
|
||
pMemory,
|
||
pFormat);
|
||
PointerContext.Enque( pElement );
|
||
PointerContext.DispatchIfRequired();
|
||
}
|
||
RpcFinally
|
||
{
|
||
PointerContext.EndContext();
|
||
}
|
||
RpcEndFinally
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrPointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
{
|
||
|
||
if ( !NdrIsLowStack(pStubMsg) )
|
||
{
|
||
NdrPointerFreeInternal(
|
||
pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
return;
|
||
}
|
||
|
||
NdrpEnquePointerFree(
|
||
pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
}
|
||
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrpRangeFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
--*/
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrSimpleStructFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a simple structure's embedded pointers which were allocated during
|
||
a remote call.
|
||
|
||
Used for FC_STRUCT and FC_PSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if ( *pFormat == FC_PSTRUCT )
|
||
{
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormat + 4 );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrConformantStructFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a conformant structure's embedded pointers which were allocated
|
||
during a remote call.
|
||
|
||
Used for FC_CSTRUCT and FC_CPSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatArray;
|
||
|
||
if ( *pFormat == FC_CSTRUCT )
|
||
return;
|
||
|
||
// Get a pointer to the conformant array's description.
|
||
pFormatArray = pFormat + 4;
|
||
pFormatArray += *((signed short *)pFormatArray);
|
||
|
||
//
|
||
// Get the conformance count. Pass a memory pointer to the beginning
|
||
// of the array.
|
||
//
|
||
NdrpComputeConformance( pStubMsg,
|
||
pMemory + *((ushort *)(pFormat + 2)),
|
||
pFormatArray );
|
||
|
||
// Must pass a format string pointing to the pointer layout.
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormat + 6 );
|
||
|
||
// Above, we walk the array pointers as well.
|
||
|
||
if ( IS_EMBED_CONF_STRUCT( pStubMsg->uFlags ) )
|
||
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrConformantVaryingStructFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a conformant varying structure's embedded pointers which were
|
||
allocated during a remote call.
|
||
|
||
Used for FC_CVSTRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatArray;
|
||
|
||
if ( *(pFormat + 6) != FC_PP )
|
||
return;
|
||
|
||
//
|
||
// Set the memory pointer to the start of the conformant array/string.
|
||
//
|
||
|
||
// Get the conformant array/string description.
|
||
pFormatArray = pFormat + 4;
|
||
pFormatArray += *((signed short *)pFormatArray);
|
||
|
||
NdrpComputeConformance( pStubMsg,
|
||
pMemory + *((ushort *)(pFormat + 2)),
|
||
pFormatArray );
|
||
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory + *((ushort *)(pFormat + 2)),
|
||
pFormatArray );
|
||
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
// Must pass a format string pointing to the pointer layout.
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormat + 6 );
|
||
|
||
// Above, we walk the array pointers as well.
|
||
|
||
if ( IS_EMBED_CONF_STRUCT( pStubMsg->uFlags ) )
|
||
SET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
}
|
||
|
||
|
||
#if 0
|
||
void RPC_ENTRY
|
||
NdrHardStructFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a hard structure's embedded pointers which were allocated during
|
||
a remote call.
|
||
|
||
Used for FC_HARD_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if ( *((short *)&pFormat[14]) )
|
||
{
|
||
pFormat += 12;
|
||
|
||
pMemory += *((ushort *)pFormat)++;
|
||
|
||
pFormat += *((short *)pFormat);
|
||
|
||
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormat)])( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrComplexStructFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a complex structure's embedded pointers which were allocated during
|
||
a remote call.
|
||
|
||
Used for FC_BOGUS_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uchar * pMemorySave;
|
||
PFORMAT_STRING pFormatPointers;
|
||
PFORMAT_STRING pFormatArray;
|
||
PFORMAT_STRING pFormatComplex;
|
||
long Align8Mod;
|
||
uchar fIsEmbeddedStruct = IS_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
|
||
//
|
||
// This is used for support of structs with doubles passed on an
|
||
// i386 stack.
|
||
//
|
||
// A cast to long is what we need.
|
||
Align8Mod = 0x7 & PtrToLong( pMemory );
|
||
|
||
pMemorySave = pStubMsg->Memory;
|
||
pStubMsg->Memory = pMemory;
|
||
|
||
pFormat += 4;
|
||
|
||
// Get conformant array description.
|
||
if ( *((ushort *)pFormat) )
|
||
pFormatArray = pFormat + *((signed short *)pFormat);
|
||
else
|
||
pFormatArray = 0;
|
||
|
||
pFormat += 2;
|
||
|
||
// Get pointer layout description.
|
||
if ( *((ushort *)pFormat) )
|
||
pFormatPointers = pFormat + *((ushort *)pFormat);
|
||
else
|
||
pFormatPointers = 0;
|
||
|
||
pFormat += 2;
|
||
|
||
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
|
||
//
|
||
// Free 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 :
|
||
pMemory += SIMPLE_TYPE_MEMSIZE(*pFormat);
|
||
break;
|
||
|
||
case FC_POINTER :
|
||
NdrPointerFree( pStubMsg,
|
||
*((uchar **)pMemory),
|
||
pFormatPointers );
|
||
|
||
pMemory += PTR_MEM_SIZE;
|
||
|
||
pFormatPointers += 4;
|
||
break;
|
||
|
||
//
|
||
// Embedded complex types.
|
||
//
|
||
case FC_EMBEDDED_COMPLEX :
|
||
// Add padding.
|
||
pMemory += pFormat[1];
|
||
|
||
pFormat += 2;
|
||
|
||
// Get the type's description.
|
||
pFormatComplex = pFormat + *((signed short UNALIGNED *)pFormat);
|
||
|
||
if ( pfnFreeRoutines[ROUTINE_INDEX(*pFormatComplex)] )
|
||
{
|
||
(*pfnFreeRoutines[ROUTINE_INDEX(*pFormatComplex)])
|
||
( pStubMsg,
|
||
(*pFormatComplex == FC_IP) ? *(uchar **)pMemory : pMemory,
|
||
pFormatComplex );
|
||
}
|
||
|
||
pMemory = NdrpMemoryIncrement( pStubMsg,
|
||
pMemory,
|
||
pFormatComplex );
|
||
|
||
//
|
||
// Increment the main format string one byte. The loop
|
||
// will increment it one more byte past the offset field.
|
||
//
|
||
pFormat++;
|
||
|
||
break;
|
||
|
||
case FC_ALIGNM2 :
|
||
ALIGN( pMemory, 0x1 );
|
||
break;
|
||
|
||
case FC_ALIGNM4 :
|
||
ALIGN( pMemory, 0x3 );
|
||
break;
|
||
|
||
case FC_ALIGNM8 :
|
||
//
|
||
// We have to play some tricks for the i386 to handle the case
|
||
// when an 8 byte aligned structure is passed by value. The
|
||
// alignment of the struct on the stack is not guaranteed to be
|
||
// on an 8 byte boundary.
|
||
//
|
||
pMemory -= Align8Mod;
|
||
ALIGN( pMemory, 0x7 );
|
||
pMemory += Align8Mod;
|
||
|
||
break;
|
||
|
||
case FC_STRUCTPAD1 :
|
||
case FC_STRUCTPAD2 :
|
||
case FC_STRUCTPAD3 :
|
||
case FC_STRUCTPAD4 :
|
||
case FC_STRUCTPAD5 :
|
||
case FC_STRUCTPAD6 :
|
||
case FC_STRUCTPAD7 :
|
||
pMemory += (*pFormat - FC_STRUCTPAD1) + 1;
|
||
break;
|
||
|
||
case FC_STRUCTPADN :
|
||
// FC_STRUCTPADN 0 <unsigned short>
|
||
pMemory += *(((unsigned short *)pFormat) + 1);
|
||
pFormat += 3;
|
||
break;
|
||
|
||
case FC_PAD :
|
||
break;
|
||
|
||
//
|
||
// Done with layout.
|
||
//
|
||
case FC_END :
|
||
goto ComplexFreeEnd;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrComplexStructFree : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return;
|
||
} // switch
|
||
} // for
|
||
|
||
ComplexFreeEnd :
|
||
|
||
// Walk the array at the top level only.
|
||
|
||
if ( pFormatArray && !fIsEmbeddedStruct &&
|
||
! IS_CONF_ARRAY_DONE( pStubMsg->uFlags ) )
|
||
{
|
||
PFREE_ROUTINE pfnFree;
|
||
|
||
switch ( *pFormatArray )
|
||
{
|
||
case FC_CARRAY :
|
||
pfnFree = NdrConformantArrayFree;
|
||
break;
|
||
|
||
case FC_CVARRAY :
|
||
pfnFree = NdrConformantVaryingArrayFree;
|
||
break;
|
||
|
||
case FC_BOGUS_ARRAY :
|
||
pfnFree = NdrComplexArrayFree;
|
||
break;
|
||
|
||
// case FC_C_CSTRING :
|
||
// case FC_C_BSTRING :
|
||
// case FC_C_WSTRING :
|
||
// case FC_C_SSTRING :
|
||
|
||
default :
|
||
pfnFree = 0;
|
||
break;
|
||
}
|
||
|
||
if ( pfnFree )
|
||
{
|
||
(*pfnFree)( pStubMsg,
|
||
pMemory,
|
||
pFormatArray );
|
||
}
|
||
}
|
||
|
||
if ( fIsEmbeddedStruct )
|
||
SET_EMBED_CONF_STRUCT( pStubMsg->uFlags );
|
||
else
|
||
RESET_CONF_ARRAY_DONE( pStubMsg->uFlags );
|
||
|
||
pStubMsg->Memory = pMemorySave;
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrFixedArrayFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a fixed array's embedded pointers which were allocated during
|
||
a remote call.
|
||
|
||
Used for FC_SMFARRAY and FC_LGFARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// We have to check this in case we get an exception before actually
|
||
// unmarshalling the array.
|
||
//
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
if ( *pFormat == FC_SMFARRAY )
|
||
pFormat += 4;
|
||
else // *pFormat == FC_LGFARRAY
|
||
pFormat += 6;
|
||
|
||
if ( *pFormat == FC_PP )
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrConformantArrayFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a one dimensional conformant array's embedded pointers which were
|
||
allocated during a remote call. Called for both top level and embedded
|
||
conformant arrays.
|
||
|
||
Used for FC_CARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatPP;
|
||
|
||
//
|
||
// We have to check this in case we get an exception before actually
|
||
// unmarshalling the array.
|
||
//
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
pFormatPP = pFormat + 8;
|
||
CORRELATION_DESC_INCREMENT( pFormatPP );
|
||
|
||
if ( *pFormatPP == FC_PP )
|
||
{
|
||
NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormatPP );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrConformantVaryingArrayFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a one dimensional conformant varying array's embedded pointers which
|
||
were allocated during a remote call. Called for both top level and
|
||
embedded conformant varying arrays.
|
||
|
||
Used for FC_CVARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatPP;
|
||
|
||
//
|
||
// We have to check this in case we get an exception before actually
|
||
// unmarshalling the array.
|
||
//
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
pFormatPP = pFormat + 12;
|
||
CORRELATION_DESC_INCREMENT( pFormatPP );
|
||
CORRELATION_DESC_INCREMENT( pFormatPP );
|
||
|
||
if ( *(pFormatPP) == FC_PP )
|
||
{
|
||
NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
//
|
||
// Set MaxCount equal to the number of shipped elements.
|
||
//
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormatPP );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrVaryingArrayFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a varying array's embedded pointers which were allocated
|
||
during a remote call. Called for both top level and embedded varying
|
||
arrays.
|
||
|
||
|
||
Used for FC_SMVARRAY and FC_LGVARRAY.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PFORMAT_STRING pFormatPointers;
|
||
|
||
//
|
||
// We have to check this in case we get an exception before actually
|
||
// unmarshalling the array.
|
||
//
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
if ( *pFormat == FC_SMVARRAY )
|
||
pFormatPointers = pFormat + 12;
|
||
else // *pFormat == FC_LGVARRAY
|
||
pFormatPointers = pFormat + 16;
|
||
CORRELATION_DESC_INCREMENT( pFormatPointers );
|
||
|
||
if ( *pFormatPointers == FC_PP )
|
||
{
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
//
|
||
// Set MaxCount equal to the number of shipped elements.
|
||
//
|
||
pStubMsg->MaxCount = pStubMsg->ActualCount;
|
||
|
||
NdrpEmbeddedPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormatPointers );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrComplexArrayFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a complex array's embedded pointers which were allocated
|
||
during a remote call. Called for both top level and embedded complex
|
||
arrays.
|
||
|
||
Used for FC_BOGUS_STRUCT.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ARRAY_INFO ArrayInfo;
|
||
PARRAY_INFO pArrayInfo;
|
||
PFREE_ROUTINE pfnFree;
|
||
PFORMAT_STRING pFormatStart;
|
||
uchar * pMemorySave;
|
||
ulong Elements;
|
||
ulong Offset, Count;
|
||
ulong MemoryElementSize;
|
||
long Dimension;
|
||
|
||
//
|
||
// We have to check this in case we get an exception before actually
|
||
// unmarshalling the array.
|
||
//
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
//
|
||
// Lots of 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;
|
||
ArrayInfo.MaxCountArray = (unsigned long *) pStubMsg->MaxCount;
|
||
ArrayInfo.OffsetArray = (ulong *) UlongToPtr( pStubMsg->Offset );
|
||
ArrayInfo.ActualCountArray = (ulong *) UlongToPtr( pStubMsg->ActualCount );
|
||
}
|
||
|
||
pArrayInfo = pStubMsg->pArrayInfo;
|
||
|
||
Dimension = pArrayInfo->Dimension;
|
||
|
||
pFormatStart = pFormat;
|
||
|
||
pFormat += 2;
|
||
|
||
// Get number of elements (0 if conformance present).
|
||
Elements = *((ushort *&)pFormat)++;
|
||
|
||
//
|
||
// Check for conformance description.
|
||
//
|
||
if ( *((long UNALIGNED *&)pFormat) != 0xffffffff )
|
||
{
|
||
Elements = (ulong) NdrpComputeConformance( pStubMsg,
|
||
pMemory,
|
||
pFormatStart );
|
||
}
|
||
|
||
pFormat += 4;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
//
|
||
// Check for variance description.
|
||
//
|
||
if ( *((long UNALIGNED *)pFormat) != 0xffffffff )
|
||
{
|
||
NdrpComputeVariance( pStubMsg,
|
||
pMemory,
|
||
pFormatStart );
|
||
|
||
Offset = pStubMsg->Offset;
|
||
Count = pStubMsg->ActualCount;
|
||
}
|
||
else
|
||
{
|
||
Offset = 0;
|
||
Count = Elements;
|
||
}
|
||
|
||
pFormat += 4;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
|
||
switch ( *pFormat )
|
||
{
|
||
case FC_EMBEDDED_COMPLEX :
|
||
pFormat += 2;
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
if ( ! (pfnFree = pfnFreeRoutines[ROUTINE_INDEX(*pFormat)]) )
|
||
goto ComplexArrayFreeEnd;
|
||
|
||
pArrayInfo->Dimension = Dimension + 1;
|
||
|
||
MemoryElementSize = (ulong)
|
||
( NdrpMemoryIncrement( pStubMsg,
|
||
pMemory,
|
||
pFormat ) - pMemory );
|
||
break;
|
||
|
||
case FC_RP :
|
||
case FC_UP :
|
||
case FC_FP :
|
||
case FC_OP :
|
||
pfnFree = NdrPointerFree;
|
||
|
||
// Need this in case we have a variant offset.
|
||
MemoryElementSize = PTR_MEM_SIZE;
|
||
break;
|
||
|
||
case FC_IP :
|
||
pfnFree = NdrInterfacePointerFree;
|
||
|
||
// Need this in case we have a variant offset.
|
||
MemoryElementSize = PTR_MEM_SIZE;
|
||
break;
|
||
|
||
default :
|
||
// Must be a basetype.
|
||
goto ComplexArrayFreeEnd;
|
||
}
|
||
|
||
pMemorySave = pMemory;
|
||
|
||
//
|
||
// If there is variance then increment the memory pointer to the first
|
||
// element actually being marshalled.
|
||
//
|
||
if ( Offset )
|
||
pMemory += Offset * MemoryElementSize;
|
||
|
||
if ( pfnFree == NdrPointerFree )
|
||
{
|
||
pStubMsg->pArrayInfo = 0;
|
||
|
||
for(; Count--; )
|
||
{
|
||
|
||
NdrPointerFree( pStubMsg,
|
||
*((uchar **)pMemory),
|
||
pFormat );
|
||
|
||
// Increment the memory pointer by the element size.
|
||
pMemory += PTR_MEM_SIZE;
|
||
|
||
}
|
||
|
||
goto ComplexArrayFreeEnd;
|
||
}
|
||
|
||
if ( ! IS_ARRAY_OR_STRING(*pFormat) )
|
||
pStubMsg->pArrayInfo = 0;
|
||
|
||
for ( ; Count--; )
|
||
{
|
||
// Keep track of multidimensional array dimension.
|
||
if ( IS_ARRAY_OR_STRING(*pFormat) )
|
||
pArrayInfo->Dimension = Dimension + 1;
|
||
|
||
(*pfnFree)( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Increment the memory pointer by the element size.
|
||
pMemory += MemoryElementSize;
|
||
}
|
||
|
||
ComplexArrayFreeEnd:
|
||
|
||
// pArrayInfo must be zero when not valid.
|
||
pStubMsg->pArrayInfo = (Dimension == 0) ? 0 : pArrayInfo;
|
||
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrEncapsulatedUnionFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees an encapsulated union's embedded pointers which were allocated
|
||
during a remote call.
|
||
|
||
Used for FC_ENCAPSULATED_UNION.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long SwitchIs;
|
||
|
||
NO_CORRELATION;
|
||
|
||
switch ( LOW_NIBBLE(pFormat[1]) )
|
||
{
|
||
case FC_SMALL :
|
||
case FC_CHAR :
|
||
SwitchIs = (long) *((char *)pMemory);
|
||
break;
|
||
case FC_USMALL :
|
||
SwitchIs = (long) *((uchar *)pMemory);
|
||
break;
|
||
|
||
case FC_ENUM16 :
|
||
case FC_SHORT :
|
||
SwitchIs = (long) *((short *)pMemory);
|
||
break;
|
||
|
||
case FC_USHORT :
|
||
case FC_WCHAR :
|
||
SwitchIs = (long) *((ushort *)pMemory);
|
||
break;
|
||
case FC_LONG :
|
||
case FC_ULONG :
|
||
case FC_ENUM32 :
|
||
// FC_INT3264 gets mapped to FC_LONG.
|
||
SwitchIs = *((long *)pMemory);
|
||
break;
|
||
default :
|
||
NDR_ASSERT(0,"NdrEncapsulatedUnionFree : bad switch type");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return;
|
||
}
|
||
|
||
// Increment memory pointer to the union.
|
||
pMemory += HIGH_NIBBLE(pFormat[1]);
|
||
|
||
NdrpUnionFree( pStubMsg,
|
||
pMemory,
|
||
pFormat + 2,
|
||
SwitchIs );
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrNonEncapsulatedUnionFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a non-encapsulated union's embedded pointers which were allocated
|
||
during a remote call.
|
||
|
||
Used for FC_NON_ENCAPSULATED_UNION.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long SwitchIs;
|
||
|
||
SwitchIs = (ulong) NdrpComputeSwitchIs( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
//
|
||
// Set the format string to the memory size and arm description.
|
||
//
|
||
pFormat += 6;
|
||
CORRELATION_DESC_INCREMENT( pFormat );
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
NdrpUnionFree( pStubMsg,
|
||
pMemory,
|
||
pFormat,
|
||
SwitchIs );
|
||
}
|
||
|
||
|
||
void
|
||
NdrpUnionFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat,
|
||
long SwitchIs )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Private routine shared by encapsulated and non-encapsulated unions for
|
||
freeing a union's embedded pointers which were allocated during a remote
|
||
call.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
SwitchIs - The union's switch is.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
long Arms;
|
||
PFREE_ROUTINE pfnFree;
|
||
|
||
// Skip the memory size field.
|
||
pFormat += 2;
|
||
|
||
Arms = (long) ( *((ushort *&)pFormat)++ & 0x0fff );
|
||
|
||
//
|
||
// Search for the 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) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Return if the arm is empty.
|
||
//
|
||
if ( ! *((ushort *)pFormat) )
|
||
return;
|
||
|
||
//
|
||
// Get the arm's description.
|
||
//
|
||
// We need a real solution after beta for simple type arms. This could
|
||
// break if we have a format string larger than about 32K.
|
||
//
|
||
if ( IS_MAGIC_UNION_BYTE(pFormat) )
|
||
return;
|
||
|
||
pFormat += *((signed short *)pFormat);
|
||
|
||
//
|
||
// If the union arm we take is a pointer, we have to dereference the
|
||
// current memory pointer since we're passed a pointer to the union
|
||
// (regardless of whether the actual parameter was a by-value union
|
||
// or a pointer to a union).
|
||
//
|
||
if ( IS_POINTER_TYPE(*pFormat) )
|
||
pMemory = *((uchar **)pMemory);
|
||
|
||
if ( pfnFree = pfnFreeRoutines[ROUTINE_INDEX(*pFormat)] )
|
||
{
|
||
(*pfnFree)( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrByteCountPointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees a byte count pointer.
|
||
|
||
Used for FC_BYTE_COUNT_POINTER.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if ( ! pMemory )
|
||
return;
|
||
|
||
//
|
||
// Free it if we didn't use the rpc buffer for it.
|
||
//
|
||
if ( (pMemory < pStubMsg->BufferStart) || (pMemory > pStubMsg->BufferEnd) )
|
||
(*pStubMsg->pfnFree)(pMemory);
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrXmitOrRepAsFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees the transmit-as object (actually the presented type instance)
|
||
and steps over the object.
|
||
|
||
There is an exceptional situation where the spec forbids stub to free
|
||
the instance. This happens when there is an [in] only parameter with
|
||
a [transmit_as()] on a component of the parameter, and the presented
|
||
typedef is composed of one or more pointers.
|
||
We have a flag in the stub msg that is set when this happens.
|
||
|
||
See mrshl.c for the description of the FC layout.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
const XMIT_ROUTINE_QUINTUPLE * pQuintuple;
|
||
unsigned short QIndex;
|
||
|
||
// Skip the token itself and Oi flag. Fetch the QuintupleIndex.
|
||
|
||
QIndex = *(unsigned short *)(pFormat + 2);
|
||
pQuintuple = pStubMsg->StubDesc->aXmitQuintuple;
|
||
|
||
// Free the presented type instance unless forbidden explicitely.
|
||
|
||
if ( ! pStubMsg->fDontCallFreeInst )
|
||
{
|
||
pStubMsg->pPresentedType = pMemory;
|
||
pQuintuple[ QIndex ].pfnFreeInst( pStubMsg );
|
||
}
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrUserMarshalFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees the usr_marshal object and steps over the object.
|
||
See mrshl.c for the description of the layouts.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
const USER_MARSHAL_ROUTINE_QUADRUPLE * pQuadruple;
|
||
unsigned short QIndex;
|
||
USER_MARSHAL_CB UserMarshalCB;
|
||
|
||
QIndex = *(unsigned short *)(pFormat + 2);
|
||
pQuadruple = pStubMsg->StubDesc->aUserMarshalQuadruple;
|
||
|
||
// Call the user to free his stuff.
|
||
|
||
NdrpInitUserMarshalCB( pStubMsg,
|
||
pFormat,
|
||
USER_MARSHAL_CB_FREE,
|
||
& UserMarshalCB);
|
||
|
||
// The user shouldn't ever free the top level object as we free it.
|
||
// He should free only pointees of his top level object.
|
||
|
||
pQuadruple[ QIndex ].pfnFree( (ulong*) &UserMarshalCB, pMemory );
|
||
|
||
// NdrpMemoryIncrement steps over the memory object.
|
||
}
|
||
|
||
|
||
void RPC_ENTRY
|
||
NdrInterfacePointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees any memory associated with an interface pointer.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Interface pointer.
|
||
pFormat - Interface pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if(pMemory != 0)
|
||
{
|
||
((IUnknown *)pMemory)->Release();
|
||
pMemory = 0;
|
||
}
|
||
}
|
||
|
||
|
||
void
|
||
NdrpEmbeddedPointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees an array's or a structure's embedded pointers which were allocated
|
||
during a remote call.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
uchar ** ppMemPtr;
|
||
uchar * pMemorySave;
|
||
ULONG_PTR MaxCountSave;
|
||
long OffsetSave;
|
||
|
||
MaxCountSave = pStubMsg->MaxCount;
|
||
OffsetSave = pStubMsg->Offset;
|
||
|
||
pMemorySave = pStubMsg->Memory;
|
||
|
||
pStubMsg->Memory = pMemory;
|
||
|
||
// Increment past the FC_PP and pad.
|
||
pFormat += 2;
|
||
|
||
for (;;)
|
||
{
|
||
if ( *pFormat == FC_END )
|
||
{
|
||
pStubMsg->Memory = pMemorySave;
|
||
break;
|
||
}
|
||
|
||
// Check for FC_FIXED_REPEAT or FC_VARIABLE_REPEAT.
|
||
if ( *pFormat != FC_NO_REPEAT )
|
||
{
|
||
pStubMsg->MaxCount = MaxCountSave;
|
||
pStubMsg->Offset = OffsetSave;
|
||
|
||
pFormat = NdrpEmbeddedRepeatPointerFree( pStubMsg,
|
||
pMemory,
|
||
pFormat );
|
||
|
||
// Continue loop to next pointer.
|
||
continue;
|
||
}
|
||
|
||
// Get the pointer to the pointer to free.
|
||
ppMemPtr = (uchar **)( pMemory + *((signed short *)(pFormat + 2)) );
|
||
|
||
// Increment to pointer description.
|
||
pFormat += 6;
|
||
|
||
NdrPointerFree(
|
||
pStubMsg,
|
||
*ppMemPtr,
|
||
pFormat );
|
||
|
||
// Increment to the next pointer description.
|
||
pFormat += 4;
|
||
}
|
||
}
|
||
|
||
|
||
PFORMAT_STRING
|
||
NdrpEmbeddedRepeatPointerFree(
|
||
PMIDL_STUB_MESSAGE pStubMsg,
|
||
uchar * pMemory,
|
||
PFORMAT_STRING pFormat )
|
||
/*++
|
||
|
||
Routine Description :
|
||
|
||
Frees an array's embedded pointers which were allocated during a remote
|
||
call.
|
||
|
||
Arguments :
|
||
|
||
pStubMsg - Pointer to the stub message.
|
||
pMemory - Pointer to be freed.
|
||
pFormat - Pointer's format string description.
|
||
|
||
Return :
|
||
|
||
Format string pointer after the array's pointer description.
|
||
|
||
--*/
|
||
{
|
||
uchar ** ppMemPtr;
|
||
uchar * pMemorySave;
|
||
PFORMAT_STRING pFormatSave;
|
||
ulong RepeatCount, RepeatIncrement, Pointers, PointersSave;
|
||
|
||
pMemorySave = pStubMsg->Memory;
|
||
|
||
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;
|
||
|
||
//
|
||
// Check if this variable repeat instance also has a variable
|
||
// offset (this would be the case for a conformant varying array
|
||
// of pointers). If so then increment the memory pointer to point
|
||
// to the actual first array element which is being marshalled.
|
||
//
|
||
if ( pFormat[1] == FC_VARIABLE_OFFSET )
|
||
pMemory += *((ushort *)(pFormat + 2)) * pStubMsg->Offset;
|
||
|
||
// else pFormat[1] == FC_FIXED_OFFSET - do nothing
|
||
|
||
// Move the format string to the increment field.
|
||
pFormat += 2;
|
||
|
||
break;
|
||
|
||
default :
|
||
NDR_ASSERT(0,"NdrEmbeddedRepeatPointerFree : bad format char");
|
||
RpcRaiseException( RPC_S_INTERNAL_ERROR );
|
||
return 0;
|
||
}
|
||
|
||
// Get the increment amount between successive pointers.
|
||
// This is actually increment to the next element, same position.
|
||
RepeatIncrement = *((ushort *&)pFormat)++;
|
||
|
||
//
|
||
// Add the offset to the beginning of this array to the Memory
|
||
// pointer. This is the offset from the current embedding structure
|
||
// to the array whose pointers we're marshalling.
|
||
//
|
||
pStubMsg->Memory += *((ushort *&)pFormat)++;
|
||
|
||
// Get the number of pointers in this repeat instance.
|
||
PointersSave = Pointers = *((ushort *&)pFormat)++;
|
||
|
||
pFormatSave = pFormat;
|
||
|
||
//
|
||
// Loop over the number of array elements.
|
||
//
|
||
for ( ; RepeatCount--;
|
||
pMemory += RepeatIncrement,
|
||
pStubMsg->Memory += RepeatIncrement )
|
||
{
|
||
pFormat = pFormatSave;
|
||
Pointers = PointersSave;
|
||
|
||
//
|
||
// Loop over the number of pointers per array element (this can be
|
||
// zero for an array of structures).
|
||
//
|
||
for ( ; Pointers--; )
|
||
{
|
||
ppMemPtr = (uchar **)(pMemory + *((signed short *)pFormat));
|
||
|
||
// Increment to pointer's description.
|
||
pFormat += 4;
|
||
|
||
NdrPointerFree(
|
||
pStubMsg,
|
||
*ppMemPtr,
|
||
pFormat );
|
||
|
||
// Increment to the next pointer's offset_in_memory.
|
||
pFormat += 4;
|
||
}
|
||
}
|
||
|
||
pStubMsg->Memory = pMemory;
|
||
|
||
// Return format string pointer past the array's pointer layout.
|
||
return pFormatSave + PointersSave * 8;
|
||
}
|
||
|
||
|