- fixed handle table structures
authorThomas Bluemel <thomas@reactsoft.com>
Sun, 13 Mar 2005 14:21:47 +0000 (14:21 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Sun, 13 Mar 2005 14:21:47 +0000 (14:21 +0000)
- implement generic executive handle tables (since there don't exist documents that describe the parameters of most of these functions (which are kernel internal only), i made them up as required)
- adjusted OB's handle manager to use ex handle tables
- adjusted the client id manager to use ex handle tables

svn path=/trunk/; revision=14007

24 files changed:
reactos/config
reactos/include/ddk/kefuncs.h
reactos/include/ntos/obtypes.h
reactos/ntoskrnl/Makefile
reactos/ntoskrnl/ex/handle.c [new file with mode: 0644]
reactos/ntoskrnl/ex/init.c
reactos/ntoskrnl/ex/sysinfo.c
reactos/ntoskrnl/ex/work.c
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/include/internal/ob.h
reactos/ntoskrnl/include/internal/ps.h
reactos/ntoskrnl/io/iomgr.c
reactos/ntoskrnl/io/pnpmgr.c
reactos/ntoskrnl/lpc/close.c
reactos/ntoskrnl/ob/handle.c
reactos/ntoskrnl/ob/object.c
reactos/ntoskrnl/ps/cid.c
reactos/ntoskrnl/ps/create.c
reactos/ntoskrnl/ps/idle.c
reactos/ntoskrnl/ps/kill.c
reactos/ntoskrnl/ps/process.c
reactos/ntoskrnl/ps/psmgr.c
reactos/ntoskrnl/ps/thread.c
reactos/subsys/win32k/misc/object.c

index 34aa938..e5de9d3 100644 (file)
@@ -15,22 +15,22 @@ ARCH := i386
 # be optimized for. 
 #
 
-OARCH := i486
+OARCH := i586
 
 #
 # Whether to compile in the kernel debugger
 #
-KDBG := 0
+KDBG := 1
 
 #
 # Whether to compile for debugging
 #
-DBG := 0
+DBG := 1
 
 #
 # Whether to compile with optimizations
 #
-OPTIMIZED := 0
+OPTIMIZED := 1
 
 #
 # Whether to compile a multiprocessor or single processor version
index 115851a..2559e46 100644 (file)
@@ -42,6 +42,15 @@ VOID STDCALL KeAcquireSpinLock (PKSPIN_LOCK  SpinLock,
 
 #ifndef __USE_W32API
 
+static __inline
+VOID
+KeMemoryBarrier(
+  VOID)
+{
+  volatile LONG Barrier;
+  __asm__ __volatile__ ("xchg %%eax, %0" : : "m" (Barrier) : "%eax");
+}
+
 VOID STDCALL KeAcquireSpinLockAtDpcLevel (IN PKSPIN_LOCK       SpinLock);
 
 #define KefAcquireSpinLockAtDpcLevel KeAcquireSpinLockAtDpcLevel
index 9094b06..86577d0 100755 (executable)
@@ -87,18 +87,42 @@ typedef struct _OBJECT_ATTRIBUTES
    PVOID SecurityQualityOfService;
 } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
 
+typedef struct _HANDLE_TABLE_ENTRY_INFO {
+    ULONG AuditMask;
+} HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO;
+
+typedef struct _HANDLE_TABLE_ENTRY {
+    union {
+        PVOID Object;
+        ULONG_PTR ObAttributes;
+        PHANDLE_TABLE_ENTRY_INFO InfoTable;
+        ULONG_PTR Value;
+    } u1;
+    union {
+        ULONG GrantedAccess;
+        USHORT GrantedAccessIndex;
+        LONG NextFreeTableEntry;
+    } u2;
+} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
+
 #endif /* __USE_W32API */
 
 typedef struct _HANDLE_TABLE
 {
-   LIST_ENTRY ListHead;
-   KSPIN_LOCK ListLock;
-} HANDLE_TABLE;
+    ULONG Flags;
+    LONG HandleCount;
+    PHANDLE_TABLE_ENTRY **Table;
+    PEPROCESS QuotaProcess;
+    HANDLE UniqueProcessId;
+    LONG FirstFreeTableEntry;
+    LONG NextIndexNeedingPool;
+    ERESOURCE HandleTableLock;
+    LIST_ENTRY HandleTableList;
+    KEVENT HandleContentionEvent;
+} HANDLE_TABLE, *PHANDLE_TABLE;
 
 #ifndef __USE_W32API
 
-typedef struct _HANDLE_TABLE *PHANDLE_TABLE;
-
 /*
  * FIXME: These will eventually become centerfold in the compliant Ob Manager
  * For now, they are only here so Device Map is properly defined before the header
index d908dfd..18b781e 100644 (file)
@@ -239,6 +239,7 @@ OBJECTS_EX = \
        ex/event.o \
        ex/evtpair.o \
        ex/fmutex.o \
+       ex/handle.o \
        ex/hashtab.o \
        ex/init.o \
        ex/interlck.o \
diff --git a/reactos/ntoskrnl/ex/handle.c b/reactos/ntoskrnl/ex/handle.c
new file mode 100644 (file)
index 0000000..a0c5c79
--- /dev/null
@@ -0,0 +1,949 @@
+/* $Id:$
+ * 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ex/handle.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
+ *
+ *  ExSweepHandleTable (???)
+ *  ExReferenceHandleDebugInfo
+ *  ExSnapShotHandleTables
+ *  ExpMoveFreeHandles (???)
+ */
+
+/* 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)
+
+#define ExAcquireHandleTableLockExclusive(HandleTable)                         \
+  ExAcquireResourceExclusiveLite(&(HandleTable)->HandleTableLock, TRUE)
+
+#define ExAcquireHandleTableLockShared(HandleTable)                            \
+  ExAcquireResourceSharedLite(&(HandleTable)->HandleTableLock, TRUE)
+
+#define ExReleaseHandleTableLock(HandleTable)                                  \
+  ExReleaseResourceLite(&(HandleTable)->HandleTableLock)
+
+/*
+   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)
+
+/******************************************************************************/
+
+VOID
+ExpInitializeHandleTables(VOID)
+{
+  ExpHandleShortWait.QuadPart = -50000;
+  InitializeListHead(&ExpHandleTableHead);
+  ExInitializeFastMutex(&ExpHandleTableListLock);
+}
+
+PHANDLE_TABLE
+ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL)
+{
+  PHANDLE_TABLE HandleTable;
+  
+  PAGED_CODE();
+  
+  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->FirstFreeTableEntry = -1; /* no entries freed so far */
+    HandleTable->NextIndexNeedingPool = 0; /* no entries freed so far, so we have to allocate already for the first handle */
+    HandleTable->UniqueProcessId = (QuotaProcess ? QuotaProcess->UniqueProcessId : PsGetCurrentProcessId());
+
+    ExInitializeResource(&HandleTable->HandleTableLock);
+
+    KeInitializeEvent(&HandleTable->HandleContentionEvent,
+                      NotificationEvent,
+                      FALSE);
+
+    RtlZeroMemory(HandleTable->Table, N_TOPLEVEL_POINTERS * sizeof(PHANDLE_TABLE_ENTRY*));
+
+    /* during bootup KeGetCurrentThread() might be NULL, needs to be fixed... */
+    if(KeGetCurrentThread() != NULL)
+    {
+      /* insert it into the global handle table list */
+      KeEnterCriticalRegion();
+
+      ExAcquireHandleTableListLock();
+      InsertTailList(&ExpHandleTableHead,
+                     &HandleTable->HandleTableList);
+      ExReleaseHandleTableListLock();
+
+      KeLeaveCriticalRegion();
+    }
+    else
+    {
+      InsertTailList(&ExpHandleTableHead,
+                     &HandleTable->HandleTableList);
+    }
+  }
+  else
+  {
+    /* FIXME - return the quota to the process */
+  }
+  
+  return HandleTable;
+}
+
+static BOOLEAN
+ExLockHandleTableEntryNoDestructionCheck(IN PHANDLE_TABLE HandleTable,
+                                         IN PHANDLE_TABLE_ENTRY Entry)
+{
+  ULONG_PTR Current, New;
+
+  PAGED_CODE();
+
+  DPRINT("Entering handle table entry 0x%x lock...\n", Entry);
+
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+
+  for(;;)
+  {
+    Current = (volatile ULONG_PTR)Entry->u1.Object;
+
+    if(!Current)
+    {
+      DPRINT("Attempted to lock empty handle table entry 0x%x or handle table shut down\n", Entry);
+      break;
+    }
+
+    if(!(Current & EX_HANDLE_ENTRY_LOCKED))
+    {
+      New = Current | EX_HANDLE_ENTRY_LOCKED;
+      if(InterlockedCompareExchangePointer(&Entry->u1.Object,
+                                           (PVOID)New,
+                                           (PVOID)Current) == (PVOID)Current)
+      {
+        DPRINT("SUCCESS handle table 0x%x entry 0x%x lock\n", HandleTable, Entry);
+        /* we acquired the lock */
+        return TRUE;
+      }
+    }
+
+    /* 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
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
+                     IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback  OPTIONAL,
+                     IN PVOID Context  OPTIONAL)
+{
+  PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
+  PEPROCESS QuotaProcess;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  
+  KeEnterCriticalRegion();
+  
+  /* ensure there's no other operations going by acquiring an exclusive lock */
+  ExAcquireHandleTableLockExclusive(HandleTable);
+  
+  ASSERT(!(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING));
+  
+  HandleTable->Flags |= EX_HANDLE_TABLE_CLOSING;
+  
+  KePulseEvent(&HandleTable->HandleContentionEvent,
+               EVENT_INCREMENT,
+               FALSE);
+  
+  /* remove the handle table from the global handle table list */
+  ExAcquireHandleTableListLock();
+  RemoveEntryList(&HandleTable->HandleTableList);
+  ExReleaseHandleTableListLock();
+  
+  /* call the callback function to cleanup the objects associated with the
+     handle table */
+  if(DestroyHandleCallback != NULL)
+  {
+    for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
+        tlp != lasttlp;
+        tlp++)
+    {
+      if((*tlp) != NULL)
+      {
+        for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
+            mlp != lastmlp;
+            mlp++)
+        {
+          if((*mlp) != NULL)
+          {
+            PHANDLE_TABLE_ENTRY curee, laste;
+            
+            for(curee = *mlp, laste = *mlp + N_SUBHANDLE_ENTRIES;
+                curee != laste;
+                curee++)
+            {
+              if(curee->u1.Object != NULL && ExLockHandleTableEntryNoDestructionCheck(HandleTable, curee))
+              {
+                DestroyHandleCallback(HandleTable, curee->u1.Object, curee->u2.GrantedAccess, Context);
+                ExUnlockHandleTableEntry(HandleTable, curee);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  QuotaProcess = HandleTable->QuotaProcess;
+  
+  /* free the tables */
+  for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
+      tlp != lasttlp;
+      tlp++)
+  {
+    if((*tlp) != NULL)
+    {
+      for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
+          mlp != lastmlp;
+          mlp++)
+      {
+        if((*mlp) != NULL)
+        {
+          ExFreePool(*mlp);
+          
+          if(QuotaProcess != NULL)
+          {
+            /* FIXME - return the quota to the process */
+          }
+        }
+      }
+
+      ExFreePool(*tlp);
+      
+      if(QuotaProcess != NULL)
+      {
+        /* FIXME - return the quota to the process */
+      }
+    }
+  }
+  
+  ExReleaseHandleTableLock(HandleTable);
+  
+  KeLeaveCriticalRegion();
+  
+  /* free the handle table */
+  ExDeleteResource(&HandleTable->HandleTableLock);
+  ExFreePool(HandleTable);
+  
+  if(QuotaProcess != NULL)
+  {
+    /* FIXME - return the quota to the process */
+  }
+}
+
+PHANDLE_TABLE
+ExDupHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL,
+                 IN PEX_DUPLICATE_HANDLE_CALLBACK DuplicateHandleCallback  OPTIONAL,
+                 IN PVOID Context  OPTIONAL,
+                 IN PHANDLE_TABLE SourceHandleTable)
+{
+  PHANDLE_TABLE HandleTable;
+  
+  PAGED_CODE();
+  
+  ASSERT(SourceHandleTable);
+
+  HandleTable = ExCreateHandleTable(QuotaProcess);
+  if(HandleTable != NULL)
+  {
+    PHANDLE_TABLE_ENTRY **tlp, **srctlp, **etlp, *mlp, *srcmlp, *emlp, stbl, srcstbl, estbl;
+    LONG tli, mli, eli;
+    
+    tli = mli = eli = 0;
+  
+    /* make sure the other handle table isn't being changed during the duplication */
+    ExAcquireHandleTableLockShared(SourceHandleTable);
+    
+    /* allocate enough tables */
+    etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
+    for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
+        srctlp != etlp;
+        srctlp++, tlp++)
+    {
+      if(*srctlp != NULL)
+      {
+        /* allocate middle level entry tables */
+        if(QuotaProcess != NULL)
+        {
+          /* FIXME - Charge process quota before allocating the handle table! */
+        }
+        
+        *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));
+          
+          KeMemoryBarrier();
+          
+          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;
+            }
+          }
+        }
+        else
+        {
+freehandletable:
+          DPRINT1("Failed to duplicate handle table 0x%x\n", SourceHandleTable);
+
+          ExReleaseHandleTableLock(SourceHandleTable);
+          
+          ExDestroyHandleTable(HandleTable,
+                               NULL,
+                               NULL);
+          /* allocate an empty handle table */
+          return ExCreateHandleTable(QuotaProcess);
+        }
+      }
+    }
+
+    /* duplicate the handles */
+    HandleTable->HandleCount = SourceHandleTable->HandleCount;
+    HandleTable->FirstFreeTableEntry = SourceHandleTable->FirstFreeTableEntry;
+    HandleTable->NextIndexNeedingPool = SourceHandleTable->NextIndexNeedingPool;
+
+    /* make sure all tables are zeroed */
+    KeMemoryBarrier();
+
+    etlp = SourceHandleTable->Table + N_TOPLEVEL_POINTERS;
+    for(srctlp = SourceHandleTable->Table, tlp = HandleTable->Table;
+        srctlp != etlp;
+        srctlp++, tlp++, tli++)
+    {
+      if(*srctlp != NULL)
+      {
+        ASSERT(*tlp != NULL);
+
+        emlp = *srctlp + N_MIDDLELEVEL_POINTERS;
+        for(srcmlp = *srctlp, mlp = *tlp;
+            srcmlp != emlp;
+            srcmlp++, mlp++, mli++)
+        {
+          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->u1.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->u1.Object = NULL;
+                  stbl->u2.NextFreeTableEntry = HandleTable->FirstFreeTableEntry;
+                  HandleTable->FirstFreeTableEntry = BUILD_HANDLE(tli, mli, eli);
+                }
+                else
+                {
+                  /* duplicate the handle and unlock it */
+                  stbl->u2.GrantedAccess = srcstbl->u2.GrantedAccess;
+                  stbl->u1.ObAttributes = srcstbl->u1.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;
+              }
+            }
+          }
+        }
+      }
+    }
+    
+    /* release the source handle table */
+    ExReleaseHandleTableLock(SourceHandleTable);
+  }
+  
+  return HandleTable;
+}
+
+static PHANDLE_TABLE_ENTRY
+ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                            OUT PLONG Handle)
+{
+  PHANDLE_TABLE_ENTRY Entry = NULL;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  ASSERT(Handle);
+  ASSERT(KeGetCurrentThread() != NULL);
+  
+  DPRINT("HT[0x%x]: HandleCount: %d\n", HandleTable, HandleTable->HandleCount);
+  
+  if(HandleTable->HandleCount < EX_MAX_HANDLES)
+  {
+    ULONG tli, mli, eli;
+    
+    if(HandleTable->FirstFreeTableEntry != -1)
+    {
+      /* there's a free handle entry we can just grab and use */
+      tli = TLI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+      mli = MLI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+      eli = ELI_FROM_HANDLE(HandleTable->FirstFreeTableEntry);
+      
+      /* the pointer should be valid in any way!!! */
+      ASSERT(HandleTable->Table[tli]);
+      ASSERT(HandleTable->Table[tli][mli]);
+      
+      Entry = &HandleTable->Table[tli][mli][eli];
+      
+      *Handle = HandleTable->FirstFreeTableEntry;
+      
+      /* save the index to the next free handle (if available) */
+      HandleTable->FirstFreeTableEntry = Entry->u2.NextFreeTableEntry;
+      Entry->u2.NextFreeTableEntry = 0;
+      Entry->u1.Object = NULL;
+      
+      HandleTable->HandleCount++;
+    }
+    else
+    {
+      /* we need to allocate a new subhandle table first */
+      PHANDLE_TABLE_ENTRY cure, laste, ntbl, *nmtbl;
+      ULONG i;
+      BOOLEAN AllocatedMtbl;
+
+      ASSERT(HandleTable->NextIndexNeedingPool <= N_MAX_HANDLE);
+      
+      /* the index of the next table to be allocated was saved in
+         NextIndexNeedingPool the last time a handle entry was allocated and
+         the subhandle entry list was full. the subhandle entry index of
+         NextIndexNeedingPool should be 0 here! */
+      tli = TLI_FROM_HANDLE(HandleTable->NextIndexNeedingPool);
+      mli = MLI_FROM_HANDLE(HandleTable->NextIndexNeedingPool);
+      DPRINT("HandleTable->NextIndexNeedingPool: 0x%x\n", HandleTable->NextIndexNeedingPool);
+      DPRINT("tli: 0x%x mli: 0x%x eli: 0x%x\n", tli, mli, ELI_FROM_HANDLE(HandleTable->NextIndexNeedingPool));
+
+      ASSERT(ELI_FROM_HANDLE(HandleTable->NextIndexNeedingPool) == 0);
+
+      DPRINT("HandleTable->Table[%d] == 0x%x\n", tli, HandleTable->Table[tli]);
+      
+      /* allocate a middle level entry list if required */
+      nmtbl = HandleTable->Table[tli];
+      if(nmtbl == NULL)
+      {
+        if(HandleTable->QuotaProcess != NULL)
+        {
+          /* FIXME - Charge process quota before allocating the handle table! */
+        }
+        
+        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 */
+          }
+          
+          return NULL;
+        }
+        
+        /* 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%x\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)
+        {
+          /* FIXME - Return process quota charged  */
+        }
+        
+        /* free the middle level entry list, if allocated, because it's empty and
+           unused */
+        if(AllocatedMtbl)
+        {
+          ExFreePool(nmtbl);
+          
+          if(HandleTable->QuotaProcess != NULL)
+          {
+            /* FIXME - Return process quota charged  */
+          }
+        }
+        
+        return NULL;
+      }
+      
+      /* let's just use the very first entry */
+      Entry = ntbl;
+      Entry->u1.ObAttributes = EX_HANDLE_ENTRY_LOCKED;
+      Entry->u2.NextFreeTableEntry = 0;
+      
+      *Handle = HandleTable->NextIndexNeedingPool;
+      
+      HandleTable->HandleCount++;
+      
+      /* set the FirstFreeTableEntry member to the second entry and chain the
+         free entries */
+      HandleTable->FirstFreeTableEntry = HandleTable->NextIndexNeedingPool + 1;
+      for(cure = Entry + 1, laste = Entry + N_SUBHANDLE_ENTRIES, i = HandleTable->FirstFreeTableEntry + 1;
+          cure != laste;
+          cure++, i++)
+      {
+        cure->u1.Object = NULL;
+        cure->u2.NextFreeTableEntry = i;
+      }
+      /* truncate the free entry list */
+      (cure - 1)->u2.NextFreeTableEntry = -1;
+
+      /* save the pointers to the allocated list(s) */
+      InterlockedExchangePointer(&nmtbl[mli], ntbl);
+      if(AllocatedMtbl)
+      {
+        InterlockedExchangePointer(&HandleTable->Table[tli], nmtbl);
+      }
+      
+      /* increment the NextIndexNeedingPool to the next index where we need to
+         allocate new memory */
+      HandleTable->NextIndexNeedingPool += N_SUBHANDLE_ENTRIES;
+    }
+  }
+  else
+  {
+    DPRINT1("Can't allocate any more handles in handle table 0x%x!\n", HandleTable);
+  }
+  
+  return Entry;
+}
+
+static VOID
+ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                        IN PHANDLE_TABLE_ENTRY Entry,
+                        IN LONG Handle)
+{
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+  ASSERT(IS_VALID_EX_HANDLE(Handle));
+  
+  DPRINT("ExpFreeHandleTableEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+  
+  /* 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 */
+  InterlockedExchangePointer(&Entry->u1.Object, NULL);
+  Entry->u2.NextFreeTableEntry = HandleTable->FirstFreeTableEntry;
+  HandleTable->FirstFreeTableEntry = Handle;
+  
+  HandleTable->HandleCount--;
+}
+
+static PHANDLE_TABLE_ENTRY
+ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                          IN LONG Handle)
+{
+  PHANDLE_TABLE_ENTRY Entry = NULL;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  
+  if(IS_VALID_EX_HANDLE(Handle))
+  {
+    ULONG tli, mli, eli;
+    PHANDLE_TABLE_ENTRY *mlp;
+    
+    tli = TLI_FROM_HANDLE(Handle);
+    mli = MLI_FROM_HANDLE(Handle);
+    eli = ELI_FROM_HANDLE(Handle);
+    
+    mlp = HandleTable->Table[tli];
+    if(Handle < HandleTable->NextIndexNeedingPool &&
+       mlp != NULL && mlp[mli] != NULL && mlp[mli][eli].u1.Object != NULL)
+    {
+      Entry = &mlp[mli][eli];
+      DPRINT("handle lookup 0x%x -> entry 0x%x [HT:0x%x] ptr: 0x%x\n", Handle, Entry, HandleTable, mlp[mli][eli].u1.Object);
+    }
+  }
+  else
+  {
+    DPRINT("Looking up invalid handle 0x%x\n", Handle);
+  }
+  
+  return Entry;
+}
+
+BOOLEAN
+ExLockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                       IN PHANDLE_TABLE_ENTRY Entry)
+{
+  ULONG_PTR Current, New;
+
+  PAGED_CODE();
+  
+  DPRINT("Entering handle table entry 0x%x lock...\n", Entry);
+  
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+  
+  for(;;)
+  {
+    Current = (volatile ULONG_PTR)Entry->u1.Object;
+    
+    if(!Current || (HandleTable->Flags & EX_HANDLE_TABLE_CLOSING))
+    {
+      DPRINT("Attempted to lock empty handle table entry 0x%x or handle table shut down\n", Entry);
+      break;
+    }
+    
+    if(!(Current & EX_HANDLE_ENTRY_LOCKED))
+    {
+      New = Current | EX_HANDLE_ENTRY_LOCKED;
+      if(InterlockedCompareExchangePointer(&Entry->u1.Object,
+                                           (PVOID)New,
+                                           (PVOID)Current) == (PVOID)Current)
+      {
+        DPRINT("SUCCESS handle table 0x%x entry 0x%x lock\n", HandleTable, Entry);
+        /* we acquired the lock */
+        return TRUE;
+      }
+    }
+
+    /* 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)
+{
+  ULONG_PTR Current, New;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+  
+  DPRINT("ExUnlockHandleTableEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+  
+  Current = (volatile ULONG_PTR)Entry->u1.Object;
+
+  ASSERT(Current & EX_HANDLE_ENTRY_LOCKED);
+  
+  New = Current & ~EX_HANDLE_ENTRY_LOCKED;
+  
+  InterlockedExchangePointer(&Entry->u1.Object,
+                             (PVOID)New);
+
+  /* we unlocked the entry, pulse the contention event so threads who're waiting
+     on the release can continue */
+  KePulseEvent(&HandleTable->HandleContentionEvent,
+               EVENT_INCREMENT,
+               FALSE);
+}
+
+LONG
+ExCreateHandle(IN PHANDLE_TABLE HandleTable,
+               IN PHANDLE_TABLE_ENTRY Entry)
+{
+  PHANDLE_TABLE_ENTRY NewHandleTableEntry;
+  LONG Handle = EX_INVALID_HANDLE;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+  
+  /* The highest bit in Entry->u1.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->u1.Object & EX_HANDLE_ENTRY_LOCKED);
+  
+  KeEnterCriticalRegion();
+  ExAcquireHandleTableLockExclusive(HandleTable);
+  
+  NewHandleTableEntry = ExpAllocateHandleTableEntry(HandleTable,
+                                                    &Handle);
+  if(NewHandleTableEntry != NULL)
+  {
+    *NewHandleTableEntry = *Entry;
+    
+    ExUnlockHandleTableEntry(HandleTable,
+                             NewHandleTableEntry);
+  }
+
+  ExReleaseHandleTableLock(HandleTable);
+  KeLeaveCriticalRegion();
+
+  return Handle;
+}
+
+BOOLEAN
+ExDestroyHandle(IN PHANDLE_TABLE HandleTable,
+                IN LONG Handle)
+{
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+  BOOLEAN Ret = FALSE;
+  
+  PAGED_CODE();
+  
+  ASSERT(HandleTable);
+  
+  KeEnterCriticalRegion();
+  ExAcquireHandleTableLockExclusive(HandleTable);
+  
+  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+                                               Handle);
+  
+  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,
+                            Handle);
+    Ret = TRUE;
+  }
+  
+  ExReleaseHandleTableLock(HandleTable);
+  KeLeaveCriticalRegion();
+  
+  return Ret;
+}
+
+VOID
+ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable,
+                       IN PHANDLE_TABLE_ENTRY Entry,
+                       IN LONG Handle)
+{
+  PAGED_CODE();
+
+  ASSERT(HandleTable);
+  ASSERT(Entry);
+  
+  /* This routine requires the entry to be locked */
+  ASSERT((ULONG_PTR)Entry->u1.Object & EX_HANDLE_ENTRY_LOCKED);
+  
+  DPRINT("DestroyHandleByEntry HT:0x%x Entry:0x%x\n", HandleTable, Entry);
+
+  KeEnterCriticalRegion();
+  ExAcquireHandleTableLockExclusive(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);
+
+  ExReleaseHandleTableLock(HandleTable);
+  KeLeaveCriticalRegion();
+}
+
+PHANDLE_TABLE_ENTRY
+ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
+                     IN LONG Handle)
+{
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+
+  PAGED_CODE();
+
+  ASSERT(HandleTable);
+  
+  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+                                               Handle);
+  if (HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
+  {
+    DPRINT("ExMapHandleToPointer HT:0x%x Entry:0x%x locked\n", HandleTable, HandleTableEntry);
+    return HandleTableEntry;
+  }
+  
+  return NULL;
+}
+
+BOOLEAN
+ExChangeHandle(IN PHANDLE_TABLE HandleTable,
+               IN LONG Handle,
+               IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
+               IN PVOID Context)
+{
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+  BOOLEAN Ret = FALSE;
+
+  PAGED_CODE();
+
+  ASSERT(HandleTable);
+  ASSERT(ChangeHandleCallback);
+
+  KeEnterCriticalRegion();
+  
+  HandleTableEntry = ExpLookupHandleTableEntry(HandleTable,
+                                               Handle);
+
+  if(HandleTableEntry != NULL && ExLockHandleTableEntry(HandleTable, HandleTableEntry))
+  {
+    Ret = ChangeHandleCallback(HandleTable,
+                               HandleTableEntry,
+                               NULL);
+
+    ExUnlockHandleTableEntry(HandleTable,
+                             HandleTableEntry);
+  }
+  
+  KeLeaveCriticalRegion();
+
+  return Ret;
+}
+
+/* EOF */
index f422db9..bb094d8 100644 (file)
@@ -662,6 +662,7 @@ ExInit3 (VOID)
   ExpInitializeMutantImplementation();
   ExpInitializeSemaphoreImplementation();
   ExpInitializeTimerImplementation();
+  ExpInitializeHandleTables();
   LpcpInitSystem();
   ExpInitializeProfileImplementation();
   ExpWin32kInit();
index f76e969..084744d 100644 (file)
@@ -617,7 +617,7 @@ QSI_DEF(SystemProcessInformation)
                SpiCur->BasePriority = pr->Pcb.BasePriority;
                SpiCur->ProcessId = pr->UniqueProcessId;
                SpiCur->InheritedFromProcessId = pr->InheritedFromUniqueProcessId;
-               SpiCur->HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
+               SpiCur->HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
                SpiCur->VmCounters.PeakVirtualSize = pr->PeakVirtualSize;
                SpiCur->VmCounters.VirtualSize = pr->VirtualSize.QuadPart;
                SpiCur->VmCounters.PageFaultCount = pr->LastFaultCount;
@@ -849,7 +849,7 @@ QSI_DEF(SystemHandleInformation)
 
         do
          {
-            hCount = hCount + ObpGetHandleCountByHandleTable(&pr->HandleTable);
+            hCount = hCount + ObpGetHandleCountByHandleTable(pr->ObjectTable);
             pr = PsGetNextProcess(pr);
 
            if ((pr == syspr) || (pr == NULL))
@@ -885,7 +885,7 @@ QSI_DEF(SystemHandleInformation)
          {
             int Count = 0, HandleCount = 0;
 
-            HandleCount = ObpGetHandleCountByHandleTable(&pr->HandleTable);
+            HandleCount = ObpGetHandleCountByHandleTable(pr->ObjectTable);
 
             for (Count = 0; HandleCount > 0 ; HandleCount--)
                {
index 8d7bac1..ff1f747 100644 (file)
@@ -85,32 +85,55 @@ ExWorkerThreadEntryPoint(IN PVOID context)
 static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
                                  KPRIORITY Priority)
 {
-   ULONG i;
-   PETHREAD Thread;
-   HANDLE   hThread;
-   
-   
-   for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
-     {
-        
-   PsCreateSystemThread(&hThread,
-                            THREAD_ALL_ACCESS,
-                            NULL,
-                            NULL,
-                            NULL,
-                            ExWorkerThreadEntryPoint,
-              WorkQueue);
-   ObReferenceObjectByHandle(hThread,
-                                 THREAD_ALL_ACCESS,
-                                 PsThreadType,
-                                 KernelMode,
-                                 (PVOID*)&Thread,
-                                 NULL);
-       KeSetPriorityThread(&Thread->Tcb,
-                           Priority);
-       ObDereferenceObject(Thread);
-   ZwClose(hThread);
-     }
+    ULONG i;
+    PETHREAD Thread;
+    HANDLE hThread;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    /* Loop through how many threads we need to create */
+    for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
+
+        /* Create the System Thread */
+        Status = PsCreateSystemThread(&hThread,
+                                      THREAD_ALL_ACCESS,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      ExWorkerThreadEntryPoint,
+                                      (PVOID)WorkQueue);
+        if(NT_SUCCESS(Status))
+        {
+          /* Get the Thread */
+          Status = ObReferenceObjectByHandle(hThread,
+                                             THREAD_SET_INFORMATION,
+                                             PsThreadType,
+                                             KernelMode,
+                                             (PVOID*)&Thread,
+                                             NULL);
+
+          if(NT_SUCCESS(Status))
+          {
+            /* Set the Priority */
+            KeSetPriorityThread(&Thread->Tcb, Priority);
+
+            /* Dereference and close handle */
+            ObDereferenceObject(Thread);
+            ZwClose(hThread);
+          }
+          else
+          {
+            DPRINT1("Unable to reference worker thread handle 0x%x, Status: 0x%x!\n", hThread, Status);
+            KEBUGCHECK(0);
+          }
+        }
+        else
+        {
+          DPRINT1("Unable to create worker thread, Status: 0x%x!\n", Status);
+          KEBUGCHECK(0);
+        }
+    }
 }
 
 VOID INIT_FUNCTION
index 8ae57b1..9aa28fd 100644 (file)
@@ -109,6 +109,65 @@ VOID
 STDCALL
 ExpInitializeExecutive(VOID);
 
+/* 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_INVALID_HANDLE (~0)
+
+#define EX_HANDLE_ENTRY_FLAGSMASK (EX_HANDLE_ENTRY_LOCKED |                    \
+                                   EX_HANDLE_ENTRY_PROTECTFROMCLOSE |          \
+                                   EX_HANDLE_ENTRY_INHERITABLE |               \
+                                   EX_HANDLE_ENTRY_AUDITONCLOSE)
+
+typedef VOID (STDCALL PEX_DESTROY_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PVOID Object, ULONG GrantedAccess, PVOID Context);
+typedef BOOLEAN (STDCALL PEX_DUPLICATE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context);
+typedef BOOLEAN (STDCALL PEX_CHANGE_HANDLE_CALLBACK)(PHANDLE_TABLE HandleTable, PHANDLE_TABLE_ENTRY HandleTableEntry, PVOID Context);
+
+VOID
+ExpInitializeHandleTables(VOID);
+PHANDLE_TABLE
+ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL);
+VOID
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
+                     IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback  OPTIONAL,
+                     IN PVOID Context  OPTIONAL);
+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);
+VOID
+ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable,
+                         IN PHANDLE_TABLE_ENTRY Entry);
+LONG
+ExCreateHandle(IN PHANDLE_TABLE HandleTable,
+               IN PHANDLE_TABLE_ENTRY Entry);
+BOOLEAN
+ExDestroyHandle(IN PHANDLE_TABLE HandleTable,
+                IN LONG Handle);
+VOID
+ExDestroyHandleByEntry(IN PHANDLE_TABLE HandleTable,
+                       IN PHANDLE_TABLE_ENTRY Entry,
+                       IN LONG Handle);
+PHANDLE_TABLE_ENTRY
+ExMapHandleToPointer(IN PHANDLE_TABLE HandleTable,
+                     IN LONG Handle);
+
+BOOLEAN
+ExChangeHandle(IN PHANDLE_TABLE HandleTable,
+               IN LONG Handle,
+               IN PEX_CHANGE_HANDLE_CALLBACK ChangeHandleCallback,
+               IN PVOID Context);
+
 /* OTHER FUNCTIONS **********************************************************/
 
 LONGLONG 
index b477878..11f4f9f 100644 (file)
@@ -228,17 +228,22 @@ enum
    OBJTYP_MAX,
 };
 
+#define HEADER_TO_BODY(objhdr)                                                 \
+  (PVOID)((ULONG_PTR)objhdr + sizeof(OBJECT_HEADER) - sizeof(COMMON_BODY_HEADER))
+
+#define BODY_TO_HEADER(objbdy)                                                 \
+  CONTAINING_RECORD(&(((PCOMMON_BODY_HEADER)objbdy)->Type), OBJECT_HEADER, Type)
 
 #define OBJECT_ALLOC_SIZE(ObjectSize) ((ObjectSize)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER))
 
+#define HANDLE_TO_EX_HANDLE(handle)                                            \
+  (LONG)(((LONG)(handle) >> 2) - 1)
+#define EX_HANDLE_TO_HANDLE(exhandle)                                          \
+  (HANDLE)(((exhandle) + 1) << 2)
 
 extern PDIRECTORY_OBJECT NameSpaceRoot;
 extern POBJECT_TYPE ObSymbolicLinkType;
 
-
-POBJECT_HEADER BODY_TO_HEADER(PVOID body);
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj);
-
 VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
                          POBJECT_HEADER Header,
                          PWSTR Name);
@@ -260,13 +265,11 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
                      PVOID* ReturnedObject,
                      PUNICODE_STRING RemainingPath,
                      POBJECT_TYPE ObjectType);
-VOID ObCloseAllHandles(struct _EPROCESS* Process);
 VOID ObDeleteHandleTable(struct _EPROCESS* Process);
 
 NTSTATUS
 ObDeleteHandle(PEPROCESS Process,
-              HANDLE Handle,
-              PVOID *ObjectBody);
+              HANDLE Handle);
 
 NTSTATUS
 ObpQueryHandleAttributes(HANDLE Handle,
index 02378c7..a4d8a2f 100644 (file)
@@ -345,7 +345,7 @@ struct _EPROCESS
   LIST_ENTRY            SessionProcessLinks;
   struct _EPORT         *DebugPort;
   struct _EPORT         *ExceptionPort;
-  HANDLE_TABLE          HandleTable;
+  PHANDLE_TABLE         ObjectTable;
   PVOID                 Token;
   FAST_MUTEX            WorkingSetLock;
   ULONG                 WorkingSetPage;
@@ -454,8 +454,6 @@ VOID PsQueueThreadReap(PETHREAD Thread);
 NTSTATUS 
 PsInitializeThread(PEPROCESS Process,
                   PETHREAD* ThreadPtr,
-                  PHANDLE ThreadHandle,
-                  ACCESS_MASK DesiredAccess,
                   POBJECT_ATTRIBUTES ObjectAttributes,
                   BOOLEAN First);
 
@@ -641,26 +639,12 @@ typedef struct _EJOB
 
 VOID INIT_FUNCTION PsInitJobManagment(VOID);
 
-/* CID */
-
-typedef struct _CID_OBJECT
-{
-  LONG ref;
-  HANDLE Handle;
-  LIST_ENTRY Entry;
-  FAST_MUTEX Lock;
-  union
-  {
-    struct _EPROCESS *Process;
-    struct _ETHREAD *Thread;
-    PVOID Object;
-  } Obj;
-} CID_OBJECT, *PCID_OBJECT;
+/* CLIENT ID */
 
 NTSTATUS PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle);
 NTSTATUS PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
-PCID_OBJECT PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType);
-VOID PsUnlockCidObject(PCID_OBJECT CidObject);
+PHANDLE_TABLE_ENTRY PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object);
+VOID PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry);
 NTSTATUS PsLockProcess(PEPROCESS Process, BOOL Timeout);
 VOID PsUnlockProcess(PEPROCESS Process);
 
index 64ae143..336aefe 100644 (file)
@@ -52,7 +52,7 @@ IopCloseFile(PVOID ObjectBody,
    
    DPRINT("IopCloseFile()\n");
    
-   if (HandleCount > 0 || FileObject->DeviceObject == NULL)
+   if (HandleCount > 1 || FileObject->DeviceObject == NULL)
      {
        return;
      }
index 6709dbf..a1b27b4 100644 (file)
@@ -1740,10 +1740,13 @@ IopInvalidateDeviceRelations(
       &IoStatusBlock,
       0,
       0);
-   BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE;
-
-   ZwClose(Handle);
+   if(NT_SUCCESS(Status))
+   {
+     BootDrivers = FALSE;
+     ZwClose(Handle);
+   }
+   else
+     BootDrivers = TRUE;
 
    /*
     * Initialize services for discovered children. Only boot drivers will
index 4f61c71..c73a8df 100644 (file)
@@ -41,8 +41,7 @@ NiClosePort (PVOID    ObjectBody, ULONG       HandleCount)
    * If the client has just closed its handle then tell the server what
    * happened and disconnect this port.
    */
-  if (HandleCount == 0 && Port->State == EPORT_CONNECTED_CLIENT && 
-      ObGetObjectPointerCount(Port) == 2)
+  if (HandleCount == 1 && Port->State == EPORT_CONNECTED_CLIENT)
     {
       DPRINT("Informing server\n");
       Message.MessageSize = sizeof(LPC_MESSAGE);
@@ -64,8 +63,7 @@ NiClosePort (PVOID    ObjectBody, ULONG       HandleCount)
    * If the server has closed all of its handles then disconnect the port,
    * don't actually notify the client until it attempts an operation.
    */
-  if (HandleCount == 0 && Port->State == EPORT_CONNECTED_SERVER && 
-      ObGetObjectPointerCount(Port) == 1)
+  if (HandleCount == 1 && Port->State == EPORT_CONNECTED_SERVER)
     {
         DPRINT("Cleaning up server\n");
        Port->OtherPort->OtherPort = NULL;
index dcc90ef..1eafa22 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
-/* TYPES *******************************************************************/
-
-/*
- * PURPOSE: Defines a handle
- */
-typedef struct _HANDLE_ENTRY
-{
-  PVOID ObjectBody;
-  ACCESS_MASK GrantedAccess;
-} HANDLE_ENTRY, *PHANDLE_ENTRY;
-
-#define HANDLE_BLOCK_ENTRIES \
-       (((4 * PAGE_SIZE) - \
-         (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(HANDLE_ENTRY))
-
-#define OB_HANDLE_FLAG_MASK    0x00000007
-#define OB_HANDLE_FLAG_AUDIT   0x00000004
-#define OB_HANDLE_FLAG_PROTECT 0x00000002
-#define OB_HANDLE_FLAG_INHERIT 0x00000001
-
-#define OB_POINTER_TO_ENTRY(Pointer) \
-  (PVOID)((ULONG_PTR)(Pointer) & ~OB_HANDLE_FLAG_MASK)
-
-#define OB_ENTRY_TO_POINTER(Entry) \
-  (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK)
-
-/*
- * PURPOSE: Defines a 4 page's worth of handles
- */
-typedef struct
-{
-   LIST_ENTRY entry;
-   ULONG allocation_hint;
-   ULONG allocation_count;
-   HANDLE_ENTRY handles[HANDLE_BLOCK_ENTRIES];
-} HANDLE_BLOCK, *PHANDLE_BLOCK;
-
-
-/* GLOBALS *******************************************************************/
-
-#define TAG_HANDLE_TABLE    TAG('H', 'T', 'B', 'L')
+#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)->u1.Object) &   \
+  ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE |           \
+  EX_HANDLE_ENTRY_AUDITONCLOSE)))
 
 /* FUNCTIONS ***************************************************************/
 
 
-/*
- * FUNCTION: Get the data structure for a handle
- * ARGUMENTS:
- *         Process = Process to get the handle for
- *         h = Handle
- * ARGUMENTS: A pointer to the information about the handle on success,
- *            NULL on failure
- */
-static PHANDLE_ENTRY
-ObpGetObjectByHandle(PHANDLE_TABLE HandleTable,
-                    HANDLE h,
-                    HANDLE_BLOCK **Block)
+VOID
+ObpDecrementHandleCount(PVOID ObjectBody)
 {
-   PLIST_ENTRY current;
-   unsigned int handle = (((unsigned int)h) >> 2) - 1;
-   unsigned int count = handle / HANDLE_BLOCK_ENTRIES;
-   HANDLE_BLOCK* blk = NULL;
-   unsigned int i;
-   
-   DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h);
-   
-   current = HandleTable->ListHead.Flink;
-   DPRINT("current %x\n",current);
-   
-   for (i = 0; i < count; i++)
-     {
-       current = current->Flink;
-       if (current == (&(HandleTable->ListHead)))
-         {
-            return(NULL);
-         }
-     }
-   
-   blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
-   if (Block)
-      *Block = blk;
-   DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
-   return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
+  POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
+
+  if ((ObjectHeader->ObjectType != NULL) &&
+      (ObjectHeader->ObjectType->Close != NULL))
+  {
+    /* the handle count should be decremented but we pass the previous value
+       to the callback */
+    ObjectHeader->ObjectType->Close(ObjectBody, NewHandleCount + 1);
+  }
+
+  if(NewHandleCount == 0)
+  {
+    ObDereferenceObject(ObjectBody);
+  }
 }
 
 
@@ -124,29 +69,32 @@ ObpQueryHandleAttributes(HANDLE Handle,
                         POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
   PEPROCESS Process;
-  KIRQL oldIrql;
-  PHANDLE_ENTRY HandleEntry;
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
+  
+  PAGED_CODE();
 
   DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
 
+  KeEnterCriticalRegion();
+
   Process = PsGetCurrentProcess();
 
-  KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
-  HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
-                                    Handle,
-                                    NULL);
-  if (HandleEntry == NULL)
+  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                          ExHandle);
+  if (HandleTableEntry == NULL)
     {
-      KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+      KeLeaveCriticalRegion();
       return STATUS_INVALID_HANDLE;
     }
 
-  HandleInfo->Inherit =
-    ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_INHERIT);
-  HandleInfo->ProtectFromClose =
-    ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT);
+  HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+  HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
 
-  KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+  ExUnlockHandleTableEntry(Process->ObjectTable,
+                           HandleTableEntry);
+
+  KeLeaveCriticalRegion();
 
   return STATUS_SUCCESS;
 }
@@ -156,37 +104,42 @@ NTSTATUS
 ObpSetHandleAttributes(HANDLE Handle,
                       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
-  PHANDLE_ENTRY HandleEntry;
   PEPROCESS Process;
-  KIRQL oldIrql;
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
+  
+  PAGED_CODE();
 
-  DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+  DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
 
   Process = PsGetCurrentProcess();
+  
+  KeEnterCriticalRegion();
 
-  KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
-  HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
-                                    Handle,
-                                    NULL);
-  if (HandleEntry == NULL)
+  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                          ExHandle);
+  if (HandleTableEntry == NULL)
     {
-      KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+      KeLeaveCriticalRegion();
       return STATUS_INVALID_HANDLE;
     }
 
   if (HandleInfo->Inherit)
-    HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_INHERIT);
+    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
   else
-    HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_INHERIT);
+    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
 
   if (HandleInfo->ProtectFromClose)
-    HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_PROTECT);
+    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
   else
-    HandleEntry->ObjectBody = (PVOID)((ULONG_PTR)HandleEntry->ObjectBody & ~OB_HANDLE_FLAG_PROTECT);
+    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
 
   /* FIXME: Do we need to set anything in the object header??? */
 
-  KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
+  ExUnlockHandleTableEntry(Process->ObjectTable,
+                           HandleTableEntry);
+
+  KeLeaveCriticalRegion();
 
   return STATUS_SUCCESS;
 }
@@ -201,46 +154,82 @@ ObDuplicateObject(PEPROCESS SourceProcess,
                  BOOLEAN InheritHandle,
                  ULONG Options)
 {
-  KIRQL oldIrql;
-  PHANDLE_ENTRY SourceHandleEntry;
+  PHANDLE_TABLE_ENTRY SourceHandleEntry;
+  HANDLE_TABLE_ENTRY NewHandleEntry;
   PVOID ObjectBody;
-
-  KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
-  SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable,
-                                          SourceHandle,
-                                          NULL);
+  POBJECT_HEADER ObjectHeader;
+  LONG ExTargetHandle;
+  LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle);
+  
+  PAGED_CODE();
+  
+  KeEnterCriticalRegion();
+  
+  SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
+                                           ExSourceHandle);
   if (SourceHandleEntry == NULL)
     {
-      KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
       return STATUS_INVALID_HANDLE;
     }
 
-  ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody);
-  ObReferenceObjectByPointer(ObjectBody,
-                            0,
-                            NULL,
-                            UserMode);
+  ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
+  ObjectBody = HEADER_TO_BODY(ObjectHeader);
+
+  NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object;
+  if(InheritHandle)
+    NewHandleEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+  else
+    NewHandleEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+  NewHandleEntry.u2.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
+                                     SourceHandleEntry->u2.GrantedAccess :
+                                     DesiredAccess);
+  
+  /* reference the object so it doesn't get deleted after releasing the lock
+     and before creating a new handle for it */
+  ObReferenceObject(ObjectBody);
   
-  if (Options & DUPLICATE_SAME_ACCESS)
+  /* increment the handle count of the object, it should always be >= 2 because
+     we're holding a handle lock to this object! if the new handle count was
+     1 here, we're in big trouble... it would've been safe to increment and
+     check the handle count without using interlocked functions because the
+     entry is locked, which means the handle count can't change. */
+  InterlockedIncrement(&ObjectHeader->HandleCount);
+  ASSERT(ObjectHeader->HandleCount >= 2);
+  
+  ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
+                           SourceHandleEntry);
+
+  KeLeaveCriticalRegion();
+
+  /* attempt to create the new handle */
+  ExTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+                                  &NewHandleEntry);
+  if (ExTargetHandle != EX_INVALID_HANDLE)
+  {
+    if (Options & DUPLICATE_CLOSE_SOURCE)
     {
-      DesiredAccess = SourceHandleEntry->GrantedAccess;
+      ObDeleteHandle(SourceProcess,
+                     SourceHandle);
     }
+    
+    ObDereferenceObject(ObjectBody);
 
-  KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-  ObCreateHandle(TargetProcess,
-                ObjectBody,
-                DesiredAccess,
-                InheritHandle,
-                TargetHandle);
-  
-  if (Options & DUPLICATE_CLOSE_SOURCE)
+    *TargetHandle = EX_HANDLE_TO_HANDLE(ExTargetHandle);
+    
+    return STATUS_SUCCESS;
+  }
+  else
+  {
+    /* decrement the handle count we previously incremented, but don't call the
+       closing procedure because we're not closing a handle! */
+    if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0)
     {
-      ZwClose(SourceHandle);
+      ObDereferenceObject(ObjectBody);
     }
-
-  ObDereferenceObject(ObjectBody);
-
-  return STATUS_SUCCESS;
+    
+    ObDereferenceObject(ObjectBody);
+    return STATUS_UNSUCCESSFUL;
+  }
 }
 
 /*
@@ -250,7 +239,7 @@ NTSTATUS STDCALL
 NtDuplicateObject (IN  HANDLE          SourceProcessHandle,
                   IN   HANDLE          SourceHandle,
                   IN   HANDLE          TargetProcessHandle,
-                  OUT  PHANDLE         UnsafeTargetHandle,
+                  OUT  PHANDLE         TargetHandle,
                   IN   ACCESS_MASK     DesiredAccess,
                   IN   BOOLEAN         InheritHandle,
                   ULONG                Options)
@@ -281,18 +270,38 @@ NtDuplicateObject (IN     HANDLE          SourceProcessHandle,
 {
    PEPROCESS SourceProcess;
    PEPROCESS TargetProcess;
-   PHANDLE_ENTRY SourceHandleEntry;
-   KIRQL oldIrql;
-   PVOID ObjectBody;
-   HANDLE TargetHandle;
-   NTSTATUS Status;
+   HANDLE hTarget;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
    
    PAGED_CODE();
    
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(TargetHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+   
    Status = ObReferenceObjectByHandle(SourceProcessHandle,
                                      PROCESS_DUP_HANDLE,
                                      NULL,
-                                     UserMode,
+                                     PreviousMode,
                                      (PVOID*)&SourceProcess,
                                      NULL);
    if (!NT_SUCCESS(Status))
@@ -303,7 +312,7 @@ NtDuplicateObject (IN       HANDLE          SourceProcessHandle,
    Status = ObReferenceObjectByHandle(TargetProcessHandle,
                                      PROCESS_DUP_HANDLE,
                                      NULL,
-                                     UserMode,
+                                     PreviousMode,
                                      (PVOID*)&TargetProcess,
                                      NULL);
    if (!NT_SUCCESS(Status))
@@ -315,134 +324,76 @@ NtDuplicateObject (IN    HANDLE          SourceProcessHandle,
    /* Check for magic handle first */
    if (SourceHandle == NtCurrentThread())
      {
-       ObReferenceObjectByHandle(SourceHandle,
-                                 PROCESS_DUP_HANDLE,
-                                 NULL,
-                                 UserMode,
-                                 &ObjectBody,
-                                 NULL);
-
-       ObCreateHandle(TargetProcess,
-                      ObjectBody,
-                      THREAD_ALL_ACCESS,
-                      InheritHandle,
-                      &TargetHandle);
+       PVOID ObjectBody;
+       
+       Status = ObReferenceObjectByHandle(SourceHandle,
+                                          PROCESS_DUP_HANDLE,
+                                          NULL,
+                                          PreviousMode,
+                                          &ObjectBody,
+                                          NULL);
+       if(NT_SUCCESS(Status))
+       {
+         Status = ObCreateHandle(TargetProcess,
+                                 ObjectBody,
+                                 THREAD_ALL_ACCESS,
+                                 InheritHandle,
+                                 &hTarget);
+
+         ObDereferenceObject(ObjectBody);
+         
+         if (Options & DUPLICATE_CLOSE_SOURCE)
+         {
+           ObDeleteHandle(SourceProcess,
+                          SourceHandle);
+         }
+       }
      }
    else
      {
-       KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
-       SourceHandleEntry = ObpGetObjectByHandle(&SourceProcess->HandleTable,
-                                               SourceHandle,
-                                               NULL);
-       if (SourceHandleEntry == NULL)
-        {
-          KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-          ObDereferenceObject(SourceProcess);
-          ObDereferenceObject(TargetProcess);
-          return(STATUS_INVALID_HANDLE);
-        }
-       ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleEntry->ObjectBody);
-       ObReferenceObjectByPointer(ObjectBody,
-                                 0,
-                                 NULL,
-                                 UserMode);
-
-       if (Options & DUPLICATE_SAME_ACCESS)
-        {
-          DesiredAccess = SourceHandleEntry->GrantedAccess;
-        }
-
-       KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-
-       ObCreateHandle(TargetProcess,
-                     ObjectBody,
-                     DesiredAccess,
-                     InheritHandle,
-                     &TargetHandle);
-     }
-   
-   if (Options & DUPLICATE_CLOSE_SOURCE)
-     {
-       ZwClose(SourceHandle);
+       Status = ObDuplicateObject(SourceProcess,
+                                  TargetProcess,
+                                  SourceHandle,
+                                  &hTarget,
+                                  DesiredAccess,
+                                  InheritHandle,
+                                  Options);
      }
-   
+
    ObDereferenceObject(TargetProcess);
    ObDereferenceObject(SourceProcess);
-   ObDereferenceObject(ObjectBody);
-   
-   Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
-   if (!NT_SUCCESS(Status))
+
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
      {
-       return(Status);
+       *TargetHandle = hTarget;
      }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
 
-   return(STATUS_SUCCESS);
+   return Status;
 }
 
-VOID ObCloseAllHandles(PEPROCESS Process)
+static VOID STDCALL
+DeleteHandleCallback(PHANDLE_TABLE HandleTable,
+                     PVOID Object,
+                     ULONG GrantedAccess,
+                     PVOID Context)
 {
-   KIRQL oldIrql;
-   PHANDLE_TABLE HandleTable;
-   PLIST_ENTRY current_entry;
-   PHANDLE_BLOCK current;
-   ULONG i;
-   PVOID ObjectBody;
-   
-   DPRINT("ObCloseAllHandles(Process %x)\n", Process);
-   
-   HandleTable = &Process->HandleTable;
-   
-   KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-   
-   current_entry = HandleTable->ListHead.Flink;
-   
-   while (current_entry != &HandleTable->ListHead)
-     {
-       current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
-       
-       for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
-         {
-            ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody);
-            
-            if (ObjectBody != NULL)
-              {
-                 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-                 
-#if 0
-                  if (Header->ObjectType == PsProcessType ||
-                     Header->ObjectType == PsThreadType)
-                   {
-                      DPRINT("Deleting handle to %x\n", ObjectBody);
-                   }
-#endif
-                 
-                 ObReferenceObjectByPointer(ObjectBody,
-                                            0,
-                                            NULL,
-                                            UserMode);
-                 InterlockedDecrement(&Header->HandleCount);
-                 current->handles[i].ObjectBody = NULL;
-                 
-                 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-                 if ((Header->ObjectType != NULL) &&
-                     (Header->ObjectType->Close != NULL))
-                   {
-                      Header->ObjectType->Close(ObjectBody,
-                                                Header->HandleCount);
-                   }
-                 
-                 ObDereferenceObject(ObjectBody);
-                 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-                 current_entry = &HandleTable->ListHead;
-                 break;
-              }
-         }
-       
-       current_entry = current_entry->Flink;
-     }
-   KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-   DPRINT("ObCloseAllHandles() finished\n");
-   DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
+  POBJECT_HEADER ObjectHeader;
+  PVOID ObjectBody;
+  
+  PAGED_CODE();
+
+  ObjectHeader = EX_OBJ_TO_HDR(Object);
+  ObjectBody = HEADER_TO_BODY(ObjectHeader);
+  
+  ObpDecrementHandleCount(ObjectBody);
 }
 
 VOID ObDeleteHandleTable(PEPROCESS Process)
@@ -450,26 +401,38 @@ VOID ObDeleteHandleTable(PEPROCESS Process)
  * FUNCTION: Deletes the handle table associated with a process
  */
 {
-   PLIST_ENTRY current = NULL;
-   PHANDLE_TABLE HandleTable = NULL;
-   
-   ObCloseAllHandles(Process);
-   
-   HandleTable = &Process->HandleTable;
-   current = RemoveHeadList(&HandleTable->ListHead);
-   
-   while (current != &HandleTable->ListHead)
-     {
-       HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current,
-                                                     HANDLE_BLOCK,
-                                                     entry);
-       DPRINT("Freeing %x\n", HandleBlock);
-       ExFreePool(HandleBlock);
-       
-       current = RemoveHeadList(&HandleTable->ListHead);
-     }
+   PAGED_CODE();
+
+   ExDestroyHandleTable(Process->ObjectTable,
+                        DeleteHandleCallback,
+                        Process);
 }
 
+static BOOLEAN STDCALL
+DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
+                        PHANDLE_TABLE_ENTRY HandleTableEntry,
+                        PVOID Context)
+{
+  POBJECT_HEADER ObjectHeader;
+  BOOLEAN Ret = FALSE;
+  
+  PAGED_CODE();
+  
+  Ret = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+  if(Ret)
+  {
+    ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
+    if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+    {
+      ObReferenceObjectByPointer(HEADER_TO_BODY(ObjectHeader),
+                                0,
+                                NULL,
+                                UserMode);
+    }
+  }
+  
+  return Ret;
+}
 
 VOID ObCreateHandleTable(PEPROCESS Parent,
                         BOOLEAN Inherit,
@@ -482,133 +445,69 @@ VOID ObCreateHandleTable(PEPROCESS Parent,
  *       Process = Process whose handle table is to be created
  */
 {
-   PHANDLE_TABLE ParentHandleTable, HandleTable;
-   KIRQL oldIrql;
-   PLIST_ENTRY parent_current;
-   ULONG i;
-   PHANDLE_BLOCK current_block, new_block;   
-
+   PAGED_CODE();
+   
    DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
          Parent,Inherit,Process);
-   
-   InitializeListHead(&(Process->HandleTable.ListHead));
-   KeInitializeSpinLock(&(Process->HandleTable.ListLock));
-   
-   if (Parent != NULL)
-     {
-       ParentHandleTable = &Parent->HandleTable;
-       HandleTable = &Process->HandleTable;
-
-       KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
-       KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
-       
-       parent_current = ParentHandleTable->ListHead.Flink;
-       
-       while (parent_current != &ParentHandleTable->ListHead)
-         {
-            current_block = CONTAINING_RECORD(parent_current,
-                                              HANDLE_BLOCK,
-                                              entry);
-            new_block = ExAllocatePoolWithTag(NonPagedPool,
-                                              sizeof(HANDLE_BLOCK),
-                                              TAG_HANDLE_TABLE);
-            if (new_block == NULL)
-            {
-               break;
-            }
-            RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
-
-            for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
-            {
-               if (current_block->handles[i].ObjectBody)
-               {
-                  if ((ULONG_PTR)current_block->handles[i].ObjectBody & OB_HANDLE_FLAG_INHERIT)
-                  {
-                     new_block->handles[i].ObjectBody = 
-                       current_block->handles[i].ObjectBody;
-                     new_block->handles[i].GrantedAccess = 
-                       current_block->handles[i].GrantedAccess;
-                     InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block->handles[i].ObjectBody))->HandleCount));
-                  }
-               }
-            }
-            InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
-            parent_current = parent_current->Flink;
-         }
-       KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
-       KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
-     }
+   if(Parent != NULL)
+   {
+     Process->ObjectTable = ExDupHandleTable(Process,
+                                             DuplicateHandleCallback,
+                                             NULL,
+                                             Parent->ObjectTable);
+   }
+   else
+   {
+     Process->ObjectTable = ExCreateHandleTable(Process);
+   }
 }
 
 
 NTSTATUS
 ObDeleteHandle(PEPROCESS Process,
-              HANDLE Handle,
-              PVOID *ObjectBody)
+              HANDLE Handle)
 {
-   PHANDLE_ENTRY HandleEntry;
+   PHANDLE_TABLE_ENTRY HandleEntry;
    PVOID Body;
-   KIRQL oldIrql;
-   PHANDLE_TABLE HandleTable;
-   POBJECT_HEADER Header;
-   HANDLE_BLOCK *Block;
+   POBJECT_HEADER ObjectHeader;
+   LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
    
    PAGED_CODE();
 
    DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
-
-   HandleTable = &Process->HandleTable;
-
-   KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-
-   HandleEntry = ObpGetObjectByHandle(HandleTable, Handle, &Block);
-   if (HandleEntry == NULL)
-     {
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-       *ObjectBody = NULL;
-       return STATUS_INVALID_HANDLE;
-     }
-
-   if ((ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_PROTECT)
-     {
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-       *ObjectBody = NULL;
-       return STATUS_HANDLE_NOT_CLOSABLE;
-     }
-
-   Body = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
-   DPRINT("ObjectBody %x\n", Body);
-   if (Body == NULL)
+   
+   KeEnterCriticalRegion();
+   
+   HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                      ExHandle);
+   if(HandleEntry != NULL)
+   {
+     if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
      {
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-       *ObjectBody = NULL;
-       return STATUS_UNSUCCESSFUL;
-     }
-
-   Header = BODY_TO_HEADER(Body);
-   ObReferenceObjectByPointer(Body,
-                             0,
-                             NULL,
-                             UserMode);
-   InterlockedDecrement(&Header->HandleCount);
-   HandleEntry->ObjectBody = NULL;
-
-   Block->allocation_count--;
-   Block->allocation_hint = (ULONG_PTR)Handle % HANDLE_BLOCK_ENTRIES;
+       ExUnlockHandleTableEntry(Process->ObjectTable,
+                                HandleEntry);
 
-   KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
+       KeLeaveCriticalRegion();
 
-   if ((Header->ObjectType != NULL) &&
-       (Header->ObjectType->Close != NULL))
-     {
-       Header->ObjectType->Close(Body, Header->HandleCount);
+       return STATUS_HANDLE_NOT_CLOSABLE;
      }
 
-   *ObjectBody = Body;
-
-   DPRINT("Finished ObDeleteHandle()\n");
-
-   return STATUS_SUCCESS;
+     ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+     Body = HEADER_TO_BODY(ObjectHeader);
+     
+     ObpDecrementHandleCount(Body);
+     
+     /* destroy and unlock the handle entry */
+     ExDestroyHandleByEntry(Process->ObjectTable,
+                            HandleEntry,
+                            ExHandle);
+     
+     KeLeaveCriticalRegion();
+     
+     return STATUS_SUCCESS;
+   }
+
+   return STATUS_INVALID_HANDLE;
 }
 
 
@@ -626,94 +525,47 @@ ObCreateHandle(PEPROCESS Process,
  * NOTE: The handle is valid only in the context of the current process
  */
 {
-   LIST_ENTRY* current;
-   unsigned int handle=1;
-   unsigned int Loop, Index, MaxIndex;
-   HANDLE_BLOCK* new_blk = NULL;
-   PHANDLE_TABLE HandleTable;
-   KIRQL oldlvl;
+   HANDLE_TABLE_ENTRY NewEntry;
+   POBJECT_HEADER ObjectHeader;
+   LONG ExHandle;
    
    PAGED_CODE();
 
    DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
 
    ASSERT(Process);
+   ASSERT(ObjectBody);
 
-   if (ObjectBody != NULL)
-     {
-       InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
-     }
-   HandleTable = &Process->HandleTable;
-   KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
-   current = HandleTable->ListHead.Flink;
-   /*
-    * Scan through the currently allocated handle blocks looking for a free
-    * slot
-    */
-   while (current != (&HandleTable->ListHead))
-     {
-       HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
-
-       DPRINT("Current %x\n",current);
+   ObjectHeader = BODY_TO_HEADER(ObjectBody);
 
-       if (blk->allocation_count == HANDLE_BLOCK_ENTRIES)
-         {
-            handle = handle + HANDLE_BLOCK_ENTRIES;
-            current = current->Flink;
-            continue;
-         }
+   ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
 
-       Index = blk->allocation_hint;
-       MaxIndex = HANDLE_BLOCK_ENTRIES;
-       for (Loop = 0; Loop < 2; Loop++)
-         {
-            for (Index = 0; Index < MaxIndex; Index++)
-              {
-                DPRINT("Considering slot %d containing %x\n", Index, blk->handles[Index]);
-                if (blk->handles[Index].ObjectBody == NULL)
-                  {
-                    blk->handles[Index].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
-                    if (Inherit)
-                      blk->handles[Index].ObjectBody = (PVOID)((ULONG_PTR)blk->handles[Index].ObjectBody | OB_HANDLE_FLAG_INHERIT);
-                    blk->handles[Index].GrantedAccess = GrantedAccess;
-                    blk->allocation_hint = Index + 1;
-                    blk->allocation_count++;
-                    KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
-                    *HandleReturn = (HANDLE)((handle + Index) << 2);
-                    return(STATUS_SUCCESS);
-                  }
-              }
-            Index = 0;
-            MaxIndex = blk->allocation_hint;
-         }
-       
-       handle = handle + HANDLE_BLOCK_ENTRIES;
-       current = current->Flink;
+   NewEntry.u1.Object = ObjectHeader;
+   if(Inherit)
+     NewEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+   else
+     NewEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+   NewEntry.u2.GrantedAccess = GrantedAccess;
+   
+   ExHandle = ExCreateHandle(Process->ObjectTable,
+                             &NewEntry);
+   DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, *HandleReturn, Process->ObjectTable);
+   if(ExHandle != EX_INVALID_HANDLE)
+   {
+     if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+     {
+      ObReferenceObjectByPointer(ObjectBody,
+                                0,
+                                NULL,
+                                UserMode);
      }
+     
+     *HandleReturn = EX_HANDLE_TO_HANDLE(ExHandle);
 
-   /*
-    * Add a new handle block to the end of the list
-    */
-   new_blk = 
-     (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK),
-                                          TAG_HANDLE_TABLE);
-   if (!new_blk)
-    {
-      *HandleReturn = (PHANDLE)NULL;
-      return(STATUS_INSUFFICIENT_RESOURCES);
-    }
-   RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK));
-   InsertTailList(&(Process->HandleTable.ListHead),
-                 &new_blk->entry);
-   new_blk->handles[0].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
-   if (Inherit)
-     new_blk->handles[0].ObjectBody = (PVOID)((ULONG_PTR)new_blk->handles[0].ObjectBody | OB_HANDLE_FLAG_INHERIT);
-   new_blk->handles[0].GrantedAccess = GrantedAccess;
-   new_blk->allocation_hint = 1;
-   new_blk->allocation_count++;
-   KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
-   *HandleReturn = (HANDLE)(handle << 2);
-   return(STATUS_SUCCESS);
+     return STATUS_SUCCESS;
+   }
+
+   return STATUS_UNSUCCESSFUL;
 }
 
 
@@ -724,31 +576,35 @@ NTSTATUS STDCALL
 ObQueryObjectAuditingByHandle(IN HANDLE Handle,
                              OUT PBOOLEAN GenerateOnClose)
 {
+  PHANDLE_TABLE_ENTRY HandleEntry;
   PEPROCESS Process;
-  KIRQL oldIrql;
-  PHANDLE_ENTRY HandleEntry;
+  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
   
   PAGED_CODE();
 
   DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
 
   Process = PsGetCurrentProcess();
-
-  KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
-  HandleEntry = ObpGetObjectByHandle(&Process->HandleTable,
-                                    Handle,
-                                    NULL);
-  if (HandleEntry == NULL)
-    {
-      KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
-      return STATUS_INVALID_HANDLE;
-    }
-
-  *GenerateOnClose = (BOOLEAN)((ULONG_PTR)HandleEntry->ObjectBody | OB_HANDLE_FLAG_AUDIT);
-
-  KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
-
-  return STATUS_SUCCESS;
+  
+  KeEnterCriticalRegion();
+
+  HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                     ExHandle);
+  if(HandleEntry != NULL)
+  {
+    *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
+    
+    ExUnlockHandleTableEntry(Process->ObjectTable,
+                             HandleEntry);
+
+    KeLeaveCriticalRegion();
+    
+    return STATUS_SUCCESS;
+  }
+  
+  KeLeaveCriticalRegion();
+  
+  return STATUS_INVALID_HANDLE;
 }
 
 
@@ -775,13 +631,14 @@ ObReferenceObjectByHandle(HANDLE Handle,
                          PVOID* Object,
                          POBJECT_HANDLE_INFORMATION HandleInformation)
 {
-   PHANDLE_ENTRY HandleEntry;
+   PHANDLE_TABLE_ENTRY HandleEntry;
    POBJECT_HEADER ObjectHeader;
-   KIRQL oldIrql;
    PVOID ObjectBody;
    ACCESS_MASK GrantedAccess;
+   PGENERIC_MAPPING GenericMapping;
    ULONG Attributes;
    NTSTATUS Status;
+   LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
    
    PAGED_CODE();
    
@@ -795,8 +652,6 @@ ObReferenceObjectByHandle(HANDLE Handle,
    if (Handle == NtCurrentProcess() && 
        (ObjectType == PsProcessType || ObjectType == NULL))
      {
-       DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
-       
        Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
                                            PROCESS_ALL_ACCESS,
                                            PsProcessType,
@@ -808,7 +663,7 @@ ObReferenceObjectByHandle(HANDLE Handle,
 
        if (HandleInformation != NULL)
          {
-           HandleInformation->HandleAttributes = 0; /* FIXME? */
+           HandleInformation->HandleAttributes = 0;
            HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
          }
 
@@ -836,7 +691,7 @@ ObReferenceObjectByHandle(HANDLE Handle,
 
        if (HandleInformation != NULL)
          {
-           HandleInformation->HandleAttributes = 0; /* FIXME? */
+           HandleInformation->HandleAttributes = 0;
            HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
          }
 
@@ -850,47 +705,52 @@ ObReferenceObjectByHandle(HANDLE Handle,
        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
    
-   KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                    &oldIrql);
-   HandleEntry = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
-                                     Handle,
-                                     NULL);
-   if (HandleEntry == NULL || HandleEntry->ObjectBody == 0)
+   KeEnterCriticalRegion();
+   
+   HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable,
+                                     ExHandle);
+   if (HandleEntry == NULL)
      {
-       KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                         oldIrql);
-       return(STATUS_INVALID_HANDLE);
+        KeLeaveCriticalRegion();
+        DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
+        return(STATUS_INVALID_HANDLE);
      }
-   ObjectBody = OB_ENTRY_TO_POINTER(HandleEntry->ObjectBody);
-   DPRINT("ObjectBody %p\n",ObjectBody);
-   ObjectHeader = BODY_TO_HEADER(ObjectBody);
-   DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
+
+   ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+   ObjectBody = HEADER_TO_BODY(ObjectHeader);
+   
+   DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, PsGetCurrentProcess()->ObjectTable);
+
    ObReferenceObjectByPointer(ObjectBody,
                              0,
                              NULL,
                              UserMode);
-   Attributes = (ULONG_PTR)HandleEntry->ObjectBody & OB_HANDLE_FLAG_MASK;
-   GrantedAccess = HandleEntry->GrantedAccess;
-   KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                    oldIrql);
-   
-   ObjectHeader = BODY_TO_HEADER(ObjectBody);
-   DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
+   Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
+                                                EX_HANDLE_ENTRY_INHERITABLE |
+                                                EX_HANDLE_ENTRY_AUDITONCLOSE);
+   GrantedAccess = HandleEntry->u2.GrantedAccess;
+   GenericMapping = ObjectHeader->ObjectType->Mapping;
 
    if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
      {
-       CHECKPOINT;
-       return(STATUS_OBJECT_TYPE_MISMATCH);
+        DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle);
+        
+        ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
+                                 HandleEntry);
+
+        KeLeaveCriticalRegion();
+        
+        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
+
+   ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
+                            HandleEntry);
    
-   if (ObjectHeader->ObjectType == PsProcessType)
-     {
-       DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
-     }
+   KeLeaveCriticalRegion();
    
-   if (DesiredAccess && AccessMode == UserMode)
+   if (DesiredAccess && AccessMode != KernelMode)
      {
-       RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
+       RtlMapGenericMask(&DesiredAccess, GenericMapping);
 
        if (!(GrantedAccess & DesiredAccess) &&
            !((~GrantedAccess) & DesiredAccess))
@@ -908,7 +768,6 @@ ObReferenceObjectByHandle(HANDLE Handle,
 
    *Object = ObjectBody;
    
-   CHECKPOINT;
    return(STATUS_SUCCESS);
 }
 
@@ -932,17 +791,12 @@ ObReferenceObjectByHandle(HANDLE Handle,
 NTSTATUS STDCALL
 NtClose(IN HANDLE Handle)
 {
-   PVOID               ObjectBody;
-   POBJECT_HEADER      Header;
    NTSTATUS Status;
    
    PAGED_CODE();
    
-   DPRINT("NtClose(Handle %x)\n",Handle);
-   
    Status = ObDeleteHandle(PsGetCurrentProcess(),
-                          Handle,
-                          &ObjectBody);
+                          Handle);
    if (!NT_SUCCESS(Status))
      {
         if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
@@ -950,11 +804,6 @@ NtClose(IN HANDLE Handle)
        return Status;
      }
    
-   Header = BODY_TO_HEADER(ObjectBody);
-   
-   DPRINT("Dereferencing %x\n", ObjectBody);
-   ObDereferenceObject(ObjectBody);
-   
    return(STATUS_SUCCESS);
 }
 
@@ -992,42 +841,7 @@ ObInsertObject(IN PVOID Object,
 ULONG
 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
 {
-  PHANDLE_BLOCK blk;
-  POBJECT_HEADER Header;
-  PVOID ObjectBody;
-  KIRQL OldIrql;
-  PLIST_ENTRY current;
-  ULONG i;
-  ULONG Count=0;
-
-  KeAcquireSpinLock(&HandleTable->ListLock, &OldIrql);
-
-  current = HandleTable->ListHead.Flink;
-  while (current != &HandleTable->ListHead)
-    {
-      blk = CONTAINING_RECORD(current, HANDLE_BLOCK, entry);
-
-      for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
-       {
-         ObjectBody = OB_ENTRY_TO_POINTER(blk->handles[i].ObjectBody);
-         if (ObjectBody != NULL)
-           {
-             Header = BODY_TO_HEADER(ObjectBody);
-
-             /* Make sure this is real. Okay! For real!*/
-             if ((Header->ObjectType != NULL) &&
-                     (Header->ObjectType->Close != NULL))
-               Count++;
-           }
-       }
-
-      current = current->Flink;
-    }
-
-  KeReleaseSpinLock(&HandleTable->ListLock,
-                   OldIrql);
-
-  return Count;
+  return HandleTable->HandleCount;
 }
 
 /*
@@ -1085,7 +899,7 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
                                int Count)
 {
       ULONG P;
-      KIRQL oldIrql;
+//      KIRQL oldIrql;
 
 //      pshi->HandleValue;
 
@@ -1097,14 +911,14 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
       P = (ULONG) Process->UniqueProcessId;
       pshi->UniqueProcessId = (USHORT) P;
 
-      KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
+//      KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
 
 //      pshi->GrantedAccess;
 //      pshi->Object;
 //      pshi->ObjectTypeIndex;
 //      pshi->HandleAttributes;
 
-      KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
+//      KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
 
       return;
 }
index d9e1580..25f7d59 100644 (file)
@@ -25,18 +25,6 @@ typedef struct _RETENTION_CHECK_PARAMS
 
 /* FUNCTIONS ************************************************************/
 
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
-{
-  return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
-}
-
-
-POBJECT_HEADER BODY_TO_HEADER(PVOID body)
-{
-  PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
-  return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
-}
-
 NTSTATUS
 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
                            IN KPROCESSOR_MODE AccessMode,
@@ -734,7 +722,7 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
   RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
 
   /* Initialize the object header */
-  DPRINT("Initalizing header\n");
+  DPRINT("Initalizing header 0x%x (%wZ)\n", Header, &Type->TypeName);
   Header->HandleCount = 0;
   Header->RefCount = 1;
   Header->ObjectType = Type;
@@ -1111,7 +1099,7 @@ ObfReferenceObject(IN PVOID Object)
       KEBUGCHECK(0);
     }
 
-  (VOID)InterlockedIncrement(&Header->RefCount);
+  InterlockedIncrement(&Header->RefCount);
 }
 
 
@@ -1137,25 +1125,23 @@ ObfDereferenceObject(IN PVOID Object)
   POBJECT_HEADER Header;
   LONG NewRefCount;
   BOOL Permanent;
-  ULONG HandleCount;
 
   ASSERT(Object);
 
   /* Extract the object header. */
   Header = BODY_TO_HEADER(Object);
   Permanent = Header->Permanent;
-  HandleCount = Header->HandleCount;
 
   /* 
      Drop our reference and get the new count so we can tell if this was the
      last reference.
   */
   NewRefCount = InterlockedDecrement(&Header->RefCount);
+  DPRINT("ObfDereferenceObject(0x%x)==%d (%wZ)\n", Object, NewRefCount, &Header->ObjectType->TypeName);
   ASSERT(NewRefCount >= 0);
 
   /* Check whether the object can now be deleted. */
   if (NewRefCount == 0 &&
-      HandleCount == 0 &&
       !Permanent)
     {
       ObpDeleteObjectDpcLevel(Header, NewRefCount);
index e388425..f311cd3 100644 (file)
 
 /* GLOBALS ******************************************************************/
 
-/*
- * FIXME - use a global handle table instead!
- */
-
-KSPIN_LOCK CidLock;
-LIST_ENTRY CidHead;
-KEVENT CidReleaseEvent;
-LONG CidCounter = 0;
-LARGE_INTEGER ShortDelay, LongDelay;
+PHANDLE_TABLE PspCidTable = NULL;
 
 #define TAG_CIDOBJECT TAG('C', 'I', 'D', 'O')
 
+#define CID_FLAG_PROCESS 0x1
+#define CID_FLAG_THREAD 0x2
+#define CID_FLAGS_MASK (CID_FLAG_PROCESS | CID_FLAG_THREAD)
+
 /* FUNCTIONS *****************************************************************/
 
 VOID INIT_FUNCTION
 PsInitClientIDManagment(VOID)
 {
-   InitializeListHead(&CidHead);
-   KeInitializeSpinLock(&CidLock);
-   KeInitializeEvent(&CidReleaseEvent, SynchronizationEvent, FALSE);
-   ShortDelay.QuadPart = -100LL;
-   LongDelay.QuadPart = -100000LL;
-}
-
-VOID
-PspReferenceCidObject(PCID_OBJECT Object)
-{
-  InterlockedIncrement(&Object->ref);
-}
-
-VOID
-PspDereferenceCidObject(PCID_OBJECT Object)
-{
-  if(InterlockedDecrement(&Object->ref) == 0)
-  {
-    ExFreePool(Object);
-  }
+  PspCidTable = ExCreateHandleTable(NULL);
+  ASSERT(PspCidTable);
 }
 
 NTSTATUS
 PsCreateCidHandle(PVOID Object, POBJECT_TYPE ObjectType, PHANDLE Handle)
 {
-  KIRQL oldIrql;
-  PCID_OBJECT cido = ExAllocatePoolWithTag(NonPagedPool,
-                                           sizeof(CID_OBJECT),
-                                           TAG_CIDOBJECT);
-  if(cido != NULL)
+  HANDLE_TABLE_ENTRY NewEntry;
+  LONG ExHandle;
+  
+  PAGED_CODE();
+  
+  NewEntry.u1.Object = Object;
+  if(ObjectType == PsThreadType)
+    NewEntry.u2.GrantedAccess = CID_FLAG_THREAD;
+  else if(ObjectType == PsProcessType)
+    NewEntry.u2.GrantedAccess = CID_FLAG_PROCESS;
+  else
   {
-    cido->ref = 1;
-    ExInitializeFastMutex(&cido->Lock);
-    cido->Obj.Object = Object;
-
-    KeAcquireSpinLock(&CidLock, &oldIrql);
-    cido->Handle = (HANDLE)((ULONG_PTR)(++CidCounter) << 2);
-    InsertTailList(&CidHead, &cido->Entry);
-    KeReleaseSpinLock(&CidLock, oldIrql);
-
-    *Handle = cido->Handle;
+    DPRINT1("Can't create CID handles for %wZ objects\n", &ObjectType->TypeName);
+    KEBUGCHECK(0);
+  }
+  
+  ExHandle = ExCreateHandle(PspCidTable,
+                            &NewEntry);
+  if(ExHandle != EX_INVALID_HANDLE)
+  {
+    *Handle = EX_HANDLE_TO_HANDLE(ExHandle);
     return STATUS_SUCCESS;
   }
   
-  return STATUS_INSUFFICIENT_RESOURCES;
+  return STATUS_UNSUCCESSFUL;
 }
 
 NTSTATUS
 PsDeleteCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
 {
-  PCID_OBJECT cido, Found = NULL;
-  PLIST_ENTRY Current;
-  KIRQL oldIrql;
+  PHANDLE_TABLE_ENTRY Entry;
+  LONG ExHandle = HANDLE_TO_EX_HANDLE(CidHandle);
   
-  if(CidHandle == NULL)
-  {
-    return STATUS_INVALID_PARAMETER;
-  }
-  
-  KeAcquireSpinLock(&CidLock, &oldIrql);
-  Current = CidHead.Flink;
-  while(Current != &CidHead)
+  PAGED_CODE();
+
+  Entry = ExMapHandleToPointer(PspCidTable,
+                               ExHandle);
+  if(Entry != NULL)
   {
-    cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
-    if(cido->Handle == CidHandle)
+    if((ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)) ||
+       (ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)))
     {
-      RemoveEntryList(&cido->Entry);
-      cido->Handle = NULL;
-      Found = cido;
-      break;
+      ExDestroyHandleByEntry(PspCidTable,
+                             Entry,
+                             ExHandle);
+      return STATUS_SUCCESS;
+    }
+    else
+    {
+      ExUnlockHandleTableEntry(PspCidTable,
+                               Entry);
+      return STATUS_OBJECT_TYPE_MISMATCH;
     }
-    Current = Current->Flink;
-  }
-  KeReleaseSpinLock(&CidLock, oldIrql);
-
-  if(Found != NULL)
-  {
-    PspDereferenceCidObject(Found);
-    return STATUS_SUCCESS;
   }
 
-  return STATUS_UNSUCCESSFUL;
+  return STATUS_INVALID_HANDLE;
 }
 
-PCID_OBJECT
-PsLockCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType)
+PHANDLE_TABLE_ENTRY
+PsLookupCidHandle(HANDLE CidHandle, POBJECT_TYPE ObjectType, PVOID *Object)
 {
-  PCID_OBJECT cido, Found = NULL;
-  PLIST_ENTRY Current;
-  KIRQL oldIrql;
+  PHANDLE_TABLE_ENTRY Entry;
   
-  if(CidHandle == NULL)
-  {
-    return NULL;
-  }
+  PAGED_CODE();
+
+  KeEnterCriticalRegion();
   
-  KeAcquireSpinLock(&CidLock, &oldIrql);
-  Current = CidHead.Flink;
-  while(Current != &CidHead)
+  Entry = ExMapHandleToPointer(PspCidTable,
+                               HANDLE_TO_EX_HANDLE(CidHandle));
+  if(Entry != NULL)
   {
-    cido = CONTAINING_RECORD(Current, CID_OBJECT, Entry);
-    if(cido->Handle == CidHandle)
+    if((ObjectType == PsProcessType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_PROCESS)) ||
+       (ObjectType == PsThreadType && ((Entry->u2.GrantedAccess & CID_FLAGS_MASK) == CID_FLAG_THREAD)))
+    {
+      *Object = Entry->u1.Object;
+      return Entry;
+    }
+    else
     {
-      Found = cido;
-      PspReferenceCidObject(Found);
-      break;
+      DPRINT1("CID Obj type mismatch handle 0x%x %wZ vs 0x%x\n", CidHandle,
+              &ObjectType->TypeName, Entry->u2.GrantedAccess);
+      ExUnlockHandleTableEntry(PspCidTable,
+                               Entry);
+      KEBUGCHECK(0);
     }
-    Current = Current->Flink;
   }
-  KeReleaseSpinLock(&CidLock, oldIrql);
   
-  if(Found != NULL)
-  {
-    ExAcquireFastMutex(&Found->Lock);
-  }
-
-  return Found;
+  KeLeaveCriticalRegion();
+  
+  return NULL;
 }
 
 VOID
-PsUnlockCidObject(PCID_OBJECT CidObject)
+PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry)
 {
-  ExReleaseFastMutex(&CidObject->Lock);
-  PspDereferenceCidObject(CidObject);
+  PAGED_CODE();
+
+  ExUnlockHandleTableEntry(PspCidTable,
+                           CidEntry);
+  KeLeaveCriticalRegion();
 }
 
 /* EOF */
index 8c85ab4..fca97ad 100644 (file)
@@ -376,7 +376,10 @@ PiDeleteThread(PVOID ObjectBody)
   Process = Thread->ThreadsProcess;
   Thread->ThreadsProcess = NULL;
 
-  PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+  if(Thread->Cid.UniqueThread != NULL)
+  {
+    PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+  }
   
   if(Thread->Tcb.Win32Thread != NULL)
   {
@@ -395,34 +398,29 @@ PiDeleteThread(PVOID ObjectBody)
 NTSTATUS
 PsInitializeThread(PEPROCESS Process,
                   PETHREAD* ThreadPtr,
-                  PHANDLE ThreadHandle,
-                  ACCESS_MASK  DesiredAccess,
-                  POBJECT_ATTRIBUTES ThreadAttributes,
+                  POBJECT_ATTRIBUTES ObjectAttributes,
                   BOOLEAN First)
 {
    PETHREAD Thread;
    NTSTATUS Status;
+   KPROCESSOR_MODE PreviousMode;
    KIRQL oldIrql;
-
+   
+   PAGED_CODE();
+   
+   PreviousMode = ExGetPreviousMode();
+   
    if (Process == NULL)
      {
        Process = PsInitialSystemProcess;
      }
-
-   /*
-    * Reference process
-    */
-   ObReferenceObjectByPointer(Process,
-                              PROCESS_CREATE_THREAD,
-                              PsProcessType,
-                              KernelMode);
    
    /*
     * Create and initialize thread
     */
-   Status = ObCreateObject(UserMode,
+   Status = ObCreateObject(PreviousMode,
                           PsThreadType,
-                          ThreadAttributes,
+                          ObjectAttributes,
                           KernelMode,
                           NULL,
                           sizeof(ETHREAD),
@@ -431,20 +429,20 @@ PsInitializeThread(PEPROCESS Process,
                           (PVOID*)&Thread);
    if (!NT_SUCCESS(Status))
      {
-        ObDereferenceObject (Process);
         return(Status);
      }
 
-  /* create a client id handle */
-  Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread);
-  if (!NT_SUCCESS(Status))
-    {
-      ObDereferenceObject (Thread);
-      ObDereferenceObject (Process);
-      return Status;
-    }
-  Thread->ThreadsProcess = Process;
-  Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+   /*
+    * Reference process
+    */
+   ObReferenceObjectByPointer(Process,
+                              PROCESS_CREATE_THREAD,
+                              PsProcessType,
+                              KernelMode);
+
+   Thread->ThreadsProcess = Process;
+   Thread->Cid.UniqueThread = NULL;
+   Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
 
    DPRINT("Thread = %x\n",Thread);
 
@@ -477,14 +475,8 @@ PsInitializeThread(PEPROCESS Process,
    KeReleaseDispatcherDatabaseLock(oldIrql);
 
    *ThreadPtr = Thread;
-   
-   Status = ObInsertObject((PVOID)Thread,
-                          NULL,
-                          DesiredAccess,
-                          0,
-                          NULL,
-                          ThreadHandle);
-   return(Status);
+
+   return STATUS_SUCCESS;
 }
 
 
@@ -737,21 +729,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
 
   Status = PsInitializeThread(Process,
                              &Thread,
-                             &hThread,
-                             DesiredAccess,
                              ObjectAttributes,
                              FALSE);
 
   ObDereferenceObject(Process);
-
+  
   if (!NT_SUCCESS(Status))
     {
       return(Status);
     }
+  
+  /* create a client id handle */
+  Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(Thread);
+      return Status;
+    }
 
   Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
   if (!NT_SUCCESS(Status))
     {
+      PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+      ObDereferenceObject(Thread);
       return(Status);
     }
 
@@ -761,6 +761,8 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
                       InitialTeb);
   if (!NT_SUCCESS(Status))
     {
+      PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
+      ObDereferenceObject(Thread);
       return(Status);
     }
   Thread->Tcb.Teb = TebBase;
@@ -808,20 +810,29 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
   PsUnblockThread(Thread, NULL, 0);
   KeReleaseDispatcherDatabaseLock(oldIrql);
 
-  _SEH_TRY
+  Status = ObInsertObject((PVOID)Thread,
+                         NULL,
+                         DesiredAccess,
+                         0,
+                         NULL,
+                         &hThread);
+  if(NT_SUCCESS(Status))
   {
-    if(ClientId != NULL)
+    _SEH_TRY
     {
-      *ClientId = Thread->Cid;
+      if(ClientId != NULL)
+      {
+        *ClientId = Thread->Cid;
+      }
+      *ThreadHandle = hThread;
     }
-    *ThreadHandle = hThread;
-  }
-  _SEH_HANDLE
-  {
-    Status = _SEH_GetExceptionCode();
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
   }
-  _SEH_END;
-
+  
   return Status;
 }
 
@@ -865,20 +876,28 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
    
    Status = PsInitializeThread(NULL,
                               &Thread,
-                              ThreadHandle,
-                              DesiredAccess,
                               ObjectAttributes,
                               FALSE);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
+
+   Status = PsCreateCidHandle(Thread,
+                              PsThreadType,
+                              &Thread->Cid.UniqueThread);
+   if(!NT_SUCCESS(Status))
+   {
+     ObDereferenceObject(Thread);
+     return Status;
+   }
    
    Thread->StartAddress = StartRoutine;
    Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext);
    if (!NT_SUCCESS(Status))
      {
-       return(Status);
+        ObDereferenceObject(Thread);
+        return(Status);
      }
 
    if (ClientId != NULL)
@@ -890,7 +909,17 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
    PsUnblockThread(Thread, NULL, 0);
    KeReleaseDispatcherDatabaseLock(oldIrql);
    
-   return(STATUS_SUCCESS);
+   Status = ObInsertObject((PVOID)Thread,
+                          NULL,
+                          DesiredAccess,
+                          0,
+                          NULL,
+                          ThreadHandle);
+   
+   /* don't dereference the thread, the initial reference serves as the keep-alive
+      reference which will be removed by the thread reaper */
+   
+   return Status;
 }
 
 
index 21bcd16..f77aa45 100644 (file)
@@ -52,34 +52,33 @@ PsInitIdleThread(VOID)
 {
    NTSTATUS Status;
    PETHREAD IdleThread;
-   HANDLE IdleThreadHandle;
+   KIRQL oldIrql;
    
-   Status = PsCreateSystemThread(&IdleThreadHandle,
-                       THREAD_ALL_ACCESS,
-                       NULL,
-                       NULL,
-                       NULL,
-                       PsIdleThreadMain,
-                       NULL);
-   if(!NT_SUCCESS(Status)) 
-   {
-       DPRINT("Couldn't create Idle System Thread!");
-       KEBUGCHECK(0);
-       return;
-   }   
-   Status = ObReferenceObjectByHandle(IdleThreadHandle,
-                                     THREAD_ALL_ACCESS,
-                                     PsThreadType,
-                                     KernelMode,
-                                     (PVOID*)&IdleThread,
-                                     NULL);
-   if(!NT_SUCCESS(Status)) 
-   {
-       DPRINT("Couldn't get pointer to Idle System Thread!");
-       KEBUGCHECK(0);
-       return;
-   }
-   NtClose(IdleThreadHandle);
+   Status = PsInitializeThread(NULL,
+                              &IdleThread,
+                              NULL,
+                              FALSE);
+   if (!NT_SUCCESS(Status))
+     {
+        DPRINT1("Couldn't create idle system thread! Status: 0x%x\n", Status);
+        KEBUGCHECK(0);
+        return;
+     }
+   
+   IdleThread->StartAddress = PsIdleThreadMain;
+   Status = KiArchInitThread(&IdleThread->Tcb, PsIdleThreadMain, NULL);
+   if (!NT_SUCCESS(Status))
+     {
+        DPRINT1("Couldn't initialize system idle thread! Status: 0x%x\n", Status);
+        ObDereferenceObject(IdleThread);
+        KEBUGCHECK(0);
+        return;
+     }
+
+   oldIrql = KeAcquireDispatcherDatabaseLock ();
+   PsUnblockThread(IdleThread, NULL, 0);
+   KeReleaseDispatcherDatabaseLock(oldIrql);
+
    KeGetCurrentPrcb()->IdleThread = &IdleThread->Tcb;
    KeSetPriorityThread(&IdleThread->Tcb, LOW_PRIORITY);
    KeSetAffinityThread(&IdleThread->Tcb, 1 << 0);
index 7a3cde7..73c8d44 100644 (file)
@@ -218,6 +218,7 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
     
     PspRunCreateProcessNotifyRoutines(CurrentProcess, FALSE);
     PsTerminateWin32Process(CurrentProcess);
+    
     PiTerminateProcess(CurrentProcess, ExitStatus);
    }
 
@@ -315,19 +316,26 @@ PiTerminateProcess(PEPROCESS Process,
           ObGetObjectHandleCount(Process));
    
    ObReferenceObject(Process);
-   if (InterlockedExchangeUL(&Process->Pcb.State, 
-                            PROCESS_STATE_TERMINATED) == 
-       PROCESS_STATE_TERMINATED)
+   if (Process->Pcb.State == PROCESS_STATE_TERMINATED)
      {
         ObDereferenceObject(Process);
        return(STATUS_SUCCESS);
      }
+
+   Process->Pcb.State = PROCESS_STATE_TERMINATED;
+   
    CurrentProcess = PsGetCurrentProcess();
    if (Process != CurrentProcess)
    {
       KeAttachProcess(&Process->Pcb);
    }
-   ObCloseAllHandles(Process);
+
+   ObDeleteHandleTable(Process);
+   if(Process->UniqueProcessId != NULL)
+   {
+     PsDeleteCidHandle(Process->UniqueProcessId, PsProcessType);
+   }
+
    if (Process != CurrentProcess)
    {
       KeDetachProcess();
index 6dd3f89..eee2f3a 100644 (file)
@@ -412,15 +412,6 @@ PsInitProcessManagment(VOID)
 
    strcpy(PsInitialSystemProcess->ImageFileName, "System");
    
-   Status = PsCreateCidHandle(PsInitialSystemProcess,
-                              PsProcessType,
-                              &PsInitialSystemProcess->UniqueProcessId);
-   if(!NT_SUCCESS(Status))
-   {
-     DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
-     return;
-   }
-   
    PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
    
    InsertHeadList(&PsActiveProcessHead,
@@ -456,7 +447,6 @@ PiDeleteProcessWorker(PVOID pContext)
   KDB_DELETEPROCESS_HOOK(Process);
 
   ObDereferenceObject(Process->Token);
-  ObDeleteHandleTable(Process);
 
   if (CurrentProcess != Process)
     {
@@ -1458,7 +1448,7 @@ NtQueryInformationProcess(IN  HANDLE ProcessHandle,
 
       case ProcessHandleCount:
       {
-       ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
+       ULONG HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
          
        _SEH_TRY
        {
@@ -2636,30 +2626,25 @@ NTSTATUS STDCALL
 PsLookupProcessByProcessId(IN HANDLE ProcessId,
                           OUT PEPROCESS *Process)
 {
-  PLIST_ENTRY current_entry;
-  PEPROCESS current;
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PEPROCESS FoundProcess;
 
-  ExAcquireFastMutex(&PspActiveProcessMutex);
+  PAGED_CODE();
 
-  current_entry = PsActiveProcessHead.Flink;
-  while (current_entry != &PsActiveProcessHead)
-    {
-      current = CONTAINING_RECORD(current_entry,
-                                 EPROCESS,
-                                 ProcessListEntry);
-      if (current->UniqueProcessId == ProcessId)
-       {
-         *Process = current;
-          ObReferenceObject(current);
-         ExReleaseFastMutex(&PspActiveProcessMutex);
-         return(STATUS_SUCCESS);
-       }
-      current_entry = current_entry->Flink;
-    }
+  ASSERT(Process);
 
-  ExReleaseFastMutex(&PspActiveProcessMutex);
+  CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
+  if(CidEntry != NULL)
+  {
+    ObReferenceObject(FoundProcess);
+
+    PsUnlockCidHandle(CidEntry);
+
+    *Process = FoundProcess;
+    return STATUS_SUCCESS;
+  }
 
-  return(STATUS_INVALID_PARAMETER);
+  return STATUS_INVALID_PARAMETER;
 }
 
 VOID
index 051d6ae..73338ec 100644 (file)
@@ -28,11 +28,23 @@ VOID PiShutdownProcessManager(VOID)
 VOID INIT_FUNCTION
 PiInitProcessManager(VOID)
 {
+   NTSTATUS Status;
+   
    PsInitClientIDManagment();
    PsInitJobManagment();
    PsInitProcessManagment();
    PsInitThreadManagment();
    PsInitIdleThread();
+   
+   Status = PsCreateCidHandle(PsInitialSystemProcess,
+                              PsProcessType,
+                              &PsInitialSystemProcess->UniqueProcessId);
+   if(!NT_SUCCESS(Status))
+   {
+     DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
+     KEBUGCHECK(0);
+   }
+   
    PsInitialiseSuspendImplementation();
    PsInitialiseW32Call();
 }
index b9e033f..2d85c83 100644 (file)
@@ -222,7 +222,7 @@ PsIsThreadTerminating(IN PETHREAD Thread)
 
 /*
  * @unimplemented
- */             
+ */
 BOOLEAN
 STDCALL
 PsIsSystemThread(
@@ -235,7 +235,7 @@ PsIsSystemThread(
 
 /*
  * @implemented
- */                       
+ */
 BOOLEAN
 STDCALL
 PsIsThreadImpersonating(
@@ -251,7 +251,7 @@ KiRequestReschedule(CCHAR Processor)
    PKPCR Pcr;
 
    Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
-   Pcr->PrcbData.QuantumEnd = TRUE;
+   Pcr->Prcb->QuantumEnd = TRUE;
    KiIpiSendRequest(1 << Processor, IPI_REQUEST_DPC);
 }
 
@@ -641,7 +641,7 @@ PsEnumThreadsByProcess(PEPROCESS Process)
 
 /*
  * @unimplemented
- */                       
+ */
 NTSTATUS
 STDCALL
 PsRemoveCreateThreadNotifyRoutine (
@@ -704,13 +704,10 @@ VOID INIT_FUNCTION
 PsPrepareForApplicationProcessorInit(ULONG Id)
 {
   PETHREAD IdleThread;
-  HANDLE IdleThreadHandle;
-  PKPCR Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE);
+  PKPRCB Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + Id * PAGE_SIZE))->Prcb;
 
   PsInitializeThread(NULL,
                     &IdleThread,
-                    &IdleThreadHandle,
-                    THREAD_ALL_ACCESS,
                     NULL,
                     FALSE);
   IdleThread->Tcb.State = THREAD_STATE_RUNNING;
@@ -719,12 +716,11 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
   IdleThread->Tcb.UserAffinity = 1 << Id;
   IdleThread->Tcb.Priority = LOW_PRIORITY;
   IdleThread->Tcb.BasePriority = LOW_PRIORITY;
-  Pcr->PrcbData.IdleThread = &IdleThread->Tcb;
-  Pcr->PrcbData.CurrentThread = &IdleThread->Tcb;
+  Prcb->IdleThread = &IdleThread->Tcb;
+  Prcb->CurrentThread = &IdleThread->Tcb;
 
   Ki386InitialStackArray[Id] = (PVOID)IdleThread->Tcb.StackLimit;
 
-  NtClose(IdleThreadHandle);
   DPRINT("IdleThread for Processor %d has PID %d\n",
           Id, IdleThread->Cid.UniqueThread);
 }
@@ -738,7 +734,6 @@ PsInitThreadManagment(VOID)
    HANDLE PiReaperThreadHandle;
    PETHREAD FirstThread;
    ULONG i;
-   HANDLE FirstThreadHandle;
    NTSTATUS Status;
 
    for (i=0; i < MAXIMUM_PRIORITY; i++)
@@ -771,14 +766,12 @@ PsInitThreadManagment(VOID)
 
    ObpCreateTypeObject(PsThreadType);
 
-   PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle,
-                     THREAD_ALL_ACCESS,NULL, TRUE);
+   PsInitializeThread(NULL, &FirstThread, NULL, TRUE);
    FirstThread->Tcb.State = THREAD_STATE_RUNNING;
    FirstThread->Tcb.FreezeCount = 0;
    FirstThread->Tcb.UserAffinity = (1 << 0);   /* Set the affinity of the first thread to the boot processor */
    FirstThread->Tcb.Affinity = (1 << 0);
    KeGetCurrentPrcb()->CurrentThread = (PVOID)FirstThread;
-   NtClose(FirstThreadHandle);
 
    DPRINT("FirstThread %x\n",FirstThread);
 
@@ -895,8 +888,8 @@ KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority)
                     {
                       for (i = 0; i < KeNumberProcessors; i++)
                       {
-                         Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-                         if (Pcr->PrcbData.CurrentThread == Thread)
+                         Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
+                         if (Pcr->Prcb->CurrentThread == Thread)
                          {
                            KeReleaseDispatcherDatabaseLockFromDpcLevel();
                             KiRequestReschedule(i);
@@ -959,7 +952,7 @@ KeSetAffinityThread(PKTHREAD        Thread,
             for (i = 0; i < KeNumberProcessors; i++)
             {
                Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-               if (Pcr->PrcbData.CurrentThread == Thread)
+               if (Pcr->Prcb->CurrentThread == Thread)
                {
                   if (!(Affinity & ProcessorMask))
                   {
@@ -988,63 +981,95 @@ KeSetAffinityThread(PKTHREAD      Thread,
 NTSTATUS STDCALL
 NtOpenThread(OUT PHANDLE ThreadHandle,
             IN ACCESS_MASK DesiredAccess,
-            IN POBJECT_ATTRIBUTES ObjectAttributes,
-            IN PCLIENT_ID ClientId)
+            IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
+            IN PCLIENT_ID ClientId  OPTIONAL)
 {
-   NTSTATUS Status = STATUS_INVALID_PARAMETER;
-   
+   KPROCESSOR_MODE PreviousMode;
+   CLIENT_ID SafeClientId;
+   HANDLE hThread;
+   NTSTATUS Status = STATUS_SUCCESS;
+
    PAGED_CODE();
 
-   if((NULL != ThreadHandle)&&(NULL != ObjectAttributes))
+   PreviousMode = ExGetPreviousMode();
+
+   if(PreviousMode != KernelMode)
    {
-      PETHREAD EThread = NULL;
+     _SEH_TRY
+     {
+       ProbeForWrite(ThreadHandle,
+                     sizeof(HANDLE),
+                     sizeof(ULONG));
+       if(ClientId != NULL)
+       {
+         ProbeForRead(ClientId,
+                      sizeof(CLIENT_ID),
+                      sizeof(ULONG));
+         SafeClientId = *ClientId;
+         ClientId = &SafeClientId;
+       }
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
 
-      if((ClientId)
-       && (ClientId->UniqueThread))
-      {
-         // It is an error to specify both
-        // ObjectAttributes.ObjectName
-         // and ClientId.
-         if((ObjectAttributes)
-          && (ObjectAttributes->ObjectName)
-          && (0 < ObjectAttributes->ObjectName->Length))
-        {
-            return(STATUS_INVALID_PARAMETER_MIX);
-        }
-        // Parameters mix OK
-         Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
-                     & EThread);
-      }
-      else if((ObjectAttributes)
-            && (ObjectAttributes->ObjectName)
-            && (0 < ObjectAttributes->ObjectName->Length))
-      {
-         // Three Ob attributes are forbidden
-         if(!(ObjectAttributes->Attributes &
-            (OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENIF)))
-        {
-            Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
-                        ObjectAttributes->Attributes,
-                        NULL,
-                        DesiredAccess,
-                        PsThreadType,
-                        UserMode,
-                        NULL,
-                        (PVOID*) & EThread);
-        }
-      }
-      // EThread may be OK...
-      if(STATUS_SUCCESS == Status)
-      {
-         Status = ObCreateHandle(PsGetCurrentProcess(),
-                     EThread,
-                     DesiredAccess,
-                     FALSE,
-                     ThreadHandle);
-         ObDereferenceObject(EThread);
-      }
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   if(!((ObjectAttributes == NULL) ^ (ClientId == NULL)))
+   {
+     DPRINT("NtOpenThread should be called with either ObjectAttributes or ClientId!\n");
+     return STATUS_INVALID_PARAMETER;
+   }
+
+   if(ClientId != NULL)
+   {
+     PETHREAD Thread;
+
+     Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
+                                       &Thread);
+     if(NT_SUCCESS(Status))
+     {
+       Status = ObInsertObject(Thread,
+                               NULL,
+                               DesiredAccess,
+                               0,
+                               NULL,
+                               &hThread);
+
+       ObDereferenceObject(Thread);
+     }
+   }
+   else
+   {
+     Status = ObOpenObjectByName(ObjectAttributes,
+                                 PsThreadType,
+                                 NULL,
+                                 PreviousMode,
+                                 DesiredAccess,
+                                 NULL,
+                                 &hThread);
+   }
+
+   if(NT_SUCCESS(Status))
+   {
+     _SEH_TRY
+     {
+       *ThreadHandle = hThread;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
    }
-   return(Status);
+
+   return Status;
 }
 
 NTSTATUS STDCALL
@@ -1074,22 +1099,26 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
                           OUT PEPROCESS *Process OPTIONAL,
                           OUT PETHREAD *Thread)
 {
-  PCID_OBJECT CidObject;
+  PHANDLE_TABLE_ENTRY CidEntry;
   PETHREAD FoundThread;
 
-  CidObject = PsLockCidHandle((HANDLE)Cid->UniqueThread, PsThreadType);
-  if(CidObject != NULL)
+  PAGED_CODE();
+
+  ASSERT(Thread);
+  ASSERT(Cid);
+
+  CidEntry = PsLookupCidHandle(Cid->UniqueThread, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
   {
-    FoundThread = CidObject->Obj.Thread;
     ObReferenceObject(FoundThread);
-    
+
+    PsUnlockCidHandle(CidEntry);
+
     if(Process != NULL)
     {
       *Process = FoundThread->ThreadsProcess;
-      ObReferenceObject(FoundThread->ThreadsProcess);
     }
-
-    PsUnlockCidObject(CidObject);
+    *Thread = FoundThread;
     return STATUS_SUCCESS;
   }
 
@@ -1104,15 +1133,21 @@ NTSTATUS STDCALL
 PsLookupThreadByThreadId(IN HANDLE ThreadId,
                         OUT PETHREAD *Thread)
 {
-  PCID_OBJECT CidObject;
-  
-  CidObject = PsLockCidHandle(ThreadId, PsThreadType);
-  if(CidObject != NULL)
+  PHANDLE_TABLE_ENTRY CidEntry;
+  PETHREAD FoundThread;
+
+  PAGED_CODE();
+
+  ASSERT(Thread);
+
+  CidEntry = PsLookupCidHandle(ThreadId, PsThreadType, (PVOID*)&FoundThread);
+  if(CidEntry != NULL)
   {
-    *Thread = CidObject->Obj.Thread;
-    ObReferenceObject(*Thread);
-    
-    PsUnlockCidObject(CidObject);
+    ObReferenceObject(FoundThread);
+
+    PsUnlockCidHandle(CidEntry);
+
+    *Thread = FoundThread;
     return STATUS_SUCCESS;
   }
 
index 7b382bb..28b04eb 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-#define HEADER_TO_BODY(ObjectHeader) \
+#define USER_HEADER_TO_BODY(ObjectHeader) \
   ((PVOID)(((PUSER_OBJECT_HEADER)ObjectHeader) + 1))
 
-#define BODY_TO_HEADER(ObjectBody) \
+#define USER_BODY_TO_HEADER(ObjectBody) \
   ((PUSER_OBJECT_HEADER)(((PUSER_OBJECT_HEADER)ObjectBody) - 1))
 
 /* FUNCTIONS *****************************************************************/
@@ -125,7 +125,7 @@ ObmpCloseAllHandles(PUSER_HANDLE_TABLE HandleTable)
          
          if (ObjectBody != NULL)
            {
-             PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+             PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
              
              ObmReferenceObjectByPointer(ObjectBody, otUnknown);
              ObjectHeader->HandleCount--;
@@ -191,7 +191,7 @@ ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable,
   
   if (ObjectBody != NULL)
     {
-      ObjectHeader = BODY_TO_HEADER(ObjectBody);
+      ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
       ObjectHeader->HandleCount--;
       ObmReferenceObjectByPointer(ObjectBody, otUnknown);
       Entry->ObjectBody = NULL;
@@ -219,7 +219,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
   if (Handle != NULL)
     {
       Status = ObmCreateHandle(HandleTable,
-                              HEADER_TO_BODY(ObjectHeader),
+                              USER_HEADER_TO_BODY(ObjectHeader),
                               Handle);
     }
 
@@ -230,7 +230,7 @@ ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable,
 ULONG FASTCALL
 ObmGetReferenceCount(PVOID ObjectBody)
 {
-  PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
 
   return ObjectHeader->RefCount;
 }
@@ -238,7 +238,7 @@ ObmGetReferenceCount(PVOID ObjectBody)
 ULONG FASTCALL
 ObmGetHandleCount(PVOID ObjectBody)
 {
-  PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  PUSER_OBJECT_HEADER ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
 
   return ObjectHeader->HandleCount;
 }
@@ -260,7 +260,7 @@ ObmReferenceObject(PVOID ObjectBody)
       return;
     }
   
-  ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
   
   ObjectHeader->RefCount++;
 
@@ -284,7 +284,7 @@ ObmDereferenceObject(PVOID ObjectBody)
       return;
     }
   
-  ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
   
   ObjectHeader->RefCount--;
   ObmpPerformRetentionChecks(ObjectHeader);
@@ -303,7 +303,7 @@ ObmReferenceObjectByPointer(PVOID ObjectBody,
 {
   PUSER_OBJECT_HEADER ObjectHeader;
   
-  ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
   
   if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
     {
@@ -331,7 +331,7 @@ ObmCreateObject(PUSER_HANDLE_TABLE HandleTable,
       return NULL;
     }
   
-  ObjectBody = HEADER_TO_BODY(ObjectHeader);
+  ObjectBody = USER_HEADER_TO_BODY(ObjectHeader);
   
   RtlZeroMemory(ObjectBody, ObjectSize);
   
@@ -369,7 +369,7 @@ ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable,
 
   if (ObjectBody != NULL) 
     {
-      BODY_TO_HEADER(ObjectBody)->HandleCount++;
+      USER_BODY_TO_HEADER(ObjectBody)->HandleCount++;
     }
   
   ObmpLockHandleTable(HandleTable);
@@ -456,7 +456,7 @@ ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable,
   
   ObmpUnlockHandleTable(HandleTable);
   
-  ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  ObjectHeader = USER_BODY_TO_HEADER(ObjectBody);
   
   if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType))
     {