- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[reactos.git] / reactos / ntoskrnl / ob / object.c
index 339cb27..a4ade3b 100644 (file)
-/* $Id: object.c,v 1.61 2003/06/02 13:03:15 ekohl Exp $
- * 
- * COPYRIGHT:     See COPYING in the top level directory
- * PROJECT:       ReactOS kernel
- * FILE:          ntoskrnl/ob/object.c
- * PURPOSE:       Implements generic object managment functions
- * PROGRAMMER:    David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *               10/06/98: Created
+/* $Id$
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ob/object.c
+ * PURPOSE:         Implements generic object managment functions
+ *
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ *                  Skywing (skywing@valhallalegends.com)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <internal/ps.h>
-#include <internal/id.h>
-#include <internal/ke.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#define UNICODE_PATH_SEP L'\\'
+#define UNICODE_NO_PATH L"..."
+#define OB_NAME_TAG TAG('O','b','N','m')
+
+typedef struct _RETENTION_CHECK_PARAMS
+{
+  WORK_QUEUE_ITEM WorkItem;
+  POBJECT_HEADER ObjectHeader;
+} RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
 
 /* FUNCTIONS ************************************************************/
 
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
+NTSTATUS
+STDCALL
+ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
+                     IN PUNICODE_STRING ObjectName,
+                     IN KPROCESSOR_MODE AccessMode)
 {
-   return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
-}
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG StringLength;
+    PWCHAR StringBuffer = NULL;
+    UNICODE_STRING LocalName = {}; /* <= GCC 4.0 + Optimizer */
+    
+    /* Initialize the Input String */
+    RtlInitUnicodeString(CapturedName, NULL);
+
+    /* Protect everything */
+    _SEH_TRY
+    {
+        /* First Probe the String */
+        DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
+        if (AccessMode != KernelMode)
+        {
+            ProbeForRead(ObjectName,
+                         sizeof(UNICODE_STRING),
+                         sizeof(USHORT));
+            LocalName = *ObjectName;
+
+            ProbeForRead(LocalName.Buffer,
+                         LocalName.Length,
+                         sizeof(WCHAR));
+        }
+        else
+        {
+            /* No probing needed */
+            LocalName = *ObjectName;
+        }
+
+        /* Make sure there really is a string */
+        DPRINT("Probing OK\n");
+        if ((StringLength = LocalName.Length))
+        {
+            /* Check that the size is a valid WCHAR multiple */
+            if ((StringLength & (sizeof(WCHAR) - 1)) ||
+                /* Check that the NULL-termination below will work */
+                (StringLength == (MAXUSHORT - sizeof(WCHAR) + 1)))
+            {
+                /* PS: Please keep the checks above expanded for clarity */
+                DPRINT1("Invalid String Length\n");
+                Status = STATUS_OBJECT_NAME_INVALID;
+            }
+            else
+            {
+                /* Allocate a non-paged buffer for this string */
+                DPRINT("Capturing String\n");
+                CapturedName->Length = StringLength;
+                CapturedName->MaximumLength = StringLength + sizeof(WCHAR);
+                if ((StringBuffer = ExAllocatePoolWithTag(NonPagedPool, 
+                                                          StringLength + sizeof(WCHAR),
+                                                          OB_NAME_TAG)))
+                {                                    
+                    /* Copy the string and null-terminate it */
+                    RtlMoveMemory(StringBuffer, LocalName.Buffer, StringLength);
+                    StringBuffer[StringLength / sizeof(WCHAR)] = UNICODE_NULL;
+                    CapturedName->Buffer = StringBuffer;
+                    DPRINT("String Captured: %wZ\n", CapturedName);
+                }
+                else
+                {
+                    /* Fail */
+                    DPRINT1("Out of Memory!\n");
+                    Status = STATUS_INSUFFICIENT_RESOURCES;
+                }
+            }
+        }
+    }
+    _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+    {
+        Status = _SEH_GetExceptionCode();
 
+        /* Remember to free the buffer in case of failure */
+        DPRINT1("Failed\n");
+        if (StringBuffer) ExFreePool(StringBuffer);
+    }
+    _SEH_END;
+    
+    /* Return */
+    DPRINT("Returning: %lx\n", Status);
+    return Status;
+}
 
-POBJECT_HEADER BODY_TO_HEADER(PVOID body)
+NTSTATUS
+STDCALL
+ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                           IN KPROCESSOR_MODE AccessMode,
+                           IN POBJECT_TYPE ObjectType,
+                           IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                           OUT PUNICODE_STRING ObjectName)
 {
-   PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
-   return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
+    NTSTATUS Status = STATUS_SUCCESS;
+    PSECURITY_DESCRIPTOR SecurityDescriptor;
+    PSECURITY_QUALITY_OF_SERVICE SecurityQos;
+    PUNICODE_STRING LocalObjectName = NULL;
+
+    /* Zero out the Capture Data */
+    DPRINT("ObpCaptureObjectAttributes\n");
+    RtlZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
+    
+    /* SEH everything here for protection */
+    _SEH_TRY
+    {
+        /* Check if we got Oba */
+        if (ObjectAttributes)
+        {
+            if (AccessMode != KernelMode)
+            {
+                DPRINT("Probing OBA\n");
+                ProbeForRead(ObjectAttributes,
+                             sizeof(OBJECT_ATTRIBUTES),
+                             sizeof(ULONG));
+            }
+        
+            /* Validate the Size and Attributes */
+            DPRINT("Validating OBA\n");
+            if ((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
+                (ObjectAttributes->Attributes & ~OBJ_VALID_ATTRIBUTES))
+            {
+                Status = STATUS_INVALID_PARAMETER;
+                DPRINT1("Invalid Size: %lx or Attributes: %lx\n",
+                       ObjectAttributes->Length, ObjectAttributes->Attributes); 
+                _SEH_LEAVE;
+            }
+        
+            /* Set some Create Info */
+            DPRINT("Creating OBCI\n");
+            ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
+            ObjectCreateInfo->Attributes = ObjectAttributes->Attributes;
+            LocalObjectName = ObjectAttributes->ObjectName;
+            SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
+            SecurityQos = ObjectAttributes->SecurityQualityOfService;
+        
+            /* Validate the SD */
+            if (SecurityDescriptor)
+            {
+                DPRINT("Probing SD: %x\n", SecurityDescriptor);
+                Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
+                                                     AccessMode,
+                                                     NonPagedPool,
+                                                     TRUE,
+                                                     &ObjectCreateInfo->SecurityDescriptor);
+                if(!NT_SUCCESS(Status))
+                {
+                    DPRINT1("Unable to capture the security descriptor!!!\n");
+                    ObjectCreateInfo->SecurityDescriptor = NULL;
+                    _SEH_LEAVE;
+                }
+            
+                DPRINT("Probe done\n");
+                ObjectCreateInfo->SecurityDescriptorCharge = 2048; /* FIXME */
+                ObjectCreateInfo->ProbeMode = AccessMode;
+            }
+        
+            /* Validate the QoS */
+            if (SecurityQos)
+            {
+                if (AccessMode != KernelMode)
+                {
+                    DPRINT("Probing QoS\n");
+                    ProbeForRead(SecurityQos,
+                                 sizeof(SECURITY_QUALITY_OF_SERVICE),
+                                 sizeof(ULONG));
+                }
+            
+                /* Save Info */
+                ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
+                ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
+            }
+        }
+        else
+        {
+            LocalObjectName = NULL;
+        }
+    }
+    _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+    {
+        Status = _SEH_GetExceptionCode();
+        DPRINT1("Failed\n");
+    }
+    _SEH_END;
+
+    if (NT_SUCCESS(Status))
+    {
+        /* Now check if the Object Attributes had an Object Name */
+        if (LocalObjectName)
+        {
+            DPRINT("Name Buffer: %wZ\n", LocalObjectName);
+            Status = ObpCaptureObjectName(ObjectName,
+                                          LocalObjectName,
+                                          AccessMode);
+        }
+        else
+        {
+            /* Clear the string */
+            RtlInitUnicodeString(ObjectName, NULL);
+
+            /* He can't have specified a Root Directory */
+            if (ObjectCreateInfo->RootDirectory)
+            {
+                DPRINT1("Invalid name\n");
+                Status = STATUS_OBJECT_NAME_INVALID;
+            }
+        }
+    }
+    else
+    {
+        DPRINT1("Failed to capture, cleaning up\n");
+        ObpReleaseCapturedAttributes(ObjectCreateInfo);
+    }
+    
+    DPRINT("Return to caller %x\n", Status);
+    return Status;
 }
 
 
-/**********************************************************************
- * NAME                                                        PRIVATE
- *     ObInitializeObject
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- */
-VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
-                       PHANDLE Handle,
-                       ACCESS_MASK DesiredAccess,
-                       POBJECT_TYPE Type,
-                       POBJECT_ATTRIBUTES ObjectAttributes)
+VOID
+STDCALL
+ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
 {
-   ObjectHeader->HandleCount = 0;
-   ObjectHeader->RefCount = 1;
-   ObjectHeader->ObjectType = Type;
-   if (ObjectAttributes != NULL &&
-       ObjectAttributes->Attributes & OBJ_PERMANENT)
-     {
-       ObjectHeader->Permanent = TRUE;
-     }
-   else
-     {
-       ObjectHeader->Permanent = FALSE;
-     }
-   RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
-   if (Handle != NULL)
-     {
-       ObCreateHandle(PsGetCurrentProcess(),
-                      HEADER_TO_BODY(ObjectHeader),
-                      DesiredAccess,
-                      ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
-                      Handle);
-     }
+    /* Release the SD, it's the only thing we allocated */
+    if (ObjectCreateInfo->SecurityDescriptor)
+    {
+        SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
+                                    ObjectCreateInfo->ProbeMode,
+                                    TRUE);
+        ObjectCreateInfo->SecurityDescriptor = NULL;                                        
+    }
 }
 
 
@@ -100,94 +287,104 @@ VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
  *
  * RETURN VALUE
  */
-NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
-                     PVOID* ReturnedObject,
-                     PUNICODE_STRING RemainingPath,
-                     POBJECT_TYPE ObjectType)
+NTSTATUS
+NTAPI
+ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+            PUNICODE_STRING ObjectName,
+            PVOID* ReturnedObject,
+            PUNICODE_STRING RemainingPath,
+            POBJECT_TYPE ObjectType)
 {
-   PVOID NextObject;
-   PVOID CurrentObject;
-   PVOID RootObject;
-   POBJECT_HEADER CurrentHeader;
-   NTSTATUS Status;
-   PWSTR Path;
-   PWSTR current;
-   UNICODE_STRING PathString;
-   ULONG Attributes;
-   
-   DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
-         "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
-   DPRINT("ObjectAttributes->ObjectName %wZ\n",
-         ObjectAttributes->ObjectName);
-
-   RtlInitUnicodeString (RemainingPath, NULL);
-
-   if (ObjectAttributes->RootDirectory == NULL)
-     {
-       ObReferenceObjectByPointer(NameSpaceRoot,
-                                  DIRECTORY_TRAVERSE,
-                                  NULL,
-                                  UserMode);
-       CurrentObject = NameSpaceRoot;
-     }
-   else
-     {
-       Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
-                                          DIRECTORY_TRAVERSE,
-                                          NULL,
-                                          UserMode,
-                                          &CurrentObject,
-                                          NULL);
-       if (!NT_SUCCESS(Status))
-         {
-            return(Status);
-         }
-     }
-   
-   Path = ObjectAttributes->ObjectName->Buffer;
-   
-   if (Path[0] == 0)
-     {
-       *ReturnedObject = CurrentObject;
-       return(STATUS_SUCCESS);
-     }
-   
-   if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
-     {
-       ObDereferenceObject(CurrentObject);
-       return(STATUS_UNSUCCESSFUL);
-     }
-   
-   if (Path)
-     {
-       RtlCreateUnicodeString (&PathString, Path);
-       current = PathString.Buffer;
-     }
-   else
-     {
-       RtlInitUnicodeString (&PathString, NULL);
-       current = NULL;
-     }
+  PVOID NextObject;
+  PVOID CurrentObject;
+  PVOID RootObject;
+  POBJECT_HEADER CurrentHeader;
+  NTSTATUS Status;
+  PWSTR current;
+  UNICODE_STRING PathString;
+  ULONG Attributes;
 
-   RootObject = CurrentObject;
-   Attributes = ObjectAttributes->Attributes;
-   if (ObjectType == ObSymbolicLinkType)
-     Attributes |= OBJ_OPENLINK;
+  PAGED_CODE();
 
-   while (TRUE)
-     {
+  DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
+        "RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
+
+  RtlInitUnicodeString (RemainingPath, NULL);
+
+  if (ObjectCreateInfo->RootDirectory == NULL)
+    {
+      ObReferenceObjectByPointer(NameSpaceRoot,
+                                DIRECTORY_TRAVERSE,
+                                NULL,
+                                ObjectCreateInfo->ProbeMode);
+      CurrentObject = NameSpaceRoot;
+    }
+  else
+    {
+      Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
+                                        0,
+                                        NULL,
+                                        ObjectCreateInfo->ProbeMode,
+                                        &CurrentObject,
+                                        NULL);
+      if (!NT_SUCCESS(Status))
+       {
+         return Status;
+       }
+    }
+
+  if (ObjectName->Length == 0 ||
+      ObjectName->Buffer[0] == UNICODE_NULL)
+    {
+      *ReturnedObject = CurrentObject;
+      return STATUS_SUCCESS;
+    }
+
+  if (ObjectCreateInfo->RootDirectory == NULL &&
+      ObjectName->Buffer[0] != L'\\')
+    {
+      ObDereferenceObject (CurrentObject);
+      DPRINT1("failed\n");
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  /* Create a zero-terminated copy of the object name */
+  PathString.Length = ObjectName->Length;
+  PathString.MaximumLength = ObjectName->Length + sizeof(WCHAR);
+  PathString.Buffer = ExAllocatePool (NonPagedPool,
+                                     PathString.MaximumLength);
+  if (PathString.Buffer == NULL)
+    {
+      ObDereferenceObject (CurrentObject);
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+  RtlCopyMemory (PathString.Buffer,
+                ObjectName->Buffer,
+                ObjectName->Length);
+  PathString.Buffer[PathString.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+  current = PathString.Buffer;
+
+  RootObject = CurrentObject;
+  Attributes = ObjectCreateInfo->Attributes;
+  if (ObjectType == ObSymbolicLinkType)
+    Attributes |= OBJ_OPENLINK;
+
+  while (TRUE)
+    {
        DPRINT("current %S\n",current);
        CurrentHeader = BODY_TO_HEADER(CurrentObject);
 
        DPRINT("Current ObjectType %wZ\n",
-              &CurrentHeader->ObjectType->TypeName);
+              &CurrentHeader->Type->Name);
 
-       if (CurrentHeader->ObjectType->Parse == NULL)
+       if (CurrentHeader->Type->TypeInfo.ParseProcedure == NULL)
          {
             DPRINT("Current object can't parse\n");
             break;
          }
-       Status = CurrentHeader->ObjectType->Parse(CurrentObject,
+       Status = CurrentHeader->Type->TypeInfo.ParseProcedure(CurrentObject,
                                                  &NextObject,
                                                  &PathString,
                                                  &current,
@@ -195,13 +392,13 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
        if (Status == STATUS_REPARSE)
          {
             /* reparse the object path */
-            NextObject = RootObject;
+            NextObject = NameSpaceRoot;
             current = PathString.Buffer;
-            
+
             ObReferenceObjectByPointer(NextObject,
                                        DIRECTORY_TRAVERSE,
                                        NULL,
-                                       UserMode);
+                                       ObjectCreateInfo->ProbeMode);
          }
 
        if (NextObject == NULL)
@@ -210,14 +407,17 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
          }
        ObDereferenceObject(CurrentObject);
        CurrentObject = NextObject;
-     }
-   
-   if (current)
-      RtlCreateUnicodeString (RemainingPath, current);
-   RtlFreeUnicodeString (&PathString);
-   *ReturnedObject = CurrentObject;
-   
-   return(STATUS_SUCCESS);
+    }
+
+  if (current)
+  {
+     RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
+  }
+
+  RtlFreeUnicodeString (&PathString);
+  *ReturnedObject = CurrentObject;
+
+  return STATUS_SUCCESS;
 }
 
 
@@ -230,115 +430,325 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
  * ARGUMENTS
  *
  * RETURN VALUE
+ *
+ * @implemented
  */
-NTSTATUS STDCALL
-ObQueryNameString (IN PVOID Object,
-                  OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
-                  IN ULONG Length,
-                  OUT PULONG ReturnLength)
+NTSTATUS 
+STDCALL
+ObQueryNameString(IN  PVOID Object,
+                  OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
+                  IN  ULONG Length,
+                  OUT PULONG ReturnLength)
 {
-  POBJECT_NAME_INFORMATION LocalInfo;
-  POBJECT_HEADER ObjectHeader;
-  ULONG LocalReturnLength;
-  NTSTATUS Status;
-
-  *ReturnLength = 0;
+    POBJECT_HEADER_NAME_INFO LocalInfo;
+    POBJECT_HEADER ObjectHeader;
+    PDIRECTORY_OBJECT ParentDirectory;
+    ULONG NameSize;
+    PWCH ObjectName;
+    NTSTATUS Status;
+
+    DPRINT("ObQueryNameString: %x, %x\n", Object, ObjectNameInfo);
+
+    /* Get the Kernel Meta-Structures */
+    ObjectHeader = BODY_TO_HEADER(Object);
+    LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
+
+    /* Check if a Query Name Procedure is available */
+    if (ObjectHeader->Type->TypeInfo.QueryNameProcedure) 
+    {  
+        /* Call the procedure */
+        DPRINT("Calling Object's Procedure\n");
+        Status = ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
+                                                                 ObjectNameInfo,
+                                                                 Length,
+                                                                 ReturnLength);
+
+        /* Return the status */
+        return Status;
+    }
 
-  if (Length < sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR))
-    return STATUS_INVALID_BUFFER_SIZE;
+    /* Check if the object doesn't even have a name */
+    if (!LocalInfo || !LocalInfo->Name.Buffer) 
+    {
+        /* We're returning the name structure */
+        DPRINT("Nameless Object\n");
+        *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
+
+        /* Check if we were given enough space */
+        if (*ReturnLength > Length) 
+        {
+            DPRINT1("Not enough buffer space\n");
+            return STATUS_INFO_LENGTH_MISMATCH;
+        }
+
+        /* Return an empty buffer */
+        ObjectNameInfo->Name.Length = 0;
+        ObjectNameInfo->Name.MaximumLength = 0;
+        ObjectNameInfo->Name.Buffer = NULL;
+
+        return STATUS_SUCCESS;
+    }
 
-  ObjectNameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
-  ObjectNameInfo->Name.Length = 0;
-  ObjectNameInfo->Name.Buffer =
-    (PWCHAR)((ULONG_PTR)ObjectNameInfo + sizeof(OBJECT_NAME_INFORMATION));
-  ObjectNameInfo->Name.Buffer[0] = 0;
+    /* 
+     * Find the size needed for the name. We won't do
+     * this during the Name Creation loop because we want
+     * to let the caller know that the buffer isn't big
+     * enough right at the beginning, not work our way through
+     * and find out at the end
+     */
+    if (Object == NameSpaceRoot) 
+    {
+        /* Size of the '\' string */
+        DPRINT("Object is Root\n");
+        NameSize = sizeof(UNICODE_PATH_SEP);
+    } 
+    else 
+    {
+        /* Get the Object Directory and add name of Object */
+        ParentDirectory = LocalInfo->Directory;
+        NameSize = sizeof(UNICODE_PATH_SEP) + LocalInfo->Name.Length;
+
+        /* Loop inside the directory to get the top-most one (meaning root) */
+        while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory)) 
+        {
+            /* Get the Name Information */
+            LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
+
+            /* Add the size of the Directory Name */
+            if (LocalInfo && LocalInfo->Directory) 
+            {
+                /* Size of the '\' string + Directory Name */
+                NameSize += sizeof(UNICODE_PATH_SEP) + LocalInfo->Name.Length;
+
+                /* Move to next parent Directory */
+                ParentDirectory = LocalInfo->Directory;
+            } 
+            else 
+            {
+                /* Directory with no name. We append "...\" */
+                DPRINT("Nameless Directory\n");
+                NameSize += sizeof(UNICODE_NO_PATH) + sizeof(UNICODE_PATH_SEP);
+                break;
+            }
+        }
+    }
 
-  ObjectHeader = BODY_TO_HEADER(Object);
+    /* Finally, add the name of the structure and the null char */
+    *ReturnLength = NameSize + sizeof(OBJECT_NAME_INFORMATION) + sizeof(UNICODE_NULL);
+    DPRINT("Final Length: %x\n", *ReturnLength);
 
-  if (ObjectHeader->ObjectType != NULL &&
-      ObjectHeader->ObjectType->QueryName != NULL)
+    /* Check if we were given enough space */
+    if (*ReturnLength > Length) 
     {
-      DPRINT ("Calling %x\n", ObjectHeader->ObjectType->QueryName);
-      Status = ObjectHeader->ObjectType->QueryName (Object,
-                                                   ObjectNameInfo,
-                                                   Length,
-                                                   ReturnLength);
-      if (!NT_SUCCESS (Status))
-       return Status;
-
-      Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-                                              &ObjectHeader->Name);
+        DPRINT1("Not enough buffer space\n");
+        return STATUS_INFO_LENGTH_MISMATCH;
     }
-  else if (ObjectHeader->Name.Length > 0 && ObjectHeader->Name.Buffer != NULL)
-    {
-      DPRINT ("Object does not have a 'QueryName' function\n");
 
-      if (ObjectHeader->Parent == NameSpaceRoot)
-       {
-         DPRINT ("Reached the root directory\n");
-         ObjectNameInfo->Name.Buffer[0] = 0;
-         Status = STATUS_SUCCESS;
-       }
-      else if (ObjectHeader->Parent != NULL)
-       {
-         LocalInfo = ExAllocatePool (NonPagedPool,
-                                     sizeof(OBJECT_NAME_INFORMATION) +
-                                     MAX_PATH * sizeof(WCHAR));
-         if (LocalInfo == NULL)
-           return STATUS_INSUFFICIENT_RESOURCES;
-
-         Status = ObQueryNameString (ObjectHeader->Parent,
-                                     LocalInfo,
-                                     MAX_PATH * sizeof(WCHAR),
-                                     &LocalReturnLength);
-         if (!NT_SUCCESS (Status))
-           {
-             ExFreePool (LocalInfo);
-             return Status;
-           }
-
-         Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-                                                  &LocalInfo->Name);
-
-         ExFreePool (LocalInfo);
-
-         if (!NT_SUCCESS (Status))
-           return Status;
-       }
-
-      DPRINT ("Object path %wZ\n", &ObjectHeader->Name);
-      Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
-                                        L"\\");
-      if (!NT_SUCCESS (Status))
-       return Status;
+    /* 
+     * Now we will actually create the name. We work backwards because
+     * it's easier to start off from the Name we have and walk up the
+     * parent directories. We use the same logic as Name Length calculation.
+     */
+    LocalInfo = HEADER_TO_OBJECT_NAME(ObjectHeader);
+    ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
+    *--ObjectName = UNICODE_NULL;
 
-      Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-                                              &ObjectHeader->Name);
-    }
-  else
+    if (Object == NameSpaceRoot) 
+    {
+        /* This is already the Root Directory, return "\\" */
+        DPRINT("Returning Root Dir\n");
+        *--ObjectName = UNICODE_PATH_SEP;
+        ObjectNameInfo->Name.Length = (USHORT)NameSize;
+        ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
+        ObjectNameInfo->Name.Buffer = ObjectName;
+
+        return STATUS_SUCCESS;
+    } 
+    else 
     {
-      DPRINT("Object is unnamed\n");
+        /* Start by adding the Object's Name */
+        ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
+        RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
+
+        /* Now parse the Parent directories until we reach the top */
+        ParentDirectory = LocalInfo->Directory;
+        while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory)) 
+        {
+            /* Get the name information */
+            LocalInfo = HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ParentDirectory));
+
+            /* Add the "\" */
+            *(--ObjectName) = UNICODE_PATH_SEP;
+
+            /* Add the Parent Directory's Name */
+            if (LocalInfo && LocalInfo->Name.Buffer) 
+            {
+                /* Add the name */
+                ObjectName = (PWCH)((ULONG_PTR)ObjectName - LocalInfo->Name.Length);
+                RtlMoveMemory(ObjectName, LocalInfo->Name.Buffer, LocalInfo->Name.Length);
+
+                /* Move to next parent */
+                ParentDirectory = LocalInfo->Directory;
+            } 
+            else 
+            {
+                /* Directory without a name, we add "..." */
+                DPRINT("Nameless Directory\n");
+                ObjectName -= sizeof(UNICODE_NO_PATH);
+                ObjectName = UNICODE_NO_PATH;
+                break;
+            }
+        }
+
+        /* Add Root Directory Name */
+        *(--ObjectName) = UNICODE_PATH_SEP;
+        DPRINT("Current Buffer: %S\n", ObjectName);
+        ObjectNameInfo->Name.Length = (USHORT)NameSize;
+        ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize + sizeof(UNICODE_NULL));
+        ObjectNameInfo->Name.Buffer = ObjectName;
+        DPRINT("Complete: %wZ\n", ObjectNameInfo);
+    }
 
-      ObjectNameInfo->Name.MaximumLength = 0;
-      ObjectNameInfo->Name.Length = 0;
-      ObjectNameInfo->Name.Buffer = NULL;
+    return STATUS_SUCCESS;
+}
 
-      Status = STATUS_SUCCESS;
+NTSTATUS
+STDCALL
+ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                  PUNICODE_STRING ObjectName,
+                  POBJECT_TYPE ObjectType,
+                  ULONG ObjectSize,
+                  POBJECT_HEADER *ObjectHeader)
+{
+    POBJECT_HEADER Header;
+    BOOLEAN HasHandleInfo = FALSE;
+    BOOLEAN HasNameInfo = FALSE;
+    BOOLEAN HasCreatorInfo = FALSE;
+    POBJECT_HEADER_HANDLE_INFO HandleInfo;
+    POBJECT_HEADER_NAME_INFO NameInfo;
+    POBJECT_HEADER_CREATOR_INFO CreatorInfo;
+    POOL_TYPE PoolType;
+    ULONG FinalSize = ObjectSize;
+    ULONG Tag;
+        
+    /* If we don't have an Object Type yet, force NonPaged */
+    DPRINT("ObpAllocateObject\n");
+    if (!ObjectType) 
+    {
+        PoolType = NonPagedPool;
+        Tag = TAG('O', 'b', 'j', 'T');
     }
-
-  if (NT_SUCCESS (Status))
+    else
     {
-      ObjectNameInfo->Name.MaximumLength =
-       (ObjectNameInfo->Name.Length) ? ObjectNameInfo->Name.Length + sizeof(WCHAR) : 0;
-      *ReturnLength =
-       sizeof(OBJECT_NAME_INFORMATION) + ObjectNameInfo->Name.MaximumLength;
-      DPRINT ("Returned object path: %wZ\n", &ObjectNameInfo->Name);
+        PoolType = ObjectType->TypeInfo.PoolType;
+        Tag = ObjectType->Key;
+    }
+    
+    DPRINT("Checking ObjectName: %x\n", ObjectName);
+    /* Check if the Object has a name */
+    if (ObjectName->Buffer) 
+    {
+        FinalSize += sizeof(OBJECT_HEADER_NAME_INFO);
+        HasNameInfo = TRUE;
+    }
+    
+    if (ObjectType)
+    {
+        /* Check if the Object maintains handle counts */
+        DPRINT("Checking ObjectType->TypeInfo: %x\n", &ObjectType->TypeInfo);
+        if (ObjectType->TypeInfo.MaintainHandleCount)
+        {
+            FinalSize += sizeof(OBJECT_HEADER_HANDLE_INFO);
+            HasHandleInfo = TRUE;
+        }
+        
+        /* Check if the Object maintains type lists */
+        if (ObjectType->TypeInfo.MaintainTypeList) 
+        {
+            FinalSize += sizeof(OBJECT_HEADER_CREATOR_INFO);
+            HasCreatorInfo = TRUE;
+        }
     }
 
-  return Status;
+    /* Allocate memory for the Object and Header */
+    DPRINT("Allocating: %x %x\n", FinalSize, Tag);
+    Header = ExAllocatePoolWithTag(PoolType, FinalSize, Tag);
+    if (!Header) {
+        DPRINT1("Not enough memory!\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+           
+    /* Initialize Handle Info */
+    if (HasHandleInfo)
+    {
+        HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
+        DPRINT("Info: %x\n", HandleInfo);
+        HandleInfo->SingleEntry.HandleCount = 0;
+        Header = (POBJECT_HEADER)(HandleInfo + 1);
+    }
+       
+    /* Initialize the Object Name Info */
+    if (HasNameInfo) 
+    {
+        NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
+        DPRINT("Info: %x %wZ\n", NameInfo, ObjectName);
+        NameInfo->Name = *ObjectName;
+        NameInfo->Directory = NULL;
+        Header = (POBJECT_HEADER)(NameInfo + 1);
+    }
+    
+    /* Initialize Creator Info */
+    if (HasCreatorInfo)
+    {
+        CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
+        DPRINT("Info: %x\n", CreatorInfo);
+        /* FIXME: Needs Alex's Init patch
+         * CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
+         */
+        InitializeListHead(&CreatorInfo->TypeList);
+        Header = (POBJECT_HEADER)(CreatorInfo + 1);
+    }
+    
+    /* Initialize the object header */
+    RtlZeroMemory(Header, ObjectSize);
+    DPRINT("Initalized header %p\n", Header);
+    Header->HandleCount = 0;
+    Header->PointerCount = 1;
+    Header->Type = ObjectType;
+    Header->Flags = OB_FLAG_CREATE_INFO;
+    
+    /* Set the Offsets for the Info */
+    if (HasHandleInfo)
+    {
+        Header->HandleInfoOffset = HasNameInfo * sizeof(OBJECT_HEADER_NAME_INFO) + 
+                                   sizeof(OBJECT_HEADER_HANDLE_INFO) +
+                                   HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
+        Header->Flags |= OB_FLAG_SINGLE_PROCESS;
+    }
+    if (HasNameInfo)
+    {
+        Header->NameInfoOffset = sizeof(OBJECT_HEADER_NAME_INFO) + 
+                                 HasCreatorInfo * sizeof(OBJECT_HEADER_CREATOR_INFO);
+    }
+    if (HasCreatorInfo) Header->Flags |= OB_FLAG_CREATOR_INFO;
+    
+    if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_PERMANENT)
+    {
+        Header->Flags |= OB_FLAG_PERMANENT;
+    }
+    if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)
+    {
+        Header->Flags |= OB_FLAG_EXCLUSIVE;
+    }
+    
+    /* Link stuff to Object Header */
+    Header->ObjectCreateInfo = ObjectCreateInfo;
+    
+    /* Return Header */
+    *ObjectHeader = Header;
+    return STATUS_SUCCESS;
 }
 
-
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     ObCreateObject@36
@@ -348,127 +758,76 @@ ObQueryNameString (IN PVOID Object,
  * ARGUMENTS
  *
  * RETURN VALUE
+ *     Status
+ *
+ * @implemented
  */
-NTSTATUS STDCALL
-ObCreateObject (OUT PHANDLE Handle,
-               IN ACCESS_MASK DesiredAccess,
-               IN POBJECT_ATTRIBUTES ObjectAttributes,
-               IN POBJECT_TYPE Type,
-               OUT PVOID *Object)
+NTSTATUS 
+STDCALL
+ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL,
+               IN POBJECT_TYPE Type,
+               IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+               IN KPROCESSOR_MODE AccessMode,
+               IN OUT PVOID ParseContext OPTIONAL,
+               IN ULONG ObjectSize,
+               IN ULONG PagedPoolCharge OPTIONAL,
+               IN ULONG NonPagedPoolCharge OPTIONAL,
+               OUT PVOID *Object)
 {
-  PVOID Parent = NULL;
-  UNICODE_STRING RemainingPath;
-  POBJECT_HEADER Header;
-  POBJECT_HEADER ParentHeader = NULL;
-  NTSTATUS Status;
-  BOOLEAN ObjectAttached = FALSE;
-  PWCHAR NamePtr;
-
-  assert_irql(APC_LEVEL);
-
-  DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n",
-        Handle, ObjectAttributes, Type);
-
-  if (ObjectAttributes != NULL &&
-      ObjectAttributes->ObjectName != NULL &&
-      ObjectAttributes->ObjectName->Buffer != NULL)
+    NTSTATUS Status;
+    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+    UNICODE_STRING ObjectName;
+    POBJECT_HEADER Header;
+    
+    DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n", 
+            Type, ObjectAttributes, Object);
+            
+    /* Allocate a Buffer for the Object Create Info */
+    DPRINT("Allocating Create Buffer\n");
+    ObjectCreateInfo = ExAllocatePoolWithTag(NonPagedPool, 
+                                             sizeof(*ObjectCreateInfo),
+                                             TAG('O','b','C', 'I'));
+
+    /* Capture all the info */
+    DPRINT("Capturing Create Info\n");
+    Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                        ObjectAttributesAccessMode,
+                                        Type,
+                                        ObjectCreateInfo,
+                                        &ObjectName);
+                                        
+    if (NT_SUCCESS(Status))
     {
-      Status = ObFindObject(ObjectAttributes,
-                           &Parent,
-                           &RemainingPath,
-                           NULL);
-      if (!NT_SUCCESS(Status))
-       {
-         DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status);
-         return(Status);
-       }
+        /* Allocate the Object */
+        DPRINT("Allocating: %wZ\n", &ObjectName);
+        Status = ObpAllocateObject(ObjectCreateInfo,
+                                   &ObjectName,
+                                   Type, 
+                                   OBJECT_ALLOC_SIZE(ObjectSize), 
+                                   &Header);
+                                   
+        if (NT_SUCCESS(Status))
+        {
+            /* Return the Object */
+            DPRINT("Returning Object\n");
+            *Object = &Header->Body;
+            
+            /* Return to caller, leave the Capture Info Alive for ObInsert */
+            return Status;
+        }
+        
+        /* Release the Capture Info, we don't need it */
+        DPRINT1("Allocation failed\n");
+        ObpReleaseCapturedAttributes(ObjectCreateInfo);
+        if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
     }
-  else
-    {
-      RtlInitUnicodeString(&RemainingPath, NULL);
-    }
-
-  RtlMapGenericMask(&DesiredAccess,
-                   Type->Mapping);
-
-  Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
-                                                OBJECT_ALLOC_SIZE(Type),
-                                                Type->Tag);
-  ObInitializeObject(Header,
-                    NULL,
-                    DesiredAccess,
-                    Type,
-                    ObjectAttributes);
-
-  if (Parent != NULL)
-    {
-      ParentHeader = BODY_TO_HEADER(Parent);
-    }
-
-  if (ParentHeader != NULL &&
-      ParentHeader->ObjectType == ObDirectoryType &&
-      RemainingPath.Buffer != NULL)
-    {
-      NamePtr = RemainingPath.Buffer;
-      if (*NamePtr == L'\\')
-       NamePtr++;
-
-      ObpAddEntryDirectory(Parent,
-                          Header,
-                          NamePtr);
-
-      ObjectAttached = TRUE;
-    }
-
-  if ((Header->ObjectType != NULL) &&
-      (Header->ObjectType->Create != NULL))
-    {
-      DPRINT("Calling %x\n", Header->ObjectType->Create);
-      Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
-                                         Parent,
-                                         RemainingPath.Buffer,
-                                         ObjectAttributes);
-      if (!NT_SUCCESS(Status))
-       {
-         if (ObjectAttached == TRUE)
-           {
-             ObpRemoveEntryDirectory(Header);
-           }
-         if (Parent)
-           {
-             ObDereferenceObject(Parent);
-           }
-         RtlFreeUnicodeString(&Header->Name);
-         RtlFreeUnicodeString(&RemainingPath);
-         ExFreePool(Header);
-         return(Status);
-       }
-    }
-  RtlFreeUnicodeString( &RemainingPath );
-
-  if (Object != NULL)
-    {
-      *Object = HEADER_TO_BODY(Header);
-    }
-
-  if (Handle != NULL)
-  {
-     ObCreateHandle(PsGetCurrentProcess(),
-                   *Object,
-                   DesiredAccess,
-                   ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE,
-                   Handle);
-  }
-
-  return(STATUS_SUCCESS);
+     
+    /* We failed, so release the Buffer */
+    DPRINT1("Capture failed\n");
+    ExFreePool(ObjectCreateInfo);
+    return Status;
 }
 
-
-NTSTATUS STDCALL
-ObReferenceObjectByPointer(IN PVOID Object,
-                          IN ACCESS_MASK DesiredAccess,
-                          IN POBJECT_TYPE ObjectType,
-                          IN KPROCESSOR_MODE AccessMode)
 /*
  * FUNCTION: Increments the pointer reference count for a given object
  * ARGUMENTS:
@@ -477,51 +836,74 @@ ObReferenceObjectByPointer(IN PVOID Object,
  *         ObjectType = Points to the object type structure
  *         AccessMode = Type of access check to perform
  * RETURNS: Status
+ *
+ * @implemented
  */
+NTSTATUS STDCALL
+ObReferenceObjectByPointer(IN PVOID Object,
+                          IN ACCESS_MASK DesiredAccess,
+                          IN POBJECT_TYPE ObjectType,
+                          IN KPROCESSOR_MODE AccessMode)
 {
    POBJECT_HEADER Header;
 
-//   DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
-//       Object,ObjectType);
-   
+   /* NOTE: should be possible to reference an object above APC_LEVEL! */
+
+   DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n",
+         Object,ObjectType);
+
    Header = BODY_TO_HEADER(Object);
-   
-   if (ObjectType != NULL && Header->ObjectType != ObjectType)
+
+   if (ObjectType != NULL && Header->Type != ObjectType)
      {
-       DPRINT("Failed %x (type was %x %S) should be %x %S\n",
+       DPRINT("Failed %p (type was %x %wZ) should be %x %wZ\n",
                Header,
-               Header->ObjectType,
-               Header->ObjectType->TypeName.Buffer,
+               Header->Type,
+               &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(Header->Type))->Name,
                ObjectType,
-    ObjectType->TypeName.Buffer);
+               &HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(ObjectType))->Name);
        return(STATUS_UNSUCCESSFUL);
      }
-   if (Header->ObjectType == PsProcessType)
+   if (Header->Type == PsProcessType)
      {
-       DPRINT("Ref p 0x%x refcount %d type %x ",
-               Object, Header->RefCount, PsProcessType);
+       DPRINT("Ref p 0x%x PointerCount %d type %x ",
+               Object, Header->PointerCount, PsProcessType);
        DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
      }
-   if (Header->ObjectType == PsThreadType)
+   if (Header->Type == PsThreadType)
      {
-       DPRINT("Deref t 0x%x with refcount %d type %x ",
-               Object, Header->RefCount, PsThreadType);
+       DPRINT("Deref t 0x%x with PointerCount %d type %x ",
+               Object, Header->PointerCount, PsThreadType);
        DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
      }
-   if (Header->CloseInProcess)
+
+   if (Header->PointerCount == 0 && !(Header->Flags & OB_FLAG_PERMANENT))
    {
+      if (Header->Type == PsProcessType)
+        {
+         return STATUS_PROCESS_IS_TERMINATING;
+       }
+      if (Header->Type == PsThreadType)
+        {
+         return STATUS_THREAD_IS_TERMINATING;
+       }
       return(STATUS_UNSUCCESSFUL);
    }
 
-   InterlockedIncrement(&Header->RefCount);
-   
+   if (1 == InterlockedIncrement(&Header->PointerCount) && !(Header->Flags & OB_FLAG_PERMANENT))
+   {
+      KEBUGCHECK(0);
+   }
+
    return(STATUS_SUCCESS);
 }
 
 
+/*
+ * @implemented
+ */
 NTSTATUS STDCALL
-ObOpenObjectByPointer(IN POBJECT Object,
+ObOpenObjectByPointer(IN PVOID Object,
                      IN ULONG HandleAttributes,
                      IN PACCESS_STATE PassedAccessState,
                      IN ACCESS_MASK DesiredAccess,
@@ -530,9 +912,11 @@ ObOpenObjectByPointer(IN POBJECT Object,
                      OUT PHANDLE Handle)
 {
    NTSTATUS Status;
-   
+
+   PAGED_CODE();
+
    DPRINT("ObOpenObjectByPointer()\n");
-   
+
    Status = ObReferenceObjectByPointer(Object,
                                       0,
                                       ObjectType,
@@ -541,62 +925,153 @@ ObOpenObjectByPointer(IN POBJECT Object,
      {
        return Status;
      }
-   
-   Status = ObCreateHandle(PsGetCurrentProcess(),
-                          Object,
-                          DesiredAccess,
-                          HandleAttributes & OBJ_INHERIT,
-                          Handle);
-   
+
+   Status = ObpCreateHandle(Object,
+                           DesiredAccess,
+                           HandleAttributes,
+                           Handle);
+
    ObDereferenceObject(Object);
-   
+
    return STATUS_SUCCESS;
 }
 
 
 static NTSTATUS
-ObpPerformRetentionChecks(POBJECT_HEADER Header)
+ObpDeleteObject(POBJECT_HEADER Header)
 {
-//  DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
-//       Header,Header->RefCount,Header->HandleCount);
+  PVOID HeaderLocation = Header;
+  POBJECT_HEADER_HANDLE_INFO HandleInfo;
+  POBJECT_HEADER_NAME_INFO NameInfo;
+  POBJECT_HEADER_CREATOR_INFO CreatorInfo;
   
-  if (Header->RefCount < 0)
+  DPRINT("ObpDeleteObject(Header %p)\n", Header);
+  if (KeGetCurrentIrql() != PASSIVE_LEVEL)
     {
-      CPRINT("Object %x/%x has invalid reference count (%d)\n",
-            Header, HEADER_TO_BODY(Header), Header->RefCount);
-      KeBugCheck(0);
+      DPRINT("ObpDeleteObject called at an unsupported IRQL.  Use ObpDeleteObjectDpcLevel instead.\n");
+      KEBUGCHECK(0);
     }
-  if (Header->HandleCount < 0)
+
+  if (Header->Type != NULL &&
+      Header->Type->TypeInfo.DeleteProcedure != NULL)
     {
-      CPRINT("Object %x/%x has invalid handle count (%d)\n",
-            Header, HEADER_TO_BODY(Header), Header->HandleCount);
-      KeBugCheck(0);
+      Header->Type->TypeInfo.DeleteProcedure(&Header->Body);
     }
-  
-  if (Header->RefCount == 0 &&
-      Header->HandleCount == 0 &&
-      Header->Permanent == FALSE)
+
+  if (Header->SecurityDescriptor != NULL)
+    {
+      ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
+    }
+    
+  if (HEADER_TO_OBJECT_NAME(Header))
     {
-      if (Header->CloseInProcess)
+      if(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer)
+        {
+          ExFreePool(HEADER_TO_OBJECT_NAME(Header)->Name.Buffer);
+        }
+    }
+  if (Header->ObjectCreateInfo)
+    {
+      ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
+      ExFreePool(Header->ObjectCreateInfo);
+    }
+    
+  /* To find the header, walk backwards from how we allocated */
+  if ((CreatorInfo = HEADER_TO_CREATOR_INFO(Header)))
+  {
+      HeaderLocation = CreatorInfo;
+  }   
+  if ((NameInfo = HEADER_TO_OBJECT_NAME(Header)))
+  {
+      HeaderLocation = NameInfo;
+  }
+  if ((HandleInfo = HEADER_TO_HANDLE_INFO(Header)))
+  {
+      HeaderLocation = HandleInfo;
+  }
+
+  DPRINT("ObPerformRetentionChecks() = Freeing object\n");
+  ExFreePool(HeaderLocation);
+
+  return(STATUS_SUCCESS);
+}
+
+
+VOID STDCALL
+ObpDeleteObjectWorkRoutine (IN PVOID Parameter)
+{
+  PRETENTION_CHECK_PARAMS Params = (PRETENTION_CHECK_PARAMS)Parameter;
+  /* ULONG Tag; */ /* See below */
+
+  ASSERT(Params);
+  ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); /* We need PAGED_CODE somewhere... */
+
+  /* Turn this on when we have ExFreePoolWithTag
+  Tag = Params->ObjectHeader->Type->Tag; */
+  ObpDeleteObject(Params->ObjectHeader);
+  ExFreePool(Params);
+  /* ExFreePoolWithTag(Params, Tag); */
+}
+
+
+STATIC NTSTATUS
+ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
+                       IN LONG OldPointerCount)
+{
+#if 0
+  if (ObjectHeader->PointerCount < 0)
+    {
+      CPRINT("Object %p/%p has invalid reference count (%d)\n",
+            ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+            ObjectHeader->PointerCount);
+      KEBUGCHECK(0);
+    }
+
+  if (ObjectHeader->HandleCount < 0)
+    {
+      CPRINT("Object %p/%p has invalid handle count (%d)\n",
+            ObjectHeader, HEADER_TO_BODY(ObjectHeader),
+            ObjectHeader->HandleCount);
+      KEBUGCHECK(0);
+    }
+#endif
+
+
+  switch (KeGetCurrentIrql ())
+    {
+    case PASSIVE_LEVEL:
+      return ObpDeleteObject (ObjectHeader);
+
+    case APC_LEVEL:
+    case DISPATCH_LEVEL:
       {
-        KeBugCheck(0);
-        return STATUS_UNSUCCESSFUL;
+       PRETENTION_CHECK_PARAMS Params;
+
+       /*
+         We use must succeed pool here because if the allocation fails
+         then we leak memory.
+       */
+       Params = (PRETENTION_CHECK_PARAMS)
+         ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
+                               sizeof(RETENTION_CHECK_PARAMS),
+                               ObjectHeader->Type->Key);
+       Params->ObjectHeader = ObjectHeader;
+       ExInitializeWorkItem(&Params->WorkItem,
+                            ObpDeleteObjectWorkRoutine,
+                            (PVOID)Params);
+       ExQueueWorkItem(&Params->WorkItem,
+                       CriticalWorkQueue);
       }
-      Header->CloseInProcess = TRUE;
-      if (Header->ObjectType != NULL &&
-         Header->ObjectType->Delete != NULL)
-       {
-         Header->ObjectType->Delete(HEADER_TO_BODY(Header));
-       }
-      if (Header->Name.Buffer != NULL)
-       {
-         ObpRemoveEntryDirectory(Header);
-         RtlFreeUnicodeString(&Header->Name);
-       }
-      DPRINT("ObPerformRetentionChecks() = Freeing object\n");
-      ExFreePool(Header);
+      return STATUS_PENDING;
+
+    default:
+      DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
+            "IRQL %u!\n", KeGetCurrentIrql());
+      KEBUGCHECK(0);
+      return STATUS_UNSUCCESSFUL;
     }
-  return(STATUS_SUCCESS);
+
+  return STATUS_SUCCESS;
 }
 
 
@@ -613,26 +1088,26 @@ ObpPerformRetentionChecks(POBJECT_HEADER Header)
  *
  * RETURN VALUE
  *     None.
+ *
+ * @implemented
  */
 VOID FASTCALL
 ObfReferenceObject(IN PVOID Object)
 {
   POBJECT_HEADER Header;
 
-  assert(Object);
+  ASSERT(Object);
 
   Header = BODY_TO_HEADER(Object);
 
-  if (Header->CloseInProcess)
+  /* No one should be referencing an object once we are deleting it. */
+  if (InterlockedIncrement(&Header->PointerCount) == 1 && !(Header->Flags & OB_FLAG_PERMANENT))
   {
-      KeBugCheck(0);
+     KEBUGCHECK(0);
   }
-  InterlockedIncrement(&Header->RefCount);
 
-  ObpPerformRetentionChecks(Header);
 }
 
-
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     ObfDereferenceObject@4
@@ -646,35 +1121,88 @@ ObfReferenceObject(IN PVOID Object)
  *
  * RETURN VALUE
  *     None.
+ *
+ * @implemented
  */
 VOID FASTCALL
 ObfDereferenceObject(IN PVOID Object)
 {
   POBJECT_HEADER Header;
-  extern POBJECT_TYPE PsProcessType;
+  LONG NewPointerCount;
+  BOOL Permanent;
 
-  assert(Object);
+  ASSERT(Object);
 
+  /* Extract the object header. */
   Header = BODY_TO_HEADER(Object);
-
-  if (Header->ObjectType == PsProcessType)
+  Permanent = Header->Flags & OB_FLAG_PERMANENT;
+
+  /*
+     Drop our reference and get the new count so we can tell if this was the
+     last reference.
+  */
+  NewPointerCount = InterlockedDecrement(&Header->PointerCount);
+  DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewPointerCount);
+  ASSERT(NewPointerCount >= 0);
+
+  /* Check whether the object can now be deleted. */
+  if (NewPointerCount == 0 &&
+      !Permanent)
     {
-      DPRINT("Deref p 0x%x with refcount %d type %x ",
-            Object, Header->RefCount, PsProcessType);
-      DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
+      ObpDeleteObjectDpcLevel(Header, NewPointerCount);
     }
-  if (Header->ObjectType == PsThreadType)
-    {
-      DPRINT("Deref t 0x%x with refcount %d type %x ",
-            Object, Header->RefCount, PsThreadType);
-      DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
-    }
-  
-  InterlockedDecrement(&Header->RefCount);
-  
-  ObpPerformRetentionChecks(Header);
 }
 
+VOID
+FASTCALL
+ObInitializeFastReference(IN PEX_FAST_REF FastRef,
+                          PVOID Object)
+{
+    /* FIXME: Fast Referencing is Unimplemented */
+    FastRef->Object = Object;
+}
+
+
+PVOID
+FASTCALL
+ObFastReferenceObject(IN PEX_FAST_REF FastRef)
+{
+    /* FIXME: Fast Referencing is Unimplemented */
+
+    /* Do a normal Reference */
+    ObReferenceObject(FastRef->Object);
+
+    /* Return the Object */
+    return FastRef->Object;
+}
+
+VOID
+FASTCALL
+ObFastDereferenceObject(IN PEX_FAST_REF FastRef,
+                        PVOID Object)
+{
+    /* FIXME: Fast Referencing is Unimplemented */
+
+    /* Do a normal Dereference */
+    ObDereferenceObject(FastRef->Object);
+}
+
+PVOID
+FASTCALL
+ObFastReplaceObject(IN PEX_FAST_REF FastRef,
+                    PVOID Object)
+{
+    PVOID OldObject = FastRef->Object;
+
+    /* FIXME: Fast Referencing is Unimplemented */
+    FastRef->Object = Object;
+
+    /* Do a normal Dereference */
+    ObDereferenceObject(OldObject);
+
+    /* Return old Object*/
+    return OldObject;
+}
 
 /**********************************************************************
  * NAME                                                        EXPORTED
@@ -688,16 +1216,20 @@ ObfDereferenceObject(IN PVOID Object)
  *
  * RETURN VALUE
  *     Reference count.
+ *
+ * @implemented
  */
 ULONG STDCALL
 ObGetObjectPointerCount(PVOID Object)
 {
   POBJECT_HEADER Header;
 
-  assert(Object);
+  PAGED_CODE();
+
+  ASSERT(Object);
   Header = BODY_TO_HEADER(Object);
 
-  return(Header->RefCount);
+  return Header->PointerCount;
 }
 
 
@@ -715,14 +1247,45 @@ ObGetObjectPointerCount(PVOID Object)
  *     Reference count.
  */
 ULONG
+NTAPI
 ObGetObjectHandleCount(PVOID Object)
 {
   POBJECT_HEADER Header;
 
-  assert(Object);
+  PAGED_CODE();
+
+  ASSERT(Object);
   Header = BODY_TO_HEADER(Object);
 
-  return(Header->HandleCount);
+  return Header->HandleCount;
+}
+
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObDereferenceObject@4
+ *
+ * DESCRIPTION
+ *     Decrements a given object's reference count and performs
+ *     retention checks.
+ *
+ * ARGUMENTS
+ *     ObjectBody = Body of the object.
+ *
+ * RETURN VALUE
+ *     None.
+ *
+ * @implemented
+ */
+
+#ifdef ObDereferenceObject
+#undef ObDereferenceObject
+#endif
+
+VOID STDCALL
+ObDereferenceObject(IN PVOID Object)
+{
+  ObfDereferenceObject(Object);
 }
 
 /* EOF */