- Silence TCPIP.
[reactos.git] / reactos / ntoskrnl / ob / handle.c
index 0e40ebf..153ff10 100644 (file)
@@ -1,4 +1,22 @@
-/* $Id: handle.c,v 1.23 2000/07/04 08:52:46 dwelch Exp $
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
  *
  * COPYRIGHT:          See COPYING in the top level directory
  * PROJECT:            ReactOS kernel
 
 /* INCLUDES ****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/ob.h>
-#include <string.h>
-#include <internal/string.h>
-#include <internal/ps.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
-/* TYPES *******************************************************************/
+#define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
 
-#define HANDLE_BLOCK_ENTRIES ((PAGESIZE-sizeof(LIST_ENTRY))/sizeof(HANDLE_REP))
+/* GLOBALS *****************************************************************/
 
-/*
- * PURPOSE: Defines a page's worth of handles
- */
-typedef struct
-{
-   LIST_ENTRY entry;
-   HANDLE_REP handles[HANDLE_BLOCK_ENTRIES];
-} HANDLE_BLOCK, *PHANDLE_BLOCK;
+PHANDLE_TABLE ObpKernelHandleTable = NULL;
+
+/* TEMPORARY HACK. DO NOT REMOVE -- Alex */
+NTSTATUS
+STDCALL
+ExpDesktopCreate(PVOID ObjectBody,
+                 PVOID Parent,
+                 PWSTR RemainingPath,
+                 POBJECT_CREATE_INFORMATION ObjectCreateInformation);
 
 /* FUNCTIONS ***************************************************************/
 
+static VOID
+ObpDecrementHandleCount(PVOID ObjectBody)
+{
+  POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
+  LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
+  DPRINT("Header: %x\n", ObjectHeader);
+  DPRINT("NewHandleCount: %x\n", NewHandleCount);
+  DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader));
 
-static PHANDLE_REP ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, HANDLE h)
-/*
- * 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
- */
+  if ((ObjectHeader->Type != NULL) &&
+      (ObjectHeader->Type->TypeInfo.CloseProcedure != NULL))
+  {
+    /* the handle count should be decremented but we pass the previous value
+       to the callback */
+    ObjectHeader->Type->TypeInfo.CloseProcedure(ObjectBody, NewHandleCount + 1);
+  }
+
+  if(NewHandleCount == 0)
+  {
+    if(HEADER_TO_OBJECT_NAME(ObjectHeader) && 
+       HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory != NULL &&
+       !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
+    {
+      /* delete the object from the namespace when the last handle got closed.
+         Only do this if it's actually been inserted into the namespace and
+         if it's not a permanent object. */
+      ObpRemoveEntryDirectory(ObjectHeader);
+    }
+
+    /* remove the keep-alive reference */
+    ObDereferenceObject(ObjectBody);
+  }
+}
+
+
+NTSTATUS
+NTAPI
+ObpQueryHandleAttributes(HANDLE Handle,
+                        POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+{
+  PHANDLE_TABLE HandleTable;
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+
+  PAGED_CODE();
+
+  DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+
+  if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+  {
+    HandleTable = ObpKernelHandleTable;
+    Handle = ObKernelHandleToHandle(Handle);
+  }
+  else
+  {
+    HandleTable = PsGetCurrentProcess()->ObjectTable;
+  }
+
+  KeEnterCriticalRegion();
+
+  HandleTableEntry = ExMapHandleToPointer(HandleTable,
+                                          Handle);
+  if (HandleTableEntry == NULL)
+    {
+      KeLeaveCriticalRegion();
+      return STATUS_INVALID_HANDLE;
+    }
+
+  HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+  HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
+
+  ExUnlockHandleTableEntry(HandleTable,
+                           HandleTableEntry);
+
+  KeLeaveCriticalRegion();
+
+  return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+NTAPI
+ObpSetHandleAttributes(HANDLE Handle,
+                      POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
+{
+  PHANDLE_TABLE HandleTable;
+  PHANDLE_TABLE_ENTRY HandleTableEntry;
+
+  PAGED_CODE();
+
+  DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
+
+  if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+  {
+    HandleTable = ObpKernelHandleTable;
+    Handle = ObKernelHandleToHandle(Handle);
+  }
+  else
+  {
+    HandleTable = PsGetCurrentProcess()->ObjectTable;
+  }
+
+  KeEnterCriticalRegion();
+
+  HandleTableEntry = ExMapHandleToPointer(HandleTable,
+                                          Handle);
+  if (HandleTableEntry == NULL)
+    {
+      KeLeaveCriticalRegion();
+      return STATUS_INVALID_HANDLE;
+    }
+
+  if (HandleInfo->Inherit)
+    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+  else
+    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+
+  if (HandleInfo->ProtectFromClose)
+    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+  else
+    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+
+  /* FIXME: Do we need to set anything in the object header??? */
+
+  ExUnlockHandleTableEntry(HandleTable,
+                           HandleTableEntry);
+
+  KeLeaveCriticalRegion();
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+ObpDeleteHandle(PHANDLE_TABLE HandleTable,
+               HANDLE Handle)
 {
-   PLIST_ENTRY current;
-   unsigned int handle = (((unsigned int)h) - 1) >> 2;
-   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++)
+   PHANDLE_TABLE_ENTRY HandleEntry;
+   PVOID Body;
+   POBJECT_HEADER ObjectHeader;
+
+   PAGED_CODE();
+
+   DPRINT("ObpDeleteHandle(Handle %x)\n",Handle);
+
+   KeEnterCriticalRegion();
+
+   HandleEntry = ExMapHandleToPointer(HandleTable,
+                                      Handle);
+   if(HandleEntry != NULL)
+   {
+     if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
      {
-       current = current->Flink;
-       if (current == (&(HandleTable->ListHead)))
-         {
-            return(NULL);
-         }
+       ExUnlockHandleTableEntry(HandleTable,
+                                HandleEntry);
+
+       KeLeaveCriticalRegion();
+
+       return STATUS_HANDLE_NOT_CLOSABLE;
      }
-   
-   blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
-   return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
+
+     ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+     Body = &ObjectHeader->Body;
+
+     ObpDecrementHandleCount(Body);
+
+     /* destroy and unlock the handle entry */
+     ExDestroyHandleByEntry(HandleTable,
+                            HandleEntry,
+                            Handle);
+
+     KeLeaveCriticalRegion();
+
+     return STATUS_SUCCESS;
+   }
+   KeLeaveCriticalRegion();
+   return STATUS_INVALID_HANDLE;
 }
 
 
-NTSTATUS STDCALL NtDuplicateObject (IN HANDLE          SourceProcessHandle,
-                                   IN  PHANDLE         SourceHandle,
-                                   IN  HANDLE          TargetProcessHandle,
-                                   OUT PHANDLE         TargetHandle,
-                                   IN  ACCESS_MASK     DesiredAccess,
-                                   IN  BOOLEAN         InheritHandle,
-                                   ULONG               Options)
+NTSTATUS
+NTAPI
+ObDuplicateObject(PEPROCESS SourceProcess,
+                 PEPROCESS TargetProcess,
+                 HANDLE SourceHandle,
+                 PHANDLE TargetHandle,
+                 ACCESS_MASK DesiredAccess,
+                 BOOLEAN InheritHandle,
+                 ULONG Options)
+{
+  PHANDLE_TABLE SourceHandleTable;
+  PHANDLE_TABLE_ENTRY SourceHandleEntry;
+  HANDLE_TABLE_ENTRY NewHandleEntry;
+  PVOID ObjectBody;
+  POBJECT_HEADER ObjectHeader;
+  ULONG NewHandleCount;
+  HANDLE NewTargetHandle;
+
+  PAGED_CODE();
+
+  if(ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
+  {
+    SourceHandleTable = ObpKernelHandleTable;
+    SourceHandle = ObKernelHandleToHandle(SourceHandle);
+  }
+  else
+  {
+    SourceHandleTable = SourceProcess->ObjectTable;
+  }
+
+  KeEnterCriticalRegion();
+
+  SourceHandleEntry = ExMapHandleToPointer(SourceHandleTable,
+                                           SourceHandle);
+  if (SourceHandleEntry == NULL)
+    {
+      KeLeaveCriticalRegion();
+      return STATUS_INVALID_HANDLE;
+    }
+
+  ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
+  ObjectBody = &ObjectHeader->Body;
+
+  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);
+  if (Options & DUPLICATE_SAME_ACCESS)
+  {
+    NewHandleEntry.u2.GrantedAccess = SourceHandleEntry->u2.GrantedAccess;
+  }
+  else
+  {
+    if (DesiredAccess & GENERIC_ANY)
+    {
+      RtlMapGenericMask(&DesiredAccess,
+                        &ObjectHeader->Type->TypeInfo.GenericMapping);
+    }
+    NewHandleEntry.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);
+
+  /* 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. */
+  NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount);
+  ASSERT(NewHandleCount >= 2);
+
+  ExUnlockHandleTableEntry(SourceHandleTable,
+                           SourceHandleEntry);
+
+  KeLeaveCriticalRegion();
+
+  /* attempt to create the new handle */
+  NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+                                   &NewHandleEntry);
+  if (NewTargetHandle != NULL)
+  {
+    if (Options & DUPLICATE_CLOSE_SOURCE)
+    {
+      ObpDeleteHandle(SourceHandleTable,
+                      SourceHandle);
+    }
+
+    ObDereferenceObject(ObjectBody);
+
+    *TargetHandle = NewTargetHandle;
+
+    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)
+    {
+      ObDereferenceObject(ObjectBody);
+    }
+
+    ObDereferenceObject(ObjectBody);
+    return STATUS_UNSUCCESSFUL;
+  }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtDuplicateObject (IN  HANDLE          SourceProcessHandle,
+                  IN   HANDLE          SourceHandle,
+                  IN   HANDLE          TargetProcessHandle,
+                  OUT  PHANDLE         TargetHandle  OPTIONAL,
+                  IN   ACCESS_MASK     DesiredAccess,
+                  IN   ULONG           InheritHandle,
+                  IN   ULONG           Options)
 /*
  * FUNCTION: Copies a handle from one process space to another
  * ARGUMENTS:
- *         SourceProcessHandle = The source process owning the handle. The 
+ *         SourceProcessHandle = The source process owning the handle. The
  *                               source process should have opened
- *                              the SourceHandle with PROCESS_DUP_HANDLE 
+ *                              the SourceHandle with PROCESS_DUP_HANDLE
  *                               access.
  *        SourceHandle = The handle to the object.
- *        TargetProcessHandle = The destination process owning the handle 
- *        TargetHandle (OUT) = Caller should supply storage for the 
- *                              duplicated handle. 
+ *        TargetProcessHandle = The destination process owning the handle
+ *        TargetHandle (OUT) = Caller should supply storage for the
+ *                              duplicated handle.
  *        DesiredAccess = The desired access to the handle.
  *        InheritHandle = Indicates wheter the new handle will be inheritable
  *                         or not.
- *        Options = Specifies special actions upon duplicating the handle. 
- *                   Can be one of the values DUPLICATE_CLOSE_SOURCE | 
- *                   DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies 
- *                   that the source handle should be closed after duplicating. 
- *                   DUPLICATE_SAME_ACCESS specifies to ignore the 
- *                   DesiredAccess paramter and just grant the same access to 
+ *        Options = Specifies special actions upon duplicating the handle.
+ *                   Can be one of the values DUPLICATE_CLOSE_SOURCE |
+ *                   DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
+ *                   that the source handle should be closed after duplicating.
+ *                   DUPLICATE_SAME_ACCESS specifies to ignore the
+ *                   DesiredAccess paramter and just grant the same access to
  *                   the new handle.
  * RETURNS: Status
  * REMARKS: This function maps to the win32 DuplicateHandle.
@@ -105,158 +379,173 @@ NTSTATUS STDCALL NtDuplicateObject (IN  HANDLE          SourceProcessHandle,
 {
    PEPROCESS SourceProcess;
    PEPROCESS TargetProcess;
-   PHANDLE_REP SourceHandleRep;
-   KIRQL oldIrql;
-   PVOID ObjectBody;
-   
-   ASSERT_IRQL(PASSIVE_LEVEL);
-   
-   ObReferenceObjectByHandle(SourceProcessHandle,
-                            PROCESS_DUP_HANDLE,
-                            NULL,
-                            UserMode,
-                            (PVOID*)&SourceProcess,
-                            NULL);
-   ObReferenceObjectByHandle(TargetProcessHandle,
-                            PROCESS_DUP_HANDLE,
-                            NULL,
-                            UserMode,
-                            (PVOID*)&TargetProcess,
-                            NULL);
-   
-   KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
-   SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
-                                         *SourceHandle);
-   if (SourceHandleRep == NULL)
+   HANDLE hTarget;
+   KPROCESSOR_MODE PreviousMode;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PAGED_CODE();
+
+   PreviousMode = ExGetPreviousMode();
+
+   if(TargetHandle != NULL && PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWriteHandle(TargetHandle);
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+
+     if(!NT_SUCCESS(Status))
      {
-       KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-       ObDereferenceObject(SourceProcess);
-       ObDereferenceObject(TargetProcess);
-       return(STATUS_INVALID_HANDLE);
+       return Status;
      }
-   ObjectBody = SourceHandleRep->ObjectBody;
-   ObReferenceObjectByPointer(ObjectBody,
-                             GENERIC_ALL,
-                             NULL,
-                             UserMode);
-   
-   if (Options & DUPLICATE_SAME_ACCESS)
+   }
+
+   Status = ObReferenceObjectByHandle(SourceProcessHandle,
+                                     PROCESS_DUP_HANDLE,
+                                     NULL,
+                                     PreviousMode,
+                                     (PVOID*)&SourceProcess,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+
+   Status = ObReferenceObjectByHandle(TargetProcessHandle,
+                                     PROCESS_DUP_HANDLE,
+                                     NULL,
+                                     PreviousMode,
+                                     (PVOID*)&TargetProcess,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       ObDereferenceObject(SourceProcess);
+       return(Status);
+     }
+
+   /* Check for magic handle first */
+   if (SourceHandle == NtCurrentThread() ||
+       SourceHandle == NtCurrentProcess())
      {
-       DesiredAccess = SourceHandleRep->GrantedAccess;
+       PVOID ObjectBody;
+       POBJECT_TYPE ObjectType;
+
+       ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType;
+
+       Status = ObReferenceObjectByHandle(SourceHandle,
+                                          0,
+                                          ObjectType,
+                                          PreviousMode,
+                                          &ObjectBody,
+                                          NULL);
+       if(NT_SUCCESS(Status))
+       {
+         if (Options & DUPLICATE_SAME_ACCESS)
+         {
+           /* grant all access rights */
+           DesiredAccess = ((ObjectType == PsThreadType) ? THREAD_ALL_ACCESS : PROCESS_ALL_ACCESS);
+         }
+         else
+         {
+           if (DesiredAccess & GENERIC_ANY)
+           {
+             RtlMapGenericMask(&DesiredAccess,
+                               &ObjectType->TypeInfo.GenericMapping);
+           }
+         }
+         Status = ObpCreateHandle(TargetProcess,
+                                  ObjectBody,
+                                  DesiredAccess,
+                                  InheritHandle,
+                                  &hTarget);
+
+         ObDereferenceObject(ObjectBody);
+
+         if (Options & DUPLICATE_CLOSE_SOURCE)
+         {
+           ObpDeleteHandle(SourceProcess->ObjectTable,
+                           SourceHandle);
+         }
+       }
      }
-   
-   KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
-   
-   ObCreateHandle(TargetProcess,
-                 ObjectBody,
-                 DesiredAccess,
-                 InheritHandle,
-                 TargetHandle);
-   
-   if (Options & DUPLICATE_CLOSE_SOURCE)
+   else
      {
-       ZwClose(*SourceHandle);
+       Status = ObDuplicateObject(SourceProcess,
+                                  TargetProcess,
+                                  SourceHandle,
+                                  &hTarget,
+                                  DesiredAccess,
+                                  InheritHandle,
+                                  Options);
      }
-   
+
    ObDereferenceObject(TargetProcess);
    ObDereferenceObject(SourceProcess);
-   ObDereferenceObject(ObjectBody);
-   
-   return(STATUS_SUCCESS);
-}
 
-VOID ObCloseAllHandles(PEPROCESS Process)
-{
-   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)
+   if(NT_SUCCESS(Status) && TargetHandle != NULL)
+   {
+     _SEH_TRY
      {
-       current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
-       
-       for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
-         {
-            ObjectBody = current->handles[i].ObjectBody;                    
-            
-            if (ObjectBody != NULL)
-              {
-                 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
-                 
-                 if (Header->ObjectType == PsProcessType ||
-                     Header->ObjectType == PsThreadType)
-                   {
-                      DPRINT("Deleting handle to %x\n", ObjectBody);
-                   }
-                 
-                 ObReferenceObjectByPointer(ObjectBody,
-                                            GENERIC_ALL,
-                                            NULL,
-                                            UserMode);
-                 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;
+       *TargetHandle = hTarget;
      }
-   KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-   DPRINT("ObCloseAllHandles() finished\n");
-   DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+
+   return Status;
 }
 
-VOID ObDeleteHandleTable(PEPROCESS Process)
-/*
- * FUNCTION: Deletes the handle table associated with a process
- */
+static VOID STDCALL
+SweepHandleCallback(PHANDLE_TABLE HandleTable,
+                    PVOID Object,
+                    ULONG GrantedAccess,
+                    PVOID Context)
 {
-   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);
-     }
+  POBJECT_HEADER ObjectHeader;
+  PVOID ObjectBody;
+
+  PAGED_CODE();
+
+  ObjectHeader = EX_OBJ_TO_HDR(Object);
+  ObjectBody = &ObjectHeader->Body;
+
+  ObpDecrementHandleCount(ObjectBody);
 }
 
+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)
+    {
+      ObReferenceObject(&ObjectHeader->Body);
+    }
+  }
+
+  return Ret;
+}
 
-VOID ObCreateHandleTable(PEPROCESS Parent,
+VOID
+NTAPI
+ObCreateHandleTable(PEPROCESS Parent,
                         BOOLEAN Inherit,
                         PEPROCESS Process)
 /*
@@ -267,301 +556,324 @@ VOID ObCreateHandleTable(PEPROCESS Parent,
  *       Process = Process whose handle table is to be created
  */
 {
-   PHANDLE_TABLE ParentHandleTable;
-   KIRQL oldIrql;
-   PLIST_ENTRY parent_current;
-   ULONG i;
-   
+   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;
-       
-       KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
-       
-       parent_current = ParentHandleTable->ListHead.Flink;
-       
-       while (parent_current != &ParentHandleTable->ListHead)
-         {
-            HANDLE_BLOCK* current_block = CONTAINING_RECORD(parent_current,
-                                                            HANDLE_BLOCK,
-                                                            entry);
-            HANDLE NewHandle;
-            
-            for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
-              {
-                 if (Inherit || current_block->handles[i].Inherit)
-                   {
-                      ObCreateHandle(Process,
-                                     current_block->handles[i].ObjectBody,
-                                     current_block->handles[i].GrantedAccess,
-                                     current_block->handles[i].Inherit,
-                                     &NewHandle);
-                   }
-                 else
-                   {
-                      ObCreateHandle(Process,
-                                     NULL,
-                                     0,
-                                     current_block->handles[i].Inherit,
-                                     &NewHandle);
-                   }
-              }
-            
-            parent_current = parent_current->Flink;
-         }
-       
-       KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
-     }
+   if(Parent != NULL)
+   {
+     Process->ObjectTable = ExDupHandleTable(Process,
+                                             DuplicateHandleCallback,
+                                             NULL,
+                                             Parent->ObjectTable);
+   }
+   else
+   {
+     Process->ObjectTable = ExCreateHandleTable(Process);
+   }
 }
 
 
-PVOID ObDeleteHandle(PEPROCESS Process, HANDLE Handle)
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process)
 {
-   PHANDLE_REP Rep;
-   PVOID ObjectBody;
-   KIRQL oldIrql;
-   PHANDLE_TABLE HandleTable;
-   POBJECT_HEADER Header;
-   
-   DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
-   
-   HandleTable = &Process->HandleTable;
-   
-   KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
-   
-   Rep = ObpGetObjectByHandle(HandleTable, Handle);
-   if (Rep == NULL)
-     {
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);     
-       return(NULL);
-     }
-   
-   ObjectBody = Rep->ObjectBody;
-   DPRINT("ObjectBody %x\n", ObjectBody);
-   if (ObjectBody != NULL)
-     {     
-       Header = BODY_TO_HEADER(ObjectBody);
-       BODY_TO_HEADER(ObjectBody)->HandleCount--;
-       ObReferenceObjectByPointer(ObjectBody,
-                                  GENERIC_ALL,
-                                  NULL,
-                                  UserMode);
-       Rep->ObjectBody = NULL;
-     
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
-   
-       if ((Header->ObjectType != NULL) &&
-           (Header->ObjectType->Close != NULL))
-         {
-            Header->ObjectType->Close(ObjectBody, Header->HandleCount);
-         }
-     }
-   else
-     {
-       KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);     
-     }
-   
-   DPRINT("Finished ObDeleteHandle()\n");
-   return(ObjectBody);
+   PAGED_CODE();
+
+   /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
+   ExSweepHandleTable(Process->ObjectTable,
+                      SweepHandleCallback,
+                      Process);
+   ExDestroyHandleTable(Process->ObjectTable);
+   Process->ObjectTable = NULL;
 }
 
 
-NTSTATUS ObCreateHandle(PEPROCESS Process,
-                       PVOID ObjectBody,
-                       ACCESS_MASK GrantedAccess,
-                       BOOLEAN Inherit,
-                       PHANDLE HandleReturn)
+NTSTATUS
+NTAPI
+ObpCreateHandle(PEPROCESS Process,
+              PVOID ObjectBody,
+              ACCESS_MASK GrantedAccess,
+              BOOLEAN Inherit,
+              PHANDLE HandleReturn)
 /*
  * FUNCTION: Add a handle referencing an object
  * ARGUMENTS:
  *         obj = Object body that the handle should refer to
  * RETURNS: The created handle
- * NOTE: THe handle is valid only in the context of the current process
+ * NOTE: The handle is valid only in the context of the current process
  */
 {
-   LIST_ENTRY* current;
-   unsigned int handle=1;
-   unsigned int i;
-   HANDLE_BLOCK* new_blk = NULL;
-   PHANDLE_TABLE HandleTable;
-   KIRQL oldlvl;
-   
-   DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
-   
-   if (ObjectBody != NULL)
+   HANDLE_TABLE_ENTRY NewEntry;
+   POBJECT_HEADER ObjectHeader;
+   HANDLE Handle;
+
+   PAGED_CODE();
+
+   DPRINT("ObpCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
+
+   ASSERT(Process);
+   ASSERT(ObjectBody);
+
+   ObjectHeader = BODY_TO_HEADER(ObjectBody);
+
+   ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
+
+   if (GrantedAccess & MAXIMUM_ALLOWED)
      {
-       BODY_TO_HEADER(ObjectBody)->HandleCount++;
+        GrantedAccess &= ~MAXIMUM_ALLOWED;
+        GrantedAccess |= GENERIC_ALL;
      }
-   
-   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))
+
+   if (GrantedAccess & GENERIC_ANY)
      {
-       HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
+       RtlMapGenericMask(&GrantedAccess,
+                        &ObjectHeader->Type->TypeInfo.GenericMapping);
+     }
 
-        DPRINT("Current %x\n",current);
+   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;
 
-       for (i=0;i<HANDLE_BLOCK_ENTRIES;i++)
-         {
-             DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
-            if (blk->handles[i].ObjectBody==NULL)
-              {
-                 blk->handles[i].ObjectBody = ObjectBody;
-                 blk->handles[i].GrantedAccess = GrantedAccess;
-                 blk->handles[i].Inherit = Inherit;
-                 KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
-                 *HandleReturn = (HANDLE)((handle + i) << 2);
-                 return(STATUS_SUCCESS);
-              }
-         }
-       
-       handle = handle + HANDLE_BLOCK_ENTRIES;
-       current = current->Flink;
+   Handle = ExCreateHandle(Process->ObjectTable,
+                           &NewEntry);
+   DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, Handle, Process->ObjectTable);
+   if(Handle != NULL)
+   {
+     if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
+     {
+      ObReferenceObjectByPointer(ObjectBody,
+                                0,
+                                NULL,
+                                UserMode);
      }
-   
-   /*
-    * Add a new handle block to the end of the list
-    */
-   new_blk = (HANDLE_BLOCK *)ExAllocatePool(NonPagedPool,sizeof(HANDLE_BLOCK));
-   memset(new_blk,0,sizeof(HANDLE_BLOCK));
-   InsertTailList(&(Process->HandleTable.ListHead),
-                 &new_blk->entry);
-   KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
-   new_blk->handles[0].ObjectBody = ObjectBody;
-   new_blk->handles[0].GrantedAccess = GrantedAccess;
-   new_blk->handles[0].Inherit = Inherit;
-   *HandleReturn = (HANDLE)(handle << 2);
-   return(STATUS_SUCCESS);   
+
+     *HandleReturn = Handle;
+
+     return STATUS_SUCCESS;
+   }
+
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+ObQueryObjectAuditingByHandle(IN HANDLE Handle,
+                             OUT PBOOLEAN GenerateOnClose)
+{
+  PHANDLE_TABLE_ENTRY HandleEntry;
+  PEPROCESS Process;
+
+  PAGED_CODE();
+
+  DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
+
+  Process = PsGetCurrentProcess();
+
+  KeEnterCriticalRegion();
+
+  HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                     Handle);
+  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;
 }
 
 
-NTSTATUS STDCALL ObReferenceObjectByHandle(HANDLE Handle,
-                                          ACCESS_MASK DesiredAccess,
-                                          POBJECT_TYPE ObjectType,
-                                          KPROCESSOR_MODE AccessMode,
-                                          PVOID* Object,
-                                          POBJECT_HANDLE_INFORMATION 
-                                                  HandleInformationPtr)
 /*
- * FUNCTION: Increments the reference count for an object and returns a 
+ * FUNCTION: Increments the reference count for an object and returns a
  * pointer to its body
  * ARGUMENTS:
  *         Handle = Handle for the object
  *         DesiredAccess = Desired access to the object
  *         ObjectType
- *         AccessMode 
+ *         AccessMode
  *         Object (OUT) = Points to the object body on return
- *         HandleInformation (OUT) = Contains information about the handle 
+ *         HandleInformation (OUT) = Contains information about the handle
  *                                   on return
  * RETURNS: Status
+ *
+ * @implemented
  */
+NTSTATUS STDCALL
+ObReferenceObjectByHandle(HANDLE Handle,
+                         ACCESS_MASK DesiredAccess,
+                         POBJECT_TYPE ObjectType,
+                         KPROCESSOR_MODE AccessMode,
+                         PVOID* Object,
+                         POBJECT_HANDLE_INFORMATION HandleInformation)
 {
-   PHANDLE_REP HandleRep;
+   PHANDLE_TABLE_ENTRY HandleEntry;
    POBJECT_HEADER ObjectHeader;
-   KIRQL oldIrql;
+   PHANDLE_TABLE HandleTable;
    PVOID ObjectBody;
    ACCESS_MASK GrantedAccess;
-   
-   ASSERT_IRQL(PASSIVE_LEVEL);
-   
+   ULONG Attributes;
+
+   PAGED_CODE();
+
    DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
           "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
           ObjectType,AccessMode,Object);
 
-   
+   if (Handle == NULL)
+     {
+       return STATUS_INVALID_HANDLE;
+     }
    /*
     * Handle special handle names
     */
-   if (Handle == NtCurrentProcess() && 
+   if (Handle == NtCurrentProcess() &&
        (ObjectType == PsProcessType || ObjectType == NULL))
      {
-       DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
-       
-       ObReferenceObjectByPointer(PsGetCurrentProcess(),
-                                  PROCESS_ALL_ACCESS,
-                                  PsProcessType,
-                                  UserMode);
-       *Object = PsGetCurrentProcess();
-       DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
-       return(STATUS_SUCCESS);
+        PEPROCESS CurrentProcess = PsGetCurrentProcess();
+
+        ObReferenceObject(CurrentProcess);
+
+       if (HandleInformation != NULL)
+         {
+           HandleInformation->HandleAttributes = 0;
+           HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
+         }
+
+       *Object = CurrentProcess;
+       DPRINT("Referencing current process %x\n", CurrentProcess);
+       return STATUS_SUCCESS;
      }
    else if (Handle == NtCurrentProcess())
      {
        CHECKPOINT;
        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
-   if (Handle == NtCurrentThread() && 
+
+   if (Handle == NtCurrentThread() &&
        (ObjectType == PsThreadType || ObjectType == NULL))
      {
-       ObReferenceObjectByPointer(PsGetCurrentThread(),
-                                  THREAD_ALL_ACCESS,
-                                  PsThreadType,
-                                  UserMode);
-       *Object = PsGetCurrentThread();
+        PETHREAD CurrentThread = PsGetCurrentThread();
+
+        ObReferenceObject(CurrentThread);
+
+       if (HandleInformation != NULL)
+         {
+           HandleInformation->HandleAttributes = 0;
+           HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
+         }
+
+       *Object = CurrentThread;
        CHECKPOINT;
-       return(STATUS_SUCCESS);
+       return STATUS_SUCCESS;
      }
    else if (Handle == NtCurrentThread())
      {
        CHECKPOINT;
        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
-   
-   KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                    &oldIrql);
-   HandleRep = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
-                                   Handle);
-   if (HandleRep == NULL || HandleRep->ObjectBody == NULL)
+
+   /* desire as much access rights as possible */
+   if (DesiredAccess & MAXIMUM_ALLOWED)
      {
-       KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                         oldIrql);
-       return(STATUS_INVALID_HANDLE);
+        DesiredAccess &= ~MAXIMUM_ALLOWED;
+        DesiredAccess |= GENERIC_ALL;
      }
-   ObjectBody = HandleRep->ObjectBody;
-   ObReferenceObjectByPointer(ObjectBody,
-                             GENERIC_ALL,
-                             NULL,
-                             UserMode);
-   GrantedAccess = HandleRep->GrantedAccess;
-   KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
-                    oldIrql);
-   
-   ObjectHeader = BODY_TO_HEADER(ObjectBody);
 
-   if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
+   if(ObIsKernelHandle(Handle, AccessMode))
+   {
+      HandleTable = ObpKernelHandleTable;
+      Handle = ObKernelHandleToHandle(Handle);
+   }
+   else
+   {
+      HandleTable = PsGetCurrentProcess()->ObjectTable;
+   }
+
+   KeEnterCriticalRegion();
+
+   HandleEntry = ExMapHandleToPointer(HandleTable,
+                                     Handle);
+   if (HandleEntry == NULL)
      {
-       CHECKPOINT;
-       return(STATUS_OBJECT_TYPE_MISMATCH);
-     }   
-   
-   if (ObjectHeader->ObjectType == PsProcessType)
+        KeLeaveCriticalRegion();
+        DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
+        return(STATUS_INVALID_HANDLE);
+     }
+
+   ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+   ObjectBody = &ObjectHeader->Body;
+
+   DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, HandleTable);
+
+   if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
      {
-       DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
+        DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
+
+        ExUnlockHandleTableEntry(HandleTable,
+                                 HandleEntry);
+
+        KeLeaveCriticalRegion();
+
+        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
-   
-   if (!(GrantedAccess & DesiredAccess) &&
-       !((~GrantedAccess) & DesiredAccess))
+
+   /* map the generic access masks if the caller asks for generic access */
+   if (DesiredAccess & GENERIC_ANY)
      {
-       CHECKPOINT;
-       return(STATUS_ACCESS_DENIED);
+        RtlMapGenericMask(&DesiredAccess,
+                          &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
      }
-   
+
+   GrantedAccess = HandleEntry->u2.GrantedAccess;
+
+   /* Unless running as KernelMode, deny access if caller desires more access
+      rights than the handle can grant */
+   if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
+     {
+        ExUnlockHandleTableEntry(HandleTable,
+                                 HandleEntry);
+
+        KeLeaveCriticalRegion();
+
+        DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
+
+        return(STATUS_ACCESS_DENIED);
+     }
+
+   ObReferenceObject(ObjectBody);
+
+   Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
+                                                EX_HANDLE_ENTRY_INHERITABLE |
+                                                EX_HANDLE_ENTRY_AUDITONCLOSE);
+
+   ExUnlockHandleTableEntry(HandleTable,
+                            HandleEntry);
+
+   KeLeaveCriticalRegion();
+
+   if (HandleInformation != NULL)
+     {
+       HandleInformation->HandleAttributes = Attributes;
+       HandleInformation->GrantedAccess = GrantedAccess;
+     }
+
    *Object = ObjectBody;
-   
-   CHECKPOINT;
+
    return(STATUS_SUCCESS);
 }
 
@@ -569,39 +881,358 @@ NTSTATUS STDCALL ObReferenceObjectByHandle(HANDLE Handle,
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     NtClose
- *     
+ *
  * DESCRIPTION
  *     Closes a handle reference to an object.
- *     
+ *
  * ARGUMENTS
  *     Handle
  *             Handle to close.
- *             
+ *
  * RETURN VALUE
  *     Status.
+ *
+ * @implemented
  */
-NTSTATUS STDCALL NtClose(HANDLE Handle)
+NTSTATUS STDCALL
+NtClose(IN HANDLE Handle)
 {
-   PVOID               ObjectBody;
-   POBJECT_HEADER      Header;
-   
-   assert_irql(PASSIVE_LEVEL);
-   
-   DPRINT("NtClose(Handle %x)\n",Handle);
-   
-   ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle);
-   if (ObjectBody == NULL)
+   PHANDLE_TABLE HandleTable;
+   NTSTATUS Status;
+
+   PAGED_CODE();
+
+   if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+   {
+      HandleTable = ObpKernelHandleTable;
+      Handle = ObKernelHandleToHandle(Handle);
+   }
+   else
+   {
+      HandleTable = PsGetCurrentProcess()->ObjectTable;
+   }
+
+   Status = ObpDeleteHandle(HandleTable,
+                           Handle);
+   if (!NT_SUCCESS(Status))
      {
-       return(STATUS_HANDLES_CLOSED);
+        if((ExGetPreviousMode() != KernelMode) &&
+           (PsGetCurrentProcess()->ExceptionPort))
+        {
+           KeRaiseUserException(Status);
+        }
+       return Status;
      }
-   
-   Header = BODY_TO_HEADER(ObjectBody);
-   
-   DPRINT("Dereferencing %x\n", ObjectBody);
-   ObDereferenceObject(ObjectBody);
-   
+
    return(STATUS_SUCCESS);
 }
 
 
+/*
+ * @implemented
+ */
+NTSTATUS 
+STDCALL
+ObInsertObject(IN PVOID Object,
+               IN PACCESS_STATE PassedAccessState OPTIONAL,
+               IN ACCESS_MASK DesiredAccess,
+               IN ULONG AdditionalReferences,
+               OUT PVOID* ReferencedObject OPTIONAL,
+               OUT PHANDLE Handle)
+{
+    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+    POBJECT_HEADER Header;
+    POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+    PVOID FoundObject = NULL;
+    POBJECT_HEADER FoundHeader = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+    UNICODE_STRING RemainingPath;
+    BOOLEAN ObjectAttached = FALSE; 
+    PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
+    SECURITY_SUBJECT_CONTEXT SubjectContext;
+
+    PAGED_CODE();
+    
+    /* Get the Header and Create Info */
+    DPRINT("ObInsertObject: %x\n", Object);
+    Header = BODY_TO_HEADER(Object);
+    ObjectCreateInfo = Header->ObjectCreateInfo;
+    ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
+    
+    /* First try to find the Object */
+    if (ObjectNameInfo && ObjectNameInfo->Name.Buffer)
+    {
+        DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo->Name);
+        Status = ObFindObject(ObjectCreateInfo,
+                              &ObjectNameInfo->Name,
+                              &FoundObject,
+                              &RemainingPath,
+                              NULL);
+        DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status);
+            return Status;
+        }
+        
+        if (FoundObject)
+        {
+            DPRINT("Getting header: %x\n", FoundObject);
+            FoundHeader = BODY_TO_HEADER(FoundObject);
+        }
+        
+        if (FoundHeader && RemainingPath.Buffer == NULL)
+        {
+            DPRINT("Object exists\n");
+            ObDereferenceObject(FoundObject);
+            return STATUS_OBJECT_NAME_COLLISION;
+        }
+    }
+    else
+    {
+        DPRINT("No name, empty remaining path\n");
+        RtlInitUnicodeString(&RemainingPath, NULL);
+    }
+
+    if (FoundHeader && FoundHeader->Type == ObDirectoryType &&
+        RemainingPath.Buffer)
+    {
+        /* The name was changed so let's update it */
+        /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
+        PVOID NewName;
+        PWSTR BufferPos = RemainingPath.Buffer;
+        ULONG Delta = 0;
+        
+        ObpAddEntryDirectory(FoundObject, Header, NULL);
+        ObjectAttached = TRUE;
+        
+        ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
+        
+        if (BufferPos[0] == L'\\')
+        {
+            BufferPos++;
+            Delta = sizeof(WCHAR);
+        }
+        NewName = ExAllocatePool(NonPagedPool, RemainingPath.MaximumLength - Delta);
+        RtlMoveMemory(NewName, BufferPos, RemainingPath.MaximumLength - Delta);
+        if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
+        ObjectNameInfo->Name.Buffer = NewName;
+        ObjectNameInfo->Name.Length = RemainingPath.Length - Delta;
+        ObjectNameInfo->Name.MaximumLength = RemainingPath.MaximumLength - Delta;
+        DPRINT("Name: %S\n", ObjectNameInfo->Name.Buffer);
+    }
+
+    if ((Header->Type == IoFileObjectType) ||
+        (Header->Type == ExDesktopObjectType) ||
+        (Header->Type->TypeInfo.OpenProcedure != NULL))
+    {    
+        DPRINT("About to call Open Routine\n");
+        if (Header->Type == IoFileObjectType)
+        {
+            /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
+            DPRINT("Calling IopCreateFile: %x\n", FoundObject);
+            Status = IopCreateFile(&Header->Body,
+                                   FoundObject,
+                                   RemainingPath.Buffer,            
+                                   ObjectCreateInfo);
+            DPRINT("Called IopCreateFile: %x\n", Status);
+                                   
+        }
+        else if (Header->Type == ExDesktopObjectType)
+        {
+            /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
+            DPRINT("Calling ExpDesktopCreate\n");
+            Status = ExpDesktopCreate(&Header->Body,
+                                      FoundObject,
+                                      RemainingPath.Buffer,            
+                                      ObjectCreateInfo);
+        }
+        else if (Header->Type->TypeInfo.OpenProcedure != NULL)
+        {
+            DPRINT("Calling %x\n", Header->Type->TypeInfo.OpenProcedure);
+            Status = Header->Type->TypeInfo.OpenProcedure(ObCreateHandle,
+                                                                &Header->Body,
+                                                                NULL,
+                                                                0,
+                                                                0);
+        }
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("Create Failed\n");
+            if (ObjectAttached == TRUE)
+            {
+                ObpRemoveEntryDirectory(Header);
+            }
+            if (FoundObject)
+            {
+                ObDereferenceObject(FoundObject);
+            }
+            RtlFreeUnicodeString(&RemainingPath);
+            return Status;
+        }
+    }
+
+    RtlFreeUnicodeString(&RemainingPath);
+  
+    DPRINT("Security Assignment in progress\n");  
+    SeCaptureSubjectContext(&SubjectContext);
+
+    /* Build the new security descriptor */
+    Status = SeAssignSecurity((FoundHeader != NULL) ? FoundHeader->SecurityDescriptor : NULL,
+                           (ObjectCreateInfo != NULL) ? ObjectCreateInfo->SecurityDescriptor : NULL,
+                           &NewSecurityDescriptor,
+                           (Header->Type == ObDirectoryType),
+                           &SubjectContext,
+                           &Header->Type->TypeInfo.GenericMapping,
+                           PagedPool);
+
+    if (NT_SUCCESS(Status))
+    {
+        DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor);
+
+        if (Header->Type->TypeInfo.SecurityProcedure != NULL)
+        {
+            /* Call the security method */
+            Status = Header->Type->TypeInfo.SecurityProcedure(&Header->Body,
+                                                                    AssignSecurityDescriptor,
+                                                                    0,
+                                                                    NewSecurityDescriptor,
+                                                                    NULL,
+                                                                    NULL,
+                                                                    NonPagedPool,
+                                                                    NULL);
+        }
+        else
+        {
+            /* Assign the security descriptor to the object header */
+            Status = ObpAddSecurityDescriptor(NewSecurityDescriptor,
+                                              &Header->SecurityDescriptor);
+            DPRINT("Object security descriptor %p\n", Header->SecurityDescriptor);
+        }
+
+        /* Release the new security descriptor */
+        SeDeassignSecurity(&NewSecurityDescriptor);
+    }
+
+    DPRINT("Security Complete\n");
+    SeReleaseSubjectContext(&SubjectContext);
+        
+    /* Create the Handle */
+    /* HACKHACK: Because of ROS's incorrect startup, this can be called
+     * without a valid Process until I finalize the startup patch,
+     * so don't create a handle if this is the case. We also don't create
+     * a handle if Handle is NULL when the Registry Code calls it, because
+     * the registry code totally bastardizes the Ob and needs to be fixed
+     */
+    DPRINT("Creating handle\n");
+    if (Handle != NULL)
+    {
+        Status = ObpCreateHandle(PsGetCurrentProcess(),
+                                 &Header->Body,
+                                 DesiredAccess,
+                                 ObjectCreateInfo->Attributes & OBJ_INHERIT,
+                                 Handle);
+        DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
+                 *Handle, Header->PointerCount, Header->HandleCount);
+    }
+    
+    /* We can delete the Create Info now */
+    Header->ObjectCreateInfo = NULL;
+    ObpReleaseCapturedAttributes(ObjectCreateInfo);
+    ExFreePool(ObjectCreateInfo);
+    
+    DPRINT("Status %x\n", Status);
+    return Status;
+}
+
+
+ULONG
+NTAPI
+ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
+{
+  return HandleTable->HandleCount;
+}
+
+/*
+ * FUNCTION: Searches the handle table of a specified process whether it contains a
+ *           valid handle to the Object we're looking for. If not, it'll create one.
+ *
+ * NOTES:
+ * The parameters of this function is basically a mixture of some of the parameters
+ * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
+ * about what this function does (by it's name) makes clear what parameters it requires.
+ * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
+ * required at all as it only has influence on the object security. This function doesn't
+ * want to get access to an object, it just looks for a valid handle and if it can't find
+ * one, it'll just create one. It wouldn't make sense to check for security again as the
+ * caller already has a pointer to the object.
+ *
+ * A test on an XP machine shows that this prototype appears to be correct.
+ *
+ * ARGUMENTS:
+ * Process = This parameter simply describes in which handle table we're looking
+ *           for a handle to the object.
+ * Object = The object pointer that we're looking for
+ * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
+ *              ObReferenceObjectByPointer() provides.
+ * HandleInformation = This one has to be the opposite meaning of the usage in
+ *                     ObReferenceObjectByHandle(). If we actually found a valid
+ *                     handle in the table, we need to check against the information
+ *                     provided so we make sure this handle has all access rights
+ *                     (and attributes?!) we need. If they don't match, we can't
+ *                     use this handle and keep looking because the caller is likely
+ *                     to depend on these access rights.
+ * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
+ *                find a suitable handle in the handle table, return this handle, if
+ *                not, we'll just create one using ObCreateHandle() with all access
+ *                rights the caller needs.
+ *
+ * RETURNS: Status
+ *
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+ObFindHandleForObject(IN PEPROCESS Process,
+                      IN PVOID Object,
+                      IN POBJECT_TYPE ObjectType,
+                      IN POBJECT_HANDLE_INFORMATION HandleInformation,
+                      OUT PHANDLE HandleReturn)
+{
+  DPRINT("ObFindHandleForObject is unimplemented!\n");
+  return STATUS_UNSUCCESSFUL;
+}
+
+VOID
+ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
+                               PEPROCESS Process,
+                               int Count)
+{
+      ULONG P;
+//      KIRQL oldIrql;
+
+//      pshi->HandleValue;
+
+/*
+   This will never work with ROS! M$, I guess uses 0 -> 65535.
+   Ros uses 0 -> 4294967295!
+ */
+
+      P = (ULONG) Process->UniqueProcessId;
+      pshi->UniqueProcessId = (USHORT) P;
+
+//      KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
+
+//      pshi->GrantedAccess;
+//      pshi->Object;
+//      pshi->TypeIndex;
+//      pshi->HandleAttributes;
+
+//      KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
+
+      return;
+}
+
+
+
 /* EOF */