- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
index 3097424..0add8fa 100644 (file)
@@ -14,6 +14,7 @@
 #define NDEBUG
 #include <internal/debug.h>
 
+extern ULONG NtGlobalFlag;
 
 /* GLOBALS ****************************************************************/
 
@@ -24,7 +25,7 @@ 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,
@@ -40,7 +41,8 @@ static GENERIC_MAPPING ObpTypeMapping = {
 
 NTSTATUS
 STDCALL
-ObpAllocateObject(POBJECT_ATTRIBUTES ObjectAttributes,
+ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
+                  PUNICODE_STRING ObjectName,
                   POBJECT_TYPE ObjectType,
                   ULONG ObjectSize,
                   POBJECT_HEADER *ObjectHeader);
@@ -62,31 +64,45 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
 {
    PVOID Object = NULL;
    UNICODE_STRING RemainingPath;
-   OBJECT_ATTRIBUTES ObjectAttributes;
+   UNICODE_STRING ObjectName;
+   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
    NTSTATUS Status;
 
    PAGED_CODE();
 
-   InitializeObjectAttributes(&ObjectAttributes,
-                             ObjectPath,
-                             Attributes | OBJ_OPENIF,
-                             NULL,
-                             NULL);
-   Status = ObFindObject(&ObjectAttributes,
+   /* Capture the name */
+   DPRINT("Capturing Name\n");
+   Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
+   if (!NT_SUCCESS(Status))
+     {
+       DPRINT("ObpCaptureObjectName() failed (Status %lx)\n", Status);
+       return Status;
+     }
+
+   /* 
+    * 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);
      }
-CHECKPOINT;
-DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
+   DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
 
    if (RemainingPath.Buffer != NULL || Object == NULL)
      {
-CHECKPOINT;
-DPRINT("Object %p\n", Object);
+        DPRINT("Object %p\n", Object);
        *ObjectPtr = NULL;
        RtlFreeUnicodeString (&RemainingPath);
        return(STATUS_OBJECT_NAME_NOT_FOUND);
@@ -136,22 +152,41 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
 {
    UNICODE_STRING RemainingPath;
    PVOID Object = NULL;
+   UNICODE_STRING ObjectName;
+   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
    NTSTATUS Status;
 
    PAGED_CODE();
 
    DPRINT("ObOpenObjectByName(...)\n");
 
-   Status = ObFindObject(ObjectAttributes,
+    /* Capture all the info */
+    DPRINT("Capturing Create Info\n");
+    Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                        AccessMode,
+                                        ObjectType,
+                                        &ObjectCreateInfo,
+                                        &ObjectName);
+   if (!NT_SUCCESS(Status))
+     {
+       DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+       return Status;
+     }
+                                        
+   Status = ObFindObject(&ObjectCreateInfo,
+                         &ObjectName,
                         &Object,
                         &RemainingPath,
                         ObjectType);
+   ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+   if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
    if (!NT_SUCCESS(Status))
      {
        DPRINT("ObFindObject() failed (Status %lx)\n", Status);
        return Status;
      }
 
+   DPRINT("OBject: %x, Remaining Path: %wZ\n", Object, &RemainingPath);
    if (Object == NULL)
      {
        RtlFreeUnicodeString(&RemainingPath);
@@ -167,7 +202,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
       ObDereferenceObject(Object);
       return Status;
    }
-
+   
    Status = ObpCreateHandle(PsGetCurrentProcess(),
                           Object,
                           DesiredAccess,
@@ -204,6 +239,7 @@ ObQueryDeviceMapInformation(PEPROCESS Process,
 }
 
 VOID
+NTAPI
 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
                     POBJECT_HEADER Header,
                     PWSTR Name)
@@ -217,8 +253,8 @@ ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
 {
   KIRQL oldlvl;
 
-  RtlpCreateUnicodeString(&Header->Name, Name, NonPagedPool);
-  Header->Parent = Parent;
+  ASSERT(HEADER_TO_OBJECT_NAME(Header));
+  HEADER_TO_OBJECT_NAME(Header)->Directory = Parent;
 
   KeAcquireSpinLock(&Parent->Lock, &oldlvl);
   InsertTailList(&Parent->head, &Header->Entry);
@@ -227,6 +263,7 @@ ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
 
 
 VOID
+NTAPI
 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
 /*
  * FUNCTION: Remove an entry from a namespace directory
@@ -238,13 +275,13 @@ ObpRemoveEntryDirectory(POBJECT_HEADER Header)
 
   DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
 
-  KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
+  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->Parent->Lock),oldlvl);
+  KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header)->Directory->Lock),oldlvl);
 }
 
 NTSTATUS
@@ -286,26 +323,26 @@ ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
      }
    if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
      {
-       return(BODY_TO_HEADER(DirectoryObject)->Parent);
+       return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject))->Directory);
      }
    while (current!=(&(DirectoryObject->head)))
      {
        current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
-       DPRINT("  Scanning: %S for: %S\n",current_obj->Name.Buffer, Name);
+       DPRINT("  Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name);
        if (Attributes & OBJ_CASE_INSENSITIVE)
          {
-            if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
+            if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
               {
-                 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
-                 return(HEADER_TO_BODY(current_obj));
+                 DPRINT("Found it %x\n",&current_obj->Body);
+                 return(&current_obj->Body);
               }
          }
        else
          {
-            if ( wcscmp(current_obj->Name.Buffer, Name)==0)
+            if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj)->Name.Buffer, Name)==0)
               {
-                 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
-                 return(HEADER_TO_BODY(current_obj));
+                 DPRINT("Found it %x\n",&current_obj->Body);
+                 return(&current_obj->Body);
               }
          }
        current = current->Flink;
@@ -325,6 +362,7 @@ ObpParseDirectory(PVOID Object,
   PWSTR Start;
   PWSTR End;
   PVOID FoundObject;
+  KIRQL oldlvl;
 
   DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
         Object,Path,*Path);
@@ -346,9 +384,11 @@ ObpParseDirectory(PVOID Object,
       *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'\\';
@@ -360,7 +400,7 @@ ObpParseDirectory(PVOID Object,
                             STANDARD_RIGHTS_REQUIRED,
                             NULL,
                             UserMode);
-
+  KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
   if (End != NULL)
     {
       *End = L'\\';
@@ -388,8 +428,11 @@ ObInit(VOID)
     /* Initialize the security descriptor cache */
     ObpInitSdCache();
 
+    /* Initialize the Default Event */
+    KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE );
+
     /* Create the Type Type */
-    DPRINT1("Creating Type Type\n");
+    DPRINT("Creating Type Type\n");
     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
     RtlInitUnicodeString(&Name, L"Type");
     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
@@ -402,7 +445,7 @@ ObInit(VOID)
     ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ObTypeObjectType);
   
     /* Create the Directory Type */
-    DPRINT1("Creating Directory Type\n");
+    DPRINT("Creating Directory Type\n");
     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
     RtlInitUnicodeString(&Name, L"Directory");
     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
@@ -430,7 +473,7 @@ ObInit(VOID)
                                  FALSE);
 
     /* Create root directory */
-    DPRINT1("Creating Root Directory\n");    
+    DPRINT("Creating Root Directory\n");    
     InitializeObjectAttributes(&ObjectAttributes,
                                NULL,
                                OBJ_PERMANENT,
@@ -445,6 +488,12 @@ ObInit(VOID)
                    0,
                    0,
                    (PVOID*)&NameSpaceRoot);
+    ObInsertObject((PVOID)NameSpaceRoot,
+                   NULL,
+                   DIRECTORY_ALL_ACCESS,
+                   0,
+                   NULL,
+                   NULL);
 
     /* Create '\ObjectTypes' directory */
     RtlInitUnicodeString(&Name, L"\\ObjectTypes");
@@ -462,11 +511,17 @@ ObInit(VOID)
                    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), L"Type");
-    ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObDirectoryType), L"Directory");
+    ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObTypeObjectType), NULL);
+    ObpAddEntryDirectory(ObpTypeDirectoryObject, BODY_TO_HEADER(ObDirectoryType), NULL);
 
     /* Create 'symbolic link' object type */
     ObInitSymbolicLinkImplementation();
@@ -484,12 +539,14 @@ ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
 {
     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);
@@ -499,28 +556,97 @@ ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
         return Status;
     }
     
-    LocalObjectType =  HEADER_TO_BODY(Header);
+    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->ObjectType = ObTypeObjectType;
+        Header->Type = ObTypeObjectType;
+        LocalObjectType->Key = TAG('O', 'b', 'j', 'T');
     }
-    
-    /* FIXME: Generate Tag */
+    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;
 }