- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
index 63957b5..56f8534 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, ObInit)
+#endif
+
+
+extern ULONG NtGlobalFlag;
 
 /* GLOBALS ****************************************************************/
 
@@ -24,7 +30,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,
@@ -64,30 +70,26 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
    PVOID Object = NULL;
    UNICODE_STRING RemainingPath;
    UNICODE_STRING ObjectName;
-   OBJECT_ATTRIBUTES ObjectAttributes;
    OBJECT_CREATE_INFORMATION ObjectCreateInfo;
    NTSTATUS Status;
 
    PAGED_CODE();
 
-   InitializeObjectAttributes(&ObjectAttributes,
-                             ObjectPath,
-                             Attributes | OBJ_OPENIF,
-                             NULL,
-                             NULL);
-    
-   /* Capture all the info */
-   DPRINT("Capturing Create Info\n");
-   Status = ObpCaptureObjectAttributes(&ObjectAttributes,
-                                       AccessMode,
-                                       ObjectType,
-                                       &ObjectCreateInfo,
-                                       &ObjectName);
+   /* Capture the name */
+   DPRINT("Capturing Name\n");
+   Status = ObpCaptureObjectName(&ObjectName, ObjectPath, AccessMode);
    if (!NT_SUCCESS(Status))
      {
-       DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", 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,
@@ -95,7 +97,6 @@ ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
                         &RemainingPath,
                         ObjectType);
 
-   ObpReleaseCapturedAttributes(&ObjectCreateInfo);
    if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
 
    if (!NT_SUCCESS(Status))
@@ -182,19 +183,18 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
                         &Object,
                         &RemainingPath,
                         ObjectType);
-   ObpReleaseCapturedAttributes(&ObjectCreateInfo);
    if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
    if (!NT_SUCCESS(Status))
      {
        DPRINT("ObFindObject() failed (Status %lx)\n", Status);
-       return Status;
+       goto Cleanup;
      }
 
-   DPRINT("OBject: %x, Remaining Path: %wZ\n", Object, &RemainingPath);
+   DPRINT("OBject: %p, Remaining Path: %wZ\n", Object, &RemainingPath);
    if (Object == NULL)
      {
-       RtlFreeUnicodeString(&RemainingPath);
-       return STATUS_UNSUCCESSFUL;
+       Status = STATUS_UNSUCCESSFUL;
+       goto Cleanup;
      }
    if (RemainingPath.Buffer != NULL)
    {
@@ -202,19 +202,21 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
          Status = STATUS_OBJECT_NAME_NOT_FOUND;
       else
          Status =STATUS_OBJECT_PATH_NOT_FOUND;
-      RtlFreeUnicodeString(&RemainingPath);
-      ObDereferenceObject(Object);
-      return Status;
+      goto Cleanup;
    }
    
-   Status = ObpCreateHandle(PsGetCurrentProcess(),
-                          Object,
-                          DesiredAccess,
-                          FALSE,
-                          Handle);
+   Status = ObpCreateHandle(Object,
+                           DesiredAccess,
+                           ObjectCreateInfo.Attributes,
+                           Handle);
 
-   ObDereferenceObject(Object);
+Cleanup:
+   if (Object != NULL)
+   {
+       ObDereferenceObject(Object);
+   }
    RtlFreeUnicodeString(&RemainingPath);
+   ObpReleaseCapturedAttributes(&ObjectCreateInfo);
 
    return Status;
 }
@@ -243,6 +245,7 @@ ObQueryDeviceMapInformation(PEPROCESS Process,
 }
 
 VOID
+NTAPI
 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
                     POBJECT_HEADER Header,
                     PWSTR Name)
@@ -266,6 +269,7 @@ ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
 
 
 VOID
+NTAPI
 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
 /*
  * FUNCTION: Remove an entry from a namespace directory
@@ -364,6 +368,7 @@ ObpParseDirectory(PVOID Object,
   PWSTR Start;
   PWSTR End;
   PVOID FoundObject;
+  KIRQL oldlvl;
 
   DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
         Object,Path,*Path);
@@ -385,9 +390,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'\\';
@@ -399,7 +406,7 @@ ObpParseDirectory(PVOID Object,
                             STANDARD_RIGHTS_REQUIRED,
                             NULL,
                             UserMode);
-
+  KeReleaseSpinLock(&(((PDIRECTORY_OBJECT)Object)->Lock), oldlvl);
   if (End != NULL)
     {
       *End = L'\\';
@@ -427,6 +434,9 @@ ObInit(VOID)
     /* 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));
@@ -535,6 +545,7 @@ ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
 {
     POBJECT_HEADER Header;
     POBJECT_TYPE LocalObjectType;
+    ULONG HeaderSize;
     NTSTATUS Status;
 
     DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName);
@@ -563,42 +574,85 @@ ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
     }
     else
     {   
-        #if 0
-        ANSI_STRING Tag;
-        ULONG i;
+        CHAR Tag[4];
+        Tag[0] = TypeName->Buffer[0];
+        Tag[1] = TypeName->Buffer[1];
+        Tag[2] = TypeName->Buffer[2];
+        Tag[3] = TypeName->Buffer[3];
         
-        DPRINT1("Convert: %wZ \n", TypeName);
-        Status = RtlUnicodeStringToAnsiString(&Tag, TypeName, TRUE);
-        DPRINT1("Convert done\n");
-        if (NT_SUCCESS(Status))
-        {
-            /* Add spaces if needed */
-            for (i = 3; i >= Tag.Length; i--) Tag.Buffer[i] = ' ';
-            
-            /* Use the first four letters */
-            LocalObjectType->Key = *(PULONG)Tag.Buffer;
-            ExFreePool(Tag.Buffer);
-        }
-        else
-        #endif
-        {
-            /* Some weird problem. Use Unicode name */
-            LocalObjectType->Key = *(PULONG)TypeName->Buffer;
-            Status = STATUS_SUCCESS;
-        }
+        /* 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;
 }