- Implement new ExHandle* implementation using pushlocks and the Windows 2003 HANDLE_...
authorAlex Ionescu <aionescu@gmail.com>
Mon, 22 Jan 2007 08:15:17 +0000 (08:15 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 22 Jan 2007 08:15:17 +0000 (08:15 +0000)
- Remove manual overrides of NTDDI_VERSION all over the thread and set it once globally, since ExHandle* was the only non-updated package. The entire kernel now builds with Windows 2003 SP1 as a target.
- Remove this entry from kernel fun.

svn path=/trunk/; revision=25586

19 files changed:
reactos/ntoskrnl/KrnlFun.c
reactos/ntoskrnl/cm/ntfunc.c
reactos/ntoskrnl/ex/handle.c
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/include/internal/ob.h
reactos/ntoskrnl/include/ntoskrnl.h
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/dpc.c
reactos/ntoskrnl/ke/gate.c
reactos/ntoskrnl/ke/gmutex.c
reactos/ntoskrnl/ke/i386/kiinit.c
reactos/ntoskrnl/ob/obhandle.c
reactos/ntoskrnl/ob/oblife.c
reactos/ntoskrnl/ob/obname.c
reactos/ntoskrnl/ob/obref.c
reactos/ntoskrnl/ob/obsecure.c
reactos/ntoskrnl/ob/obwait.c
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/rtl/libsupp.c

index 12890aa..5f27d66 100644 (file)
@@ -8,9 +8,6 @@
 //                     Do NOT ask when it will be fixed.
 //              Failure to respect this will *ACHIEVE NOTHING*.
 //
-// Ex:
-//  - Use pushlocks for handle implementation.
-//
 // Ke2:
 //  - Dispatcher Rewrite (DPCs-Timers-Waits).
 //
index eb1078b..74b9c6b 100644 (file)
@@ -66,7 +66,7 @@ CmpCreateHandle(PVOID ObjectBody,
     ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
 
     /* check that this is a valid kernel pointer */
-    ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
+    //ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
 
     if (GrantedAccess & MAXIMUM_ALLOWED)
     {
@@ -82,9 +82,9 @@ CmpCreateHandle(PVOID ObjectBody,
 
     NewEntry.Object = ObjectHeader;
     if(HandleAttributes & OBJ_INHERIT)
-        NewEntry.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+        NewEntry.ObAttributes |= OBJ_INHERIT;
     else
-        NewEntry.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+        NewEntry.ObAttributes &= ~OBJ_INHERIT;
     NewEntry.GrantedAccess = GrantedAccess;
 
     if ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
index a595242..2e68cbe 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/ex/handle.c
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/ex/init.c
  * PURPOSE:         Generic Executive Handle Tables
- *
- * PROGRAMMERS:     Thomas Weidenmueller <w3seek@reactos.com>
- *
- *  TODO:
- *
- *  - the last entry of a subhandle list should be reserved for auditing
- *
- *  ExReferenceHandleDebugInfo
- *  ExSnapShotHandleTables
- *  ExpMoveFreeHandles (???)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Thomas Weidenmueller <w3seek@reactos.com>
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
-
 #define NDEBUG
-#include <internal/debug.h>
-
-static LIST_ENTRY ExpHandleTableHead;
-static FAST_MUTEX ExpHandleTableListLock;
-static LARGE_INTEGER ExpHandleShortWait;
-
-#define ExAcquireHandleTableListLock()                                         \
-  ExAcquireFastMutexUnsafe(&ExpHandleTableListLock)
-
-#define ExReleaseHandleTableListLock()                                         \
-  ExReleaseFastMutexUnsafe(&ExpHandleTableListLock)
+#include <debug.h>
 
-#define ExAcquireHandleLockExclusive(HandleTable)                         \
-  ExAcquireResourceExclusiveLite(&(HandleTable)->HandleLock, TRUE)
+/* GLOBALS *******************************************************************/
 
-#define ExAcquireHandleLockShared(HandleTable)                            \
-  ExAcquireResourceSharedLite(&(HandleTable)->HandleLock, TRUE)
+LIST_ENTRY HandleTableListHead;
+EX_PUSH_LOCK HandleTableListLock;
+#define SizeOfHandle(x) sizeof(HANDLE) * x
 
-#define ExReleaseHandleLock(HandleTable)                                  \
-  ExReleaseResourceLite(&(HandleTable)->HandleLock)
-
-/*
-   5 bits: reserved
-   8 bits: top level index
-   10 bits: middle level index
-   9 bits: sub handle index
-*/
-#define N_TLI_BITS 8 /* top level index */
-#define N_MLI_BITS 10 /* middle level index */
-#define N_EI_BITS 9 /* sub handle index */
-#define TLI_OFFSET (N_MLI_BITS + N_EI_BITS)
-#define MLI_OFFSET N_EI_BITS
-#define EI_OFFSET 0
-
-#define N_TOPLEVEL_POINTERS (1 << N_TLI_BITS)
-#define N_MIDDLELEVEL_POINTERS (1 << N_MLI_BITS)
-#define N_SUBHANDLE_ENTRIES (1 << N_EI_BITS)
-#define EX_MAX_HANDLES (N_TOPLEVEL_POINTERS * N_MIDDLELEVEL_POINTERS * N_SUBHANDLE_ENTRIES)
-
-#define VALID_HANDLE_MASK (((N_TOPLEVEL_POINTERS - 1) << TLI_OFFSET) |         \
-  ((N_MIDDLELEVEL_POINTERS - 1) << MLI_OFFSET) | ((N_SUBHANDLE_ENTRIES - 1) << EI_OFFSET))
-#define TLI_FROM_HANDLE(index) (ULONG)(((index) >> TLI_OFFSET) & (N_TOPLEVEL_POINTERS - 1))
-#define MLI_FROM_HANDLE(index) (ULONG)(((index) >> MLI_OFFSET) & (N_MIDDLELEVEL_POINTERS - 1))
-#define ELI_FROM_HANDLE(index) (ULONG)(((index) >> EI_OFFSET) & (N_SUBHANDLE_ENTRIES - 1))
-
-#define N_MAX_HANDLE (N_TOPLEVEL_POINTERS * N_MIDDLELEVEL_POINTERS * N_SUBHANDLE_ENTRIES)
-
-#define BUILD_HANDLE(tli, mli, eli) ((((tli) & (N_TOPLEVEL_POINTERS - 1)) << TLI_OFFSET) | \
-  (((mli) & (N_MIDDLELEVEL_POINTERS - 1)) << MLI_OFFSET) | (((eli) & (N_SUBHANDLE_ENTRIES - 1)) << EI_OFFSET))
-
-#define IS_INVALID_EX_HANDLE(index)                                            \
-  (((index) & ~VALID_HANDLE_MASK) != 0)
-#define IS_VALID_EX_HANDLE(index)                                              \
-  (((index) & ~VALID_HANDLE_MASK) == 0)
-
-#define HANDLE_TO_EX_HANDLE(handle)                                            \
-  (LONG)(((LONG)(handle) >> 2) - 1)
-#define EX_HANDLE_TO_HANDLE(exhandle)                                          \
-  (HANDLE)(((exhandle) + 1) << 2)
-
-static BOOLEAN ExpInitialized = FALSE;
-
-/******************************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 
 VOID
+NTAPI
 ExpInitializeHandleTables(VOID)
 {
-  ExpHandleShortWait.QuadPart = -50000;
-  InitializeListHead(&ExpHandleTableHead);
-  ExInitializeFastMutex(&ExpHandleTableListLock);
-
-  ExpInitialized = TRUE;
+    /* Initialize the list of handle tables and the lock */
+    InitializeListHead(&HandleTableListHead);
+    ExInitializePushLock((PULONG_PTR)&HandleTableListLock);
 }
 
-PHANDLE_TABLE
-ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL)
+PHANDLE_TABLE_ENTRY
+NTAPI
+ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                          IN EXHANDLE LookupHandle)
 {
-  PHANDLE_TABLE HandleTable;
-
-  PAGED_CODE();
+    ULONG i, j, k, TableLevel, NextHandle;
+    ULONG_PTR TableBase;
+    PHANDLE_TABLE_ENTRY Entry = NULL;
+    EXHANDLE Handle = LookupHandle;
+    PCHAR Level1, Level2, Level3;
+
+    /* Clear the tag bits and check what the next handle is */
+    Handle.TagBits = 0;
+    NextHandle = HandleTable->NextHandleNeedingPool;
+    if (Handle.Value >= NextHandle) return NULL;
+
+    /* Get the table code */
+    TableBase = (ULONG_PTR)HandleTable->TableCode;
+
+    /* Extract the table level and actual table base */
+    TableLevel = (ULONG)(TableBase & 3);
+    TableBase = TableBase - TableLevel;
+
+    /* Check what level we're running at */
+    switch (TableLevel)
+    {
+        /* Direct index */
+        case 0:
+
+            /* Use level 1 and just get the entry directlry */
+            Level1 = (PUCHAR)TableBase;
+            Entry = (PVOID)&Level1[Handle.Value *
+                                   (sizeof(HANDLE_TABLE_ENTRY) /
+                                    SizeOfHandle(1))];
+            break;
+
+        /* Nested index into mid level */
+        case 1:
+
+            /* Get the second table and index into it */
+            Level2 = (PUCHAR)TableBase;
+            i = Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES);
+
+            /* Substract this index, and get the next one */
+            Handle.Value -= i;
+            j = Handle.Value /
+                (SizeOfHandle(LOW_LEVEL_ENTRIES) / sizeof(PHANDLE_TABLE_ENTRY));
+
+            /* Now get the next table and get the entry from it */
+            Level1 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&Level2[j];
+            Entry = (PVOID)&Level1[i *
+                                   (sizeof(HANDLE_TABLE_ENTRY) /
+                                    SizeOfHandle(1))];
+            break;
+
+        /* Nested index into high level */
+        case 2:
+
+            /* Start with the 3rd level table */
+            Level3 = (PUCHAR)TableBase;
+            i = Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES);
+
+            /* Subtract this index and get the index for the next lower table */
+            Handle.Value -= i;
+            k = Handle.Value /
+                (SizeOfHandle(LOW_LEVEL_ENTRIES) / sizeof(PHANDLE_TABLE_ENTRY));
+
+            /* Get the remaining index in the 2nd level table */
+            j = k % (MID_LEVEL_ENTRIES * sizeof(PHANDLE_TABLE_ENTRY));
+
+            /* Get the remaining index, which is in the third table */
+            k -= j;
+            k /= MID_LEVEL_ENTRIES;
+
+            /* Extract the table level for the handle in each table */
+            Level2 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&Level3[k];
+            Level1 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&Level2[j];
+
+            /* Get the handle table entry */
+            Entry = (PVOID)&Level1[i *
+                                   (sizeof(HANDLE_TABLE_ENTRY) /
+                                    SizeOfHandle(1))];
+
+        default:
+
+            /* All done */
+            break;
+    }
 
-  if(!ExpInitialized)
-  {
-    KEBUGCHECK(0);
-  }
-
-  if(QuotaProcess != NULL)
-  {
-    /* FIXME - Charge process quota before allocating the handle table! */
-  }
-
-  /* allocate enough memory for the handle table and the lowest level */
-  HandleTable = ExAllocatePoolWithTag(NonPagedPool,
-                                      sizeof(HANDLE_TABLE) + (N_TOPLEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY*)),
-                                      TAG('E', 'x', 'H', 't'));
-  if(HandleTable != NULL)
-  {
-    /* initialize the handle table */
-    HandleTable->Flags = 0;
-    HandleTable->HandleCount = 0;
-    HandleTable->Table = (PHANDLE_TABLE_ENTRY**)(HandleTable + 1);
-    HandleTable->QuotaProcess = QuotaProcess;
-    HandleTable->FirstFree = -1; /* no entries freed so far */
-    HandleTable->NextHandleNeedingPool = 0; /* no entries freed so far, so we have to allocate already for the first handle */
-    HandleTable->UniqueProcessId = (QuotaProcess ? QuotaProcess->UniqueProcessId : NULL);
+    /* Return the handle entry */
+    return Entry;
+}
 
-    ExInitializeResource(&HandleTable->HandleLock);
+PVOID
+NTAPI
+ExpAllocateTablePagedPool(IN PEPROCESS Process OPTIONAL,
+                          IN SIZE_T Size)
+{
+    PVOID Buffer;
 
-    KeInitializeEvent(&HandleTable->HandleContentionEvent,
-                      NotificationEvent,
-                      FALSE);
+    /* Do the allocation */
+    Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG('O', 'b', 't', 'b'));
+    if (Buffer)
+    {
+        /* Clear the memory */
+        RtlZeroMemory(Buffer, Size);
 
-    RtlZeroMemory(HandleTable->Table, N_TOPLEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY*));
+        /* Check if we have a process to charge quota */
+        if (Process)
+        {
+            /* FIXME: Charge quota */
+        }
+    }
 
-    /* during bootup KeGetCurrentThread() might be NULL, needs to be fixed... */
-    if(KeGetCurrentThread() != NULL)
-    {
-      /* insert it into the global handle table list */
-      KeEnterCriticalRegion();
+    /* Return the allocated memory */
+    return Buffer;
+}
 
-      ExAcquireHandleTableListLock();
-      InsertTailList(&ExpHandleTableHead,
-                     &HandleTable->HandleTableList);
-      ExReleaseHandleTableListLock();
+PVOID
+NTAPI
+ExpAllocateTablePagedPoolNoZero(IN PEPROCESS Process OPTIONAL,
+                                IN SIZE_T Size)
+{
+    PVOID Buffer;
 
-      KeLeaveCriticalRegion();
-    }
-    else
+    /* Do the allocation */
+    Buffer = ExAllocatePoolWithTag(PagedPool, Size, TAG('O', 'b', 't', 'b'));
+    if (Buffer)
     {
-      InsertTailList(&ExpHandleTableHead,
-                     &HandleTable->HandleTableList);
+        /* Check if we have a process to charge quota */
+        if (Process)
+        {
+            /* FIXME: Charge quota */
+        }
     }
-  }
-  else
-  {
-    /* FIXME - return the quota to the process */
-  }
 
-  return HandleTable;
+    /* Return the allocated memory */
+    return Buffer;
 }
 
 VOID
-ExSweepHandleTable(IN PHANDLE_TABLE HandleTable,
-                   IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback  OPTIONAL,
-                   IN PVOID Context  OPTIONAL)
+NTAPI
+ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL,
+                      IN PVOID Buffer,
+                      IN SIZE_T Size)
 {
-  PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
-  LONG ExHandle = 0;
-
-  PAGED_CODE();
-
-  ASSERT(HandleTable);
+    /* Free the buffer */
+    ExFreePool(Buffer);
+    if (Process)
+    {
+        /* FIXME: Release quota */
+    }
+}
 
-  KeEnterCriticalRegion();
+VOID
+NTAPI
+ExpFreeLowLevelTable(IN PEPROCESS Process,
+                     IN PHANDLE_TABLE_ENTRY TableEntry)
+{
+    /* Check if we have an entry */
+    if (TableEntry[0].Object)
+    {
+        /* Free the entry */
+        ExpFreeTablePagedPool(Process,
+                              TableEntry[0].Object,
+                              LOW_LEVEL_ENTRIES *
+                              sizeof(HANDLE_TABLE_ENTRY_INFO));
+    }
 
-  /* ensure there's no other operations going by acquiring an exclusive lock */
-  ExAcquireHandleLockExclusive(HandleTable);
+    /* Free the table */
+    ExpFreeTablePagedPool(Process, TableEntry, PAGE_SIZE);
+}
 
-  ASSERT(!(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING));
+VOID
+NTAPI
+ExpFreeHandleTable(IN PHANDLE_TABLE HandleTable)
+{
+    PEPROCESS Process = HandleTable->QuotaProcess;
+    ULONG i, j;
+    ULONG TableLevel = (ULONG)(HandleTable->TableCode & 3);
+    ULONG_PTR TableBase = HandleTable->TableCode & ~3;
+    PHANDLE_TABLE_ENTRY Level1, *Level2, **Level3;
+    PAGED_CODE();
+
+    /* Check which level we're at */
+    if (!TableLevel)
+    {
+        /* Select the first level table base and just free it */
+        Level1 = (PVOID)TableBase;
+        ExpFreeLowLevelTable(Process, Level1);
+    }
+    else if (TableLevel == 1)
+    {
+        /* Select the second level table base */
+        Level2 = (PVOID)TableBase;
 
-  HandleTable->Flags |= EX_HANDLE_TABLE_CLOSING;
+        /* Loop each mid level entry */
+        for (i = 0; i < MID_LEVEL_ENTRIES; i++)
+        {
+            /* Leave if we've reached the last entry */
+            if (!Level2[i]) break;
 
-  KePulseEvent(&HandleTable->HandleContentionEvent,
-               EVENT_INCREMENT,
-               FALSE);
+            /* Free the second level table */
+            ExpFreeLowLevelTable(Process, Level2[i]);
+        }
 
-  /* call the callback function to cleanup the objects associated with the
-     handle table */
-  for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
-      tlp != lasttlp;
-      tlp++)
-  {
-    if((*tlp) != NULL)
+        /* Free the second level table */
+        ExpFreeTablePagedPool(Process, Level2, PAGE_SIZE);
+    }
+    else
     {
-      for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
-          mlp != lastmlp;
-          mlp++)
-      {
-        if((*mlp) != NULL)
+        /* Select the third level table base */
+        Level3 = (PVOID)TableBase;
+
+        /* Loop each high level entry */
+        for (i = 0; i < HIGH_LEVEL_ENTRIES; i++)
         {
-          PHANDLE_TABLE_ENTRY curee, laste;
+            /* Leave if we've reached the last entry */
+            if (!Level3[i]) break;
 
-          for(curee = *mlp, laste = *mlp + N_SUBHANDLE_ENTRIES;
-              curee != laste;
-              curee++)
-          {
-            if(curee->Object != NULL && SweepHandleCallback != NULL)
+            /* Loop each mid level entry */
+            for (j = 0; j < MID_LEVEL_ENTRIES; j++)
             {
-              curee->ObAttributes |= EX_HANDLE_ENTRY_LOCKED;
-              SweepHandleCallback(curee, EX_HANDLE_TO_HANDLE(ExHandle), Context);
+                /* Leave if we've reached the last entry */
+                if (!Level3[i][j]) break;
+
+                /* Free the second level table */
+                ExpFreeLowLevelTable(Process, Level3[i][j]);
             }
 
-            ExHandle++;
-          }
+            /* Free the third level table entry */
+            ExpFreeTablePagedPool(Process, Level3[i], PAGE_SIZE);
         }
-        else
-          break;
-      }
-    }
-    else
-      break;
-  }
 
-  ExReleaseHandleLock(HandleTable);
+        /* Free the third level table */
+        ExpFreeTablePagedPool(Process,
+                              Level3,
+                              HIGH_LEVEL_ENTRIES *
+                              sizeof(PHANDLE_TABLE_ENTRY));
+    }
 
-  KeLeaveCriticalRegion();
+    /* Free the actual table and check if we need to release quota */
+    ExFreePool(HandleTable);
+    if (Process)
+    {
+        /* FIXME: TODO */
+    }
 }
 
 VOID
-ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable)
+NTAPI
+ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                        IN EXHANDLE Handle,
+                        IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 {
-  PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
-  PEPROCESS QuotaProcess;
+    ULONG OldValue, NewValue, *Free;
+    ULONG i;
+    PAGED_CODE();
 
-  PAGED_CODE();
+    /* Sanity checks */
+    ASSERT(HandleTableEntry->Object == NULL);
+    ASSERT(HandleTableEntry == ExpLookupHandleTableEntry(HandleTable, Handle));
 
-  ASSERT(HandleTable);
-  ASSERT(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING);
+    /* Decrement the handle count */
+    InterlockedDecrement(&HandleTable->HandleCount);
 
-  KeEnterCriticalRegion();
+    /* Mark the handle as free */
+    NewValue = (ULONG)Handle.Value & ~(SizeOfHandle(1) - 1);
 
-  /* at this point the table should not be queried or altered anymore,
-     no locks should be necessary */
+    /* Check if we're FIFO */
+    if (!HandleTable->StrictFIFO)
+    {
+        /* Select a lock index */
+        i = (NewValue >> 2) % 4;
 
-  ASSERT(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING);
+        /* Select which entry to use */
+        Free = (HandleTable->HandleTableLock[i].Locked) ?
+                &HandleTable->FirstFree : &HandleTable->LastFree;
+    }
+    else
+    {
+        /* No need to worry about locking, take the last entry */
+        Free = &HandleTable->LastFree;
+    }
 
-  /* remove the handle table from the global handle table list */
-  ExAcquireHandleTableListLock();
-  RemoveEntryList(&HandleTable->HandleTableList);
-  ExReleaseHandleTableListLock();
+    /* Start value change loop */
+    for (;;)
+    {
+        /* Get the current value and write */
+        OldValue = *Free;
+        HandleTableEntry->NextFreeTableEntry = (ULONG)OldValue;
+        if (InterlockedCompareExchange(Free, NewValue, OldValue) == OldValue)
+        {
+            /* Break out, we're done. Make sure the handle value makes sense */
+            ASSERT((OldValue & FREE_HANDLE_MASK) <
+                   HandleTable->NextHandleNeedingPool);
+            break;
+        }
+    }
+}
 
-  QuotaProcess = HandleTable->QuotaProcess;
+PHANDLE_TABLE
+NTAPI
+ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL,
+                       IN BOOLEAN NewTable)
+{
+    PHANDLE_TABLE HandleTable;
+    PHANDLE_TABLE_ENTRY HandleTableTable, HandleEntry;
+    ULONG i;
+    PAGED_CODE();
+
+    /* Allocate the table */
+    HandleTable = ExAllocatePoolWithTag(PagedPool,
+                                        sizeof(HANDLE_TABLE),
+                                        TAG('O', 'b', 't', 'b'));
+    if (!HandleTable) return NULL;
+
+    /* Check if we have a process */
+    if (Process)
+    {
+        /* FIXME: Charge quota */
+    }
 
-  /* free the tables */
-  for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
-      tlp != lasttlp;
-      tlp++)
-  {
-    if((*tlp) != NULL)
+    /* Clear the table */
+    RtlZeroMemory(HandleTable, sizeof(HANDLE_TABLE));
+
+    /* Now allocate the first level structures */
+    HandleTableTable = ExpAllocateTablePagedPoolNoZero(Process, PAGE_SIZE);
+    if (!HandleTableTable)
     {
-      for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
-          mlp != lastmlp;
-          mlp++)
-      {
-        if((*mlp) != NULL)
+        /* Failed, free the table */
+        ExFreePool(HandleTable);
+        return NULL;
+    }
+
+    /* Write the pointer to our first level structures */
+    HandleTable->TableCode = (ULONG_PTR)HandleTableTable;
+
+    /* Initialize the first entry */
+    HandleEntry = &HandleTableTable[0];
+    HandleEntry->NextFreeTableEntry = -2;
+    HandleEntry->Value = 0;
+
+    /* Check if this is a new table */
+    if (NewTable)
+    {
+        /* Go past the root entry */
+        HandleEntry++;
+
+        /* Loop every low level entry */
+        for (i = 1; i < (LOW_LEVEL_ENTRIES - 1); i++)
         {
-          ExFreePool(*mlp);
+            /* Set up the free data */
+            HandleEntry->Value = 0;
+            HandleEntry->NextFreeTableEntry = (i + 1) * SizeOfHandle(1);
 
-          if(QuotaProcess != NULL)
-          {
-            /* FIXME - return the quota to the process */
-          }
+            /* Move to the next entry */
+            HandleEntry++;
         }
-      }
-
-      ExFreePool(*tlp);
 
-      if(QuotaProcess != NULL)
-      {
-        /* FIXME - return the quota to the process */
-      }
+        /* Terminate the last entry */
+        HandleEntry->Value = 0;
+        HandleEntry->NextFreeTableEntry = 0;
+        HandleTable->FirstFree = SizeOfHandle(1);
     }
-  }
 
-  KeLeaveCriticalRegion();
+    /* Set the next handle needing pool after our allocated page from above */
+    HandleTable->NextHandleNeedingPool = LOW_LEVEL_ENTRIES * SizeOfHandle(1);
 
-  /* free the handle table */
-  ExDeleteResource(&HandleTable->HandleLock);
-  ExFreePool(HandleTable);
+    /* Setup the rest of the handle table data */
+    HandleTable->QuotaProcess = Process;
+    HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId;
+    HandleTable->Flags = 0;
+
+    /* Loop all the handle table locks */
+    for (i = 0; i < 4; i++) HandleTable->HandleTableLock[i].Value = 0;
 
-  if(QuotaProcess != NULL)
-  {
-    /* FIXME - return the quota to the process */
-  }
+    /* Initialize the contention event lock and return the lock */
+    HandleTable->HandleContentionEvent.Value = 0;
+    return HandleTable;
 }
 
-PHANDLE_TABLE
-ExDupHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL,
-                 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback  OPTIONAL,
-                 IN PVOID Context  OPTIONAL,
-                 IN PHANDLE_TABLE SourceHandleTable)
+PHANDLE_TABLE_ENTRY
+NTAPI
+ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable,
+                         IN BOOLEAN DoInit)
 {
-  PHANDLE_TABLE HandleTable;
+    ULONG i, Base;
+    PHANDLE_TABLE_ENTRY Low, HandleEntry;
+
+    /* Allocate the low level table */
+    Low = ExpAllocateTablePagedPoolNoZero(HandleTable->QuotaProcess,
+                                          PAGE_SIZE);
+    if (!Low) return NULL;
 
-  PAGED_CODE();
+    /* Setup the initial entry */
+    HandleEntry = &Low[0];
+    HandleEntry->NextFreeTableEntry = -2;
+    HandleEntry->Value = 0;
+
+    /* Check if we're initializing */
+    if (DoInit)
+    {
+        /* Go to the next entry and the base entry */
+        HandleEntry++;
+        Base = HandleTable->NextHandleNeedingPool + SizeOfHandle(2);
+
+        /* Loop each entry */
+        for (i = Base;
+             i < Base + SizeOfHandle(LOW_LEVEL_ENTRIES - 2);
+             i += SizeOfHandle(1))
+        {
+            /* Free this entry and move on to the next one */
+            HandleEntry->NextFreeTableEntry = i;
+            HandleEntry->Value = 0;
+            HandleEntry++;
+        }
 
-  ASSERT(SourceHandleTable);
+        /* Terminate the last entry */
+        HandleEntry->NextFreeTableEntry = 0;
+        HandleEntry->Value = 0;
+    }
 
-  HandleTable = ExCreateHandleTable(QuotaProcess);
-  if(HandleTable != NULL)
-  {
-    PHANDLE_TABLE_ENTRY **tlp, **srctlp, **etlp, *mlp, *srcmlp, *emlp, stbl, srcstbl, estbl;
-    LONG tli, mli, eli;
+    /* Return the low level table */
+    return Low;
+}
 
-    tli = mli = eli = 0;
+PHANDLE_TABLE_ENTRY*
+NTAPI
+ExpAllocateMidLevelTable(IN PHANDLE_TABLE HandleTable,
+                         IN BOOLEAN DoInit,
+                         OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
+{
+    PHANDLE_TABLE_ENTRY *Mid, Low;
 
-    /* make sure the other handle table isn't being changed during the duplication */
-    ExAcquireHandleLockShared(SourceHandleTable);
+    /* Allocate the mid level table */
+    Mid = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, PAGE_SIZE);
+    if (!Mid) return NULL;
 
-    /* allocate enough tables */
-    etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
-    for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
-        srctlp != etlp;
-        srctlp++, tlp++)
+    /* Allocate a new low level for it */
+    Low = ExpAllocateLowLevelTable(HandleTable, DoInit);
+    if (!Low)
     {
-      if(*srctlp != NULL)
-      {
-        /* allocate middle level entry tables */
-        if(QuotaProcess != NULL)
-        {
-          /* FIXME - Charge process quota before allocating the handle table! */
-        }
+        /* We failed, free the mid table */
+        ExpFreeTablePagedPool(HandleTable->QuotaProcess, Mid, PAGE_SIZE);
+        return NULL;
+    }
 
-        *tlp = ExAllocatePoolWithTag(PagedPool,
-                                     N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY),
-                                     TAG('E', 'x', 'H', 't'));
-        if(*tlp != NULL)
-        {
-          RtlZeroMemory(*tlp, N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY));
+    /* Link the tables and return the pointer */
+    Mid[0] = Low;
+    *LowTableEntry = Low;
+    return Mid;
+}
 
-          KeMemoryBarrier();
+BOOLEAN
+NTAPI
+ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable,
+                                IN BOOLEAN DoInit)
+{
+    ULONG i, j, Index;
+    PHANDLE_TABLE_ENTRY Low, *Mid, **High, *SecondLevel, **ThirdLevel;
+    ULONG NewFree, FirstFree;
+    PVOID Value;
+    ULONG_PTR TableBase = HandleTable->TableCode & ~3;
+    ULONG TableLevel = (ULONG)(TableBase & 3);
+    PAGED_CODE();
+
+    /* Check how many levels we already have */
+    if (!TableLevel)
+    {
+        /* Allocate a mid level, since we only have a low level */
+        Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
+        if (!Mid) return FALSE;
 
-          emlp = *srctlp + N_MIDDLELEVEL_POINTERS;
-          for(srcmlp = *srctlp, mlp = *tlp;
-              srcmlp != emlp;
-              srcmlp++, mlp++)
-          {
-            if(*srcmlp != NULL)
-            {
-              /* allocate subhandle tables */
-              if(QuotaProcess != NULL)
-              {
-                /* FIXME - Charge process quota before allocating the handle table! */
-              }
-
-              *mlp = ExAllocatePoolWithTag(PagedPool,
-                                           N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY),
-                                           TAG('E', 'x', 'H', 't'));
-              if(*mlp != NULL)
-              {
-                RtlZeroMemory(*mlp, N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY));
-              }
-              else
-              {
-                goto freehandletable;
-              }
-            }
-            else
-            {
-              *mlp = NULL;
-            }
-          }
+        /* Link up the tables */
+        Mid[1] = Mid[0];
+        Mid[0] = (PVOID)TableBase;
+
+        /* Write the new level and attempt to change the table code */
+        TableBase = ((ULONG_PTR)Mid) | 1;
+        Value = InterlockedExchangePointer(&HandleTable->TableCode, TableBase);
+    }
+    else if (TableLevel == 1)
+    {
+        /* Setup the 2nd level table */
+        SecondLevel = (PVOID)TableBase;
+
+        /* Get if the next index can fit in the table */
+        i = HandleTable->NextHandleNeedingPool /
+            SizeOfHandle(LOW_LEVEL_ENTRIES);
+        if (i < MID_LEVEL_ENTRIES)
+        {
+            /* We need to allocate a new table */
+            Low = ExpAllocateLowLevelTable(HandleTable, DoInit);
+            if (!Low) return FALSE;
+
+            /* Update the table */
+            Value = InterlockedExchangePointer(&SecondLevel[i], Low);
+            ASSERT(Value == NULL);
         }
         else
         {
-freehandletable:
-          DPRINT1("Failed to duplicate handle table 0x%p\n", SourceHandleTable);
+            /* We need a new high level table */
+            High = ExpAllocateTablePagedPool(HandleTable->QuotaProcess,
+                                             HIGH_LEVEL_ENTRIES);
+            if (!High) return FALSE;
+
+            /* Allocate a new mid level table as well */
+            Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
+            if (!Mid)
+            {
+                /* We failed, free the high level table as welll */
+                ExpFreeTablePagedPool(HandleTable->QuotaProcess,
+                                      High,
+                                      HIGH_LEVEL_ENTRIES);
+                return FALSE;
+            }
 
-          ExReleaseHandleLock(SourceHandleTable);
+            /* Link up the tables */
+            High[0] = (PVOID)TableBase;
+            High[1] = Mid;
 
-          ExDestroyHandleTable(HandleTable);
-          /* allocate an empty handle table */
-          return ExCreateHandleTable(QuotaProcess);
+            /* Write the new table and change the table code */
+            TableBase = ((ULONG_PTR)High) | 2;
+            Value = InterlockedExchangePointer(&HandleTable->TableCode,
+                                               (PVOID)TableBase);
         }
-      }
     }
+    else if (TableLevel == 2)
+    {
+        /* Setup the 3rd level table */
+        ThirdLevel = (PVOID)TableBase;
+
+        /* Get the index and check if it can fit */
+        i = HandleTable->NextHandleNeedingPool / SizeOfHandle(MAX_MID_INDEX);
+        if (i >= HIGH_LEVEL_ENTRIES) return FALSE;
 
-    /* duplicate the handles */
-    HandleTable->HandleCount = SourceHandleTable->HandleCount;
-    HandleTable->FirstFree = SourceHandleTable->FirstFree;
-    HandleTable->NextHandleNeedingPool = SourceHandleTable->NextHandleNeedingPool;
+        /* Check if there's no mid-level table */
+        if (!ThirdLevel[i])
+        {
+            /* Allocate a new mid level table */
+            Mid = ExpAllocateMidLevelTable(HandleTable, DoInit, &Low);
+            if (!Mid) return FALSE;
 
-    /* make sure all tables are zeroed */
-    KeMemoryBarrier();
+            /* Update the table pointer */
+            Value = InterlockedExchangePointer(&ThirdLevel[i], Mid);
+            ASSERT(Value == NULL);
+        }
+        else
+        {
+            /* We have one, check at which index we should insert our entry */
+            Index  = (HandleTable->NextHandleNeedingPool / SizeOfHandle(1)) -
+                      i * MAX_MID_INDEX;
+            j = Index / LOW_LEVEL_ENTRIES;
+
+            /* Allocate a new low level */
+            Low = ExpAllocateLowLevelTable(HandleTable, DoInit);
+            if (!Low) return FALSE;
+
+            /* Update the table pointer */
+            Value = InterlockedExchangePointer(&ThirdLevel[i][j], Low);
+            ASSERT(Value == NULL);
+        }
+    }
+
+    /* Update the index of the next handle */
+    Index = InterlockedExchangeAdd(&HandleTable->NextHandleNeedingPool,
+                                   SizeOfHandle(LOW_LEVEL_ENTRIES));
 
-    etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
-    for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
-        srctlp != etlp;
-        srctlp++, tlp++, tli++)
+    /* Check if need to initialize the table */
+    if (DoInit)
     {
-      if(*srctlp != NULL)
-      {
-        ASSERT(*tlp != NULL);
+        /* Create a new index number */
+        Index += SizeOfHandle(1);
 
-        emlp = *srctlp + N_MIDDLELEVEL_POINTERS;
-        for(srcmlp = *srctlp, mlp = *tlp;
-            srcmlp != emlp;
-            srcmlp++, mlp++, mli++)
+        /* Start free index change loop */
+        for (;;)
         {
-          if(*srcmlp != NULL)
-          {
-            ASSERT(*mlp != NULL);
-
-            /* walk all handle entries and duplicate them if wanted */
-            estbl = *srcmlp + N_SUBHANDLE_ENTRIES;
-            for(srcstbl = *srcmlp, stbl = *mlp;
-                srcstbl != estbl;
-                srcstbl++, stbl++, eli++)
-            {
-              /* try to duplicate the source handle */
-              if(srcstbl->Object != NULL &&
-                 ExLockHandleTableEntry(SourceHandleTable,
-                                        srcstbl))
-              {
-                /* ask the caller if this handle should be duplicated */
-                if(DuplicateHandleCallback != NULL &&
-                   !DuplicateHandleCallback(HandleTable,
-                                            srcstbl,
-                                            Context))
-                {
-                  /* free the entry and chain it into the free list */
-                  HandleTable->HandleCount--;
-                  stbl->Object = NULL;
-                  stbl->NextFreeTableEntry = HandleTable->FirstFree;
-                  HandleTable->FirstFree = BUILD_HANDLE(tli, mli, eli);
-                }
-                else
-                {
-                  /* duplicate the handle and unlock it */
-                  stbl->GrantedAccess = srcstbl->GrantedAccess;
-                  stbl->ObAttributes = srcstbl->ObAttributes & ~EX_HANDLE_ENTRY_LOCKED;
-                }
-                ExUnlockHandleTableEntry(SourceHandleTable,
-                                         srcstbl);
-              }
-              else
-              {
-                /* this is a free handle table entry, copy over the entire
-                   structure as-is */
-                *stbl = *srcstbl;
-              }
-            }
-          }
+            /* Setup the first free index */
+            FirstFree = HandleTable->FirstFree;
+            Low[LOW_LEVEL_ENTRIES - 1].NextFreeTableEntry = FirstFree;
+
+            /* Change the index */
+            NewFree = InterlockedCompareExchange(&HandleTable->FirstFree,
+                                                 Index,
+                                                 FirstFree);
+            if (NewFree == FirstFree) break;
         }
-      }
     }
 
-    /* release the source handle table */
-    ExReleaseHandleLock(SourceHandleTable);
-  }
-
-  return HandleTable;
+    /* All done */
+    return TRUE;
 }
 
-static PHANDLE_TABLE_ENTRY
-ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
-                            OUT PHANDLE Handle)
+ULONG
+NTAPI
+ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable)
 {
-  PHANDLE_TABLE_ENTRY Entry = NULL;
+    ULONG LastFree, i;
 
-  PAGED_CODE();
+    /* Clear the last free index */
+    LastFree = InterlockedExchange(&HandleTable->LastFree, 0);
 
-  ASSERT(HandleTable);
-  ASSERT(Handle);
-  ASSERT(KeGetCurrentThread() != NULL);
+    /* Check if we had no index */
+    if (!LastFree) return LastFree;
 
-  DPRINT("HT[0x%p]: HandleCount: %d\n", HandleTable, HandleTable->HandleCount);
-
-  if(HandleTable->HandleCount < EX_MAX_HANDLES)
-  {
-    ULONG tli, mli, eli;
+    /* Acquire the locks we need */
+    for (i = 1; i < 4; i++)
+    {
+        /* Acquire this lock exclusively */
+        ExWaitOnPushLock(&HandleTable->HandleTableLock[i]);
+    }
 
-    if(HandleTable->FirstFree != -1)
+    /* Check if we're not strict FIFO */
+    if (!HandleTable->StrictFIFO)
     {
-      /* there's a free handle entry we can just grab and use */
-      tli = TLI_FROM_HANDLE(HandleTable->FirstFree);
-      mli = MLI_FROM_HANDLE(HandleTable->FirstFree);
-      eli = ELI_FROM_HANDLE(HandleTable->FirstFree);
+        /* Update the first free index */
+        if (!InterlockedCompareExchange(&HandleTable->FirstFree, LastFree, 0))
+        {
+            /* We're done, exit */
+            return LastFree;
+        }
+    }
 
-      /* the pointer should be valid in any way!!! */
-      ASSERT(HandleTable->Table[tli]);
-      ASSERT(HandleTable->Table[tli][mli]);
+    /* We are strict FIFO, we need to reverse the entries */
+    KEBUGCHECK(0);
+    return LastFree;
+}
 
-      Entry = &HandleTable->Table[tli][mli][eli];
+PHANDLE_TABLE_ENTRY
+NTAPI
+ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                            OUT PEXHANDLE NewHandle)
+{
+    ULONG OldValue, NewValue, NewValue1;
+    PHANDLE_TABLE_ENTRY Entry;
+    EXHANDLE Handle;
+    BOOLEAN Result;
+    ULONG i;
+
+    /* Start allocation loop */
+    for (;;)
+    {
+        /* Get the current link */
+        OldValue = HandleTable->FirstFree;
+        while (!OldValue)
+        {
+            /* No free entries remain, lock the handle table */
+            KeEnterCriticalRegion();
+            ExAcquirePushLockExclusive(&HandleTable->HandleTableLock[0]);
 
-      *Handle = EX_HANDLE_TO_HANDLE(HandleTable->FirstFree);
+            /* Check the value again */
+            OldValue = HandleTable->FirstFree;
+            if (OldValue)
+            {
+                /* Another thread has already created a new level, bail out */
+                ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
+                KeLeaveCriticalRegion();
+                break;
+            }
 
-      /* save the index to the next free handle (if available) */
-      HandleTable->FirstFree = Entry->NextFreeTableEntry;
-      Entry->NextFreeTableEntry = 0;
-      Entry->Object = NULL;
+            /* Now move any free handles */
+            OldValue = ExpMoveFreeHandles(HandleTable);
+            if (OldValue)
+            {
+                /* Another thread has already moved them, bail out */
+                ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
+                KeLeaveCriticalRegion();
+                break;
+            }
 
-      HandleTable->HandleCount++;
-    }
-    else
-    {
-      /* we need to allocate a new subhandle table first */
-      PHANDLE_TABLE_ENTRY cure, laste, ntbl, *nmtbl;
-      ULONG i;
-      BOOLEAN AllocatedMtbl;
+            /* We're the first one through, so do the actual allocation */
+            Result = ExpAllocateHandleTableEntrySlow(HandleTable, TRUE);
 
-      ASSERT(HandleTable->NextHandleNeedingPool <= N_MAX_HANDLE);
+            /* Unlock the table and get the value now */
+            ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
+            KeLeaveCriticalRegion();
+            OldValue = HandleTable->FirstFree;
 
-      /* the index of the next table to be allocated was saved in
-         NextHandleNeedingPool the last time a handle entry was allocated and
-         the subhandle entry list was full. the subhandle entry index of
-         NextHandleNeedingPool should be 0 here! */
-      tli = TLI_FROM_HANDLE(HandleTable->NextHandleNeedingPool);
-      mli = MLI_FROM_HANDLE(HandleTable->NextHandleNeedingPool);
-      DPRINT("HandleTable->NextHandleNeedingPool: 0x%x\n", HandleTable->NextHandleNeedingPool);
-      DPRINT("tli: 0x%x mli: 0x%x eli: 0x%x\n", tli, mli, ELI_FROM_HANDLE(HandleTable->NextHandleNeedingPool));
+            /* Check if allocation failed */
+            if (!Result)
+            {
+                /* Check if nobody else went through here */
+                if (!OldValue)
+                {
+                    /* We're still the only thread around, so fail */
+                    NewHandle->GenericHandleOverlay = NULL;
+                    return NULL;
+                }
+            }
+        }
+
+        /* We made it, write the current value */
+        Handle.Value = (OldValue & FREE_HANDLE_MASK);
 
-      ASSERT(ELI_FROM_HANDLE(HandleTable->NextHandleNeedingPool) == 0);
+        /* Lookup the entry for this handle */
+        Entry = ExpLookupHandleTableEntry(HandleTable, Handle);
 
-      DPRINT("HandleTable->Table[%d] == 0x%p\n", tli, HandleTable->Table[tli]);
+        /* Get an available lock and acquire it */
+        i = ((OldValue & FREE_HANDLE_MASK) >> 2) % 4;
+        KeEnterCriticalRegion();
+        ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]);
 
-      /* allocate a middle level entry list if required */
-      nmtbl = HandleTable->Table[tli];
-      if(nmtbl == NULL)
-      {
-        if(HandleTable->QuotaProcess != NULL)
+        /* Check if the value changed after acquiring the lock */
+        if (OldValue != HandleTable->FirstFree)
         {
-          /* FIXME - Charge process quota before allocating the handle table! */
+            /* It did, so try again */
+            ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
+            KeLeaveCriticalRegion();
+            continue;
         }
 
-        nmtbl = ExAllocatePoolWithTag(PagedPool,
-                                      N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY),
-                                      TAG('E', 'x', 'H', 't'));
-        if(nmtbl == NULL)
-        {
-          if(HandleTable->QuotaProcess != NULL)
-          {
-            /* FIXME - return the quota to the process */
-          }
+        /* Now get the next value and do the compare */
+        NewValue = Entry->NextFreeTableEntry;
+        NewValue1 = InterlockedCompareExchange(&HandleTable->FirstFree,
+                                               NewValue,
+                                               OldValue);
 
-          return NULL;
-        }
+        /* The change was done, so release the lock */
+        ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
+        KeLeaveCriticalRegion();
 
-        /* clear the middle level entry list */
-        RtlZeroMemory(nmtbl, N_MIDDLELEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY));
-
-        /* make sure the table was zeroed before we set one item */
-        KeMemoryBarrier();
-
-        /* note, don't set the the pointer in the top level list yet because we
-           might screw up lookups if allocating a subhandle entry table failed
-           and this newly allocated table might get freed again */
-        AllocatedMtbl = TRUE;
-      }
-      else
-      {
-        AllocatedMtbl = FALSE;
-
-        /* allocate a subhandle entry table in any case! */
-        ASSERT(nmtbl[mli] == NULL);
-      }
-
-      DPRINT("HandleTable->Table[%d][%d] == 0x%p\n", tli, mli, nmtbl[mli]);
-
-      if(HandleTable->QuotaProcess != NULL)
-      {
-        /* FIXME - Charge process quota before allocating the handle table! */
-      }
-
-      ntbl = ExAllocatePoolWithTag(PagedPool,
-                                   N_SUBHANDLE_ENTRIES * sizeof(HANDLE_TABLE_ENTRY),
-                                   TAG('E', 'x', 'H', 't'));
-      if(ntbl == NULL)
-      {
-        if(HandleTable->QuotaProcess != NULL)
+        /* Check if the compare was successful */
+        if (NewValue1 == OldValue)
         {
-          /* FIXME - Return process quota charged  */
+            /* Make sure that the new handle is in range, and break out */
+            ASSERT((NewValue & FREE_HANDLE_MASK) <
+                   HandleTable->NextHandleNeedingPool);
+            break;
         }
-
-        /* free the middle level entry list, if allocated, because it's empty and
-           unused */
-        if(AllocatedMtbl)
+        else
         {
-          ExFreePool(nmtbl);
-
-          if(HandleTable->QuotaProcess != NULL)
-          {
-            /* FIXME - Return process quota charged  */
-          }
+            /* The compare failed, make sure we expected it */
+            ASSERT((NewValue1 & FREE_HANDLE_MASK) !=
+                   (OldValue & FREE_HANDLE_MASK));
         }
+    }
 
-        return NULL;
-      }
-
-      /* let's just use the very first entry */
-      Entry = ntbl;
-      Entry->ObAttributes = EX_HANDLE_ENTRY_LOCKED;
-      Entry->NextFreeTableEntry = 0;
-
-      *Handle = EX_HANDLE_TO_HANDLE(HandleTable->NextHandleNeedingPool);
-
-      HandleTable->HandleCount++;
-
-      /* set the FirstFree member to the second entry and chain the
-         free entries */
-      HandleTable->FirstFree = HandleTable->NextHandleNeedingPool + 1;
-      for(cure = Entry + 1, laste = Entry + N_SUBHANDLE_ENTRIES, i = HandleTable->FirstFree + 1;
-          cure != laste;
-          cure++, i++)
-      {
-        cure->Object = NULL;
-        cure->NextFreeTableEntry = i;
-      }
-      /* truncate the free entry list */
-      (cure - 1)->NextFreeTableEntry = -1;
-
-      /* save the pointers to the allocated list(s) */
-      (void)InterlockedExchangePointer(&nmtbl[mli], ntbl);
-      if(AllocatedMtbl)
-      {
-        (void)InterlockedExchangePointer(&HandleTable->Table[tli], nmtbl);
-      }
-
-      /* increment the NextHandleNeedingPool to the next index where we need to
-         allocate new memory */
-      HandleTable->NextHandleNeedingPool += N_SUBHANDLE_ENTRIES;
-    }
-  }
-  else
-  {
-    DPRINT1("Can't allocate any more handles in handle table 0x%p!\n", HandleTable);
-  }
-
-  return Entry;
+    /* Increase the number of handles */
+    InterlockedIncrement(&HandleTable->HandleCount);
+
+    /* Return the handle and the entry */
+    *NewHandle = Handle;
+    return Entry;
 }
 
-static VOID
-ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
-                        IN PHANDLE_TABLE_ENTRY Entry,
-                        IN LONG Handle)
+PHANDLE_TABLE
+NTAPI
+ExCreateHandleTable(IN PEPROCESS Process OPTIONAL)
 {
-  PAGED_CODE();
+    PHANDLE_TABLE HandleTable;
+    PAGED_CODE();
+
+    /* Allocate the handle table */
+    HandleTable = ExpAllocateHandleTable(Process, TRUE);
+    if (!HandleTable) return NULL;
 
-  ASSERT(HandleTable);
-  ASSERT(Entry);
-  ASSERT(IS_VALID_EX_HANDLE(Handle));
+    /* Acquire the handle table lock */
+    KeEnterCriticalRegion();
+    ExAcquirePushLockExclusive(&HandleTableListLock);
 
-  DPRINT("ExpFreeHandleTableEntry HT:0x%p Entry:0x%p\n", HandleTable, Entry);
+    /* Insert it into the list */
+    InsertTailList(&HandleTableListHead, &HandleTable->HandleTableList);
 
-  /* automatically unlock the entry if currently locked. We however don't notify
-     anyone who waited on the handle because we're holding an exclusive lock after
-     all and these locks will fail then */
-  (void)InterlockedExchangePointer(&Entry->Object, NULL);
-  Entry->NextFreeTableEntry = HandleTable->FirstFree;
-  HandleTable->FirstFree = Handle;
+    /* Release the lock */
+    ExReleasePushLockExclusive(&HandleTableListLock);
+    KeLeaveCriticalRegion();
 
-  HandleTable->HandleCount--;
+    /* Return the handle table */
+    return HandleTable;
 }
 
-static PHANDLE_TABLE_ENTRY
-ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,
-                          IN LONG Handle)
+HANDLE
+NTAPI
+ExCreateHandle(IN PHANDLE_TABLE HandleTable,
+               IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 {
-  PHANDLE_TABLE_ENTRY Entry = NULL;
+    EXHANDLE Handle;
+    PHANDLE_TABLE_ENTRY NewEntry;
+    PAGED_CODE();
 
-  PAGED_CODE();
+    /* Start with a clean handle */
+    Handle.GenericHandleOverlay = NULL;
 
-  ASSERT(HandleTable);
-
-  if(IS_VALID_EX_HANDLE(Handle))
-  {
-    ULONG tli, mli, eli;
-    PHANDLE_TABLE_ENTRY *mlp;
+    /* Allocate a new entry */
+    NewEntry = ExpAllocateHandleTableEntry(HandleTable, &Handle);
+    if (NewEntry)
+    {
+        /* Enter a critical region */
+        KeEnterCriticalRegion();
 
-    tli = TLI_FROM_HANDLE(Handle);
-    mli = MLI_FROM_HANDLE(Handle);
-    eli = ELI_FROM_HANDLE(Handle);
+        /* Write the entry */
+        *NewEntry = *HandleTableEntry;
 
-    mlp = HandleTable->Table[tli];
-    if(Handle < HandleTable->NextHandleNeedingPool &&
-       mlp != NULL && mlp[mli] != NULL && mlp[mli][eli].Object != NULL)
-    {
-      Entry = &mlp[mli][eli];
-      DPRINT("handle lookup 0x%x -> entry 0x%p [HT:0x%p] ptr: 0x%p\n", Handle, Entry, HandleTable, mlp[mli][eli].Object);
+        /* Unlock it and leave the critical region */
+        ExUnlockHandleTableEntry(HandleTable, NewEntry);
+        KeLeaveCriticalRegion();
     }
-  }
-  else
-  {
-    DPRINT("Looking up invalid handle 0x%x\n", Handle);
-  }
 
-  return Entry;
+    /* Return the handle value */
+    return Handle.GenericHandleOverlay;
 }
 
-BOOLEAN
-ExLockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
-                       IN PHANDLE_TABLE_ENTRY Entry)
+VOID
+NTAPI
+ExpBlockOnLockedHandleEntry(IN PHANDLE_TABLE HandleTable,
+                            IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 {
-  ULONG_PTR Current, New;
-
-  PAGED_CODE();
-
-  DPRINT("Entering handle table entry 0x%p lock...\n", Entry);
+    LONG_PTR OldValue;
+    DEFINE_WAIT_BLOCK(WaitBlock);
 
-  ASSERT(HandleTable);
-  ASSERT(Entry);
+    /* Block on the pushlock */
+    ExBlockPushLock(&HandleTable->HandleContentionEvent, WaitBlock);
 
-  for(;;)
-  {
-    Current = (volatile ULONG_PTR)Entry->Object;
-
-    if(!Current || (HandleTable->Flags & EX_HANDLE_TABLE_CLOSING))
+    /* Get the current value and check if it's been unlocked */
+    OldValue = HandleTableEntry->Value;
+    if (!(OldValue) || (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT))
     {
-      DPRINT("Attempted to lock empty handle table entry 0x%p or handle table shut down\n", Entry);
-      break;
+        /* Unblock the pushlock and return */
+        ExfUnblockPushLock(&HandleTable->HandleContentionEvent, WaitBlock);
     }
-
-    if(!(Current & EX_HANDLE_ENTRY_LOCKED))
+    else
     {
-      New = Current | EX_HANDLE_ENTRY_LOCKED;
-      if(InterlockedCompareExchangePointer(&Entry->Object,
-                                           (PVOID)New,
-                                           (PVOID)Current) == (PVOID)Current)
-      {
-        DPRINT("SUCCESS handle table 0x%p entry 0x%p lock\n", HandleTable, Entry);
-        /* we acquired the lock */
-        return TRUE;
-      }
+        /* Wait for it to be unblocked */
+        ExWaitForUnblockPushLock(&HandleTable->HandleContentionEvent,
+                                 WaitBlock);
     }
-
-    /* wait about 5ms at maximum so we don't wait forever in unfortunate
-       co-incidences where releasing the lock in another thread happens right
-       before we're waiting on the contention event to get pulsed, which might
-       never happen again... */
-    KeWaitForSingleObject(&HandleTable->HandleContentionEvent,
-                          Executive,
-                          KernelMode,
-                          FALSE,
-                          &ExpHandleShortWait);
-  }
-
-  return FALSE;
 }
 
-VOID
-ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
-                         IN PHANDLE_TABLE_ENTRY Entry)
+BOOLEAN
+NTAPI
+ExpLockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                        IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 {
-  ULONG_PTR Current, New;
-
-  PAGED_CODE();
+    LONG_PTR NewValue, OldValue;
 
-  ASSERT(HandleTable);
-  ASSERT(Entry);
+    /* Sanity check */
+    ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
+           (KeGetCurrentIrql() == APC_LEVEL));
 
-  DPRINT("ExUnlockHandleTableEntry HT:0x%p Entry:0x%p\n", HandleTable, Entry);
+    /* Start lock loop */
+    for (;;)
+    {
+        /* Get the current value and check if it's locked */
+        OldValue = (LONG_PTR)HandleTableEntry->Object;
+        if (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT)
+        {
+            /* It's not locked, remove the lock bit to lock it */
+            NewValue = OldValue & ~EXHANDLE_TABLE_ENTRY_LOCK_BIT;
+            if (InterlockedCompareExchangePointer(&HandleTableEntry->Object,
+                                                  NewValue,
+                                                  OldValue) == (PVOID)OldValue)
+            {
+                /* We locked it, get out */
+                return TRUE;
+            }
+        }
+        else
+        {
+            /* We couldn't lock it, bail out if it's been freed */
+            if (!OldValue) return FALSE;
+        }
 
-  Current = (volatile ULONG_PTR)Entry->Object;
+        /* It's locked, wait for it to be unlocked */
+        ExpBlockOnLockedHandleEntry(HandleTable, HandleTableEntry);
+    }
+}
 
-  ASSERT(Current & EX_HANDLE_ENTRY_LOCKED);
+VOID
+NTAPI
+ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                         IN PHANDLE_TABLE_ENTRY HandleTableEntry)
+{
+    LONG_PTR OldValue;
+    PAGED_CODE();
 
-  New = Current & ~EX_HANDLE_ENTRY_LOCKED;
+    /* Sanity check */
+    ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
+           (KeGetCurrentIrql() == APC_LEVEL));
 
-  (void)InterlockedExchangePointer(&Entry->Object,
-                                   (PVOID)New);
+    /* Set the lock bit and make sure it wasn't earlier */
+    OldValue = InterlockedOr(&HandleTableEntry->Value,
+                             EXHANDLE_TABLE_ENTRY_LOCK_BIT);
+    ASSERT((OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
 
-  /* we unlocked the entry, pulse the contention event so threads who're waiting
-     on the release can continue */
-  KePulseEvent(&HandleTable->HandleContentionEvent,
-               EVENT_INCREMENT,
-               FALSE);
+    /* Unblock any waiters */
+    ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
 }
 
-HANDLE
-ExCreateHandle(IN PHANDLE_TABLE HandleTable,
-               IN PHANDLE_TABLE_ENTRY Entry)
+VOID
+NTAPI
+ExRemoveHandleTable(IN PHANDLE_TABLE HandleTable)
 {
-  PHANDLE_TABLE_ENTRY NewHandleTableEntry;
-  HANDLE Handle = NULL;
-
-  PAGED_CODE();
+    PAGED_CODE();
 
-  ASSERT(HandleTable);
-  ASSERT(Entry);
+    /* Acquire the table lock */
+    KeEnterCriticalRegion();
+    ExAcquirePushLockExclusive(&HandleTableListLock);
 
-  /* The highest bit in Entry->Object has to be 1 so we make sure it's a
-     pointer to kmode memory. It will cleared though because it also indicates
-     the lock */
-  ASSERT((ULONG_PTR)Entry->Object & EX_HANDLE_ENTRY_LOCKED);
+    /* Remove the table and reset the list */
+    RemoveEntryList(&HandleTable->HandleTableList);
+    InitializeListHead(&HandleTable->HandleTableList);
 
-  KeEnterCriticalRegion();
-  ExAcquireHandleLockExclusive(HandleTable);
+    /* Release the lock */
+    ExReleasePushLockExclusive(&HandleTableListLock);
+    KeLeaveCriticalRegion();
+}
 
-  NewHandleTableEntry = ExpAllocateHandleTableEntry(HandleTable,
-                                                    &Handle);
-  if(NewHandleTableEntry != NULL)
-  {
-    *NewHandleTableEntry = *Entry;
+VOID
+NTAPI
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
+                     IN PVOID DestroyHandleProcedure OPTIONAL)
+{
+    PAGED_CODE();
 
-    ExUnlockHandleTableEntry(HandleTable,
-                             NewHandleTableEntry);
-  }
+    /* Remove the handle from the list */
+    ExRemoveHandleTable(HandleTable);
 
-  ExReleaseHandleLock(HandleTable);
-  KeLeaveCriticalRegion();
+    /* Check if we have a desotry callback */
+    if (DestroyHandleProcedure)
+    {
+        /* FIXME: */
+        KEBUGCHECK(0);
+    }
 
-  return Handle;
+    /* Free the handle table */
+    ExpFreeHandleTable(HandleTable);
 }
 
 BOOLEAN
+NTAPI
 ExDestroyHandle(IN PHANDLE_TABLE HandleTable,
-                IN HANDLE Handle)
+                IN HANDLE Handle,
+                IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
 {
-  PHANDLE_TABLE_ENTRY HandleTableEntry;
-  LONG ExHandle;
-  BOOLEAN Ret = FALSE;
+    EXHANDLE ExHandle;
+    PVOID Object;
+    PAGED_CODE();
 
-  PAGED_CODE();
+    /* Setup the actual handle value */
+    ExHandle.GenericHandleOverlay = Handle;
 
-  ASSERT(HandleTable);
-  
-  ExHandle = HANDLE_TO_EX_HANDLE(Handle);
+    /* Enter a critical region and check if we have to lookup the handle */
+    KeEnterCriticalRegion();
+    if (!HandleTableEntry)
+    {
+        /* Lookup the entry */
+        HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
+
+        /* Make sure that we found an entry, and that it's valid */
+        if (!(HandleTableEntry) ||
+            !(HandleTableEntry->Object) ||
+            (HandleTableEntry->NextFreeTableEntry == -2))
+        {
+            /* Invalid handle, fail */
+            KeLeaveCriticalRegion();
+            return FALSE;
+        }
+
+        /* Lock the entry */
+        if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+        {
+            /* Couldn't lock, fail */
+            KeLeaveCriticalRegion();
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* Make sure the handle is locked */
+        ASSERT((HandleTableEntry->Value & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
+    }
 
-  KeEnterCriticalRegion();
-  ExAcquireHandleLockExclusive(HandleTable);
+    /* Clear the handle */
+    Object = InterlockedExchangePointer(&HandleTableEntry->Object, NULL);
 
-  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
-                                               ExHandle);
+    /* Sanity checks */
+    ASSERT(Object != NULL);
+    ASSERT((((ULONG_PTR)Object) & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
 
-  if(HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
-  {
-    /* free and automatically unlock the handle. However we don't need to pulse
-       the contention event since other locks on this entry will fail */
-    ExpFreeHandleTableEntry(HandleTable,
-                            HandleTableEntry,
-                            ExHandle);
-    Ret = TRUE;
-  }
+    /* Unblock the pushlock */
+    ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
 
-  ExReleaseHandleLock(HandleTable);
-  KeLeaveCriticalRegion();
+    /* Free the actual entry */
+    ExpFreeHandleTableEntry(HandleTable, ExHandle, HandleTableEntry);
 
-  return Ret;
+    /* If we got here, return success */
+    KeLeaveCriticalRegion();
+    return TRUE;
 }
 
-VOID
-ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable,
-                       IN PHANDLE_TABLE_ENTRY Entry,
-                       IN HANDLE Handle)
+PHANDLE_TABLE_ENTRY
+NTAPI
+ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
+                     IN HANDLE Handle)
 {
-  PAGED_CODE();
+    EXHANDLE ExHandle;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    PAGED_CODE();
 
-  ASSERT(HandleTable);
-  ASSERT(Entry);
+    /* Set the handle value */
+    ExHandle.GenericHandleOverlay = Handle;
 
-  /* This routine requires the entry to be locked */
-  ASSERT((ULONG_PTR)Entry->Object & EX_HANDLE_ENTRY_LOCKED);
+    /* Fail if we got an invalid index */
+    if (!(ExHandle.Index & (LOW_LEVEL_ENTRIES - 1))) return NULL;
 
-  DPRINT("DestroyHandleByEntry HT:0x%p Entry:0x%p\n", HandleTable, Entry);
+    /* Do the lookup */
+    HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
+    if (!HandleTableEntry) return NULL;
 
-    KeEnterCriticalRegion();
-    ExAcquireHandleLockExclusive(HandleTable);
-
-    /* free and automatically unlock the handle. However we don't need to pulse
-       the contention event since other locks on this entry will fail */
-    ExpFreeHandleTableEntry(HandleTable,
-                            Entry,
-                            HANDLE_TO_EX_HANDLE(Handle));
+    /* Lock it */
+    if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) return NULL;
 
-    ExReleaseHandleLock(HandleTable);
-    KeLeaveCriticalRegion();
+    /* Return the entry */
+    return HandleTableEntry;
 }
 
-PHANDLE_TABLE_ENTRY
-ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
-                     IN HANDLE Handle)
+PHANDLE_TABLE
+NTAPI
+ExDupHandleTable(IN PEPROCESS Process,
+                 IN PHANDLE_TABLE HandleTable,
+                 IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
+                 IN ULONG_PTR Mask)
 {
-  PHANDLE_TABLE_ENTRY HandleTableEntry;
+    PHANDLE_TABLE NewTable;
+    EXHANDLE Handle;
+    PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry;
+    BOOLEAN Failed = FALSE;
+    PAGED_CODE();
+
+    /* Allocate the duplicated copy */
+    NewTable = ExpAllocateHandleTable(Process, FALSE);
+    if (!NewTable) return NULL;
+
+    /* Loop each entry */
+    while (NewTable->NextHandleNeedingPool <
+            HandleTable->NextHandleNeedingPool)
+    {
+        /* Insert it into the duplicated copy */
+        if (!ExpAllocateHandleTableEntrySlow(NewTable, FALSE))
+        {
+            /* Insert failed, free the new copy and return */
+            ExpFreeHandleTable(NewTable);
+            return NULL;
+        }
+    }
 
-  PAGED_CODE();
+    /* Setup the initial handle table data */
+    NewTable->HandleCount = 0;
+    NewTable->ExtraInfoPages = 0;
+    NewTable->FirstFree = 0;
 
-  ASSERT(HandleTable);
+    /* Setup the first handle value  */
+    Handle.Value = SizeOfHandle(1);
 
-  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
-                                               HANDLE_TO_EX_HANDLE(Handle));
-  if (HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
-  {
-    DPRINT("ExMapHandleToPointer HT:0x%p Entry:0x%p locked\n", HandleTable, HandleTableEntry);
-    return HandleTableEntry;
-  }
+    /* Enter a critical region and lookup the new entry */
+    KeEnterCriticalRegion();
+    while ((NewEntry = ExpLookupHandleTableEntry(NewTable, Handle)))
+    {
+        /* Lookup the old entry */
+        HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle);
 
-  return NULL;
+        /* Loop each entry */
+        do
+        {
+            /* Check if it doesn't match the audit mask */
+            if (!(HandleTableEntry->Value & Mask))
+            {
+                /* Free it since we won't use it */
+                Failed = TRUE;
+            }
+            else
+            {
+                /* Lock the entry */
+                if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+                {
+                    /* Free it since we can't lock it, so we won't use it */
+                    Failed = TRUE;
+                }
+                else
+                {
+                    /* Copy the handle value */
+                    *NewEntry = *HandleTableEntry;
+
+                    /* Call the duplicate callback */
+                    if (DupHandleProcedure(Process,
+                                           HandleTable,
+                                           HandleTableEntry,
+                                           NewEntry))
+                    {
+                        /* Lock the entry, increase the handle count */
+                        NewEntry->Value |= EXHANDLE_TABLE_ENTRY_LOCK_BIT;
+                        NewTable->HandleCount++;
+                    }
+                    else
+                    {
+                        /* Duplication callback refused, fail */
+                        Failed = TRUE;
+                    }
+                }
+            }
+
+            /* Check if we failed earlier and need to free */
+            if (Failed)
+            {
+                /* Free this entry */
+                NewEntry->Object = NULL;
+                NewEntry->NextFreeTableEntry = NewTable->FirstFree;
+                NewTable->FirstFree = Handle.Value;
+            }
+
+            /* Increase the handle value and move to the next entry */
+            Handle.Value += SizeOfHandle(1);
+            NewEntry++;
+            HandleTableEntry++;
+        } while (Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES));
+
+        /* We're done, skip the last entry */
+        Handle.Value += SizeOfHandle(1);
+    }
+
+    /* Acquire the table lock and insert this new table into the list */
+    ExAcquirePushLockExclusive(&HandleTableListLock);
+    InsertTailList(&HandleTableListHead, &NewTable->HandleTableList);
+    ExReleasePushLockExclusive(&HandleTableListLock);
+
+    /* Leave the critical region we entered previously and return the table */
+    KeLeaveCriticalRegion();
+    return NewTable;
 }
 
 BOOLEAN
+NTAPI
 ExChangeHandle(IN PHANDLE_TABLE HandleTable,
                IN HANDLE Handle,
-               IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
-               IN PVOID Context)
+               IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
+               IN ULONG_PTR Context)
 {
-  PHANDLE_TABLE_ENTRY HandleTableEntry;
-  BOOLEAN Ret = FALSE;
+    EXHANDLE ExHandle;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    BOOLEAN Result = FALSE;
+    PAGED_CODE();
 
-  PAGED_CODE();
+    /* Set the handle value */
+    ExHandle.GenericHandleOverlay = Handle;
 
-  ASSERT(HandleTable);
-  ASSERT(ChangeHandleCallback);
+    /* Find the entry for this handle */
+    HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
 
-  KeEnterCriticalRegion();
+    /* Make sure that we found an entry, and that it's valid */
+    if (!(HandleTableEntry) ||
+        !(HandleTableEntry->Object) ||
+        (HandleTableEntry->NextFreeTableEntry == -2))
+    {
+        /* It isn't, fail */
+        return FALSE;
+    }
 
-  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
-                                               HANDLE_TO_EX_HANDLE(Handle));
+    /* Enter a critical region */
+    KeEnterCriticalRegion();
 
-  if(HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
-  {
-    Ret = ChangeHandleCallback(HandleTable,
-                               HandleTableEntry,
-                               Context);
+    /* Try locking the handle entry */
+    if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+    {
+        /* Call the change routine and unlock the entry */
+        Result = ChangeRoutine(HandleTableEntry, Context);
+        ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
+    }
 
-    ExUnlockHandleTableEntry(HandleTable,
-                             HandleTableEntry);
-  }
+    /* Leave the critical region and return the callback result */
+    KeLeaveCriticalRegion();
+    return Result;
+}
 
-  KeLeaveCriticalRegion();
+VOID
+NTAPI
+ExSweepHandleTable(IN PHANDLE_TABLE HandleTable,
+                   IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
+                   IN PVOID Context)
+{
+    EXHANDLE Handle;
+    PHANDLE_TABLE_ENTRY HandleTableEntry;
+    PAGED_CODE();
 
-  return Ret;
-}
+    /* Set the initial value and loop the entries */
+    Handle.Value = SizeOfHandle(1);
+    while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
+    {
+        /* Loop each handle */
+        do
+        {
+            /* Lock the entry */
+            if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
+            {
+                /* Notify the callback routine */
+                EnumHandleProcedure(HandleTableEntry,
+                                    Handle.GenericHandleOverlay,
+                                    Context);
+            }
+
+            /* Go to the next handle and entry */
+            Handle.Value += SizeOfHandle(1);
+            HandleTableEntry++;
+        } while (Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES));
 
-/* EOF */
+        /* Skip past the last entry */
+        Handle.Value += SizeOfHandle(1);
+    }
+}
index 7951e52..002736c 100644 (file)
@@ -21,6 +21,20 @@ ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
 ULONG ExpUnicodeCaseTableDataOffset;
 PVOID ExpNlsSectionPointer;
 
+typedef struct _EXHANDLE
+{
+    union
+    {
+        struct
+        {
+            ULONG TagBits:2;
+            ULONG Index:30;
+        };
+        HANDLE GenericHandleOverlay;
+        ULONG_PTR Value;
+    };
+} EXHANDLE, *PEXHANDLE;
+
 typedef struct _ETIMER
 {
     KTIMER KeTimer;
@@ -42,13 +56,6 @@ typedef struct
 
 #define MAX_FAST_REFS           7
 
-#define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) &                \
-  ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE |           \
-  EX_HANDLE_ENTRY_AUDITONCLOSE)))
-#define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->Object) &   \
-  ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE |           \
-  EX_HANDLE_ENTRY_AUDITONCLOSE)))
-
 /* Note: we only use a spinlock on SMP. On UP, we cli/sti intead */
 #ifndef CONFIG_SMP
 #define ExAcquireResourceLock(l, i) { \
@@ -68,6 +75,27 @@ typedef struct
 #define ExRundownCompleted                              _ExRundownCompleted
 #define ExGetPreviousMode                               KeGetPreviousMode
 
+
+//
+// Various bits tagged on the handle or handle table
+//
+#define EXHANDLE_TABLE_ENTRY_LOCK_BIT    1
+#define FREE_HANDLE_MASK                -1
+
+//
+// Number of entries in each table level
+//
+#define LOW_LEVEL_ENTRIES   (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))
+#define MID_LEVEL_ENTRIES   (PAGE_SIZE / sizeof(PHANDLE_TABLE_ENTRY))
+#define HIGH_LEVEL_ENTRIES  (65535 / (LOW_LEVEL_ENTRIES * MID_LEVEL_ENTRIES))
+
+//
+// Maximum index in each table level before we need another table
+//
+#define MAX_LOW_INDEX       LOW_LEVEL_ENTRIES
+#define MAX_MID_INDEX       (MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
+#define MAX_HIGH_INDEX      (MID_LEVEL_ENTRIES * MID_LEVEL_ENTRIES * LOW_LEVEL_ENTRIES)
+
 //
 // Detect GCC 4.1.2+
 //
@@ -308,104 +336,98 @@ ExfWaitForRundownProtectionRelease(
 
 /* HANDLE TABLE FUNCTIONS ***************************************************/
 
-#define EX_HANDLE_ENTRY_LOCKED (1 << ((sizeof(PVOID) * 8) - 1))
-#define EX_HANDLE_ENTRY_PROTECTFROMCLOSE (1 << 0)
-#define EX_HANDLE_ENTRY_INHERITABLE (1 << 1)
-#define EX_HANDLE_ENTRY_AUDITONCLOSE (1 << 2)
-
-#define EX_HANDLE_TABLE_CLOSING 0x1
-
-#define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED |                    \
-                                   EX_HANDLE_ENTRY_PROTECTFROMCLOSE |          \
-                                   EX_HANDLE_ENTRY_INHERITABLE |               \
-                                   EX_HANDLE_ENTRY_AUDITONCLOSE)
-
-typedef VOID (NTAPI PEX_SWEEP_HANDLE_CALLBACK)(
+typedef VOID
+(NTAPI *PEX_SWEEP_HANDLE_CALLBACK)(
     PHANDLE_TABLE_ENTRY HandleTableEntry,
-    HANDLE Handle,  
+    HANDLE Handle,
     PVOID Context
 );
 
-typedef BOOLEAN (NTAPI PEX_DUPLICATE_HANDLE_CALLBACK)(
-    PHANDLE_TABLE HandleTable, 
-    PHANDLE_TABLE_ENTRY HandleTableEntry, 
-    PVOID Context
-);
-
-typedef BOOLEAN (NTAPI PEX_CHANGE_HANDLE_CALLBACK)(
-    PHANDLE_TABLE HandleTable, 
-    PHANDLE_TABLE_ENTRY HandleTableEntry, 
-    PVOID Context
+typedef BOOLEAN
+(NTAPI *PEX_DUPLICATE_HANDLE_CALLBACK)(
+    IN PEPROCESS Process,
+    IN PHANDLE_TABLE HandleTable,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry,
+    IN PHANDLE_TABLE_ENTRY NewEntry
 );
 
-VOID
-ExpInitializeHandleTables(VOID);
-
-PHANDLE_TABLE
-ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL);
-
-VOID
-ExDestroyHandleTable(
-    IN PHANDLE_TABLE HandleTable
+typedef BOOLEAN
+(NTAPI *PEX_CHANGE_HANDLE_CALLBACK)(
+    PHANDLE_TABLE_ENTRY HandleTableEntry,
+    ULONG_PTR Context
 );
 
 VOID
-ExSweepHandleTable(
-    IN PHANDLE_TABLE HandleTable,
-    IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback  OPTIONAL,
-    IN PVOID Context  OPTIONAL
+NTAPI
+ExpInitializeHandleTables(
+    VOID
 );
 
 PHANDLE_TABLE
-ExDupHandleTable(
-    IN PEPROCESS QuotaProcess  OPTIONAL,
-    IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback  OPTIONAL,
-    IN PVOID Context  OPTIONAL,
-    IN PHANDLE_TABLE SourceHandleTable
-);
-
-BOOLEAN
-ExLockHandleTableEntry(
-    IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY Entry
+NTAPI
+ExCreateHandleTable(
+    IN PEPROCESS Process OPTIONAL
 );
 
 VOID
+NTAPI
 ExUnlockHandleTableEntry(
     IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY Entry
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry
 );
 
 HANDLE
+NTAPI
 ExCreateHandle(
     IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY Entry
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry
 );
 
-BOOLEAN
-ExDestroyHandle(
+VOID
+NTAPI
+ExDestroyHandleTable(
     IN PHANDLE_TABLE HandleTable,
-    IN HANDLE Handle
+    IN PVOID DestroyHandleProcedure OPTIONAL
 );
 
-VOID
-ExDestroyHandleByEntry(
+BOOLEAN
+NTAPI
+ExDestroyHandle(
     IN PHANDLE_TABLE HandleTable,
-    IN PHANDLE_TABLE_ENTRY Entry,
-    IN HANDLE Handle
+    IN HANDLE Handle,
+    IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL
 );
 
 PHANDLE_TABLE_ENTRY
+NTAPI
 ExMapHandleToPointer(
     IN PHANDLE_TABLE HandleTable,
     IN HANDLE Handle
 );
 
+PHANDLE_TABLE
+NTAPI
+ExDupHandleTable(
+    IN PEPROCESS Process,
+    IN PHANDLE_TABLE HandleTable,
+    IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure,
+    IN ULONG_PTR Mask
+);
+
 BOOLEAN
+NTAPI
 ExChangeHandle(
     IN PHANDLE_TABLE HandleTable,
     IN HANDLE Handle,
-    IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
+    IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine,
+    IN ULONG_PTR Context
+);
+
+VOID
+NTAPI
+ExSweepHandleTable(
+    IN PHANDLE_TABLE HandleTable,
+    IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure,
     IN PVOID Context
 );
 
@@ -797,7 +819,7 @@ ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
 VOID
 FORCEINLINE
 ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
-{
+{  
     /* Check if we're locked */
     if (PushLock->Locked)
     {
index f9fbf9c..24d498b 100644 (file)
      GENERIC_EXECUTE |                                  \
      GENERIC_ALL)
 
+//
+// Handle Bit Flags
+//
+#define OBJ_PROTECT_CLOSE                               0x01
+//#define OBJ_INHERIT                                   0x02
+#define OBJ_AUDIT_OBJECT_CLOSE                          0x04
+#define OBJ_HANDLE_ATTRIBUTES                           (OBJ_PROTECT_CLOSE |\
+                                                         OBJ_INHERIT |      \
+                                                         OBJ_AUDIT_OBJECT_CLOSE)
+
 //
 // Identifies a Kernel Handle
 //
 #define ObpGetHandleCountByHandleTable(HandleTable)     \
     ((PHANDLE_TABLE)HandleTable)->HandleCount
 
+//
+// Converts from an EXHANDLE object to a POBJECT_HEADER
+//
+#define ObpGetHandleObject(x)                           \
+    ((POBJECT_HEADER)((ULONG_PTR)x->Object & ~OBJ_HANDLE_ATTRIBUTES))
+
 //
 // Context Structures for Ex*Handle Callbacks
 //
@@ -214,9 +230,8 @@ ObpLookupObjectName(
 BOOLEAN
 NTAPI
 ObpSetHandleAttributes(
-    IN PHANDLE_TABLE HandleTable,
     IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
-    IN PVOID Context
+    IN ULONG_PTR Context
 );
 
 VOID
index ddddc6d..8b245d1 100644 (file)
@@ -8,7 +8,9 @@
 
 /* INCLUDES ******************************************************************/
 
-/* Tells the WDK that we don't want to import */
+/* Always target Windows 2003 Service Pack 1 */
+#undef NTDDI_VERSION
+#define NTDDI_VERSION NTDDI_WS03SP1
 #define NTKERNELAPI
 
 /* DDK/IFS/NDK Headers */
index 5a12ee2..8d4830a 100644 (file)
@@ -8,7 +8,6 @@
 
 /* INCLUDES *****************************************************************/
 
-#define NTDDI_VERSION NTDDI_WS03
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
@@ -952,3 +951,4 @@ KeAreAllApcsDisabled(VOID)
 
 
 
+
index 49b2a89..e18eb0e 100644 (file)
@@ -10,8 +10,6 @@
 
 /* INCLUDES ******************************************************************/
 
-#define NTDDI_VERSION NTDDI_WS03
-
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
index 3f82d63..f45dc75 100644 (file)
@@ -8,7 +8,6 @@
 
 /* INCLUDES *****************************************************************/
 
-#define NTDDI_VERSION NTDDI_WS03
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
index bf3d477..fb7dadb 100644 (file)
@@ -9,7 +9,6 @@
 
 /* INCLUDES ******************************************************************/
 
-#define NTDDI_VERSION NTDDI_WS03SP1
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
index 5965b31..032a6b3 100644 (file)
@@ -8,7 +8,6 @@
 
 /* INCLUDES *****************************************************************/
 
-#define NTDDI_VERSION NTDDI_WS03SP1
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
@@ -788,3 +787,4 @@ AppCpuInit:
     KiIdleLoop();
 }
 
+
index fc98005..9383bd8 100644 (file)
@@ -131,16 +131,13 @@ ObpReferenceProcessObjectByHandle(IN HANDLE Handle,
     if (HandleEntry)
     {
         /* Get the object header and validate the type*/
-        ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+        ObjectHeader = ObpGetHandleObject(HandleEntry);
 
         /* Get the granted access and validate it */
         GrantedAccess = HandleEntry->GrantedAccess;
 
         /* Mask out the internal attributes */
-        Attributes = HandleEntry->ObAttributes &
-                     (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                      EX_HANDLE_ENTRY_INHERITABLE |
-                      EX_HANDLE_ENTRY_AUDITONCLOSE);
+        Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
 
         /* Fill out the information */
         HandleInformation->HandleAttributes = Attributes;
@@ -588,7 +585,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
     PAGED_CODE();
 
     /* Get the object data */
-    ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+    ObjectHeader = ObpGetHandleObject(HandleEntry);
     ObjectType = ObjectHeader->Type;
     Body = &ObjectHeader->Body;
     GrantedAccess = HandleEntry->GrantedAccess;
@@ -621,7 +618,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
     }
 
     /* The callback allowed us to close it, but does the handle itself? */
-    if ((HandleEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) &&
+    if ((HandleEntry->ObAttributes & OBJ_PROTECT_CLOSE) &&
         !(IgnoreHandleProtection))
     {
         /* It doesn't, are we from user mode? */
@@ -650,7 +647,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
     }
 
     /* Destroy and unlock the handle entry */
-    ExDestroyHandleByEntry(HandleTable, HandleEntry, Handle);
+    ExDestroyHandle(HandleTable, Handle, HandleEntry);
 
     /* Now decrement the handle count */
     ObpDecrementHandleCount(Body, PsGetCurrentProcess(), GrantedAccess);
@@ -1258,10 +1255,7 @@ ObpCreateUnnamedHandle(IN PVOID Object,
     NewEntry.Object = ObjectHeader;
 
     /* Mask out the internal attributes */
-    NewEntry.ObAttributes |= HandleAttributes &
-                             (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                              EX_HANDLE_ENTRY_INHERITABLE |
-                              EX_HANDLE_ENTRY_AUDITONCLOSE);
+    NewEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES;
 
     /* Remove what's not in the valid access mask */
     GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask |
@@ -1460,14 +1454,11 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
     if (AccessState->GenerateOnClose)
     {
         /* Force the attribute on */
-        HandleAttributes|= EX_HANDLE_ENTRY_AUDITONCLOSE;
+        HandleAttributes|= OBJ_AUDIT_OBJECT_CLOSE;
     }
 
     /* Mask out the internal attributes */
-    NewEntry.ObAttributes |= HandleAttributes &
-                             (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                              EX_HANDLE_ENTRY_INHERITABLE |
-                              EX_HANDLE_ENTRY_AUDITONCLOSE);
+    NewEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES;
 
     /* Get the original desired access */
     DesiredAccess = AccessState->RemainingDesiredAccess |
@@ -1697,9 +1688,6 @@ ObpCloseHandle(IN HANDLE Handle,
 *
 *     The ObpSetHandleAttributes routine <FILLMEIN>
 *
-* @param HandleTable
-*        <FILLMEIN>.
-*
 * @param HandleTableEntry
 *        <FILLMEIN>.
 *
@@ -1713,12 +1701,11 @@ ObpCloseHandle(IN HANDLE Handle,
 *--*/
 BOOLEAN
 NTAPI
-ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
-                       IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
-                       IN PVOID Context)
+ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
+                       IN ULONG_PTR Context)
 {
-    POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = Context;
-    POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
+    POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = (PVOID)Context;
+    POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
     PAGED_CODE();
 
     /* Don't allow operations on kernel objects */
@@ -1740,24 +1727,24 @@ ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
         }
 
         /* Set the flag */
-        HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+        HandleTableEntry->ObAttributes |= OBJ_INHERIT;
     }
     else
     {
         /* Otherwise this implies we're removing the flag */
-        HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+        HandleTableEntry->ObAttributes &= ~OBJ_INHERIT;
     }
 
     /* Check if making the handle protected */
     if (SetHandleInfo->Information.ProtectFromClose)
     {
         /* Set the flag */
-        HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+        HandleTableEntry->ObAttributes |= OBJ_PROTECT_CLOSE;
     }
     else
     {
         /* Otherwise, remove it */
-        HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+        HandleTableEntry->ObAttributes &= ~OBJ_PROTECT_CLOSE;
     }
 
     /* Return success */
@@ -1823,9 +1810,10 @@ ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry,
 *--*/
 BOOLEAN
 NTAPI
-ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable,
-                           IN PHANDLE_TABLE_ENTRY HandleTableEntry,
-                           IN PVOID Context)
+ObpDuplicateHandleCallback(IN PEPROCESS Process,
+                           IN PHANDLE_TABLE HandleTable,
+                           IN PHANDLE_TABLE_ENTRY OldEntry,
+                           IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 {
     POBJECT_HEADER ObjectHeader;
     BOOLEAN Ret = FALSE;
@@ -1834,11 +1822,17 @@ ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable,
     PAGED_CODE();
 
     /* Make sure that the handle is inheritable */
-    Ret = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+    Ret = (HandleTableEntry->ObAttributes & OBJ_INHERIT) != 0;
     if (Ret)
     {
         /* Get the object header */
-        ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
+        ObjectHeader = ObpGetHandleObject(HandleTableEntry);
+
+        /* Increment the pointer count */
+        InterlockedIncrement(&ObjectHeader->PointerCount);
+
+        /* Release the handle lock */
+        ExUnlockHandleTableEntry(HandleTable, OldEntry);
 
         /* Setup the access state */
         AccessState.PreviouslyGrantedAccess = HandleTableEntry->GrantedAccess;
@@ -1848,18 +1842,19 @@ ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable,
                                          &AccessState,
                                          KernelMode,
                                          HandleTableEntry->ObAttributes,
-                                         PsGetCurrentProcess(),
+                                         Process,
                                          ObInheritHandle);
         if (!NT_SUCCESS(Status))
         {
             /* Return failure */
+            ObDereferenceObject(&ObjectHeader->Body);
             Ret = FALSE;
         }
-        else
-        {
-            /* Otherwise increment the pointer count */
-            InterlockedIncrement(&ObjectHeader->PointerCount);
-        }
+    }
+    else
+    {
+        /* Release the handle lock */
+        ExUnlockHandleTableEntry(HandleTable, OldEntry);
     }
 
     /* Return duplication result */
@@ -1906,9 +1901,9 @@ ObpCreateHandleTable(IN PEPROCESS Parent,
 
         /* Duplicate the parent's */
         HandleTable = ExDupHandleTable(Process,
+                                       HandleTable,
                                        ObpDuplicateHandleCallback,
-                                       NULL,
-                                       HandleTable);
+                                       OBJ_INHERIT);
     }
     else
     {
@@ -1981,7 +1976,7 @@ ObKillProcess(IN PEPROCESS Process)
 
     /* Destroy the object table */
     Process->ObjectTable = NULL;
-    ExDestroyHandleTable(HandleTable);
+    ExDestroyHandleTable(HandleTable, NULL);
 }
 
 NTSTATUS
@@ -2121,10 +2116,7 @@ ObDuplicateObject(IN PEPROCESS SourceProcess,
 
     /* Fill out the entry */
     NewHandleEntry.Object = ObjectHeader;
-    NewHandleEntry.ObAttributes |= HandleAttributes &
-                                   (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                                    EX_HANDLE_ENTRY_INHERITABLE |
-                                    EX_HANDLE_ENTRY_AUDITONCLOSE);
+    NewHandleEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES;
 
     /* Check if we're using a generic mask */
     if (DesiredAccess & GENERIC_ACCESS)
index e400a67..fea5357 100644 (file)
@@ -1442,10 +1442,9 @@ NtQueryObject(IN HANDLE ObjectHandle,
                                ObjectInformation;
 
                 /* Set the flags */
-                HandleFlags->Inherit = (HandleInfo.HandleAttributes &
-                                        EX_HANDLE_ENTRY_INHERITABLE) != 0;
+                HandleFlags->Inherit = HandleInfo.HandleAttributes & OBJ_INHERIT;
                 HandleFlags->ProtectFromClose = (HandleInfo.HandleAttributes &
-                                                 EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
+                                                 OBJ_PROTECT_CLOSE) != 0;
 
                 /* Break out with success */
                 Status = STATUS_SUCCESS;
@@ -1581,7 +1580,7 @@ NtSetInformationObject(IN HANDLE ObjectHandle,
     if (!ExChangeHandle(ObjectTable,
                         ObjectHandle,
                         ObpSetHandleAttributes,
-                        &Context))
+                        (ULONG_PTR)&Context))
     {
         /* Some failure */
         Status = STATUS_ACCESS_DENIED;
index 143a1bc..2795d4e 100644 (file)
@@ -11,7 +11,6 @@
 
 /* INCLUDES ******************************************************************/
 
-#define NTDDI_VERSION NTDDI_WINXP
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
index 22b6285..951e001 100644 (file)
@@ -560,7 +560,7 @@ ObReferenceObjectByHandle(IN HANDLE Handle,
     if (HandleEntry)
     {
         /* Get the object header and validate the type*/
-        ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+        ObjectHeader = ObpGetHandleObject(HandleEntry);
         if (!(ObjectType) || (ObjectType == ObjectHeader->Type))
         {
             /* Get the granted access and validate it */
@@ -572,10 +572,7 @@ ObReferenceObjectByHandle(IN HANDLE Handle,
                 InterlockedIncrement(&ObjectHeader->PointerCount);
 
                 /* Mask out the internal attributes */
-                Attributes = HandleEntry->ObAttributes &
-                             (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                              EX_HANDLE_ENTRY_INHERITABLE |
-                              EX_HANDLE_ENTRY_AUDITONCLOSE);
+                Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
 
                 /* Check if the caller wants handle information */
                 if (HandleInformation)
index 7bd9006..2d81a8d 100644 (file)
@@ -829,8 +829,7 @@ ObQueryObjectAuditingByHandle(IN HANDLE Handle,
     if(HandleEntry)
     {
         /* Check if the flag is set */
-        *GenerateOnClose = (HandleEntry->ObAttributes &
-                            EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
+        *GenerateOnClose = HandleEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE;
 
         /* Unlock the entry */
         ExUnlockHandleTableEntry(HandleTable, HandleEntry);
index 65b38a2..a110604 100644 (file)
@@ -181,7 +181,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
         }
 
         /* Get the Object Header */
-        ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+        ObjectHeader = ObpGetHandleObject(HandleEntry);
 
         /* Get default Object */
         DefaultObject = ObjectHeader->Type->DefaultObject;
index d5009c1..d5e05d0 100644 (file)
@@ -310,7 +310,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
     if (Process->UniqueProcessId)
     {
         /* Delete the PID */
-        if (!(ExDestroyHandle(PspCidTable, Process->UniqueProcessId)))
+        if (!(ExDestroyHandle(PspCidTable, Process->UniqueProcessId, NULL)))
         {
             /* Something wrong happened, bugcheck */
             KEBUGCHECK(CID_HANDLE_DELETION);
@@ -360,7 +360,7 @@ PspDeleteThread(IN PVOID ObjectBody)
     if (Thread->Cid.UniqueThread)
     {
         /* Delete the CID Handle */
-        if (!(ExDestroyHandle(PspCidTable, Thread->Cid.UniqueThread)))
+        if (!(ExDestroyHandle(PspCidTable, Thread->Cid.UniqueThread, NULL)))
         {
             /* Something wrong happened, bugcheck */
             KEBUGCHECK(CID_HANDLE_DELETION);
index 78f3692..5f8a461 100644 (file)
@@ -259,7 +259,7 @@ RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable)
       ExSweepHandleTable(AtomTable->ExHandleTable,
                          NULL,
                          NULL);
-      ExDestroyHandleTable(AtomTable->ExHandleTable);
+      ExDestroyHandleTable(AtomTable->ExHandleTable, NULL);
       AtomTable->ExHandleTable = NULL;
    }
 }
@@ -308,7 +308,8 @@ VOID
 RtlpFreeAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
 {
    ExDestroyHandle(AtomTable->ExHandleTable,
-                   (HANDLE)((ULONG_PTR)Entry->HandleIndex << 2));
+                   (HANDLE)((ULONG_PTR)Entry->HandleIndex << 2),
+                   NULL);
 }
 
 BOOLEAN
@@ -336,7 +337,8 @@ RtlpCreateAtomHandle(PRTL_ATOM_TABLE AtomTable, PRTL_ATOM_TABLE_ENTRY Entry)
       }
       else
          ExDestroyHandle(AtomTable->ExHandleTable,
-                         Handle);
+                         Handle,
+                         NULL);
    }
    
    return FALSE;