- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
index 9b6ac7c..56f8534 100644 (file)
-/*
+/* $Id$
+ *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
  * FILE:           ntoskrnl/ob/namespc.c
  * PURPOSE:        Manages the system namespace
- * PROGRAMMER:     David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                 22/05/98: Created
+ *
+ * PROGRAMMERS:    David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES ***************************************************************/
 
-#include <windows.h>
-#include <wstring.h>
-#include <ddk/ntddk.h>
-#include <internal/objmgr.h>
-#include <internal/string.h>
-#include <internal/kernel.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ObInit)
+#endif
+
+
+extern ULONG NtGlobalFlag;
+
 /* GLOBALS ****************************************************************/
 
-OBJECT_TYPE DirectoryObjectType = {{0,0,NULL},
-                                   0,
-                                   0,
-                                   ULONG_MAX,
-                                   ULONG_MAX,
-                                   sizeof(DEVICE_OBJECT),
-                                   0,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   };
-
-static struct
-{
-   OBJECT_HEADER hdr;
-//   DIRECTORY_OBJECT directory;
-   LIST_ENTRY head;
-} namespc_root;
+POBJECT_TYPE ObDirectoryType = NULL;
+POBJECT_TYPE ObTypeObjectType = NULL;
+
+PDIRECTORY_OBJECT NameSpaceRoot = NULL;
+PDIRECTORY_OBJECT ObpTypeDirectoryObject = NULL;
+ /* FIXME: Move this somewhere else once devicemap support is in */
+PDEVICE_MAP ObSystemDeviceMap = NULL;
+KEVENT ObpDefaultObject;
+
+static GENERIC_MAPPING ObpDirectoryMapping = {
+       STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
+       STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
+       STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
+       DIRECTORY_ALL_ACCESS};
+
+static GENERIC_MAPPING ObpTypeMapping = {
+       STANDARD_RIGHTS_READ,
+       STANDARD_RIGHTS_WRITE,
+       STANDARD_RIGHTS_EXECUTE,
+       0x000F0001};
+
+NTSTATUS
+STDCALL
+ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                  PUNICODE_STRING ObjectName,
+                  POBJECT_TYPE ObjectType,
+                  ULONG ObjectSize,
+                  POBJECT_HEADER *ObjectHeader);
 
 /* FUNCTIONS **************************************************************/
 
-NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle,
-                              ACCESS_MASK DesiredAccess,
-                              POBJECT_ATTRIBUTES ObjectAttributes)
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
+                       ULONG Attributes,
+                       PACCESS_STATE PassedAccessState,
+                       ACCESS_MASK DesiredAccess,
+                       POBJECT_TYPE ObjectType,
+                       KPROCESSOR_MODE AccessMode,
+                       PVOID ParseContext,
+                       PVOID* ObjectPtr)
 {
-   PVOID Object;
+   PVOID Object = NULL;
+   UNICODE_STRING RemainingPath;
+   UNICODE_STRING ObjectName;
+   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
    NTSTATUS Status;
-   
-   Status = ObOpenObjectByName(ObjectAttributes,&Object);
+
+   PAGED_CODE();
+
+   /* Capture the name */
+   DPRINT("Capturing Name\n");
+   Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
    if (!NT_SUCCESS(Status))
      {
-       return(Status);
+       DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
+       return Status;
      }
-       
-   if (BODY_TO_HEADER(Object)->Type!=OBJTYP_DIRECTORY)
+
+   /* 
+    * Create a fake ObjectCreateInfo structure. Note that my upcoming
+    * ObFindObject refactoring will remove the need for this hack.
+    */
+   ObjectCreateInfo.RootDirectory = NULL;
+   ObjectCreateInfo.Attributes = Attributes;
+     
+   Status = ObFindObject(&ObjectCreateInfo,
+                         &ObjectName,
+                        &Object,
+                        &RemainingPath,
+                        ObjectType);
+
+   if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+   if (!NT_SUCCESS(Status))
      {
-       return(STATUS_UNSUCCESSFUL);
+       return(Status);
      }
-   
-   *DirectoryHandle = ObAddHandle(Object);
-   return(STATUS_SUCCESS);
-}
+   DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
 
-NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle,
-                               OUT POBJDIR_INFORMATION DirObjInformation, 
-                               IN ULONG                BufferLength, 
-                               IN BOOLEAN              GetNextIndex, 
-                               IN BOOLEAN              IgnoreInputIndex, 
-                               IN OUT PULONG           ObjectIndex,
-                               OUT PULONG              DataWritten OPTIONAL)
-{
-   POBJECT_HEADER hdr = ObGetObjectByHandle(DirObjHandle);
-   PDIRECTORY_OBJECT dir = (PDIRECTORY_OBJECT)(HEADER_TO_BODY(hdr));
-   PLIST_ENTRY current_entry;
-   POBJECT_HEADER current;
-   PWSTR outbuffer = (PWSTR)(ObjectIndex);
-   
-   current_entry = dir->head.Flink;
-   while (current_entry!=NULL)
+   if (RemainingPath.Buffer != NULL || Object == NULL)
      {
-       current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,entry);
-       if (BufferLength < wstrlen(current->name.Buffer))
-            {
-               return(STATUS_SUCCESS);
-            }
-       BufferLength = BufferLength - wstrlen(current->name.Buffer);
-//     wcscpy(outbuffer,current->name.Buffer);
-       outbuffer = outbuffer + wstrlen(current->name.Buffer);
-       current_entry = current_entry->Flink;
+        DPRINT("Object %p\n", Object);
+       *ObjectPtr = NULL;
+       RtlFreeUnicodeString (&RemainingPath);
+       return(STATUS_OBJECT_NAME_NOT_FOUND);
      }
+   *ObjectPtr = Object;
+   RtlFreeUnicodeString (&RemainingPath);
    return(STATUS_SUCCESS);
 }
 
 
-NTSTATUS ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes,
-                           PVOID* Object)
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     ObOpenObjectByName
+ *
+ * DESCRIPTION
+ *     Obtain a handle to an existing object.
+ *
+ * ARGUMENTS
+ *     ObjectAttributes
+ *             ...
+ *     ObjectType
+ *             ...
+ *     ParseContext
+ *             ...
+ *     AccessMode
+ *             ...
+ *     DesiredAccess
+ *             ...
+ *     PassedAccessState
+ *             ...
+ *     Handle
+ *             Handle to close.
+ *
+ * RETURN VALUE
+ *     Status.
+ *
+ * @implemented
+ */
+NTSTATUS STDCALL
+ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
+                  IN POBJECT_TYPE ObjectType,
+                  IN OUT PVOID ParseContext,
+                  IN KPROCESSOR_MODE AccessMode,
+                  IN ACCESS_MASK DesiredAccess,
+                  IN PACCESS_STATE PassedAccessState,
+                  OUT PHANDLE Handle)
 {
-   
-   DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",
-         ObjectAttributes,Object);
-   DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",
-         ObjectAttributes->ObjectName,ObjectAttributes->ObjectName->Buffer);
-   
-   *Object = ObLookupObject(ObjectAttributes->RootDirectory, 
-                              ObjectAttributes->ObjectName->Buffer);
-   DPRINT("*Object %x\n",*Object);
-   if ((*Object)==NULL)
+   UNICODE_STRING RemainingPath;
+   PVOID Object = NULL;
+   UNICODE_STRING ObjectName;
+   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+   NTSTATUS Status;
+
+   PAGED_CODE();
+
+   DPRINT("ObOpenObjectByName(...)\n");
+
+    /* Capture all the info */
+    DPRINT("Capturing Create Info\n");
+    Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                        AccessMode,
+                                        ObjectType,
+                                        &ObjectCreateInfo,
+                                        &ObjectName);
+   if (!NT_SUCCESS(Status))
      {
-       return(STATUS_NO_SUCH_FILE);
+       DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+       return Status;
      }
-   return(STATUS_SUCCESS);
+                                        
+   Status = ObFindObject(&ObjectCreateInfo,
+                         &ObjectName,
+                        &Object,
+                        &RemainingPath,
+                        ObjectType);
+   if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+   if (!NT_SUCCESS(Status))
+     {
+       DPRINT("ObFindObject() failed (Status %lx)\n", Status);
+       goto Cleanup;
+     }
+
+   DPRINT("OBject: %p, Remaining Path: %wZ\n", Object, &RemainingPath);
+   if (Object == NULL)
+     {
+       Status = STATUS_UNSUCCESSFUL;
+       goto Cleanup;
+     }
+   if (RemainingPath.Buffer != NULL)
+   {
+      if (wcschr(RemainingPath.Buffer + 1, L'\\') == NULL)
+         Status = STATUS_OBJECT_NAME_NOT_FOUND;
+      else
+         Status =STATUS_OBJECT_PATH_NOT_FOUND;
+      goto Cleanup;
+   }
+   
+   Status = ObpCreateHandle(Object,
+                           DesiredAccess,
+                           ObjectCreateInfo.Attributes,
+                           Handle);
+
+Cleanup:
+   if (Object != NULL)
+   {
+       ObDereferenceObject(Object);
+   }
+   RtlFreeUnicodeString(&RemainingPath);
+   ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+
+   return Status;
 }
 
-void ObjNamespcInit(void)
-/*
- * FUNCTION: Initialize the object manager namespace
- */
+VOID
+STDCALL
+ObQueryDeviceMapInformation(PEPROCESS Process,
+                           PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
 {
-   ANSI_STRING ansi_str;
-   
-   ObInitializeObjectHeader(OBJTYP_DIRECTORY,NULL,&namespc_root.hdr);
-   InitializeListHead(&namespc_root.head);
-   
-   RtlInitAnsiString(&ansi_str,"Directory");
-   RtlAnsiStringToUnicodeString(&DirectoryObjectType.TypeName,&ansi_str,
-                               TRUE);
-   ObRegisterType(OBJTYP_DIRECTORY,&DirectoryObjectType);
+       //KIRQL OldIrql ;
+
+       /*
+        * FIXME: This is an ugly hack for now, to always return the System Device Map
+        * instead of returning the Process Device Map. Not important yet since we don't use it
+        */
+
+        /* FIXME: Acquire the DeviceMap Spinlock */
+        // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
+
+        /* Make a copy */
+        DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
+        RtlMoveMemory(DeviceMapInfo->Query.DriveType, ObSystemDeviceMap->DriveType, sizeof(ObSystemDeviceMap->DriveType));
+
+        /* FIXME: Release the DeviceMap Spinlock */
+        // KeReleasepinLock(DeviceMap->Lock, OldIrql);
 }
 
-NTSTATUS ZwCreateDirectoryObject(PHANDLE DirectoryHandle,
-                                ACCESS_MASK DesiredAccess,
-                                POBJECT_ATTRIBUTES ObjectAttributes)
+VOID
+NTAPI
+ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
+                    POBJECT_HEADER Header,
+                    PWSTR Name)
 /*
- * FUNCTION: Creates or opens a directory object (a container for other
- * objects)
+ * FUNCTION: Add an entry to a namespace directory
  * ARGUMENTS:
- *        DirectoryHandle (OUT) = Caller supplied storage for the handle
- *                                of the directory
- *        DesiredAccess = Access desired to the directory
- *        ObjectAttributes = Object attributes initialized with
- *                           InitializeObjectAttributes
- * RETURNS: Status
+ *         Parent = directory to add in
+ *         Header = Header of the object to add the entry for
+ *         Name = Name to give the entry
  */
 {
-   PDIRECTORY_OBJECT dir;
-   
-   dir = ObGenericCreateObject(DirectoryHandle,DesiredAccess,ObjectAttributes,
-                              OBJTYP_DIRECTORY);
-   
-   /*
-    * Initialize the object body
-    */
-   InitializeListHead(&dir->head);
+  KIRQL oldlvl;
 
-   return(STATUS_SUCCESS);
+  ASSERT(HEADER_TO_OBJECT_NAME(Header));
+  HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
+
+  KeAcquireSpinLock(&Parent->Lock, &oldlvl);
+  InsertTailList(&Parent->head, &Header->Entry);
+  KeReleaseSpinLock(&Parent->Lock, oldlvl);
 }
 
-VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,
-                               PUNICODE_STRING ObjectName,
-                               ULONG Attributes,
-                               HANDLE RootDirectory,
-                               PSECURITY_DESCRIPTOR SecurityDescriptor)
+
+VOID
+NTAPI
+ObpRemoveEntryDirectory(POBJECT_HEADER Header)
 /*
- * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a 
- * subsequent call to ZwCreateXXX or ZwOpenXXX
+ * FUNCTION: Remove an entry from a namespace directory
  * ARGUMENTS:
- *        InitializedAttributes (OUT) = Caller supplied storage for the
- *                                      object attributes
- *        ObjectName = Full path name for object
- *        Attributes = Attributes for the object
- *        RootDirectory = Where the object should be placed or NULL
- *        SecurityDescriptor = Ignored
- * 
- * NOTE:
- *     Either ObjectName is a fully qualified pathname or a path relative
- *     to RootDirectory
+ *         Header = Header of the object to remove
  */
 {
-   DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
-         "ObjectName %x Attributes %x RootDirectory %x)\n",
-         InitializedAttributes,ObjectName,Attributes,RootDirectory);
-   InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES);
-   InitializedAttributes->RootDirectory=RootDirectory;
-   InitializedAttributes->ObjectName=ObjectName;
-   InitializedAttributes->Attributes=Attributes;
-   InitializedAttributes->SecurityDescriptor=SecurityDescriptor;
-   InitializedAttributes->SecurityQualityOfService=NULL;
+  KIRQL oldlvl;
+
+  DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
+
+  KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),&oldlvl);
+  if (Header->Entry.Flink && Header->Entry.Blink)
+  {
+    RemoveEntryList(&(Header->Entry));
+    Header->Entry.Flink = Header->Entry.Blink = NULL;
+  }
+  KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
 }
 
-static PVOID ObDirLookup(PDIRECTORY_OBJECT dir, PWSTR name)
-/*
- * FUNCTION: Looks up an entry within a namespace directory
- * ARGUMENTS:
- *        dir = Directory to lookup in
- *        name = Entry name to find
- * RETURNS: A pointer to the object body if found
- *          NULL otherwise
- */
+NTSTATUS
+STDCALL
+ObpCreateDirectory(OB_OPEN_REASON Reason,
+                   PVOID ObjectBody,
+                   PEPROCESS Process,
+                   ULONG HandleCount,
+                   ACCESS_MASK GrantedAccess)
+{
+    PDIRECTORY_OBJECT Directory = ObjectBody;
+    
+    if (Reason == ObCreateHandle)
+    {
+        InitializeListHead(&Directory->head);
+        KeInitializeSpinLock(&Directory->Lock);
+    }
+    
+    return STATUS_SUCCESS;
+}
+
+PVOID
+ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
+                     PWSTR Name,
+                     ULONG Attributes)
 {
-   LIST_ENTRY* current = ((PDIRECTORY_OBJECT)dir)->head.Flink;
+   PLIST_ENTRY current = DirectoryObject->head.Flink;
    POBJECT_HEADER current_obj;
-   DPRINT("ObDirLookup(dir %x, name %w)\n",dir,name);
-   if (name[0]==0)
+
+   DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
+
+   if (Name[0]==0)
      {
-       return(BODY_TO_HEADER(dir));
+       return(DirectoryObject);
      }
-   if (name[0]=='.'&&name[1]==0)
+   if (Name[0]=='.' && Name[1]==0)
      {
-       return(BODY_TO_HEADER(dir));
+       return(DirectoryObject);
      }
-   if (name[0]=='.'&&name[1]=='.'&&name[2]==0)
+   if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
      {
-       UNIMPLEMENTED;
-       return(NULL);
+       return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory);
      }
-   while (current!=NULL)
+   while (current!=(&(DirectoryObject->head)))
      {
-       current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,entry);
-       if ( wcscmp(current_obj->name.Buffer, name)==0)
+       current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
+       DPRINT("  Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name);
+       if (Attributes & OBJ_CASE_INSENSITIVE)
+         {
+            if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
+              {
+                 DPRINT("Found it %x\n",&current_obj->Body);
+                 return(&current_obj->Body);
+              }
+         }
+       else
          {
-            return(current_obj);
+            if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
+              {
+                 DPRINT("Found it %x\n",&current_obj->Body);
+                 return(&current_obj->Body);
+              }
          }
        current = current->Flink;
      }
+   DPRINT("    Not Found: %s() = NULL\n",__FUNCTION__);
    return(NULL);
 }
 
 
-VOID ObCreateEntry(PDIRECTORY_OBJECT parent,POBJECT_HEADER Object)
-/*
- * FUNCTION: Add an entry to a namespace directory
- * ARGUMENTS:
- *         parent = directory to add in
- *         name = Name to give the entry
- *         Object = Header of the object to add the entry for
- */
+NTSTATUS STDCALL
+ObpParseDirectory(PVOID Object,
+                 PVOID * NextObject,
+                 PUNICODE_STRING FullPath,
+                 PWSTR * Path,
+                 ULONG Attributes)
 {
-   DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent,Object,Object->name.Buffer,
-         Object->name.Buffer);
-   DPRINT("root type %d\n",namespc_root.hdr.Type);
-   DPRINT("%x\n",&(namespc_root.hdr.Type));
-   DPRINT("type %x\n",&(parent->Type));
-   DPRINT("type %x\n",&(BODY_TO_HEADER(parent)->Type));
-   DPRINT("type %d\n",parent->Type);
-   assert(parent->Type == OBJTYP_DIRECTORY);
-   
-   /*
-    * Insert ourselves in our parents list
-    */
-   InsertTailList(&parent->head,&Object->entry);
+  PWSTR Start;
+  PWSTR End;
+  PVOID FoundObject;
+  KIRQL oldlvl;
+
+  DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
+        Object,Path,*Path);
+
+  *NextObject = NULL;
+
+  if ((*Path) == NULL)
+    {
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  Start = *Path;
+  if (*Start == L'\\')
+    Start++;
+
+  End = wcschr(Start, L'\\');
+  if (End != NULL)
+    {
+      *End = 0;
+    }
+
+  KeAcquireSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), &oldlvl);
+  FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
+  if (FoundObject == NULL)
+    {
+      KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+      if (End != NULL)
+       {
+         *End = L'\\';
+       }
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  ObReferenceObjectByPointer(FoundObject,
+                            STANDARD_RIGHTS_REQUIRED,
+                            NULL,
+                            UserMode);
+  KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
+  if (End != NULL)
+    {
+      *End = L'\\';
+      *Path = End;
+    }
+  else
+    {
+      *Path = NULL;
+    }
+
+  *NextObject = FoundObject;
+
+  return STATUS_SUCCESS;
 }
 
-PVOID ObLookupObject(HANDLE rooth, PWSTR string)
-/*
- * FUNCTION: Lookup an object within the system namespc
- * ARGUMENTS:
- *         root = Directory to start lookup from
- *         _string = Pathname to lookup
- * RETURNS: On success a pointer to the object body
- *          On failure NULL
- */
+VOID 
+INIT_FUNCTION
+ObInit(VOID)
 {
-   PWSTR current;
-   PWSTR next;
-   PDIRECTORY_OBJECT current_dir = NULL;
-   POBJECT_HEADER current_hdr;
-   
-   DPRINT("root %x string %w\n",rooth,string);
-   
-   if (rooth==NULL)
-     {
-       current_dir = HEADER_TO_BODY(&(namespc_root.hdr));
-     }
-   else
-     {
-       ObReferenceObjectByHandle(rooth,DIRECTORY_TRAVERSE,NULL,
-                                 UserMode,(PVOID*)&current_dir,NULL);
-     }
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING Name;
+    SECURITY_DESCRIPTOR SecurityDescriptor;
+    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
+
+    /* Initialize the security descriptor cache */
+    ObpInitSdCache();
+
+    /* Initialize the Default Event */
+    KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
+
+    /* Create the Type Type */
+    DPRINT("Creating Type Type\n");
+    RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+    RtlInitUnicodeString(&Name, L"Type");
+    ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+    ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
+    ObjectTypeInitializer.UseDefaultObject = TRUE;
+    ObjectTypeInitializer.MaintainTypeList = TRUE;
+    ObjectTypeInitializer.PoolType = NonPagedPool;
+    ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
+    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
+    ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
   
-   /*
-    * Bit of a hack this
-    */
-   if (string[0]==0)
-   {
-      DPRINT("current_dir %x\n",current_dir);
-      DPRINT("type %d\n",current_dir->Type);
-      return(current_dir);
-   }
+    /* Create the Directory Type */
+    DPRINT("Creating Directory Type\n");
+    RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
+    RtlInitUnicodeString(&Name, L"Directory");
+    ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
+    ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
+    ObjectTypeInitializer.UseDefaultObject = FALSE;
+    ObjectTypeInitializer.OpenProcedure = ObpCreateDirectory;
+    ObjectTypeInitializer.ParseProcedure = ObpParseDirectory;
+    ObjectTypeInitializer.MaintainTypeList = FALSE;
+    ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
+    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DIRECTORY_OBJECT);
+    ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObDirectoryType);
 
-   DPRINT("string = %w\n",string);
-   
-   if (string[0]!='\\')
-     {
-        printk("(%s:%d) Non absolute pathname passed to %s\n",__FILE__,
-               __LINE__,__FUNCTION__);
-       return(NULL);
-     }
-      
-   current = string+1;
-   DPRINT("current %w\n",current);
-   next = wcschr(string+1,'\\');
-   if (next!=NULL)
-     {
-       *next=0;
-     }
-   DPRINT("next %x\n",next);
-   
-   while (next!=NULL)
-     {
-        DPRINT("Scanning %w next %w current %x\n",current,next+1,
-              current_dir);
-       
-       /*
-        * Check the current object is a directory
-        */
-       if (current_dir->Type!=OBJTYP_DIRECTORY)
-         {
-             printk("(%s:%d) Bad path component\n",__FILE__,
-                    __LINE__);
-            ExFreePool(string);
-            return(NULL);
-         }
-       
-       /*
-        * Lookup the next component of the path in the directory
-        */
-       current_hdr=(PDIRECTORY_OBJECT)ObDirLookup(current_dir,current);
-       if (current_hdr==NULL)
-         {
-             printk("(%s:%d) Path component not found\n",__FILE__,
-                    __LINE__);
-            ExFreePool(string);
-            return(NULL);
-         }
-       current_dir = HEADER_TO_BODY(current_hdr);
-         
-       current = next+1;
-       next = wcschr(next+1,'\\');
-       if (next!=NULL)
-         {
-            *next=0;
-         }
-     }
-   
-   DPRINT("current_dir %x current %x\n",current_dir,current);
-   DPRINT("current %w\n",current);
-   current_hdr = ObDirLookup(current_dir,current);
-   if (current_hdr==NULL)
-   {
-        return(NULL);
-   }
-   DPRINT("Returning %x %x\n",current_hdr,HEADER_TO_BODY(current_hdr));
-   return(HEADER_TO_BODY(current_hdr));
+    /* Create security descriptor */
+    RtlCreateSecurityDescriptor(&SecurityDescriptor,
+                                SECURITY_DESCRIPTOR_REVISION1);
+    RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
+                                  SeAliasAdminsSid,
+                                  FALSE);
+    RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
+                                  SeLocalSystemSid,
+                                  FALSE);
+    RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
+                                 TRUE,
+                                 SePublicDefaultDacl,
+                                 FALSE);
+
+    /* Create root directory */
+    DPRINT("Creating Root Directory\n");    
+    InitializeObjectAttributes(&ObjectAttributes,
+                               NULL,
+                               OBJ_PERMANENT,
+                               NULL,
+                               &SecurityDescriptor);
+    ObCreateObject(KernelMode,
+                   ObDirectoryType,
+                   &ObjectAttributes,
+                   KernelMode,
+                   NULL,
+                   sizeof(DIRECTORY_OBJECT),
+                   0,
+                   0,
+                   (PVOID*)&NameSpaceRoot);
+    ObInsertObject((PVOID)NameSpaceRoot,
+                   NULL,
+                   DIRECTORY_ALL_ACCESS,
+                   0,
+                   NULL,
+                   NULL);
+
+    /* Create '\ObjectTypes' directory */
+    RtlInitUnicodeString(&Name, L"\\ObjectTypes");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               OBJ_PERMANENT,
+                               NULL,
+                               &SecurityDescriptor);
+    ObCreateObject(KernelMode,
+                   ObDirectoryType,
+                   &ObjectAttributes,
+                   KernelMode,
+                   NULL,
+                   sizeof(DIRECTORY_OBJECT),
+                   0,
+                   0,
+                   (PVOID*)&ObpTypeDirectoryObject);
+    ObInsertObject((PVOID)ObpTypeDirectoryObject,
+                   NULL,
+                   DIRECTORY_ALL_ACCESS,
+                   0,
+                   NULL,
+                   NULL);
+    
+    /* Insert the two objects we already created but couldn't add */
+    /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
+    ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObTypeObjectType), NULL);
+    ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObDirectoryType), NULL);
+
+    /* Create 'symbolic link' object type */
+    ObInitSymbolicLinkImplementation();
+
+    /* FIXME: Hack Hack! */
+    ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
+    RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
 }
+
+NTSTATUS
+STDCALL
+ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
+                    PUNICODE_STRING TypeName,
+                    POBJECT_TYPE *ObjectType)
+{
+    POBJECT_HEADER Header;
+    POBJECT_TYPE LocalObjectType;
+    ULONG HeaderSize;
+    NTSTATUS Status;
+
+    DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName);
+    
+    /* Allocate the Object */
+    Status = ObpAllocateObject(NULL, 
+                               TypeName,
+                               ObTypeObjectType, 
+                               OBJECT_ALLOC_SIZE(sizeof(OBJECT_TYPE)),
+                               &Header);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ObpAllocateObject failed!\n");
+        return Status;
+    }
+    
+    LocalObjectType = (POBJECT_TYPE)&Header->Body;
+    DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType, Header);
+    
+    /* Check if this is the first Object Type */
+    if (!ObTypeObjectType)
+    {
+        ObTypeObjectType = LocalObjectType;
+        Header->Type = ObTypeObjectType;
+        LocalObjectType->Key = TAG('O', 'b', 'j', 'T');
+    }
+    else
+    {   
+        CHAR Tag[4];
+        Tag[0] = TypeName->Buffer[0];
+        Tag[1] = TypeName->Buffer[1];
+        Tag[2] = TypeName->Buffer[2];
+        Tag[3] = TypeName->Buffer[3];
+        
+        /* Set Tag */
+        DPRINT("Convert: %s \n", Tag);
+        LocalObjectType->Key = *(PULONG)Tag;
+    }
+    
+    /* Set it up */
+    LocalObjectType->TypeInfo = *ObjectTypeInitializer;
+    LocalObjectType->Name = *TypeName;
+    LocalObjectType->TypeInfo.PoolType = ObjectTypeInitializer->PoolType;
+
+    /* These two flags need to be manually set up */
+    Header->Flags |= OB_FLAG_KERNEL_MODE | OB_FLAG_PERMANENT;
+
+    /* Check if we have to maintain a type list */
+    if (NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST)
+    {
+        /* Enable support */
+        LocalObjectType->TypeInfo.MaintainTypeList = TRUE;
+    }
+
+    /* Calculate how much space our header'll take up */
+    HeaderSize = sizeof(OBJECT_HEADER) + sizeof(OBJECT_HEADER_NAME_INFO) +
+                 (ObjectTypeInitializer->MaintainHandleCount ? 
+                 sizeof(OBJECT_HEADER_HANDLE_INFO) : 0);
+
+    /* Update the Pool Charges */
+    if (ObjectTypeInitializer->PoolType == NonPagedPool)
+    {
+        LocalObjectType->TypeInfo.DefaultNonPagedPoolCharge += HeaderSize;
+    }
+    else
+    {
+        LocalObjectType->TypeInfo.DefaultPagedPoolCharge += HeaderSize;
+    }
+    
+    /* All objects types need a security procedure */
+    if (!ObjectTypeInitializer->SecurityProcedure)
+    {
+        LocalObjectType->TypeInfo.SecurityProcedure = SeDefaultObjectMethod;
+    }
+
+    /* Select the Wait Object */
+    if (LocalObjectType->TypeInfo.UseDefaultObject)
+    {
+        /* Add the SYNCHRONIZE access mask since it's waitable */
+        LocalObjectType->TypeInfo.ValidAccessMask |= SYNCHRONIZE;
+
+        /* Use the "Default Object", a simple event */
+        LocalObjectType->DefaultObject = &ObpDefaultObject;
+    }
+    /* Special system objects get an optimized hack so they can be waited on */
+    else if (TypeName->Length == 8 && !wcscmp(TypeName->Buffer, L"File"))
+    {
+        LocalObjectType->DefaultObject = (PVOID)FIELD_OFFSET(FILE_OBJECT, Event);
+    }
+    /* FIXME: When LPC stops sucking, add a hack for Waitable Ports */
+    else
+    {
+        /* No default Object */
+        LocalObjectType->DefaultObject = NULL;
+    }
+
+    /* Initialize Object Type components */
+    ExInitializeResourceLite(&LocalObjectType->Mutex);
+    InitializeListHead(&LocalObjectType->TypeList);
+
+    /* Insert it into the Object Directory */
+    if (ObpTypeDirectoryObject)
+    {
+        ObpAddEntryDirectory(ObpTypeDirectoryObject, Header, TypeName->Buffer);
+        ObReferenceObject(ObpTypeDirectoryObject);
+    }
+
+    *ObjectType = LocalObjectType;
+    return Status;
+} 
+
+/* EOF */