- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[reactos.git] / reactos / ntoskrnl / ob / handle.c
index b8dd343..483d6f7 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
-#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)))
+#define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
 
-/* FUNCTIONS ***************************************************************/
+/* GLOBALS *****************************************************************/
 
+PHANDLE_TABLE ObpKernelHandleTable = NULL;
 
-VOID
+/* 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);
+  PROS_OBJECT_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));
 
-  if ((ObjectHeader->ObjectType != NULL) &&
-      (ObjectHeader->ObjectType->Close != NULL))
+  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->ObjectType->Close(ObjectBody, NewHandleCount + 1);
+    ObjectHeader->Type->TypeInfo.CloseProcedure(NULL, ObjectBody, 0, NewHandleCount + 1, 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((PROS_OBJECT_HEADER)ObjectHeader);
+    }
+
+    /* remove the keep-alive reference */
     ObDereferenceObject(ObjectBody);
   }
 }
 
 
 NTSTATUS
+NTAPI
 ObpQueryHandleAttributes(HANDLE Handle,
                         POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
-  PEPROCESS Process;
   PHANDLE_TABLE_ENTRY HandleTableEntry;
-  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
-  
+  PEPROCESS Process, CurrentProcess;
+  KAPC_STATE ApcState;
+  BOOLEAN AttachedToProcess = FALSE;
+  NTSTATUS Status = STATUS_SUCCESS;
+
   PAGED_CODE();
 
-  DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
+  DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle);
+  CurrentProcess = PsGetCurrentProcess();
 
   KeEnterCriticalRegion();
 
-  Process = PsGetCurrentProcess();
+  if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+  {
+    Process = PsInitialSystemProcess;
+    Handle = ObKernelHandleToHandle(Handle);
 
-  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
-                                          ExHandle);
-  if (HandleTableEntry == NULL)
+    if (Process != CurrentProcess)
     {
-      KeLeaveCriticalRegion();
-      return STATUS_INVALID_HANDLE;
+      KeStackAttachProcess(&Process->Pcb,
+                           &ApcState);
+      AttachedToProcess = TRUE;
     }
+  }
+  else
+  {
+    Process = CurrentProcess;
+  }
+
+  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                          Handle);
+  if (HandleTableEntry != NULL)
+  {
+    HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
+    HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
 
-  HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
-  HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
+    ExUnlockHandleTableEntry(Process->ObjectTable,
+                             HandleTableEntry);
+  }
+  else
+    Status = STATUS_INVALID_HANDLE;
 
-  ExUnlockHandleTableEntry(Process->ObjectTable,
-                           HandleTableEntry);
+  if (AttachedToProcess)
+  {
+    KeUnstackDetachProcess(&ApcState);
+  }
 
   KeLeaveCriticalRegion();
 
-  return STATUS_SUCCESS;
+  return Status;
 }
 
 
 NTSTATUS
+NTAPI
 ObpSetHandleAttributes(HANDLE Handle,
                       POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
 {
-  PEPROCESS Process;
   PHANDLE_TABLE_ENTRY HandleTableEntry;
-  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
-  
+  PEPROCESS Process, CurrentProcess;
+  KAPC_STATE ApcState;
+  BOOLEAN AttachedToProcess = FALSE;
+  NTSTATUS Status = STATUS_SUCCESS;
+
   PAGED_CODE();
 
-  DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
+  DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
+  CurrentProcess = PsGetCurrentProcess();
 
-  Process = PsGetCurrentProcess();
-  
   KeEnterCriticalRegion();
 
-  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
-                                          ExHandle);
-  if (HandleTableEntry == NULL)
+  if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+  {
+    Process = PsInitialSystemProcess;
+    Handle = ObKernelHandleToHandle(Handle);
+
+    if (Process != CurrentProcess)
     {
-      KeLeaveCriticalRegion();
-      return STATUS_INVALID_HANDLE;
+      KeStackAttachProcess(&Process->Pcb,
+                           &ApcState);
+      AttachedToProcess = TRUE;
     }
-
-  if (HandleInfo->Inherit)
-    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+  }
   else
-    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
+  {
+    Process = CurrentProcess;
+  }
 
-  if (HandleInfo->ProtectFromClose)
-    HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
-  else
-    HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+  HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                          Handle);
+  if (HandleTableEntry != NULL)
+  {
+    if (HandleInfo->Inherit)
+      HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
+    else
+      HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
 
-  /* FIXME: Do we need to set anything in the object header??? */
+    if (HandleInfo->ProtectFromClose)
+      HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
+    else
+      HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
 
-  ExUnlockHandleTableEntry(Process->ObjectTable,
-                           HandleTableEntry);
+    /* FIXME: Do we need to set anything in the object header??? */
+
+    ExUnlockHandleTableEntry(Process->ObjectTable,
+                             HandleTableEntry);
+  }
+  else
+    Status = STATUS_INVALID_HANDLE;
+
+  if (AttachedToProcess)
+  {
+    KeUnstackDetachProcess(&ApcState);
+  }
 
   KeLeaveCriticalRegion();
 
-  return STATUS_SUCCESS;
+  return Status;
+}
+
+
+static NTSTATUS
+ObpDeleteHandle(HANDLE Handle)
+{
+   PHANDLE_TABLE_ENTRY HandleEntry;
+   PVOID Body;
+   PROS_OBJECT_HEADER ObjectHeader;
+   PHANDLE_TABLE ObjectTable;
+
+   PAGED_CODE();
+
+   DPRINT("ObpDeleteHandle(Handle %p)\n",Handle);
+
+   ObjectTable = PsGetCurrentProcess()->ObjectTable;
+
+   KeEnterCriticalRegion();
+
+   HandleEntry = ExMapHandleToPointer(ObjectTable,
+                                      Handle);
+   if(HandleEntry != NULL)
+   {
+     if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
+     {
+       ExUnlockHandleTableEntry(ObjectTable,
+                                HandleEntry);
+
+       KeLeaveCriticalRegion();
+
+       return STATUS_HANDLE_NOT_CLOSABLE;
+     }
+
+     ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
+     Body = &ObjectHeader->Body;
+
+    /* destroy and unlock the handle entry */
+     ExDestroyHandleByEntry(ObjectTable,
+                            HandleEntry,
+                            Handle);
+
+     ObpDecrementHandleCount(Body);
+
+     KeLeaveCriticalRegion();
+
+     return STATUS_SUCCESS;
+   }
+   KeLeaveCriticalRegion();
+   return STATUS_INVALID_HANDLE;
 }
 
 
 NTSTATUS
+NTAPI
 ObDuplicateObject(PEPROCESS SourceProcess,
                  PEPROCESS TargetProcess,
                  HANDLE SourceHandle,
                  PHANDLE TargetHandle,
                  ACCESS_MASK DesiredAccess,
-                 BOOLEAN InheritHandle,
+                 ULONG HandleAttributes,
                  ULONG Options)
 {
   PHANDLE_TABLE_ENTRY SourceHandleEntry;
   HANDLE_TABLE_ENTRY NewHandleEntry;
+  BOOLEAN AttachedToProcess = FALSE;
   PVOID ObjectBody;
-  POBJECT_HEADER ObjectHeader;
-  LONG ExTargetHandle;
-  LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle);
-  
+  PROS_OBJECT_HEADER ObjectHeader;
+  ULONG NewHandleCount;
+  HANDLE NewTargetHandle;
+  PEPROCESS CurrentProcess;
+  KAPC_STATE ApcState;
+  NTSTATUS Status = STATUS_SUCCESS;
+
   PAGED_CODE();
-  
+
+  if(SourceProcess == NULL ||
+     ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
+  {
+    SourceProcess = PsInitialSystemProcess;
+    SourceHandle = ObKernelHandleToHandle(SourceHandle);
+  }
+
+  CurrentProcess = PsGetCurrentProcess();
+
   KeEnterCriticalRegion();
-  
+
+  if (SourceProcess != CurrentProcess)
+  {
+    KeStackAttachProcess(&SourceProcess->Pcb,
+                         &ApcState);
+    AttachedToProcess = TRUE;
+  }
   SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
-                                           ExSourceHandle);
+                                           SourceHandle);
   if (SourceHandleEntry == NULL)
     {
+      if (AttachedToProcess)
+      {
+        KeUnstackDetachProcess(&ApcState);
+      }
+
       KeLeaveCriticalRegion();
       return STATUS_INVALID_HANDLE;
     }
 
   ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
-  ObjectBody = HEADER_TO_BODY(ObjectHeader);
+  ObjectBody = &ObjectHeader->Body;
 
   NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object;
-  if(InheritHandle)
+  if(HandleAttributes & OBJ_INHERIT)
     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. */
-  InterlockedIncrement(&ObjectHeader->HandleCount);
-  ASSERT(ObjectHeader->HandleCount >= 2);
-  
+  NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount);
+  ASSERT(NewHandleCount >= 2);
+
   ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
                            SourceHandleEntry);
 
-  KeLeaveCriticalRegion();
+  if (AttachedToProcess)
+  {
+    KeUnstackDetachProcess(&ApcState);
+    AttachedToProcess = FALSE;
+  }
+
+  if (TargetProcess != CurrentProcess)
+  {
+    KeStackAttachProcess(&TargetProcess->Pcb,
+                         &ApcState);
+    AttachedToProcess = TRUE;
+  }
 
   /* attempt to create the new handle */
-  ExTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
-                                  &NewHandleEntry);
-  if (ExTargetHandle != EX_INVALID_HANDLE)
+  NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
+                                   &NewHandleEntry);
+  if (AttachedToProcess)
+  {
+    KeUnstackDetachProcess(&ApcState);
+    AttachedToProcess = FALSE;
+  }
+
+  if (NewTargetHandle != NULL)
   {
     if (Options & DUPLICATE_CLOSE_SOURCE)
     {
-      ObDeleteHandle(SourceProcess,
-                     SourceHandle);
+      if (SourceProcess != CurrentProcess)
+      {
+        KeStackAttachProcess(&SourceProcess->Pcb,
+                             &ApcState);
+        AttachedToProcess = TRUE;
+      }
+
+      /* delete the source handle */
+      ObpDeleteHandle(SourceHandle);
+
+      if (AttachedToProcess)
+      {
+        KeUnstackDetachProcess(&ApcState);
+      }
     }
-    
+
     ObDereferenceObject(ObjectBody);
 
-    *TargetHandle = EX_HANDLE_TO_HANDLE(ExTargetHandle);
-    
-    return STATUS_SUCCESS;
+    *TargetHandle = NewTargetHandle;
   }
   else
   {
@@ -227,43 +407,46 @@ ObDuplicateObject(PEPROCESS SourceProcess,
     {
       ObDereferenceObject(ObjectBody);
     }
-    
+
     ObDereferenceObject(ObjectBody);
-    return STATUS_UNSUCCESSFUL;
+    Status = STATUS_UNSUCCESSFUL;
   }
+
+  KeLeaveCriticalRegion();
+
+  return Status;
 }
 
 /*
  * @implemented
  */
-NTSTATUS STDCALL 
+NTSTATUS STDCALL
 NtDuplicateObject (IN  HANDLE          SourceProcessHandle,
                   IN   HANDLE          SourceHandle,
                   IN   HANDLE          TargetProcessHandle,
-                  OUT  PHANDLE         TargetHandle,
+                  OUT  PHANDLE         TargetHandle  OPTIONAL,
                   IN   ACCESS_MASK     DesiredAccess,
-                  IN   BOOLEAN         InheritHandle,
-                  ULONG                Options)
+                  IN   ULONG           HandleAttributes,
+                  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 
+ *        HandleAttributes = The desired handle attributes.
+ *        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.
@@ -271,34 +454,35 @@ NtDuplicateObject (IN     HANDLE          SourceProcessHandle,
 {
    PEPROCESS SourceProcess;
    PEPROCESS TargetProcess;
+   PEPROCESS CurrentProcess;
    HANDLE hTarget;
+   BOOLEAN AttachedToProcess = FALSE;
    KPROCESSOR_MODE PreviousMode;
+   KAPC_STATE ApcState;
    NTSTATUS Status = STATUS_SUCCESS;
-   
+
    PAGED_CODE();
-   
+
    PreviousMode = ExGetPreviousMode();
-   
-   if(PreviousMode != KernelMode)
+
+   if(TargetHandle != NULL && PreviousMode != KernelMode)
    {
      _SEH_TRY
      {
-       ProbeForWrite(TargetHandle,
-                     sizeof(HANDLE),
-                     sizeof(ULONG));
+       ProbeForWriteHandle(TargetHandle);
      }
      _SEH_HANDLE
      {
        Status = _SEH_GetExceptionCode();
      }
      _SEH_END;
-     
+
      if(!NT_SUCCESS(Status))
      {
        return Status;
      }
    }
-   
+
    Status = ObReferenceObjectByHandle(SourceProcessHandle,
                                      PROCESS_DUP_HANDLE,
                                      NULL,
@@ -322,31 +506,74 @@ NtDuplicateObject (IN     HANDLE          SourceProcessHandle,
        return(Status);
      }
 
+   CurrentProcess = PsGetCurrentProcess();
+
    /* Check for magic handle first */
-   if (SourceHandle == NtCurrentThread())
+   if (SourceHandle == NtCurrentThread() ||
+       SourceHandle == NtCurrentProcess())
      {
        PVOID ObjectBody;
-       
+       POBJECT_TYPE ObjectType;
+
+       ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType;
+
        Status = ObReferenceObjectByHandle(SourceHandle,
-                                          PROCESS_DUP_HANDLE,
-                                          NULL,
+                                          0,
+                                          ObjectType,
                                           PreviousMode,
                                           &ObjectBody,
                                           NULL);
        if(NT_SUCCESS(Status))
        {
-         Status = ObCreateHandle(TargetProcess,
-                                 ObjectBody,
-                                 THREAD_ALL_ACCESS,
-                                 InheritHandle,
-                                 &hTarget);
+         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);
+           }
+         }
+
+         if (TargetProcess != CurrentProcess)
+         {
+           KeStackAttachProcess(&TargetProcess->Pcb,
+                                &ApcState);
+           AttachedToProcess = TRUE;
+         }
+
+         Status = ObpCreateHandle(ObjectBody,
+                                  DesiredAccess,
+                                  HandleAttributes,
+                                  &hTarget);
+
+         if (AttachedToProcess)
+         {
+           KeUnstackDetachProcess(&ApcState);
+           AttachedToProcess = FALSE;
+         }
 
          ObDereferenceObject(ObjectBody);
-         
+
          if (Options & DUPLICATE_CLOSE_SOURCE)
          {
-           ObDeleteHandle(SourceProcess,
-                          SourceHandle);
+           if (SourceProcess != CurrentProcess)
+           {
+             KeStackAttachProcess(&SourceProcess->Pcb,
+                                  &ApcState);
+             AttachedToProcess = TRUE;
+           }
+
+           ObpDeleteHandle(SourceHandle);
+
+           if (AttachedToProcess)
+           {
+             KeUnstackDetachProcess(&ApcState);
+           }
          }
        }
      }
@@ -357,14 +584,14 @@ NtDuplicateObject (IN     HANDLE          SourceProcessHandle,
                                   SourceHandle,
                                   &hTarget,
                                   DesiredAccess,
-                                  InheritHandle,
+                                  HandleAttributes,
                                   Options);
      }
 
    ObDereferenceObject(TargetProcess);
    ObDereferenceObject(SourceProcess);
 
-   if(NT_SUCCESS(Status))
+   if(NT_SUCCESS(Status) && TargetHandle != NULL)
    {
      _SEH_TRY
      {
@@ -381,32 +608,20 @@ NtDuplicateObject (IN     HANDLE          SourceProcessHandle,
 }
 
 static VOID STDCALL
-DeleteHandleCallback(PHANDLE_TABLE HandleTable,
-                     PVOID Object,
-                     ULONG GrantedAccess,
-                     PVOID Context)
+SweepHandleCallback(PHANDLE_TABLE HandleTable,
+                    PVOID Object,
+                    ULONG GrantedAccess,
+                    PVOID Context)
 {
-  POBJECT_HEADER ObjectHeader;
+  PROS_OBJECT_HEADER ObjectHeader;
   PVOID ObjectBody;
-  
+
   PAGED_CODE();
 
   ObjectHeader = EX_OBJ_TO_HDR(Object);
-  ObjectBody = HEADER_TO_BODY(ObjectHeader);
-  
-  ObpDecrementHandleCount(ObjectBody);
-}
+  ObjectBody = &ObjectHeader->Body;
 
-VOID ObDeleteHandleTable(PEPROCESS Process)
-/*
- * FUNCTION: Deletes the handle table associated with a process
- */
-{
-   PAGED_CODE();
-
-   ExDestroyHandleTable(Process->ObjectTable,
-                        DeleteHandleCallback,
-                        Process);
+  ObpDecrementHandleCount(ObjectBody);
 }
 
 static BOOLEAN STDCALL
@@ -414,28 +629,27 @@ DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
                         PHANDLE_TABLE_ENTRY HandleTableEntry,
                         PVOID Context)
 {
-  POBJECT_HEADER ObjectHeader;
+  PROS_OBJECT_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);
+      ObReferenceObject(&ObjectHeader->Body);
     }
   }
-  
+
   return Ret;
 }
 
-VOID ObCreateHandleTable(PEPROCESS Parent,
+VOID
+NTAPI
+ObCreateHandleTable(PEPROCESS Parent,
                         BOOLEAN Inherit,
                         PEPROCESS Process)
 /*
@@ -447,7 +661,7 @@ VOID ObCreateHandleTable(PEPROCESS Parent,
  */
 {
    PAGED_CODE();
-   
+
    DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
          Parent,Inherit,Process);
    if(Parent != NULL)
@@ -464,60 +678,27 @@ VOID ObCreateHandleTable(PEPROCESS Parent,
 }
 
 
-NTSTATUS
-ObDeleteHandle(PEPROCESS Process,
-              HANDLE Handle)
+VOID
+STDCALL
+ObKillProcess(PEPROCESS Process)
 {
-   PHANDLE_TABLE_ENTRY HandleEntry;
-   PVOID Body;
-   POBJECT_HEADER ObjectHeader;
-   LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
-   
    PAGED_CODE();
 
-   DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
-   
-   KeEnterCriticalRegion();
-   
-   HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
-                                      ExHandle);
-   if(HandleEntry != NULL)
-   {
-     if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
-     {
-       ExUnlockHandleTableEntry(Process->ObjectTable,
-                                HandleEntry);
-
-       KeLeaveCriticalRegion();
-
-       return STATUS_HANDLE_NOT_CLOSABLE;
-     }
-
-     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;
-   }
-   KeLeaveCriticalRegion();
-   return STATUS_INVALID_HANDLE;
+   /* 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)
+NTAPI
+ObpCreateHandle(PVOID ObjectBody,
+               ACCESS_MASK GrantedAccess,
+               ULONG HandleAttributes,
+               PHANDLE HandleReturn)
 /*
  * FUNCTION: Add a handle referencing an object
  * ARGUMENTS:
@@ -527,41 +708,84 @@ ObCreateHandle(PEPROCESS Process,
  */
 {
    HANDLE_TABLE_ENTRY NewEntry;
-   POBJECT_HEADER ObjectHeader;
-   LONG ExHandle;
-   
+   PEPROCESS Process, CurrentProcess;
+   PROS_OBJECT_HEADER ObjectHeader;
+   HANDLE Handle;
+   KAPC_STATE ApcState;
+   BOOLEAN AttachedToProcess = FALSE;
+
    PAGED_CODE();
 
-   DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
+   DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody);
 
-   ASSERT(Process);
    ASSERT(ObjectBody);
 
+   CurrentProcess = PsGetCurrentProcess();
+
    ObjectHeader = BODY_TO_HEADER(ObjectBody);
 
+   /* check that this is a valid kernel pointer */
    ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
 
+   if (GrantedAccess & MAXIMUM_ALLOWED)
+     {
+        GrantedAccess &= ~MAXIMUM_ALLOWED;
+        GrantedAccess |= GENERIC_ALL;
+     }
+
+   if (GrantedAccess & GENERIC_ANY)
+     {
+       RtlMapGenericMask(&GrantedAccess,
+                        &ObjectHeader->Type->TypeInfo.GenericMapping);
+     }
+
    NewEntry.u1.Object = ObjectHeader;
-   if(Inherit)
+   if(HandleAttributes & OBJ_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 ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
+       ExGetPreviousMode == KernelMode)
+   {
+       Process = PsInitialSystemProcess;
+       if (Process != CurrentProcess)
+       {
+           KeStackAttachProcess(&Process->Pcb,
+                                &ApcState);
+           AttachedToProcess = TRUE;
+       }
+   }
+   else
+   {
+       Process = CurrentProcess;
+       /* mask out the OBJ_KERNEL_HANDLE attribute */
+       HandleAttributes &= ~OBJ_KERNEL_HANDLE;
+   }
+
+   Handle = ExCreateHandle(Process->ObjectTable,
+                           &NewEntry);
+
+   if (AttachedToProcess)
    {
+       KeUnstackDetachProcess(&ApcState);
+   }
+
+   if(Handle != NULL)
+   {
+     if (HandleAttributes & OBJ_KERNEL_HANDLE)
+     {
+       /* mark the handle value */
+       Handle = ObMarkHandleAsKernelHandle(Handle);
+     }
+
      if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
      {
-      ObReferenceObjectByPointer(ObjectBody,
-                                0,
-                                NULL,
-                                UserMode);
+       ObReferenceObject(ObjectBody);
      }
-     
-     *HandleReturn = EX_HANDLE_TO_HANDLE(ExHandle);
+
+     *HandleReturn = Handle;
 
      return STATUS_SUCCESS;
    }
@@ -578,47 +802,67 @@ ObQueryObjectAuditingByHandle(IN HANDLE Handle,
                              OUT PBOOLEAN GenerateOnClose)
 {
   PHANDLE_TABLE_ENTRY HandleEntry;
-  PEPROCESS Process;
-  LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
-  
+  PEPROCESS Process, CurrentProcess;
+  KAPC_STATE ApcState;
+  BOOLEAN AttachedToProcess = FALSE;
+  NTSTATUS Status = STATUS_SUCCESS;
+
   PAGED_CODE();
 
-  DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
+  DPRINT("ObQueryObjectAuditingByHandle(Handle %p)\n", Handle);
+
+  CurrentProcess = PsGetCurrentProcess();
 
-  Process = PsGetCurrentProcess();
-  
   KeEnterCriticalRegion();
 
+  if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
+  {
+    Process = PsInitialSystemProcess;
+    Handle = ObKernelHandleToHandle(Handle);
+
+    if (Process != CurrentProcess)
+    {
+      KeStackAttachProcess(&Process->Pcb,
+                           &ApcState);
+      AttachedToProcess = TRUE;
+    }
+  }
+  else
+     Process = CurrentProcess;
+
   HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
-                                     ExHandle);
+                                     Handle);
   if(HandleEntry != NULL)
   {
     *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
-    
+
     ExUnlockHandleTableEntry(Process->ObjectTable,
                              HandleEntry);
+  }
+  else
+    Status = STATUS_INVALID_HANDLE;
 
-    KeLeaveCriticalRegion();
-    
-    return STATUS_SUCCESS;
+  if (AttachedToProcess)
+  {
+    KeUnstackDetachProcess(&ApcState);
   }
-  
+
   KeLeaveCriticalRegion();
-  
-  return STATUS_INVALID_HANDLE;
+
+  return Status;
 }
 
 
 /*
- * 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
  *
@@ -633,34 +877,34 @@ ObReferenceObjectByHandle(HANDLE Handle,
                          POBJECT_HANDLE_INFORMATION HandleInformation)
 {
    PHANDLE_TABLE_ENTRY HandleEntry;
-   POBJECT_HEADER ObjectHeader;
+   PROS_OBJECT_HEADER ObjectHeader;
    PVOID ObjectBody;
    ACCESS_MASK GrantedAccess;
-   PGENERIC_MAPPING GenericMapping;
    ULONG Attributes;
-   NTSTATUS Status;
-   LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
-   
+   PEPROCESS CurrentProcess, Process;
+   BOOLEAN AttachedToProcess = FALSE;
+   KAPC_STATE ApcState;
+
    PAGED_CODE();
-   
-   DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
-          "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
+
+   DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
+          "ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
           ObjectType,AccessMode,Object);
 
+   if (Handle == NULL)
+     {
+       return STATUS_INVALID_HANDLE;
+     }
+
+   CurrentProcess = PsGetCurrentProcess();
+
    /*
     * Handle special handle names
     */
-   if (Handle == NtCurrentProcess() && 
+   if (Handle == NtCurrentProcess() &&
        (ObjectType == PsProcessType || ObjectType == NULL))
      {
-       Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
-                                           PROCESS_ALL_ACCESS,
-                                           PsProcessType,
-                                           UserMode);
-       if (! NT_SUCCESS(Status))
-         {
-           return Status;
-         }
+        ObReferenceObject(CurrentProcess);
 
        if (HandleInformation != NULL)
          {
@@ -668,8 +912,8 @@ ObReferenceObjectByHandle(HANDLE Handle,
            HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
          }
 
-       *Object = PsGetCurrentProcess();
-       DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
+       *Object = CurrentProcess;
+       DPRINT("Referencing current process %p\n", CurrentProcess);
        return STATUS_SUCCESS;
      }
    else if (Handle == NtCurrentProcess())
@@ -678,17 +922,12 @@ ObReferenceObjectByHandle(HANDLE Handle,
        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
 
-   if (Handle == NtCurrentThread() && 
+   if (Handle == NtCurrentThread() &&
        (ObjectType == PsThreadType || ObjectType == NULL))
      {
-       Status = ObReferenceObjectByPointer(PsGetCurrentThread(),
-                                           THREAD_ALL_ACCESS,
-                                           PsThreadType,
-                                           UserMode);
-       if (! NT_SUCCESS(Status))
-         {
-           return Status;
-         }
+        PETHREAD CurrentThread = PsGetCurrentThread();
+
+        ObReferenceObject(CurrentThread);
 
        if (HandleInformation != NULL)
          {
@@ -696,7 +935,7 @@ ObReferenceObjectByHandle(HANDLE Handle,
            HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
          }
 
-       *Object = PsGetCurrentThread();
+       *Object = CurrentThread;
        CHECKPOINT;
        return STATUS_SUCCESS;
      }
@@ -705,62 +944,112 @@ ObReferenceObjectByHandle(HANDLE Handle,
        CHECKPOINT;
        return(STATUS_OBJECT_TYPE_MISMATCH);
      }
-   
+
+   /* desire as much access rights as possible */
+   if (DesiredAccess & MAXIMUM_ALLOWED)
+     {
+        DesiredAccess &= ~MAXIMUM_ALLOWED;
+        DesiredAccess |= GENERIC_ALL;
+     }
+
+   if(ObIsKernelHandle(Handle, AccessMode))
+   {
+      Process = PsInitialSystemProcess;
+      Handle = ObKernelHandleToHandle(Handle);
+   }
+   else
+   {
+      Process = CurrentProcess;
+   }
+
    KeEnterCriticalRegion();
-   
-   HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable,
-                                     ExHandle);
+
+   if (Process != CurrentProcess)
+   {
+     KeStackAttachProcess(&Process->Pcb,
+                          &ApcState);
+     AttachedToProcess = TRUE;
+   }
+
+   HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
+                                     Handle);
    if (HandleEntry == NULL)
      {
+        if (AttachedToProcess)
+        {
+            KeUnstackDetachProcess(&ApcState);
+        }
         KeLeaveCriticalRegion();
-        DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
+        DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
         return(STATUS_INVALID_HANDLE);
      }
 
    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 = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
-                                                EX_HANDLE_ENTRY_INHERITABLE |
-                                                EX_HANDLE_ENTRY_AUDITONCLOSE);
-   GrantedAccess = HandleEntry->u2.GrantedAccess;
-   GenericMapping = ObjectHeader->ObjectType->Mapping;
+   ObjectBody = &ObjectHeader->Body;
+
+   DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
 
-   if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
+   if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
      {
-        DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle);
-        
-        ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
+        DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
+
+        ExUnlockHandleTableEntry(Process->ObjectTable,
                                  HandleEntry);
 
+        if (AttachedToProcess)
+        {
+            KeUnstackDetachProcess(&ApcState);
+        }
+
         KeLeaveCriticalRegion();
-        
+
         return(STATUS_OBJECT_TYPE_MISMATCH);
      }
 
-   ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
-                            HandleEntry);
-   
-   KeLeaveCriticalRegion();
-   
-   if (DesiredAccess && AccessMode != KernelMode)
+   /* map the generic access masks if the caller asks for generic access */
+   if (DesiredAccess & GENERIC_ANY)
      {
-       RtlMapGenericMask(&DesiredAccess, GenericMapping);
+        RtlMapGenericMask(&DesiredAccess,
+                          &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
+     }
 
-       if (!(GrantedAccess & DesiredAccess) &&
-           !((~GrantedAccess) & DesiredAccess))
-         {
-            CHECKPOINT;
-            return(STATUS_ACCESS_DENIED);
-         }
+   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(Process->ObjectTable,
+                                 HandleEntry);
+
+        if (AttachedToProcess)
+        {
+            KeUnstackDetachProcess(&ApcState);
+        }
+
+        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(Process->ObjectTable,
+                            HandleEntry);
+
+   if (AttachedToProcess)
+   {
+       KeUnstackDetachProcess(&ApcState);
+   }
+
+   KeLeaveCriticalRegion();
+
    if (HandleInformation != NULL)
      {
        HandleInformation->HandleAttributes = Attributes;
@@ -768,7 +1057,7 @@ ObReferenceObjectByHandle(HANDLE Handle,
      }
 
    *Object = ObjectBody;
-   
+
    return(STATUS_SUCCESS);
 }
 
@@ -776,14 +1065,14 @@ ObReferenceObjectByHandle(HANDLE Handle,
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     NtClose
- *     
+ *
  * DESCRIPTION
  *     Closes a handle reference to an object.
- *     
+ *
  * ARGUMENTS
  *     Handle
  *             Handle to close.
- *             
+ *
  * RETURN VALUE
  *     Status.
  *
@@ -792,19 +1081,49 @@ ObReferenceObjectByHandle(HANDLE Handle,
 NTSTATUS STDCALL
 NtClose(IN HANDLE Handle)
 {
+   PEPROCESS Process, CurrentProcess;
+   BOOLEAN AttachedToProcess = FALSE;
+   KAPC_STATE ApcState;
    NTSTATUS Status;
-   
+   KPROCESSOR_MODE PreviousMode;
+
    PAGED_CODE();
-   
-   Status = ObDeleteHandle(PsGetCurrentProcess(),
-                          Handle);
+
+   PreviousMode = ExGetPreviousMode();
+   CurrentProcess = PsGetCurrentProcess();
+
+   if(ObIsKernelHandle(Handle, PreviousMode))
+   {
+      Process = PsInitialSystemProcess;
+      Handle = ObKernelHandleToHandle(Handle);
+
+      if (Process != CurrentProcess)
+      {
+        KeStackAttachProcess(&Process->Pcb,
+                             &ApcState);
+        AttachedToProcess = TRUE;
+      }
+   }
+   else
+      Process = CurrentProcess;
+
+   Status = ObpDeleteHandle(Handle);
+
+   if (AttachedToProcess)
+   {
+     KeUnstackDetachProcess(&ApcState);
+   }
+
    if (!NT_SUCCESS(Status))
      {
-        if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
+        if((PreviousMode != KernelMode) &&
+           (CurrentProcess->ExceptionPort))
+        {
            KeRaiseUserException(Status);
+        }
        return Status;
      }
-   
+
    return(STATUS_SUCCESS);
 }
 
@@ -812,34 +1131,223 @@ NtClose(IN HANDLE Handle)
 /*
  * @implemented
  */
-NTSTATUS STDCALL
+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)
+               IN PACCESS_STATE PassedAccessState OPTIONAL,
+               IN ACCESS_MASK DesiredAccess,
+               IN ULONG AdditionalReferences,
+               OUT PVOID* ReferencedObject OPTIONAL,
+               OUT PHANDLE Handle)
 {
-  POBJECT_HEADER ObjectHeader;
-  ACCESS_MASK Access;
-  
-  PAGED_CODE();
+    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+    PROS_OBJECT_HEADER Header;
+    POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+    PVOID FoundObject = NULL;
+    PROS_OBJECT_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);
+    }
 
-  Access = DesiredAccess;
-  ObjectHeader = BODY_TO_HEADER(Object);
+    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, (PROS_OBJECT_HEADER)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);
+    }
 
-  RtlMapGenericMask(&Access,
-                   ObjectHeader->ObjectType->Mapping);
+    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,
+                                                                NULL,
+                                                                &Header->Body,
+                                                                0,
+                                                                0);
+        }
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("Create Failed\n");
+            if (ObjectAttached == TRUE)
+            {
+                ObpRemoveEntryDirectory((PROS_OBJECT_HEADER)Header);
+            }
+            if (FoundObject)
+            {
+                ObDereferenceObject(FoundObject);
+            }
+            RtlFreeUnicodeString(&RemainingPath);
+            return Status;
+        }
+    }
 
-  return(ObCreateHandle(PsGetCurrentProcess(),
-                       Object,
-                       Access,
-                       ObjectHeader->Inherit,
-                       Handle));
+    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(&Header->Body,
+                                 DesiredAccess,
+                                 ObjectCreateInfo->Attributes,
+                                 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;
@@ -890,7 +1398,7 @@ ObFindHandleForObject(IN PEPROCESS Process,
                       IN POBJECT_HANDLE_INFORMATION HandleInformation,
                       OUT PHANDLE HandleReturn)
 {
-  UNIMPLEMENTED;
+  DPRINT("ObFindHandleForObject is unimplemented!\n");
   return STATUS_UNSUCCESSFUL;
 }
 
@@ -904,7 +1412,7 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
 
 //      pshi->HandleValue;
 
-/* 
+/*
    This will never work with ROS! M$, I guess uses 0 -> 65535.
    Ros uses 0 -> 4294967295!
  */
@@ -916,7 +1424,7 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
 
 //      pshi->GrantedAccess;
 //      pshi->Object;
-//      pshi->ObjectTypeIndex;
+//      pshi->TypeIndex;
 //      pshi->HandleAttributes;
 
 //      KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );