PHANDLE_TABLE_ENTRY
ExpLookupHandleTableEntry (
IN PHANDLE_TABLE HandleTable,
IN EXHANDLE tHandle
)
/*++
Routine Description:
This routine looks up and returns the table entry for the
specified handle value.
Arguments:
HandleTable - Supplies the handle table being queried
tHandle - Supplies the handle value being queried
Return Value:
Returns a pointer to the corresponding table entry for the input
handle. Or NULL if the handle value is invalid (i.e., too large
for the tables current allocation.
--*/
{
ULONG_PTR i,j,k;
ULONG_PTR CapturedTable;
ULONG TableLevel;
PHANDLE_TABLE_ENTRY Entry = NULL;
EXHANDLE Handle;
PUCHAR TableLevel1;
PUCHAR TableLevel2;
PUCHAR TableLevel3;
ULONG_PTR MaxHandle;
PAGED_CODE();
//
// Extract the handle index
//
Handle = tHandle;
Handle.TagBits = 0;
MaxHandle = *(volatile ULONG *) &HandleTable->NextHandleNeedingPool;
//
// See if this can be a valid handle given the table levels.
//
if (Handle.Value >= MaxHandle) {
return NULL;
}
//
// Now fetch the table address and level bits. We must preserve the
// ordering here.
//
CapturedTable = *(volatile ULONG_PTR *) &HandleTable->TableCode;
//
// we need to capture the current table. This routine is lock free
// so another thread may change the table at HandleTable->TableCode
//
TableLevel = (ULONG)(CapturedTable & LEVEL_CODE_MASK);
CapturedTable = CapturedTable - TableLevel;
//
// The lookup code depends on number of levels we have
//
switch (TableLevel) {
case 0:
//
// We have a simple index into the array, for a single level
// handle table
//
TableLevel1 = (PUCHAR) CapturedTable;
//
// The index for this level is already scaled by a factor of 4. Take advantage of this
//
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[Handle.Value *
(sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
case 1:
//
// we have a 2 level handle table. We need to get the upper index
// and lower index into the array
//
TableLevel2 = (PUCHAR) CapturedTable;
i = Handle.Value % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
Handle.Value -= i;
j = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2[j];
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
case 2:
//
// We have here a three level handle table.
//
TableLevel3 = (PUCHAR) CapturedTable;
i = Handle.Value % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
Handle.Value -= i;
k = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
j = k % (MIDLEVEL_COUNT * sizeof (PHANDLE_TABLE_ENTRY));
k -= j;
k /= MIDLEVEL_COUNT;
TableLevel2 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel3[k];
TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2[j];
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
default :
_assume (0);
}
return Entry;
}