forget update de.rc
[reactos.git] / reactos / ntoskrnl / cm / regobj.c
index 0bb1984..b824c85 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$
- * 
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/cm/regobj.c
@@ -14,6 +14,8 @@
 
 #include "cm.h"
 
+extern LIST_ENTRY CmiKeyObjectListHead;
+extern ULONG CmiTimer;
 
 static NTSTATUS
 CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
@@ -76,10 +78,22 @@ CmiObjectParse(PVOID ParsedObject,
                KeyName.Length);
   KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] = 0;
 
+  /* Acquire hive lock */
+  KeEnterCriticalRegion();
+  ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
 
-  FoundObject = CmiScanKeyList(ParsedKey,
-                              &KeyName,
-                              Attributes);
+  Status = CmiScanKeyList(ParsedKey,
+                         &KeyName,
+                         Attributes,
+                         &FoundObject);
+  if (!NT_SUCCESS(Status))
+  {
+     ExReleaseResourceLite(&CmiRegistryLock);
+     KeLeaveCriticalRegion();
+     RtlFreeUnicodeString(&KeyName);
+     return Status;
+  }
   if (FoundObject == NULL)
     {
       Status = CmiScanForSubKey(ParsedKey->RegistryHive,
@@ -91,6 +105,8 @@ CmiObjectParse(PVOID ParsedObject,
                                Attributes);
       if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
        {
+          ExReleaseResourceLite(&CmiRegistryLock);
+          KeLeaveCriticalRegion();
          RtlFreeUnicodeString(&KeyName);
          return(STATUS_UNSUCCESSFUL);
        }
@@ -104,6 +120,9 @@ CmiObjectParse(PVOID ParsedObject,
                                    &LinkPath);
          if (NT_SUCCESS(Status))
            {
+              ExReleaseResourceLite(&CmiRegistryLock);
+              KeLeaveCriticalRegion();
+
              DPRINT("LinkPath '%wZ'\n", &LinkPath);
 
              /* build new FullPath for reparsing */
@@ -140,7 +159,7 @@ CmiObjectParse(PVOID ParsedObject,
        }
 
       /* Create new key object and put into linked list */
-      DPRINT("CmiObjectParse: %s\n", Path);
+      DPRINT("CmiObjectParse: %S\n", *Path);
       Status = ObCreateObject(KernelMode,
                              CmiKeyType,
                              NULL,
@@ -152,18 +171,32 @@ CmiObjectParse(PVOID ParsedObject,
                              (PVOID*)&FoundObject);
       if (!NT_SUCCESS(Status))
        {
+          ExReleaseResourceLite(&CmiRegistryLock);
+          KeLeaveCriticalRegion();
          RtlFreeUnicodeString(&KeyName);
          return(Status);
        }
+    DPRINT("Inserting Key into Object Tree\n");
+    Status =  ObInsertObject((PVOID)FoundObject,
+                             NULL,
+                             KEY_ALL_ACCESS,
+                             0,
+                             NULL,
+                             NULL);
+    DPRINT("Status %x\n", Status);
+
+      /* Add the keep-alive reference */
+      ObReferenceObject(FoundObject);
 
       FoundObject->Flags = 0;
       FoundObject->KeyCell = SubKeyCell;
       FoundObject->KeyCellOffset = BlockOffset;
       FoundObject->RegistryHive = ParsedKey->RegistryHive;
+      InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
       RtlpCreateUnicodeString(&FoundObject->Name,
               KeyName.Buffer, NonPagedPool);
       CmiAddKeyToList(ParsedKey, FoundObject);
-      DPRINT("Created object 0x%x\n", FoundObject);
+      DPRINT("Created object 0x%p\n", FoundObject);
     }
   else
     {
@@ -180,6 +213,11 @@ CmiObjectParse(PVOID ParsedObject,
            {
              DPRINT("LinkPath '%wZ'\n", &LinkPath);
 
+              ExReleaseResourceLite(&CmiRegistryLock);
+              KeLeaveCriticalRegion();
+
+             ObDereferenceObject(FoundObject);
+
              /* build new FullPath for reparsing */
              TargetPath.MaximumLength = LinkPath.MaximumLength;
              if (EndPtr != NULL)
@@ -212,13 +250,15 @@ CmiObjectParse(PVOID ParsedObject,
              return(STATUS_REPARSE);
            }
        }
-
-      ObReferenceObjectByPointer(FoundObject,
-                                STANDARD_RIGHTS_REQUIRED,
-                                NULL,
-                                UserMode);
     }
 
+  RemoveEntryList(&FoundObject->ListEntry);
+  InsertHeadList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+  FoundObject->TimeStamp = CmiTimer;
+
+  ExReleaseResourceLite(&CmiRegistryLock);
+  KeLeaveCriticalRegion();
+
   DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
 
   *Path = EndPtr;
@@ -232,35 +272,6 @@ CmiObjectParse(PVOID ParsedObject,
   return(STATUS_SUCCESS);
 }
 
-
-NTSTATUS STDCALL
-CmiObjectCreate(PVOID ObjectBody,
-               PVOID Parent,
-               PWSTR RemainingPath,
-               POBJECT_ATTRIBUTES ObjectAttributes)
-{
-  PKEY_OBJECT KeyObject = ObjectBody;
-  PWSTR Start;
-
-  KeyObject->ParentKey = Parent;
-  if (RemainingPath)
-    {
-      Start = RemainingPath;
-      if(*Start == L'\\')
-       Start++;
-      RtlpCreateUnicodeString(&KeyObject->Name,
-              Start, NonPagedPool);
-    }
-   else
-    {
-      RtlInitUnicodeString(&KeyObject->Name,
-                          NULL);
-    }
-
-  return STATUS_SUCCESS;
-}
-
-
 VOID STDCALL
 CmiObjectDelete(PVOID DeletedObject)
 {
@@ -274,11 +285,16 @@ CmiObjectDelete(PVOID DeletedObject)
 
   ObReferenceObject (ParentKeyObject);
 
+  /* Acquire hive lock */
+  KeEnterCriticalRegion();
+  ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
   if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
     {
       DPRINT1("Key not found in parent list ???\n");
     }
 
+  RemoveEntryList(&KeyObject->ListEntry);
   RtlFreeUnicodeString(&KeyObject->Name);
 
   if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
@@ -302,6 +318,9 @@ CmiObjectDelete(PVOID DeletedObject)
 
   ObDereferenceObject (ParentKeyObject);
 
+  ExReleaseResourceLite(&CmiRegistryLock);
+  KeLeaveCriticalRegion();
+
   if (KeyObject->NumberOfSubKeys)
     {
       KEBUGCHECK(REGISTRY_ERROR);
@@ -317,7 +336,7 @@ CmiObjectDelete(PVOID DeletedObject)
 static NTSTATUS
 CmiQuerySecurityDescriptor(PKEY_OBJECT KeyObject,
                           SECURITY_INFORMATION SecurityInformation,
-                          PSECURITY_DESCRIPTOR SecurityDescriptor,
+                          PISECURITY_DESCRIPTOR SecurityDescriptor,
                           PULONG BufferLength)
 {
   ULONG_PTR Current;
@@ -431,7 +450,10 @@ CmiObjectSecurity(PVOID ObjectBody,
                  SECURITY_OPERATION_CODE OperationCode,
                  SECURITY_INFORMATION SecurityInformation,
                  PSECURITY_DESCRIPTOR SecurityDescriptor,
-                 PULONG BufferLength)
+                 PULONG BufferLength,
+                 PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+                 POOL_TYPE PoolType,
+                 PGENERIC_MAPPING GenericMapping)
 {
   DPRINT("CmiObjectSecurity() called\n");
 
@@ -468,49 +490,49 @@ CmiObjectQueryName (PVOID ObjectBody,
                    ULONG Length,
                    PULONG ReturnLength)
 {
-  POBJECT_NAME_INFORMATION LocalInfo;
   PKEY_OBJECT KeyObject;
-  ULONG LocalReturnLength;
   NTSTATUS Status;
 
   DPRINT ("CmiObjectQueryName() called\n");
 
   KeyObject = (PKEY_OBJECT)ObjectBody;
 
-  LocalInfo = ExAllocatePool (NonPagedPool,
-                             sizeof(OBJECT_NAME_INFORMATION) +
-                               MAX_PATH * sizeof(WCHAR));
-  if (LocalInfo == NULL)
-    return STATUS_INSUFFICIENT_RESOURCES;
-
   if (KeyObject->ParentKey != KeyObject)
     {
       Status = ObQueryNameString (KeyObject->ParentKey,
-                                 LocalInfo,
-                                 MAX_PATH * sizeof(WCHAR),
-                                 &LocalReturnLength);
+                                 ObjectNameInfo,
+                                 Length,
+                                 ReturnLength);
     }
   else
     {
       /* KeyObject is the root key */
-      Status = ObQueryNameString (BODY_TO_HEADER(KeyObject)->Parent,
-                                 LocalInfo,
-                                 MAX_PATH * sizeof(WCHAR),
-                                 &LocalReturnLength);
+      Status = ObQueryNameString (HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(KeyObject))->Directory,
+                                 ObjectNameInfo,
+                                 Length,
+                                 ReturnLength);
     }
 
-  if (!NT_SUCCESS (Status))
+  if (!NT_SUCCESS(Status) && Status != STATUS_INFO_LENGTH_MISMATCH)
     {
-      ExFreePool (LocalInfo);
       return Status;
     }
-  DPRINT ("Parent path: %wZ\n", &LocalInfo->Name);
+  (*ReturnLength) += sizeof(WCHAR) + KeyObject->Name.Length;
 
-  Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
-                                          &LocalInfo->Name);
-  ExFreePool (LocalInfo);
-  if (!NT_SUCCESS (Status))
-    return Status;
+  if (Status == STATUS_INFO_LENGTH_MISMATCH || *ReturnLength > Length)
+    {
+      return STATUS_INFO_LENGTH_MISMATCH;
+    }
+
+  if (ObjectNameInfo->Name.Buffer == NULL)
+    {
+      ObjectNameInfo->Name.Buffer = (PWCHAR)(ObjectNameInfo + 1);
+      ObjectNameInfo->Name.Length = 0;
+      ObjectNameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
+    }
+
+
+  DPRINT ("Parent path: %wZ\n", ObjectNameInfo->Name);
 
   Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
                                     L"\\");
@@ -532,11 +554,9 @@ VOID
 CmiAddKeyToList(PKEY_OBJECT ParentKey,
                PKEY_OBJECT NewKey)
 {
-  KIRQL OldIrql;
 
   DPRINT("ParentKey %.08x\n", ParentKey);
 
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
 
   if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
     {
@@ -561,14 +581,13 @@ CmiAddKeyToList(PKEY_OBJECT ParentKey,
   /*      to allow a dichotomic search */
   ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
 
-  DPRINT("Reference parent key: 0x%x\n", ParentKey);
+  DPRINT("Reference parent key: 0x%p\n", ParentKey);
 
   ObReferenceObjectByPointer(ParentKey,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
                UserMode);
   NewKey->ParentKey = ParentKey;
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 }
 
 
@@ -576,11 +595,9 @@ NTSTATUS
 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
 {
   PKEY_OBJECT ParentKey;
-  KIRQL OldIrql;
   DWORD Index;
 
   ParentKey = KeyToRemove->ParentKey;
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: If list maintained in alphabetic order, use dichotomic search */
   for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
     {
@@ -591,33 +608,30 @@ CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
                          &ParentKey->SubKeys[Index + 1],
                          (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
          ParentKey->NumberOfSubKeys--;
-         KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
          DPRINT("Dereference parent key: 0x%x\n", ParentKey);
-       
+
          ObDereferenceObject(ParentKey);
          return STATUS_SUCCESS;
        }
     }
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
   return STATUS_UNSUCCESSFUL;
 }
 
 
-PKEY_OBJECT
+NTSTATUS
 CmiScanKeyList(PKEY_OBJECT Parent,
               PUNICODE_STRING KeyName,
-              ULONG Attributes)
+              ULONG Attributes,
+              PKEY_OBJECT* ReturnedObject)
 {
   PKEY_OBJECT CurKey;
-  KIRQL OldIrql;
   ULONG Index;
 
   DPRINT("Scanning key list for: %wZ (Parent: %wZ)\n",
         KeyName, &Parent->Name);
 
-  KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
   /* FIXME: if list maintained in alphabetic order, use dichotomic search */
   for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
     {
@@ -627,8 +641,7 @@ CmiScanKeyList(PKEY_OBJECT Parent,
          if ((KeyName->Length == CurKey->Name.Length)
              && (_wcsicmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
            {
-             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-             return CurKey;
+             break;
            }
        }
       else
@@ -636,14 +649,26 @@ CmiScanKeyList(PKEY_OBJECT Parent,
          if ((KeyName->Length == CurKey->Name.Length)
              && (wcscmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
            {
-             KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-             return CurKey;
+             break;
            }
        }
     }
-  KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
 
-  return NULL;
+  if (Index < Parent->NumberOfSubKeys)
+  {
+     if (CurKey->Flags & KO_MARKED_FOR_DELETE)
+     {
+        *ReturnedObject = NULL;
+       return STATUS_UNSUCCESSFUL;
+     }
+     ObReferenceObject(CurKey);
+     *ReturnedObject = CurKey;
+  }
+  else
+  {
+     *ReturnedObject = NULL;
+  }
+  return STATUS_SUCCESS;
 }
 
 
@@ -652,7 +677,7 @@ CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
                 PKEY_CELL KeyCell,
                 PUNICODE_STRING TargetPath)
 {
-  UNICODE_STRING LinkName = ROS_STRING_INITIALIZER(L"SymbolicLinkValue");
+  UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
   PVALUE_CELL ValueCell;
   PDATA_CELL DataCell;
   NTSTATUS Status;