252 lines
8.7 KiB
C
252 lines
8.7 KiB
C
/*
|
|
* Full Pointer Translation Routines
|
|
*
|
|
* Copyright 2006 Robert Shearman
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "rpc.h"
|
|
#include "rpcndr.h"
|
|
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
|
|
|
|
PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers,
|
|
XLAT_SIDE XlatSide)
|
|
{
|
|
ULONG NumberOfBuckets;
|
|
PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables));
|
|
|
|
TRACE("(%d, %d)\n", NumberOfPointers, XlatSide);
|
|
|
|
if (!NumberOfPointers) NumberOfPointers = 512;
|
|
NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1;
|
|
|
|
pXlatTables->RefIdToPointer.XlatTable =
|
|
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
sizeof(void *) * NumberOfPointers);
|
|
pXlatTables->RefIdToPointer.StateTable =
|
|
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
sizeof(unsigned char) * NumberOfPointers);
|
|
pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers;
|
|
|
|
TRACE("NumberOfBuckets = %d\n", NumberOfBuckets);
|
|
pXlatTables->PointerToRefId.XlatTable =
|
|
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets);
|
|
pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets;
|
|
pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1;
|
|
|
|
pXlatTables->NextRefId = 1;
|
|
pXlatTables->XlatSide = XlatSide;
|
|
|
|
return pXlatTables;
|
|
}
|
|
|
|
void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
|
|
{
|
|
ULONG i;
|
|
|
|
TRACE("(%p)\n", pXlatTables);
|
|
|
|
/* free the entries in the table */
|
|
for (i = 0; i < pXlatTables->PointerToRefId.NumberOfBuckets; i++)
|
|
{
|
|
PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
|
|
for (XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[i];
|
|
XlatTableEntry; )
|
|
{
|
|
PFULL_PTR_TO_REFID_ELEMENT Next = XlatTableEntry->Next;
|
|
HeapFree(GetProcessHeap(), 0, XlatTableEntry);
|
|
XlatTableEntry = Next;
|
|
}
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable);
|
|
HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
|
|
HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pXlatTables);
|
|
}
|
|
|
|
static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId)
|
|
{
|
|
if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries)
|
|
{
|
|
pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2;
|
|
pXlatTables->RefIdToPointer.XlatTable =
|
|
HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
pXlatTables->RefIdToPointer.XlatTable,
|
|
sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries);
|
|
pXlatTables->RefIdToPointer.StateTable =
|
|
HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
pXlatTables->RefIdToPointer.StateTable,
|
|
sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries);
|
|
|
|
if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable)
|
|
pXlatTables->RefIdToPointer.NumberOfEntries = 0;
|
|
}
|
|
}
|
|
|
|
int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables,
|
|
void *pPointer, unsigned char QueryType,
|
|
ULONG *pRefId )
|
|
{
|
|
ULONG Hash = 0;
|
|
unsigned int i;
|
|
PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
|
|
|
|
TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId);
|
|
|
|
if (!pPointer)
|
|
{
|
|
*pRefId = 0;
|
|
return 1;
|
|
}
|
|
|
|
/* simple hashing algorithm, don't know whether it matches native */
|
|
for (i = 0; i < sizeof(pPointer); i++)
|
|
Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
|
|
|
|
XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
|
|
for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
|
|
if (pPointer == XlatTableEntry->Pointer)
|
|
{
|
|
*pRefId = XlatTableEntry->RefId;
|
|
if (XlatTableEntry->State & QueryType)
|
|
return 1;
|
|
XlatTableEntry->State |= QueryType;
|
|
return 0;
|
|
}
|
|
|
|
XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
|
|
XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
|
|
XlatTableEntry->Pointer = pPointer;
|
|
XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++;
|
|
XlatTableEntry->State = QueryType;
|
|
pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
|
|
|
|
/* insert pointer into mapping table */
|
|
expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId);
|
|
if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId)
|
|
{
|
|
pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
|
|
pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
|
|
ULONG RefId, unsigned char QueryType,
|
|
void **ppPointer)
|
|
{
|
|
TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer);
|
|
|
|
if (!RefId)
|
|
return 1;
|
|
|
|
expand_pointer_table_if_necessary(pXlatTables, RefId);
|
|
|
|
pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId);
|
|
|
|
if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
|
|
{
|
|
*ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
|
|
if (QueryType)
|
|
{
|
|
if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType)
|
|
return 1;
|
|
pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType;
|
|
return 0;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
*ppPointer = NULL;
|
|
return 0;
|
|
}
|
|
|
|
void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
|
|
ULONG RefId, void *pPointer)
|
|
{
|
|
ULONG Hash = 0;
|
|
unsigned int i;
|
|
PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
|
|
|
|
TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer);
|
|
|
|
/* simple hashing algorithm, don't know whether it matches native */
|
|
for (i = 0; i < sizeof(pPointer); i++)
|
|
Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
|
|
|
|
XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
|
|
XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
|
|
XlatTableEntry->Pointer = pPointer;
|
|
XlatTableEntry->RefId = RefId;
|
|
XlatTableEntry->State = 0;
|
|
pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
|
|
|
|
/* insert pointer into mapping table */
|
|
expand_pointer_table_if_necessary(pXlatTables, RefId);
|
|
if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
|
|
pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
|
|
}
|
|
|
|
int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer)
|
|
{
|
|
ULONG Hash = 0;
|
|
unsigned int i;
|
|
PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
|
|
ULONG RefId = 0;
|
|
|
|
TRACE("(%p, %p)\n", pXlatTables, Pointer);
|
|
|
|
if (!Pointer)
|
|
return 1;
|
|
|
|
/* simple hashing algorithm, don't know whether it matches native */
|
|
for (i = 0; i < sizeof(Pointer); i++)
|
|
Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i];
|
|
|
|
XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
|
|
for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
|
|
if (Pointer == XlatTableEntry->Pointer)
|
|
{
|
|
if (XlatTableEntry->State & 0x20)
|
|
return 0;
|
|
XlatTableEntry->State |= 0x20;
|
|
RefId = XlatTableEntry->RefId;
|
|
break;
|
|
}
|
|
|
|
if (!XlatTableEntry)
|
|
return 0;
|
|
|
|
if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
|
|
{
|
|
pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|