Skip to content

Commit

Permalink
[NTOS:EX] Fix handle table code for x64.
Browse files Browse the repository at this point in the history
Based on patch by Ivan Labutin. See PR reactos#115
  • Loading branch information
tkreuzer committed Dec 28, 2017
1 parent 74f92c3 commit 993c11f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 38 deletions.
64 changes: 34 additions & 30 deletions ntoskrnl/ex/handle.c
Expand Up @@ -18,6 +18,7 @@
LIST_ENTRY HandleTableListHead;
EX_PUSH_LOCK HandleTableListLock;
#define SizeOfHandle(x) (sizeof(HANDLE) * (x))
#define INDEX_TO_HANDLE_VALUE(x) ((x) << HANDLE_TAG_BITS)

/* PRIVATE FUNCTIONS *********************************************************/

Expand Down Expand Up @@ -67,12 +68,14 @@ ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,

/* Get the mid level pointer array */
PointerArray = PointerArray[Handle.HighIndex];
ASSERT(PointerArray != NULL);

/* Fall through */
case 1:

/* Get the handle array */
HandleArray = PointerArray[Handle.MidIndex];
ASSERT(HandleArray != NULL);

/* Fall through */
case 0:
Expand Down Expand Up @@ -255,8 +258,8 @@ ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
IN EXHANDLE Handle,
IN PHANDLE_TABLE_ENTRY HandleTableEntry)
{
ULONG OldValue, NewValue, *Free;
ULONG i;
ULONG OldValue, *Free;
ULONG LockIndex;
PAGED_CODE();

/* Sanity checks */
Expand All @@ -267,16 +270,16 @@ ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
InterlockedDecrement(&HandleTable->HandleCount);

/* Mark the handle as free */
NewValue = (ULONG)Handle.Value & ~(SizeOfHandle(1) - 1);
Handle.TagBits = 0;

/* Check if we're FIFO */
if (!HandleTable->StrictFIFO)
{
/* Select a lock index */
i = (NewValue >> 2) % 4;
LockIndex = Handle.Index % 4;

/* Select which entry to use */
Free = (HandleTable->HandleTableLock[i].Locked) ?
Free = (HandleTable->HandleTableLock[LockIndex].Locked) ?
&HandleTable->FirstFree : &HandleTable->LastFree;
}
else
Expand All @@ -290,8 +293,8 @@ ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
{
/* Get the current value and write */
OldValue = *Free;
HandleTableEntry->NextFreeTableEntry = (ULONG)OldValue;
if (InterlockedCompareExchange((PLONG) Free, NewValue, OldValue) == OldValue)
HandleTableEntry->NextFreeTableEntry = OldValue;
if (InterlockedCompareExchange((PLONG)Free, Handle.AsULONG, OldValue) == OldValue)
{
/* Break out, we're done. Make sure the handle value makes sense */
ASSERT((OldValue & FREE_HANDLE_MASK) <
Expand Down Expand Up @@ -354,7 +357,7 @@ ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL,
{
/* Set up the free data */
HandleEntry->Value = 0;
HandleEntry->NextFreeTableEntry = (i + 1) * SizeOfHandle(1);
HandleEntry->NextFreeTableEntry = INDEX_TO_HANDLE_VALUE(i + 1);

/* Move to the next entry */
HandleEntry++;
Expand All @@ -363,11 +366,11 @@ ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL,
/* Terminate the last entry */
HandleEntry->Value = 0;
HandleEntry->NextFreeTableEntry = 0;
HandleTable->FirstFree = SizeOfHandle(1);
HandleTable->FirstFree = INDEX_TO_HANDLE_VALUE(1);
}

/* Set the next handle needing pool after our allocated page from above */
HandleTable->NextHandleNeedingPool = LOW_LEVEL_ENTRIES * SizeOfHandle(1);
HandleTable->NextHandleNeedingPool = INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES);

/* Setup the rest of the handle table data */
HandleTable->QuotaProcess = Process;
Expand Down Expand Up @@ -409,12 +412,12 @@ ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable,
{
/* Go to the next entry and the base entry */
HandleEntry++;
Base = HandleTable->NextHandleNeedingPool + SizeOfHandle(2);
Base = HandleTable->NextHandleNeedingPool + INDEX_TO_HANDLE_VALUE(2);

/* Loop each entry */
for (i = Base;
i < Base + SizeOfHandle(LOW_LEVEL_ENTRIES - 2);
i += SizeOfHandle(1))
i < Base + INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES - 2);
i += INDEX_TO_HANDLE_VALUE(1))
{
/* Free this entry and move on to the next one */
HandleEntry->NextFreeTableEntry = i;
Expand Down Expand Up @@ -494,7 +497,7 @@ ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable,

/* Get if the next index can fit in the table */
i = HandleTable->NextHandleNeedingPool /
SizeOfHandle(LOW_LEVEL_ENTRIES);
INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES);
if (i < MID_LEVEL_ENTRIES)
{
/* We need to allocate a new table */
Expand Down Expand Up @@ -539,7 +542,7 @@ ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable,
ThirdLevel = (PVOID)TableBase;

/* Get the index and check if it can fit */
i = HandleTable->NextHandleNeedingPool / SizeOfHandle(MAX_MID_INDEX);
i = HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(MAX_MID_INDEX);
if (i >= HIGH_LEVEL_ENTRIES) return FALSE;

/* Check if there's no mid-level table */
Expand All @@ -556,8 +559,8 @@ ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable,
else
{
/* We have one, check at which index we should insert our entry */
Index = (HandleTable->NextHandleNeedingPool / SizeOfHandle(1)) -
i * MAX_MID_INDEX;
Index = (HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(1)) -
i * MAX_MID_INDEX;
j = Index / LOW_LEVEL_ENTRIES;

/* Allocate a new low level */
Expand All @@ -577,13 +580,13 @@ ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable,

/* Update the index of the next handle */
Index = InterlockedExchangeAdd((PLONG) &HandleTable->NextHandleNeedingPool,
SizeOfHandle(LOW_LEVEL_ENTRIES));
INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));

/* Check if need to initialize the table */
if (DoInit)
{
/* Create a new index number */
Index += SizeOfHandle(1);
Index += INDEX_TO_HANDLE_VALUE(1);

/* Start free index change loop */
for (;;)
Expand Down Expand Up @@ -646,7 +649,7 @@ ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
{
ULONG OldValue, NewValue, NewValue1;
PHANDLE_TABLE_ENTRY Entry;
EXHANDLE Handle;
EXHANDLE Handle, OldHandle;
BOOLEAN Result;
ULONG i;

Expand Down Expand Up @@ -709,7 +712,8 @@ ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
Entry = ExpLookupHandleTableEntry(HandleTable, Handle);

/* Get an available lock and acquire it */
i = ((OldValue & FREE_HANDLE_MASK) >> 2) % 4;
OldHandle.Value = OldValue;
i = OldHandle.Index % 4;
KeEnterCriticalRegion();
ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]);

Expand Down Expand Up @@ -1063,7 +1067,7 @@ ExDupHandleTable(IN PEPROCESS Process,
NewTable->FirstFree = 0;

/* Setup the first handle value */
Handle.Value = SizeOfHandle(1);
Handle.Value = INDEX_TO_HANDLE_VALUE(1);

/* Enter a critical region and lookup the new entry */
KeEnterCriticalRegion();
Expand Down Expand Up @@ -1125,13 +1129,13 @@ ExDupHandleTable(IN PEPROCESS Process,
}

/* Increase the handle value and move to the next entry */
Handle.Value += SizeOfHandle(1);
Handle.Value += INDEX_TO_HANDLE_VALUE(1);
NewEntry++;
HandleTableEntry++;
} while (Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES));
} while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));

/* We're done, skip the last entry */
Handle.Value += SizeOfHandle(1);
Handle.Value += INDEX_TO_HANDLE_VALUE(1);
}

/* Acquire the table lock and insert this new table into the list */
Expand Down Expand Up @@ -1198,7 +1202,7 @@ ExSweepHandleTable(IN PHANDLE_TABLE HandleTable,
PAGED_CODE();

/* Set the initial value and loop the entries */
Handle.Value = SizeOfHandle(1);
Handle.Value = INDEX_TO_HANDLE_VALUE(1);
while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
{
/* Loop each handle */
Expand All @@ -1214,12 +1218,12 @@ ExSweepHandleTable(IN PHANDLE_TABLE HandleTable,
}

/* Go to the next handle and entry */
Handle.Value += SizeOfHandle(1);
Handle.Value += INDEX_TO_HANDLE_VALUE(1);
HandleTableEntry++;
} while (Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES));
} while (Handle.Value % INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES));

/* Skip past the last entry */
Handle.Value += SizeOfHandle(1);
Handle.Value += INDEX_TO_HANDLE_VALUE(1);
}
}

Expand Down Expand Up @@ -1271,7 +1275,7 @@ ExEnumHandleTable(IN PHANDLE_TABLE HandleTable,
}

/* Go to the next entry */
Handle.Value += SizeOfHandle(1);
Handle.Value += INDEX_TO_HANDLE_VALUE(1);
}

/* Leave the critical region and return callback result */
Expand Down
20 changes: 12 additions & 8 deletions ntoskrnl/include/internal/ex.h
Expand Up @@ -68,25 +68,29 @@ VOID NTAPI ExpDebuggerWorker(IN PVOID Context);
#define HANDLE_LOW_BITS (PAGE_SHIFT - 3)
#define HANDLE_HIGH_BITS (PAGE_SHIFT - 2)
#endif
#define KERNEL_FLAG_BITS (sizeof(PVOID)*8 - 31)
#define HANDLE_TAG_BITS (2)
#define HANDLE_INDEX_BITS (HANDLE_LOW_BITS + 2*HANDLE_HIGH_BITS)
#define KERNEL_FLAG_BITS (sizeof(PVOID)*8 - HANDLE_INDEX_BITS - HANDLE_TAG_BITS)

typedef union _EXHANDLE
{
struct
{
ULONG_PTR TagBits:2;
ULONG_PTR Index:29;
ULONG_PTR TagBits: HANDLE_TAG_BITS;
ULONG_PTR Index: HANDLE_INDEX_BITS;
ULONG_PTR KernelFlag : KERNEL_FLAG_BITS;
};
struct
{
ULONG_PTR TagBits2:2;
ULONG_PTR LowIndex:HANDLE_LOW_BITS;
ULONG_PTR MidIndex:HANDLE_HIGH_BITS;
ULONG_PTR HighIndex:HANDLE_HIGH_BITS;
ULONG_PTR KernelFlag:KERNEL_FLAG_BITS;
ULONG_PTR TagBits2: HANDLE_TAG_BITS;
ULONG_PTR LowIndex: HANDLE_LOW_BITS;
ULONG_PTR MidIndex: HANDLE_HIGH_BITS;
ULONG_PTR HighIndex: HANDLE_HIGH_BITS;
ULONG_PTR KernelFlag2: KERNEL_FLAG_BITS;
};
HANDLE GenericHandleOverlay;
ULONG_PTR Value;
ULONG AsULONG;
} EXHANDLE, *PEXHANDLE;

typedef struct _ETIMER
Expand Down

0 comments on commit 993c11f

Please sign in to comment.