[NTOS:EX] Fix handle table code for x64.
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Mon, 13 Nov 2017 18:00:31 +0000 (19:00 +0100)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 29 Dec 2017 18:44:09 +0000 (19:44 +0100)
Based on patch by Ivan Labutin. See PR #115

ntoskrnl/ex/handle.c
ntoskrnl/include/internal/ex.h

index b9732f3..5c26ccd 100644 (file)
@@ -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 *********************************************************/
 
@@ -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:
@@ -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 */
@@ -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
@@ -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) <
@@ -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++;
@@ -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;
@@ -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;
@@ -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 */
@@ -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 */
@@ -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 */
@@ -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 (;;)
@@ -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;
 
@@ -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]);
 
@@ -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();
@@ -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 */
@@ -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 */
@@ -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);
     }
 }
 
@@ -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 */
index 3834249..09ba464 100644 (file)
@@ -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