Free all allocated memory in ObpDeleteObject.
[reactos.git] / reactos / ntoskrnl / ob / object.c
index 2d94ad8..fc27eb3 100644 (file)
@@ -1,14 +1,12 @@
 /* $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)
- * UPDATE HISTORY:
- *               10/06/98: Created
- *               09/13/03: Fixed various ObXxx routines to not call retention
- *                         checks directly at a raised IRQL.
+ *
+ * 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 *****************************************************************/
@@ -24,275 +22,248 @@ typedef struct _RETENTION_CHECK_PARAMS
   POBJECT_HEADER ObjectHeader;
 } RETENTION_CHECK_PARAMS, *PRETENTION_CHECK_PARAMS;
 
-
 /* FUNCTIONS ************************************************************/
 
-PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
-{
-  return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
-}
-
-
-POBJECT_HEADER BODY_TO_HEADER(PVOID body)
-{
-  PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
-  return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
-}
-
 NTSTATUS
-ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
-                           IN KPROCESSOR_MODE AccessMode,
-                           IN POOL_TYPE PoolType,
-                           IN BOOLEAN CaptureIfKernel,
-                           OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes  OPTIONAL,
-                           OUT PUNICODE_STRING ObjectName  OPTIONAL)
+STDCALL
+ObpCaptureObjectName(IN OUT PUNICODE_STRING CapturedName,
+                     IN PUNICODE_STRING ObjectName,
+                     IN KPROCESSOR_MODE AccessMode)
 {
-  OBJECT_ATTRIBUTES AttributesCopy;
-  NTSTATUS Status = STATUS_SUCCESS;
-  
-  /* at least one output parameter must be != NULL! */
-  ASSERT(((ULONG_PTR)CapturedObjectAttributes ^ (ULONG_PTR)ObjectName) != 0);
-  
-  if(ObjectAttributes == NULL)
-  {
-failbasiccleanup:
-    if(ObjectName != NULL)
-    {
-      RtlInitUnicodeString(ObjectName, NULL);
-    }
-    if(CapturedObjectAttributes != NULL)
-    {
-      RtlZeroMemory(CapturedObjectAttributes, sizeof(CAPTURED_OBJECT_ATTRIBUTES));
-    }
-    return Status; /* STATUS_SUCCESS */
-  }
-  
-  if(AccessMode != KernelMode)
-  {
-    _SEH_TRY
-    {
-      ProbeForRead(ObjectAttributes,
-                   sizeof(ObjectAttributes),
-                   sizeof(ULONG));
-      /* make a copy on the stack */
-      AttributesCopy = *ObjectAttributes;
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
+    NTSTATUS Status = STATUS_SUCCESS;
+    UNICODE_STRING LocalName;
     
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-  }
-  else if(AccessMode == KernelMode && !CaptureIfKernel)
-  {
-    if(ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))
-    {
-      /* we don't have to capture any memory, the caller considers the passed data
-         as valid */
-      if(ObjectName != NULL)
-      {
-        *ObjectName = *ObjectAttributes->ObjectName;
-      }
-      if(CapturedObjectAttributes != NULL)
-      {
-        CapturedObjectAttributes->RootDirectory = ObjectAttributes->RootDirectory;
-        CapturedObjectAttributes->Attributes = ObjectAttributes->Attributes;
-        CapturedObjectAttributes->SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
-      }
-
-      return STATUS_SUCCESS;
-    }
-    else
+    /* First Probe the String */
+    DPRINT("ObpCaptureObjectName: %wZ\n", ObjectName);
+    if (AccessMode != KernelMode)
     {
-      Status = STATUS_INVALID_PARAMETER;
-      goto failbasiccleanup;
-    }
-  }
-  else
-  {
-    AttributesCopy = *ObjectAttributes;
-  }
-  
-  /* if Length isn't as expected, bail with an invalid parameter status code so
-     the caller knows he passed garbage... */
-  if(AttributesCopy.Length != sizeof(OBJECT_ATTRIBUTES))
-  {
-    Status = STATUS_INVALID_PARAMETER;
-    goto failbasiccleanup;
-  }
-  
-  if(CapturedObjectAttributes != NULL)
-  {
-    CapturedObjectAttributes->RootDirectory = AttributesCopy.RootDirectory;
-    CapturedObjectAttributes->Attributes = AttributesCopy.Attributes;
-
-    if(AttributesCopy.SecurityDescriptor != NULL)
-    {
-      Status = SeCaptureSecurityDescriptor(AttributesCopy.SecurityDescriptor,
-                                           AccessMode,
-                                           PoolType,
-                                           TRUE,
-                                           &CapturedObjectAttributes->SecurityDescriptor);
-      if(!NT_SUCCESS(Status))
-      {
-        DPRINT1("Unable to capture the security descriptor!!!\n");
-        goto failbasiccleanup;
-      }
-    }
-    else
-    {
-      CapturedObjectAttributes->SecurityDescriptor = NULL;
-    }
-  }
-  
-  if(ObjectName != NULL)
-  {
-    if(AttributesCopy.ObjectName != NULL)
-    {
-      UNICODE_STRING OriginalCopy;
-      
-      if(AccessMode != KernelMode)
-      {
+        DPRINT("Probing Struct\n");
         _SEH_TRY
         {
-          /* probe the ObjectName structure and make a local stack copy of it */
-          ProbeForRead(AttributesCopy.ObjectName,
-                       sizeof(UNICODE_STRING),
-                       sizeof(ULONG));
-          OriginalCopy = *AttributesCopy.ObjectName;
-          if(OriginalCopy.Length > 0)
-          {
-            ProbeForRead(OriginalCopy.Buffer,
-                         OriginalCopy.Length,
-                         sizeof(WCHAR));
-          }
+            /* FIXME: Explorer or win32 broken I think */
+            #if 0
+            ProbeForRead(ObjectName,
+                         sizeof(UNICODE_STRING),
+                         sizeof(USHORT));
+            #endif
+            LocalName = *ObjectName;
         }
         _SEH_HANDLE
         {
-          Status = _SEH_GetExceptionCode();
+            Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
         
-        if(NT_SUCCESS(Status))
+        if (NT_SUCCESS(Status))
         {
-          if(OriginalCopy.Length > 0)
-          {
-            ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
-            ObjectName->Buffer = ExAllocatePool(PoolType,
-                                                ObjectName->MaximumLength);
-            if(ObjectName->Buffer != NULL)
+            DPRINT("Probing OK\n");
+             _SEH_TRY
             {
-              _SEH_TRY
-              {
-                /* no need to probe OriginalCopy.Buffer again, we already did that
-                   when capturing the UNICODE_STRING structure itself */
-                RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
-                ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
-              }
-              _SEH_HANDLE
-              {
-                Status = _SEH_GetExceptionCode();
-              }
-              _SEH_END;
+                #if 0
+                DPRINT("Probing buffer\n");
+                ProbeForRead(LocalName.Buffer,
+                             LocalName.Length,
+                             sizeof(USHORT));
+                #endif
             }
-            else
+            _SEH_HANDLE
             {
-              Status = STATUS_INSUFFICIENT_RESOURCES;
+                Status = _SEH_GetExceptionCode();
             }
-          }
-          else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
-          {
-            /* if the caller specified a root directory, there must be an object name! */
-            Status = STATUS_OBJECT_NAME_INVALID;
-          }
+            _SEH_END;
         }
+        
+        /* Fail if anything up to here died */
+        if (!NT_SUCCESS(Status)) 
+        {
+            DPRINT1("Probing failed\n");
+            return Status;
+        }
+    }
+    else
+    {
+        LocalName = *ObjectName;
+    }
+    
+    /* Make sure there really is a string */
+    DPRINT("Probing OK\n");
+    if (LocalName.Length)
+    {
+        /* Allocate a non-paged buffer for this string */
+        DPRINT("Capturing String\n");
+        CapturedName->Length = LocalName.Length;
+        CapturedName->MaximumLength = LocalName.Length + sizeof(WCHAR);
+        CapturedName->Buffer = ExAllocatePoolWithTag(NonPagedPool, 
+                                                     CapturedName->MaximumLength,
+                                                     TAG('O','b','N','m'));
+                                                     
+        /* Copy the string and null-terminate it */
+        RtlMoveMemory(CapturedName->Buffer, LocalName.Buffer, LocalName.Length);
+        CapturedName->Buffer[LocalName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+        DPRINT("String Captured: %p, %wZ\n", CapturedName, CapturedName);
+    }
+    
+    return Status;
+}
 
-        /* handle failure */
-        if(!NT_SUCCESS(Status))
+NTSTATUS
+STDCALL
+ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                           IN KPROCESSOR_MODE AccessMode,
+                           IN POBJECT_TYPE ObjectType,
+                           IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                           OUT PUNICODE_STRING ObjectName)
+{
+    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));
+    
+    /* Check if we got Oba */
+    if (ObjectAttributes)
+    {
+        if (AccessMode != KernelMode)
         {
-failallocatedcleanup:
-          if(ObjectName->Buffer)
-          {
-            ExFreePool(ObjectName->Buffer);
-          }
-          if(CapturedObjectAttributes != NULL)
-          {
-            /* cleanup allocated resources */
-            SeReleaseSecurityDescriptor(CapturedObjectAttributes->SecurityDescriptor,
-                                        AccessMode,
-                                        TRUE);
-          }
-          goto failbasiccleanup;
+            DPRINT("Probing OBA\n");
+            _SEH_TRY
+            {
+                /* FIXME: SMSS SENDS BULLSHIT. */
+                #if 0
+                ProbeForRead(ObjectAttributes,
+                             sizeof(ObjectAttributes),
+                             sizeof(ULONG));
+                #endif
+            }
+            _SEH_HANDLE
+            {
+                Status = _SEH_GetExceptionCode();
+            }
+            _SEH_END;
         }
-      }
-      else /* AccessMode == KernelMode */
-      {
-        OriginalCopy = *AttributesCopy.ObjectName;
         
-        if(OriginalCopy.Length > 0)
+        /* Validate the Size */
+        DPRINT("Validating OBA\n");
+        if (ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES))
         {
-          ObjectName->MaximumLength = OriginalCopy.Length + sizeof(WCHAR);
-          ObjectName->Buffer = ExAllocatePool(PoolType,
-                                              ObjectName->MaximumLength);
-          if(ObjectName->Buffer != NULL)
-          {
-            RtlCopyMemory(ObjectName->Buffer, OriginalCopy.Buffer, OriginalCopy.Length);
-            ObjectName->Buffer[OriginalCopy.Length / sizeof(WCHAR)] = L'\0';
-          }
-          else
-          {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-          }
+            Status = STATUS_INVALID_PARAMETER;
         }
-        else if(AttributesCopy.RootDirectory != NULL /* && OriginalCopy.Length == 0 */)
+
+        /* Fail if SEH or Size Validation failed */
+        if(!NT_SUCCESS(Status))
         {
-          /* if the caller specified a root directory, there must be an object name! */
-          Status = STATUS_OBJECT_NAME_INVALID;
+            DPRINT1("ObpCaptureObjectAttributes failed to probe object attributes\n");
+            goto fail;
         }
         
-        if(!NT_SUCCESS(Status))
+        /* 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)
         {
-          goto failallocatedcleanup;
+            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;
+                goto fail;
+            }
+            
+            DPRINT("Probe done\n");
+            ObjectCreateInfo->SecurityDescriptorCharge = 0; /* FIXME */
+            ObjectCreateInfo->ProbeMode = AccessMode;
         }
-      }
+        
+        /* Validate the QoS */
+        if (SecurityQos)
+        {
+            if (AccessMode != KernelMode)
+            {
+                DPRINT("Probing QoS\n");
+                _SEH_TRY
+                {
+                    ProbeForRead(SecurityQos,
+                                 sizeof(SECURITY_QUALITY_OF_SERVICE),
+                                 sizeof(ULONG));
+                }
+                _SEH_HANDLE
+                {
+                    Status = _SEH_GetExceptionCode();
+                }
+                _SEH_END;
+            }
+
+            if(!NT_SUCCESS(Status))
+            {
+                DPRINT1("Unable to capture QoS!!!\n");
+                goto fail;
+            }
+            
+            ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
+            ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
+        }
+    }
+    
+    /* Clear Local Object Name */
+    DPRINT("Clearing name\n");
+    RtlZeroMemory(ObjectName, sizeof(UNICODE_STRING));
+    
+    /* Now check if the Object Attributes had an Object Name */
+    if (LocalObjectName)
+    {
+        DPRINT("Name Buffer: %x\n", LocalObjectName->Buffer);
+        Status = ObpCaptureObjectName(ObjectName,
+                                      LocalObjectName,
+                                      AccessMode);
     }
     else
     {
-      RtlInitUnicodeString(ObjectName, NULL);
+        /* He can't have specified a Root Directory */
+        if (ObjectCreateInfo->RootDirectory)
+        {
+            DPRINT1("Invalid name\n");
+            Status = STATUS_OBJECT_NAME_INVALID;
+        }
+    }
+    
+fail:
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to capture, cleaning up\n");
+        ObpReleaseCapturedAttributes(ObjectCreateInfo);
     }
-  }
-  
-  return Status;
+    
+    DPRINT("Return to caller\n");
+    return Status;
 }
 
+
 VOID
-ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes  OPTIONAL,
-                           IN PUNICODE_STRING ObjectName  OPTIONAL,
-                           IN KPROCESSOR_MODE AccessMode,
-                           IN BOOLEAN CaptureIfKernel)
+STDCALL
+ObpReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo)
 {
-  /* WARNING - You need to pass the same parameters to this function as you passed
-               to ObpCaptureObjectAttributes() to avoid memory leaks */
-  if(AccessMode != KernelMode ||
-     (AccessMode == KernelMode && CaptureIfKernel))
-  {
-    if(CapturedObjectAttributes != NULL &&
-       CapturedObjectAttributes->SecurityDescriptor != NULL)
-    {
-      ExFreePool(CapturedObjectAttributes->SecurityDescriptor);
-      CapturedObjectAttributes->SecurityDescriptor = NULL;
-    }
-    if(ObjectName != NULL &&
-       ObjectName->Length > 0)
+    /* Release the SD, it's the only thing we allocated */
+    if (ObjectCreateInfo->SecurityDescriptor)
     {
-      ExFreePool(ObjectName->Buffer);
+        SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
+                                    ObjectCreateInfo->ProbeMode,
+                                    TRUE);
+        ObjectCreateInfo->SecurityDescriptor = NULL;                                        
     }
-  }
 }
 
 
@@ -320,7 +291,8 @@ ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttribut
  * RETURN VALUE
  */
 NTSTATUS
-ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
+ObFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+            PUNICODE_STRING ObjectName,
             PVOID* ReturnedObject,
             PUNICODE_STRING RemainingPath,
             POBJECT_TYPE ObjectType)
@@ -333,16 +305,15 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
   PWSTR current;
   UNICODE_STRING PathString;
   ULONG Attributes;
-  PUNICODE_STRING ObjectName;
 
-  DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
-        "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
-  DPRINT("ObjectAttributes->ObjectName %wZ\n",
-        ObjectAttributes->ObjectName);
+  PAGED_CODE();
+
+  DPRINT("ObFindObject(ObjectCreateInfo %x, ReturnedObject %x, "
+        "RemainingPath %x)\n",ObjectCreateInfo,ReturnedObject,RemainingPath);
 
   RtlInitUnicodeString (RemainingPath, NULL);
 
-  if (ObjectAttributes->RootDirectory == NULL)
+  if (ObjectCreateInfo->RootDirectory == NULL)
     {
       ObReferenceObjectByPointer(NameSpaceRoot,
                                 DIRECTORY_TRAVERSE,
@@ -352,8 +323,8 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
     }
   else
     {
-      Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
-                                        DIRECTORY_TRAVERSE,
+      Status = ObReferenceObjectByHandle(ObjectCreateInfo->RootDirectory,
+                                        0,
                                         NULL,
                                         UserMode,
                                         &CurrentObject,
@@ -364,7 +335,6 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
        }
     }
 
-  ObjectName = ObjectAttributes->ObjectName;
   if (ObjectName->Length == 0 ||
       ObjectName->Buffer[0] == UNICODE_NULL)
     {
@@ -372,10 +342,11 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
       return STATUS_SUCCESS;
     }
 
-  if (ObjectAttributes->RootDirectory == NULL &&
+  if (ObjectCreateInfo->RootDirectory == NULL &&
       ObjectName->Buffer[0] != L'\\')
     {
       ObDereferenceObject (CurrentObject);
+      DPRINT1("failed\n");
       return STATUS_UNSUCCESSFUL;
     }
 
@@ -398,7 +369,7 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
   current = PathString.Buffer;
 
   RootObject = CurrentObject;
-  Attributes = ObjectAttributes->Attributes;
+  Attributes = ObjectCreateInfo->Attributes;
   if (ObjectType == ObSymbolicLinkType)
     Attributes |= OBJ_OPENLINK;
 
@@ -408,14 +379,14 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
        CurrentHeader = BODY_TO_HEADER(CurrentObject);
 
        DPRINT("Current ObjectType %wZ\n",
-              &CurrentHeader->ObjectType->TypeName);
+              &CurrentHeader->ObjectType->Name);
 
-       if (CurrentHeader->ObjectType->Parse == NULL)
+       if (CurrentHeader->ObjectType->TypeInfo.ParseProcedure == NULL)
          {
             DPRINT("Current object can't parse\n");
             break;
          }
-       Status = CurrentHeader->ObjectType->Parse(CurrentObject,
+       Status = CurrentHeader->ObjectType->TypeInfo.ParseProcedure(CurrentObject,
                                                  &NextObject,
                                                  &PathString,
                                                  &current,
@@ -425,7 +396,7 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
             /* reparse the object path */
             NextObject = NameSpaceRoot;
             current = PathString.Buffer;
-            
+
             ObReferenceObjectByPointer(NextObject,
                                        DIRECTORY_TRAVERSE,
                                        NULL,
@@ -441,7 +412,10 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
     }
 
   if (current)
-     RtlCreateUnicodeString (RemainingPath, current);
+  {
+     RtlpCreateUnicodeString (RemainingPath, current, NonPagedPool);
+  }
+
   RtlFreeUnicodeString (&PathString);
   *ReturnedObject = CurrentObject;
 
@@ -472,6 +446,8 @@ ObQueryNameString (IN PVOID Object,
   ULONG LocalReturnLength;
   NTSTATUS Status;
 
+  PAGED_CODE();
+
   *ReturnLength = 0;
 
   if (Length < sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR))
@@ -486,26 +462,26 @@ ObQueryNameString (IN PVOID Object,
   ObjectHeader = BODY_TO_HEADER(Object);
 
   if (ObjectHeader->ObjectType != NULL &&
-      ObjectHeader->ObjectType->QueryName != NULL)
+      ObjectHeader->ObjectType->TypeInfo.QueryNameProcedure != NULL)
     {
-      DPRINT ("Calling %x\n", ObjectHeader->ObjectType->QueryName);
-      Status = ObjectHeader->ObjectType->QueryName (Object,
+      DPRINT ("Calling %x\n", ObjectHeader->ObjectType->TypeInfo.QueryNameProcedure);
+      Status = ObjectHeader->ObjectType->TypeInfo.QueryNameProcedure (Object,
                                                    ObjectNameInfo,
                                                    Length,
                                                    ReturnLength);
     }
-  else if (ObjectHeader->Name.Length > 0 && ObjectHeader->Name.Buffer != NULL)
+  else if (ObjectHeader->NameInfo->Name.Length > 0 && ObjectHeader->NameInfo->Name.Buffer != NULL)
     {
       DPRINT ("Object does not have a 'QueryName' function\n");
 
-      if (ObjectHeader->Parent == NameSpaceRoot)
+      if (ObjectHeader->NameInfo->Directory == NameSpaceRoot)
        {
          DPRINT ("Reached the root directory\n");
          ObjectNameInfo->Name.Length = 0;
          ObjectNameInfo->Name.Buffer[0] = 0;
          Status = STATUS_SUCCESS;
        }
-      else if (ObjectHeader->Parent != NULL)
+      else if (ObjectHeader->NameInfo->Directory != NULL)
        {
          LocalInfo = ExAllocatePool (NonPagedPool,
                                      sizeof(OBJECT_NAME_INFORMATION) +
@@ -513,7 +489,7 @@ ObQueryNameString (IN PVOID Object,
          if (LocalInfo == NULL)
            return STATUS_INSUFFICIENT_RESOURCES;
 
-         Status = ObQueryNameString (ObjectHeader->Parent,
+         Status = ObQueryNameString (ObjectHeader->NameInfo->Directory,
                                      LocalInfo,
                                      MAX_PATH * sizeof(WCHAR),
                                      &LocalReturnLength);
@@ -532,14 +508,14 @@ ObQueryNameString (IN PVOID Object,
            return Status;
        }
 
-      DPRINT ("Object path %wZ\n", &ObjectHeader->Name);
+      DPRINT ("Object path %wZ\n", &ObjectHeader->NameInfo->Name);
       Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
                                         L"\\");
       if (!NT_SUCCESS (Status))
        return Status;
 
       Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-                                              &ObjectHeader->Name);
+                                              &ObjectHeader->NameInfo->Name);
     }
   else
     {
@@ -564,6 +540,67 @@ ObQueryNameString (IN PVOID Object,
   return Status;
 }
 
+NTSTATUS
+STDCALL
+ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                  PUNICODE_STRING ObjectName,
+                  POBJECT_TYPE ObjectType,
+                  ULONG ObjectSize,
+                  POBJECT_HEADER *ObjectHeader)
+{
+    POBJECT_HEADER Header;
+    POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+    POOL_TYPE PoolType;
+    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');
+    }
+    else
+    {
+        PoolType = ObjectType->TypeInfo.PoolType;
+        Tag = ObjectType->Key;
+    }
+    
+    /* Allocate memory for the Object */
+    Header = ExAllocatePoolWithTag(PoolType, ObjectSize, Tag);
+    if (!Header) {
+        DPRINT1("Not enough memory!\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    
+    /* Initialize the object header */
+    RtlZeroMemory(Header, ObjectSize);
+    DPRINT("Initalizing header %p\n", Header);
+    Header->HandleCount = 0;
+    Header->RefCount = 1;
+    Header->ObjectType = ObjectType;
+    if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_PERMANENT)
+    {
+        Header->Permanent = TRUE;
+    }
+    if (ObjectCreateInfo && ObjectCreateInfo->Attributes & OBJ_INHERIT)
+    {
+        Header->Inherit = TRUE;
+    }
+       
+    /* Initialize the Object Name Info [part of header in OB 2.0] */
+    ObjectNameInfo = ExAllocatePool(PoolType, ObjectSize);
+    ObjectNameInfo->Name = *ObjectName;
+    ObjectNameInfo->Directory = NULL;
+    
+    /* Link stuff to Object Header */
+    Header->NameInfo = ObjectNameInfo;
+    Header->ObjectCreateInfo = ObjectCreateInfo;
+    
+    /* Return Header */
+    *ObjectHeader = Header;
+    return STATUS_SUCCESS;
+}
 
 /**********************************************************************
  * NAME                                                        EXPORTED
@@ -578,212 +615,72 @@ ObQueryNameString (IN PVOID Object,
  *
  * @implemented
  */
-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)
+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;
-  PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
-  SECURITY_SUBJECT_CONTEXT SubjectContext;
-
-  ASSERT_IRQL(APC_LEVEL);
-  
-  if(ObjectAttributesAccessMode == UserMode && ObjectAttributes != NULL)
-  {
-    Status = STATUS_SUCCESS;
-    _SEH_TRY
-    {
-      ProbeForRead(ObjectAttributes,
-                   sizeof(OBJECT_ATTRIBUTES),
-                   sizeof(ULONG));
-    }
-    _SEH_HANDLE
-    {
-      Status = _SEH_GetExceptionCode();
-    }
-    _SEH_END;
+    NTSTATUS Status;
+    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
+    UNICODE_STRING ObjectName;
+    POBJECT_HEADER Header;
     
-    if(!NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-  }
-
-  DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
-        Type, ObjectAttributes, Object);
-
-  if (Type == NULL)
-    {
-      DPRINT1("Invalid object type!\n");
-      return STATUS_INVALID_PARAMETER;
-    }
-
-  if (ObjectAttributes != NULL &&
-      ObjectAttributes->ObjectName != NULL &&
-      ObjectAttributes->ObjectName->Buffer != NULL)
-    {
-      Status = ObFindObject(ObjectAttributes,
-                           &Parent,
-                           &RemainingPath,
-                           NULL);
-      if (!NT_SUCCESS(Status))
-       {
-         DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status);
-         return Status;
-       }
-    }
-  else
-    {
-      RtlInitUnicodeString(&RemainingPath, NULL);
-    }
-
-  Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool,
-                                                OBJECT_ALLOC_SIZE(ObjectSize),
-                                                Type->Tag);
-  if (Header == NULL) {
-       DPRINT1("Not enough memory!\n");
-       return STATUS_INSUFFICIENT_RESOURCES;
-  }
-
-  RtlZeroMemory(Header, OBJECT_ALLOC_SIZE(ObjectSize));
-
-  /* Initialize the object header */
-  DPRINT("Initalizing header\n");
-  Header->HandleCount = 0;
-  Header->RefCount = 1;
-  Header->ObjectType = Type;
-  if (ObjectAttributes != NULL &&
-      ObjectAttributes->Attributes & OBJ_PERMANENT)
-    {
-      Header->Permanent = TRUE;
-    }
-  else
-    {
-      Header->Permanent = FALSE;
-    }
-
-  if (ObjectAttributes != NULL &&
-      ObjectAttributes->Attributes & OBJ_INHERIT)
-    {
-      Header->Inherit = TRUE;
-    }
-  else
-    {
-      Header->Inherit = FALSE;
-    }
-
-  RtlInitUnicodeString(&(Header->Name),NULL);
-
-  DPRINT("Getting Parent and adding entry\n");
-  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;
-    }
-
-  DPRINT("About to call Create Routine\n");
-  if (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);
-         DPRINT("Create Failed\n");
-         return Status;
-       }
-    }
-  RtlFreeUnicodeString(&RemainingPath);
-
-  SeCaptureSubjectContext(&SubjectContext);
-
-  DPRINT("Security Assignment in progress\n");
-  /* Build the new security descriptor */
-  Status = SeAssignSecurity((ParentHeader != NULL) ? ParentHeader->SecurityDescriptor : NULL,
-                           (ObjectAttributes != NULL) ? ObjectAttributes->SecurityDescriptor : NULL,
-                           &NewSecurityDescriptor,
-                           (Header->ObjectType == ObDirectoryType),
-                           &SubjectContext,
-                           Header->ObjectType->Mapping,
-                           PagedPool);
-  if (NT_SUCCESS(Status))
-    {
-      DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor);
-
-      if (Header->ObjectType->Security != NULL)
-       {
-         /* Call the security method */
-         Status = Header->ObjectType->Security(HEADER_TO_BODY(Header),
-                                               AssignSecurityDescriptor,
-                                               0,
-                                               NewSecurityDescriptor,
-                                               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);
-
-  if (Object != NULL)
+    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,
+                                        AccessMode,
+                                        Type,
+                                        ObjectCreateInfo,
+                                        &ObjectName);
+                                        
+    if (NT_SUCCESS(Status))
     {
-      *Object = HEADER_TO_BODY(Header);
+        /* 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_TO_BODY(Header);
+            
+            /* 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);
     }
-
-  DPRINT("Sucess!\n");
-  return STATUS_SUCCESS;
+     
+    /* We failed, so release the Buffer */
+    DPRINT1("Capture failed\n");
+    ExFreePool(ObjectCreateInfo);
+    return Status;
 }
 
-
 /*
  * FUNCTION: Increments the pointer reference count for a given object
  * ARGUMENTS:
@@ -803,11 +700,13 @@ ObReferenceObjectByPointer(IN PVOID Object,
 {
    POBJECT_HEADER Header;
 
+   /* 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)
      {
        DPRINT("Failed %x (type was %x %S) should be %x %S\n",
@@ -830,8 +729,8 @@ ObReferenceObjectByPointer(IN PVOID Object,
                Object, Header->RefCount, PsThreadType);
        DPRINT("eip %x\n", ((PULONG)&Object)[-1]);
      }
-   if (Header->CloseInProcess)
+
+   if (Header->RefCount == 0 && !Header->Permanent)
    {
       if (Header->ObjectType == PsProcessType)
         {
@@ -844,8 +743,11 @@ ObReferenceObjectByPointer(IN PVOID Object,
       return(STATUS_UNSUCCESSFUL);
    }
 
-   InterlockedIncrement(&Header->RefCount);
-   
+   if (1 == InterlockedIncrement(&Header->RefCount) && !Header->Permanent)
+   {
+      KEBUGCHECK(0);
+   }
+
    return(STATUS_SUCCESS);
 }
 
@@ -863,9 +765,11 @@ ObOpenObjectByPointer(IN POBJECT Object,
                      OUT PHANDLE Handle)
 {
    NTSTATUS Status;
-   
+
+   PAGED_CODE();
+
    DPRINT("ObOpenObjectByPointer()\n");
-   
+
    Status = ObReferenceObjectByPointer(Object,
                                       0,
                                       ObjectType,
@@ -874,15 +778,15 @@ ObOpenObjectByPointer(IN POBJECT Object,
      {
        return Status;
      }
-   
-   Status = ObCreateHandle(PsGetCurrentProcess(),
+
+   Status = ObpCreateHandle(PsGetCurrentProcess(),
                           Object,
                           DesiredAccess,
                           (BOOLEAN)(HandleAttributes & OBJ_INHERIT),
                           Handle);
-   
+
    ObDereferenceObject(Object);
-   
+
    return STATUS_SUCCESS;
 }
 
@@ -897,21 +801,29 @@ ObpDeleteObject(POBJECT_HEADER Header)
       KEBUGCHECK(0);
     }
 
+  if (Header->ObjectType != NULL &&
+      Header->ObjectType->TypeInfo.DeleteProcedure != NULL)
+    {
+      Header->ObjectType->TypeInfo.DeleteProcedure(HEADER_TO_BODY(Header));
+    }
+
   if (Header->SecurityDescriptor != NULL)
     {
       ObpRemoveSecurityDescriptor(Header->SecurityDescriptor);
     }
-
-  if (Header->ObjectType != NULL &&
-      Header->ObjectType->Delete != NULL)
+    
+  if (Header->NameInfo)
     {
-      Header->ObjectType->Delete(HEADER_TO_BODY(Header));
+      if(Header->NameInfo->Name.Buffer)
+        {
+          ExFreePool(Header->NameInfo->Name.Buffer);
+        }
+      ExFreePool(Header->NameInfo);
     }
-
-  if (Header->Name.Buffer != NULL)
+  if (Header->ObjectCreateInfo)
     {
-      ObpRemoveEntryDirectory(Header);
-      RtlFreeUnicodeString(&Header->Name);
+      ObpReleaseCapturedAttributes(Header->ObjectCreateInfo);
+      ExFreePool(Header->ObjectCreateInfo);
     }
 
   DPRINT("ObPerformRetentionChecks() = Freeing object\n");
@@ -942,10 +854,11 @@ STATIC NTSTATUS
 ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
                        IN LONG OldRefCount)
 {
+#if 0
   if (ObjectHeader->RefCount < 0)
     {
       CPRINT("Object %p/%p has invalid reference count (%d)\n",
-            ObjectHeader, HEADER_TO_BODY(ObjectHeader), 
+            ObjectHeader, HEADER_TO_BODY(ObjectHeader),
             ObjectHeader->RefCount);
       KEBUGCHECK(0);
     }
@@ -953,28 +866,23 @@ ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
   if (ObjectHeader->HandleCount < 0)
     {
       CPRINT("Object %p/%p has invalid handle count (%d)\n",
-            ObjectHeader, HEADER_TO_BODY(ObjectHeader), 
+            ObjectHeader, HEADER_TO_BODY(ObjectHeader),
             ObjectHeader->HandleCount);
       KEBUGCHECK(0);
     }
+#endif
+
 
-  if (ObjectHeader->CloseInProcess)
-    {
-      KEBUGCHECK(0);
-      return STATUS_UNSUCCESSFUL;
-    }
-  ObjectHeader->CloseInProcess = TRUE;
-  
   switch (KeGetCurrentIrql ())
     {
     case PASSIVE_LEVEL:
       return ObpDeleteObject (ObjectHeader);
-      
+
     case APC_LEVEL:
     case DISPATCH_LEVEL:
       {
        PRETENTION_CHECK_PARAMS Params;
-       
+
        /*
          We use must succeed pool here because if the allocation fails
          then we leak memory.
@@ -982,7 +890,7 @@ ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
        Params = (PRETENTION_CHECK_PARAMS)
          ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
                                sizeof(RETENTION_CHECK_PARAMS),
-                               ObjectHeader->ObjectType->Tag);
+                               ObjectHeader->ObjectType->Key);
        Params->ObjectHeader = ObjectHeader;
        ExInitializeWorkItem(&Params->WorkItem,
                             ObpDeleteObjectWorkRoutine,
@@ -991,7 +899,7 @@ ObpDeleteObjectDpcLevel(IN POBJECT_HEADER ObjectHeader,
                        CriticalWorkQueue);
       }
       return STATUS_PENDING;
-      
+
     default:
       DPRINT("ObpDeleteObjectDpcLevel called at unsupported "
             "IRQL %u!\n", KeGetCurrentIrql());
@@ -1029,15 +937,13 @@ ObfReferenceObject(IN PVOID Object)
   Header = BODY_TO_HEADER(Object);
 
   /* No one should be referencing an object once we are deleting it. */
-  if (Header->CloseInProcess)
-    {
-      KEBUGCHECK(0);
-    }
+  if (InterlockedIncrement(&Header->RefCount) == 1 && !Header->Permanent)
+  {
+     KEBUGCHECK(0);
+  }
 
-  (VOID)InterlockedIncrement(&Header->RefCount);
 }
 
-
 /**********************************************************************
  * NAME                                                        EXPORTED
  *     ObfDereferenceObject@4
@@ -1060,31 +966,79 @@ ObfDereferenceObject(IN PVOID Object)
   POBJECT_HEADER Header;
   LONG NewRefCount;
   BOOL Permanent;
-  ULONG HandleCount;
 
   ASSERT(Object);
 
   /* Extract the object header. */
   Header = BODY_TO_HEADER(Object);
   Permanent = Header->Permanent;
-  HandleCount = Header->HandleCount;
 
-  /* 
+  /*
      Drop our reference and get the new count so we can tell if this was the
      last reference.
   */
   NewRefCount = InterlockedDecrement(&Header->RefCount);
+  DPRINT("ObfDereferenceObject(0x%x)==%d\n", Object, NewRefCount);
   ASSERT(NewRefCount >= 0);
 
   /* Check whether the object can now be deleted. */
   if (NewRefCount == 0 &&
-      HandleCount == 0 &&
       !Permanent)
     {
       ObpDeleteObjectDpcLevel(Header, NewRefCount);
     }
 }
 
+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
@@ -1106,6 +1060,8 @@ ObGetObjectPointerCount(PVOID Object)
 {
   POBJECT_HEADER Header;
 
+  PAGED_CODE();
+
   ASSERT(Object);
   Header = BODY_TO_HEADER(Object);
 
@@ -1131,6 +1087,8 @@ ObGetObjectHandleCount(PVOID Object)
 {
   POBJECT_HEADER Header;
 
+  PAGED_CODE();
+
   ASSERT(Object);
   Header = BODY_TO_HEADER(Object);