720 lines
20 KiB
C++
720 lines
20 KiB
C++
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|||
|
|
|||
|
Copyright (c) 1993 Microsoft Corporation
|
|||
|
|
|||
|
Module Name :
|
|||
|
|
|||
|
fullptr.c
|
|||
|
|
|||
|
Abstract :
|
|||
|
|
|||
|
This file contains the APIs for handling full pointers in the NDR engine
|
|||
|
and inlined stubs for MIDL 2.0.
|
|||
|
|
|||
|
Author :
|
|||
|
|
|||
|
David Kays dkays January 1994.
|
|||
|
|
|||
|
Revision History :
|
|||
|
|
|||
|
---------------------------------------------------------------------*/
|
|||
|
|
|||
|
#include "ndrp.h"
|
|||
|
|
|||
|
static void
|
|||
|
NdrFullPointerXlatRealloc ( PFULL_PTR_XLAT_TABLES pXlatTables, ulong RefId );
|
|||
|
|
|||
|
|
|||
|
PFULL_PTR_XLAT_TABLES RPC_ENTRY
|
|||
|
NdrFullPointerXlatInit(
|
|||
|
ulong NumberOfPointers,
|
|||
|
XLAT_SIDE XlatSide )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
Allocates full pointer support data structures for an RPC call.
|
|||
|
|
|||
|
Arguments :
|
|||
|
|
|||
|
NumberOfPointer - If possible, the stub passes in the total number
|
|||
|
of possible full pointers that will be used during a call.
|
|||
|
|
|||
|
Return value :
|
|||
|
|
|||
|
A pointer to the full pointer translations tables used during an rpc call.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables;
|
|||
|
uint RefIdToPointerEntries;
|
|||
|
uint PointerToRefIdBuckets;
|
|||
|
BOOL fOutOfMemory = FALSE;
|
|||
|
|
|||
|
pXlatTables = (PFULL_PTR_XLAT_TABLES)
|
|||
|
I_RpcAllocate(sizeof(FULL_PTR_XLAT_TABLES));
|
|||
|
|
|||
|
// Because old compilers didn't initialize the xlat ptr in stubmsg
|
|||
|
// at the client in Os mode, we cannot raise exception right away.
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
fOutOfMemory = TRUE;
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Determine the size of both translation tables.
|
|||
|
//
|
|||
|
if ( NumberOfPointers )
|
|||
|
{
|
|||
|
ulong Shift, Bitmask;
|
|||
|
|
|||
|
RefIdToPointerEntries = (uint) NumberOfPointers;
|
|||
|
|
|||
|
//
|
|||
|
// Find the smallest power of 2 which is greater than
|
|||
|
// RefIdToPointerEntries.
|
|||
|
//
|
|||
|
for ( Shift = 0, Bitmask = 0x80000000;
|
|||
|
! (Bitmask & (ulong) RefIdToPointerEntries);
|
|||
|
Shift++, Bitmask >>= 1 )
|
|||
|
;
|
|||
|
|
|||
|
PointerToRefIdBuckets = (uint)((0xffffffff >> Shift) + 1);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
RefIdToPointerEntries = DEFAULT_REF_ID_TO_POINTER_TABLE_ELEMENTS;
|
|||
|
PointerToRefIdBuckets = DEFAULT_POINTER_TO_REF_ID_TABLE_BUCKETS;
|
|||
|
}
|
|||
|
|
|||
|
// Make sure we can clean up correctly later if case of an exception.
|
|||
|
|
|||
|
pXlatTables->RefIdToPointer.XlatTable = 0;
|
|||
|
pXlatTables->RefIdToPointer.StateTable = 0;
|
|||
|
pXlatTables->PointerToRefId.XlatTable = 0;
|
|||
|
pXlatTables->RefIdToPointer.NumberOfEntries = 0;
|
|||
|
pXlatTables->PointerToRefId.NumberOfBuckets = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the ref id to pointer tables.
|
|||
|
//
|
|||
|
pXlatTables->RefIdToPointer.XlatTable =
|
|||
|
(void **) I_RpcAllocate( RefIdToPointerEntries * sizeof(void *) );
|
|||
|
|
|||
|
if ( ! pXlatTables->RefIdToPointer.XlatTable )
|
|||
|
fOutOfMemory = TRUE;
|
|||
|
else
|
|||
|
{
|
|||
|
MIDL_memset( pXlatTables->RefIdToPointer.XlatTable,
|
|||
|
0,
|
|||
|
RefIdToPointerEntries * sizeof(void *) );
|
|||
|
|
|||
|
pXlatTables->RefIdToPointer.StateTable =
|
|||
|
(uchar *) I_RpcAllocate( RefIdToPointerEntries * sizeof(uchar) );
|
|||
|
|
|||
|
if ( ! pXlatTables->RefIdToPointer.StateTable )
|
|||
|
fOutOfMemory = TRUE;
|
|||
|
else
|
|||
|
{
|
|||
|
MIDL_memset( pXlatTables->RefIdToPointer.StateTable,
|
|||
|
0,
|
|||
|
RefIdToPointerEntries * sizeof(uchar) );
|
|||
|
|
|||
|
pXlatTables->RefIdToPointer.NumberOfEntries = RefIdToPointerEntries;
|
|||
|
|
|||
|
//
|
|||
|
// Intialize the pointer to ref id tables.
|
|||
|
//
|
|||
|
pXlatTables->PointerToRefId.XlatTable =
|
|||
|
(PFULL_PTR_TO_REFID_ELEMENT *)
|
|||
|
I_RpcAllocate( PointerToRefIdBuckets *
|
|||
|
sizeof(PFULL_PTR_TO_REFID_ELEMENT) );
|
|||
|
|
|||
|
if ( ! pXlatTables->PointerToRefId.XlatTable )
|
|||
|
fOutOfMemory = TRUE;
|
|||
|
else
|
|||
|
{
|
|||
|
MIDL_memset( pXlatTables->PointerToRefId.XlatTable,
|
|||
|
0,
|
|||
|
PointerToRefIdBuckets * sizeof(PFULL_PTR_TO_REFID_ELEMENT) );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( fOutOfMemory )
|
|||
|
{
|
|||
|
NdrFullPointerXlatFree( pXlatTables );
|
|||
|
|
|||
|
if ( XlatSide == XLAT_SERVER )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
else
|
|||
|
{
|
|||
|
// The old compilers generate a code for the client side that
|
|||
|
// doesn't initialize the table pointer and the stub msg
|
|||
|
// initialization is after call to xlat initialize.
|
|||
|
// So, we are down to checking the pointer when used.
|
|||
|
|
|||
|
return( 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pXlatTables->PointerToRefId.NumberOfBuckets = PointerToRefIdBuckets;
|
|||
|
pXlatTables->PointerToRefId.HashMask = PointerToRefIdBuckets - 1;
|
|||
|
|
|||
|
pXlatTables->NextRefId = 1;
|
|||
|
|
|||
|
pXlatTables->XlatSide = XlatSide;
|
|||
|
|
|||
|
return pXlatTables;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void RPC_ENTRY
|
|||
|
NdrFullPointerXlatFree(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
Free the full pointer support data structures for an rpc call.
|
|||
|
|
|||
|
Arguments :
|
|||
|
|
|||
|
pXlatTables - Full pointer translation tables data structure to free.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT * HashTable;
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT pElement, pTemp;
|
|||
|
ulong Buckets;
|
|||
|
ulong i;
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
return;
|
|||
|
|
|||
|
//
|
|||
|
// Free the ref id to pointer tables.
|
|||
|
//
|
|||
|
if ( pXlatTables->RefIdToPointer.XlatTable )
|
|||
|
I_RpcFree( pXlatTables->RefIdToPointer.XlatTable );
|
|||
|
|
|||
|
if ( pXlatTables->RefIdToPointer.StateTable )
|
|||
|
I_RpcFree( pXlatTables->RefIdToPointer.StateTable );
|
|||
|
|
|||
|
//
|
|||
|
// Free the pointer to ref id table.
|
|||
|
//
|
|||
|
HashTable = pXlatTables->PointerToRefId.XlatTable;
|
|||
|
|
|||
|
if ( HashTable )
|
|||
|
{
|
|||
|
Buckets = pXlatTables->PointerToRefId.NumberOfBuckets;
|
|||
|
|
|||
|
for ( i = 0; i < Buckets; i++ )
|
|||
|
if ( HashTable[i] )
|
|||
|
for ( pElement = HashTable[i]; pElement; pElement = pTemp )
|
|||
|
{
|
|||
|
pTemp = pElement->Next;
|
|||
|
|
|||
|
I_RpcFree(pElement);
|
|||
|
}
|
|||
|
|
|||
|
I_RpcFree( HashTable );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Free the translation table structure.
|
|||
|
//
|
|||
|
I_RpcFree( pXlatTables );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int RPC_ENTRY
|
|||
|
NdrFullPointerQueryPointer(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables,
|
|||
|
void * pPointer,
|
|||
|
uchar QueryType,
|
|||
|
ulong * pRefId )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
This routine checks if a full pointer is in the full pointer translation
|
|||
|
table and is marked with the given state.
|
|||
|
|
|||
|
If there is no current translation for this pointer then a translation is
|
|||
|
inserted in the given translation table and a ref id is assigned if pRefId
|
|||
|
is non-null.
|
|||
|
|
|||
|
Arguments :
|
|||
|
|
|||
|
pXlatTable - The full pointer translation tables.
|
|||
|
pPointer - The pointer to check.
|
|||
|
QueryType - The type of query, either FULL_POINTER_MARSHALLED or
|
|||
|
FULL_POINTER_BUF_SIZED.
|
|||
|
pRefId - The ref id for the pointer is returned if this parameter
|
|||
|
is non-null.
|
|||
|
|
|||
|
Return Value :
|
|||
|
|
|||
|
TRUE if the given pointer was null or a translation for the full pointer
|
|||
|
was found and had the QueryType set, FALSE otherwise.
|
|||
|
|
|||
|
A return value of FALSE indicates that the pointee should be sized or
|
|||
|
marshalled.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT * HashTable;
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT pElement;
|
|||
|
ulong HashTableIndex;
|
|||
|
|
|||
|
if ( ! pPointer )
|
|||
|
{
|
|||
|
if ( pRefId )
|
|||
|
*pRefId = 0;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
HashTable = pXlatTables->PointerToRefId.XlatTable;
|
|||
|
|
|||
|
//
|
|||
|
// Lookup pPointer in PointerToRefId table.
|
|||
|
//
|
|||
|
|
|||
|
HashTableIndex = PTR_HASH( pPointer, pXlatTables->PointerToRefId.HashMask );
|
|||
|
|
|||
|
for ( pElement = HashTable[HashTableIndex];
|
|||
|
pElement;
|
|||
|
pElement = pElement->Next )
|
|||
|
{
|
|||
|
if ( pElement->Pointer == pPointer )
|
|||
|
{
|
|||
|
if ( CHECK_FULL_POINTER_STATE( pElement->State, QueryType ) )
|
|||
|
{
|
|||
|
if ( pRefId )
|
|||
|
*pRefId = pElement->RefId;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// Assign a ref id now if it doesn't have one and pRefId is
|
|||
|
// non null.
|
|||
|
//
|
|||
|
if ( pRefId && ! pElement->RefId )
|
|||
|
pElement->RefId = pXlatTables->NextRefId++;
|
|||
|
|
|||
|
SET_FULL_POINTER_STATE( pElement->State, QueryType );
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If there is no translation for the pointer then insert a new one.
|
|||
|
//
|
|||
|
if ( ! pElement )
|
|||
|
{
|
|||
|
pElement = (PFULL_PTR_TO_REFID_ELEMENT)
|
|||
|
I_RpcAllocate( sizeof(FULL_PTR_TO_REFID_ELEMENT) );
|
|||
|
|
|||
|
if ( ! pElement )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
pElement->State = 0;
|
|||
|
|
|||
|
SET_FULL_POINTER_STATE( pElement->State, QueryType );
|
|||
|
|
|||
|
pElement->Pointer = pPointer;
|
|||
|
|
|||
|
if ( pRefId )
|
|||
|
pElement->RefId = pXlatTables->NextRefId++;
|
|||
|
else
|
|||
|
pElement->RefId = 0;
|
|||
|
|
|||
|
pElement->Next = HashTable[HashTableIndex];
|
|||
|
HashTable[HashTableIndex] = pElement;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the ref id return value.
|
|||
|
//
|
|||
|
if ( pRefId )
|
|||
|
{
|
|||
|
//
|
|||
|
// We get here the first time we marshall a new full pointer.
|
|||
|
//
|
|||
|
*pRefId = pElement->RefId;
|
|||
|
|
|||
|
//
|
|||
|
// We insert the reverse translation if we're on the client side.
|
|||
|
//
|
|||
|
if ( pXlatTables->XlatSide == XLAT_CLIENT )
|
|||
|
{
|
|||
|
if ( *pRefId >= pXlatTables->RefIdToPointer.NumberOfEntries )
|
|||
|
NdrFullPointerXlatRealloc( pXlatTables, *pRefId );
|
|||
|
|
|||
|
pXlatTables->RefIdToPointer.XlatTable[*pRefId] = pPointer;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int RPC_ENTRY
|
|||
|
NdrFullPointerQueryRefId(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables,
|
|||
|
ulong RefId,
|
|||
|
uchar QueryType,
|
|||
|
void ** ppPointer )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
This routine checks if a ref id is in the full pointer translation table
|
|||
|
and is marked with the given state.
|
|||
|
|
|||
|
If a translation is found and ppPointer is non-null then *ppPointer is set
|
|||
|
to the value of the ref id's pointer value.
|
|||
|
|
|||
|
If this routine returns FALSE for a FULL_POINTER_UNMARSHALLED query then
|
|||
|
the full pointer should be allocated and a call to
|
|||
|
NdrFullPointerInsertRefId must be made.
|
|||
|
|
|||
|
If this routine returns FALSE for a FULL_POINTER_MEM_SIZED query then
|
|||
|
the size of the full pointer's pointee should be added to the current
|
|||
|
memory sizing calculation.
|
|||
|
|
|||
|
Arguments :
|
|||
|
|
|||
|
pXlatTable - The full pointer translation tables.
|
|||
|
pRefId - The ref id to search for.
|
|||
|
QueryType - The type of query, either FULL_POINTER_UNMARSHALLED or
|
|||
|
FULL_POINTER_MEM_SIZED.
|
|||
|
ppPointer - Holds the returned pointer value for the ref id if it is
|
|||
|
found.
|
|||
|
|
|||
|
Return Value :
|
|||
|
|
|||
|
TRUE if the ref id is 0 or a translation for the ref id is found and had
|
|||
|
the QueryType set, FALSE otherwise.
|
|||
|
|
|||
|
A return value of FALSE indicates that the pointee should be sized or
|
|||
|
unmarshalled.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
uchar * StateTable;
|
|||
|
void * Pointer;
|
|||
|
|
|||
|
if ( ! RefId )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
if ( RefId >= pXlatTables->NextRefId )
|
|||
|
pXlatTables->NextRefId = RefId + 1;
|
|||
|
|
|||
|
if ( RefId >= pXlatTables->RefIdToPointer.NumberOfEntries )
|
|||
|
NdrFullPointerXlatRealloc( pXlatTables, RefId );
|
|||
|
|
|||
|
StateTable = pXlatTables->RefIdToPointer.StateTable;
|
|||
|
|
|||
|
Pointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
|
|||
|
|
|||
|
//
|
|||
|
// We make this check first. It's possible that we will already have
|
|||
|
// a translation for the ref id, but it simply won't be marked yet with
|
|||
|
// the proper state. In this case we still want to return the correct
|
|||
|
// pointer value from the translation tables, but we'll still end up
|
|||
|
// returning false when we make the state check.
|
|||
|
//
|
|||
|
if ( ppPointer )
|
|||
|
{
|
|||
|
//
|
|||
|
// We have to make sure and always copy the pointer's value from
|
|||
|
// the table. This way we handle the case when a pointer's VALUE
|
|||
|
// changes to a pointer which has a currently valid RefId (an
|
|||
|
// example of this could happen when a server swaps the values of
|
|||
|
// two [in,out] double pointers).
|
|||
|
//
|
|||
|
// Pointer will be null if this is the first time we've seen or used
|
|||
|
// this ref id.
|
|||
|
//
|
|||
|
*ppPointer = Pointer;
|
|||
|
}
|
|||
|
|
|||
|
if ( CHECK_FULL_POINTER_STATE( StateTable[RefId], QueryType ) )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SET_FULL_POINTER_STATE( StateTable[RefId], QueryType );
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void RPC_ENTRY
|
|||
|
NdrFullPointerInsertRefId(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables,
|
|||
|
ulong RefId,
|
|||
|
void * pPointer )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
This routine inserts a ref id to pointer translation in the full pointer
|
|||
|
translation table.
|
|||
|
|
|||
|
Arguments :
|
|||
|
|
|||
|
pXlatTable - The full pointer translation tables.
|
|||
|
pRefId - The ref id.
|
|||
|
pPointer - The pointer.
|
|||
|
|
|||
|
Return Value :
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
// unused: uchar * StateTable;
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
//
|
|||
|
// Ref id should be non-zero.
|
|||
|
//
|
|||
|
NDR_ASSERT( RefId, "NdrFullPointerInsertRefId : Ref id is zero" );
|
|||
|
|
|||
|
//
|
|||
|
// Ref id should fit in the current table.
|
|||
|
//
|
|||
|
NDR_ASSERT( RefId < pXlatTables->RefIdToPointer.NumberOfEntries,
|
|||
|
"NdrFullPointerInsertRefId : Ref Id too large" );
|
|||
|
|
|||
|
//
|
|||
|
// There should currently be no pointer translation for this ref id.
|
|||
|
//
|
|||
|
NDR_ASSERT( ! pXlatTables->RefIdToPointer.XlatTable[RefId],
|
|||
|
"NdrFullPointerInsertRefId : Translation already exists" );
|
|||
|
|
|||
|
//
|
|||
|
// Insert the translation.
|
|||
|
//
|
|||
|
pXlatTables->RefIdToPointer.XlatTable[RefId] = pPointer;
|
|||
|
|
|||
|
//
|
|||
|
// If we're on the server side then insert the inverse translation.
|
|||
|
//
|
|||
|
if ( pXlatTables->XlatSide == XLAT_SERVER )
|
|||
|
{
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT pElement;
|
|||
|
long HashTableIndex;
|
|||
|
|
|||
|
pElement = (PFULL_PTR_TO_REFID_ELEMENT)
|
|||
|
I_RpcAllocate( sizeof(FULL_PTR_TO_REFID_ELEMENT) );
|
|||
|
|
|||
|
if ( ! pElement )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
pElement->State = 0;
|
|||
|
pElement->Pointer = pPointer;
|
|||
|
pElement->RefId = RefId;
|
|||
|
|
|||
|
HashTableIndex = PTR_HASH( pPointer,
|
|||
|
pXlatTables->PointerToRefId.HashMask );
|
|||
|
|
|||
|
pElement->Next = pXlatTables->PointerToRefId.XlatTable[HashTableIndex];
|
|||
|
pXlatTables->PointerToRefId.XlatTable[HashTableIndex] = pElement;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int RPC_ENTRY
|
|||
|
NdrFullPointerFree(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables,
|
|||
|
void * pPointer )
|
|||
|
/***
|
|||
|
|
|||
|
Routine description :
|
|||
|
|
|||
|
Removes a full pointer from the translation tables, and frees it's
|
|||
|
associated translation data.
|
|||
|
|
|||
|
Return value :
|
|||
|
|
|||
|
TRUE if the pointer has not yet been freed or is null, FALSE otherwise.
|
|||
|
|
|||
|
***/
|
|||
|
{
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT * HashTable;
|
|||
|
PFULL_PTR_TO_REFID_ELEMENT pElement;
|
|||
|
ulong HashTableIndex;
|
|||
|
|
|||
|
if ( ! pPointer )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
HashTable = pXlatTables->PointerToRefId.XlatTable;
|
|||
|
|
|||
|
//
|
|||
|
// Lookup pPointer in PointerToRefId table.
|
|||
|
//
|
|||
|
|
|||
|
HashTableIndex = PTR_HASH( pPointer, pXlatTables->PointerToRefId.HashMask );
|
|||
|
|
|||
|
for ( pElement = HashTable[HashTableIndex];
|
|||
|
pElement;
|
|||
|
pElement = pElement->Next )
|
|||
|
{
|
|||
|
if ( pElement->Pointer == pPointer )
|
|||
|
{
|
|||
|
if ( CHECK_FULL_POINTER_STATE(pElement->State,FULL_POINTER_FREED) )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SET_FULL_POINTER_STATE(pElement->State,FULL_POINTER_FREED);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// There is an instance when a full pointer is encountered for the first
|
|||
|
// time during freeing. This occurs if an [in] full pointer is changed
|
|||
|
// by the server manager routine. If this occurs we must insert the new
|
|||
|
// full pointer so we can keep track of it so that we don't free it more
|
|||
|
// than once.
|
|||
|
//
|
|||
|
|
|||
|
pElement = (PFULL_PTR_TO_REFID_ELEMENT)
|
|||
|
I_RpcAllocate( sizeof(FULL_PTR_TO_REFID_ELEMENT) );
|
|||
|
|
|||
|
if ( ! pElement )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
pElement->State = 0;
|
|||
|
pElement->Pointer = pPointer;
|
|||
|
|
|||
|
HashTableIndex = PTR_HASH( pPointer,
|
|||
|
pXlatTables->PointerToRefId.HashMask );
|
|||
|
|
|||
|
pElement->Next = pXlatTables->PointerToRefId.XlatTable[HashTableIndex];
|
|||
|
pXlatTables->PointerToRefId.XlatTable[HashTableIndex] = pElement;
|
|||
|
|
|||
|
SET_FULL_POINTER_STATE( pElement->State, FULL_POINTER_FREED );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static void
|
|||
|
NdrFullPointerXlatRealloc(
|
|||
|
PFULL_PTR_XLAT_TABLES pXlatTables,
|
|||
|
ulong RefId)
|
|||
|
{
|
|||
|
void * pMemory;
|
|||
|
uint Entries;
|
|||
|
|
|||
|
if ( ! pXlatTables )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
Entries = (uint) pXlatTables->RefIdToPointer.NumberOfEntries;
|
|||
|
|
|||
|
// If the number is much larger than the previous one, most likely the
|
|||
|
// number is invalid. Before we have a concrete solution to replace the
|
|||
|
// current fixed array of RefIdToPointer lookup, this can catch most
|
|||
|
// of the failures.
|
|||
|
if ( RefId >= 2 * Entries )
|
|||
|
RpcRaiseException( RPC_X_BAD_STUB_DATA );
|
|||
|
//
|
|||
|
// Realloc RefIdToPointerTable. Allocate twice as many entries.
|
|||
|
//
|
|||
|
pMemory = I_RpcAllocate( Entries * sizeof(void *) * 2 );
|
|||
|
|
|||
|
if ( ! pMemory )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
//
|
|||
|
// Now copy the current entries into the new memory.
|
|||
|
//
|
|||
|
RpcpMemoryCopy( pMemory,
|
|||
|
pXlatTables->RefIdToPointer.XlatTable,
|
|||
|
Entries * sizeof( void * ) );
|
|||
|
|
|||
|
//
|
|||
|
// Set the new entries to 0.
|
|||
|
//
|
|||
|
MIDL_memset( (char *) pMemory + Entries * sizeof( void *),
|
|||
|
0,
|
|||
|
Entries * sizeof( void *) );
|
|||
|
|
|||
|
//
|
|||
|
// Free the old table.
|
|||
|
//
|
|||
|
I_RpcFree( pXlatTables->RefIdToPointer.XlatTable );
|
|||
|
|
|||
|
//
|
|||
|
// Get the new table.
|
|||
|
//
|
|||
|
pXlatTables->RefIdToPointer.XlatTable = (void**)pMemory;
|
|||
|
|
|||
|
//
|
|||
|
// Realloc RefIdToPointerState
|
|||
|
//
|
|||
|
pMemory = I_RpcAllocate( Entries * sizeof(uchar) * 2 );
|
|||
|
|
|||
|
if ( ! pMemory )
|
|||
|
RpcRaiseException( RPC_S_OUT_OF_MEMORY );
|
|||
|
|
|||
|
//
|
|||
|
// Now copy the current entries into the new memory.
|
|||
|
//
|
|||
|
RpcpMemoryCopy( pMemory,
|
|||
|
pXlatTables->RefIdToPointer.StateTable,
|
|||
|
Entries * sizeof(uchar) );
|
|||
|
|
|||
|
//
|
|||
|
// Set the new entries to 0.
|
|||
|
//
|
|||
|
MIDL_memset( (char *) pMemory + Entries * sizeof(uchar),
|
|||
|
0,
|
|||
|
Entries * sizeof(uchar) );
|
|||
|
|
|||
|
//
|
|||
|
// Free the old table.
|
|||
|
//
|
|||
|
I_RpcFree( pXlatTables->RefIdToPointer.StateTable );
|
|||
|
|
|||
|
//
|
|||
|
// Get the new table.
|
|||
|
//
|
|||
|
pXlatTables->RefIdToPointer.StateTable = (uchar*)pMemory;
|
|||
|
|
|||
|
//
|
|||
|
// Update number of entries.
|
|||
|
//
|
|||
|
pXlatTables->RefIdToPointer.NumberOfEntries *= 2;
|
|||
|
}
|
|||
|
|