Use ERESOURCE to lock registry hives.
authorEric Kohl <eric.kohl@reactos.org>
Tue, 26 Nov 2002 15:31:41 +0000 (15:31 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Tue, 26 Nov 2002 15:31:41 +0000 (15:31 +0000)
Keep open hives in a global list.

svn path=/trunk/; revision=3794

reactos/ntoskrnl/cm/cm.h
reactos/ntoskrnl/cm/ntfunc.c
reactos/ntoskrnl/cm/regfile.c
reactos/ntoskrnl/cm/registry.c
reactos/ntoskrnl/cm/rtlfunc.c

index 69a345d..3799acc 100644 (file)
 #define  SAM_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SAM"
 #define  SEC_REG_FILE                  L"\\SystemRoot\\System32\\Config\\SECURITY"
 
+#define  REG_SYSTEM_FILE_NAME          L"\\SYSTEM"
+#define  REG_SOFTWARE_FILE_NAME                L"\\SOFTWARE"
+#define  REG_USER_FILE_NAME            L"\\DEFAULT"
+#define  REG_SAM_FILE_NAME             L"\\SAM"
+#define  REG_SEC_FILE_NAME             L"\\SECURITY"
+
 #define  REG_BLOCK_SIZE                4096
 #define  REG_HBIN_DATA_OFFSET          32
 #define  REG_BIN_ID                    0x6e696268
@@ -228,6 +234,7 @@ typedef struct _DATA_CELL
 
 typedef struct _REGISTRY_HIVE
 {
+  LIST_ENTRY HiveList;
   ULONG  Flags;
   UNICODE_STRING  Filename;
   ULONG  FileSize;
@@ -240,8 +247,8 @@ typedef struct _REGISTRY_HIVE
   ULONG  FreeListMax;
   PCELL_HEADER *FreeList;
   BLOCK_OFFSET *FreeListOffset;
-//  KSPIN_LOCK  RegLock;
-  KSEMAPHORE RegSem;
+  ERESOURCE HiveResource;
+
 //  NTSTATUS  (*Extend)(ULONG NewSize);
 //  PVOID  (*Flush)(VOID);
 } REGISTRY_HIVE, *PREGISTRY_HIVE;
@@ -314,6 +321,9 @@ extern PREGISTRY_HIVE CmiVolatileHive;
 extern POBJECT_TYPE CmiKeyType;
 extern KSPIN_LOCK CmiKeyListLock;
 
+extern LIST_ENTRY CmiHiveListHead;
+extern KSPIN_LOCK CmiHiveListLock;
+
 
 VOID
 CmiVerifyBinCell(PHBIN BinCell);
@@ -376,6 +386,9 @@ CmiCreateRegistryHive(PWSTR Filename,
   PREGISTRY_HIVE *RegistryHive,
   BOOLEAN CreateNew);
 
+NTSTATUS
+CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive);
+
 ULONG
 CmiGetMaxNameLength(IN PREGISTRY_HIVE  RegistryHive,
   IN PKEY_CELL  KeyCell);
index 43217f3..dd9d8ea 100644 (file)
@@ -38,12 +38,12 @@ static BOOLEAN CmiRegistryInitialized = FALSE;
 
 NTSTATUS STDCALL
 NtCreateKey(OUT PHANDLE KeyHandle,
-       IN ACCESS_MASK DesiredAccess,
-       IN POBJECT_ATTRIBUTES ObjectAttributes,
-       IN ULONG TitleIndex,
-       IN PUNICODE_STRING Class,
-       IN ULONG CreateOptions,
-       OUT PULONG Disposition)
+           IN ACCESS_MASK DesiredAccess,
+           IN POBJECT_ATTRIBUTES ObjectAttributes,
+           IN ULONG TitleIndex,
+           IN PUNICODE_STRING Class,
+           IN ULONG CreateOptions,
+           OUT PULONG Disposition)
 {
   UNICODE_STRING RemainingPath;
   PKEY_OBJECT KeyObject;
@@ -52,17 +52,19 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   PWSTR End;
 
   DPRINT("NtCreateKey (Name %wZ  KeyHandle %x  Root %x)\n",
-         ObjectAttributes->ObjectName,
-         KeyHandle,
-         ObjectAttributes->RootDirectory);
+        ObjectAttributes->ObjectName,
+        KeyHandle,
+        ObjectAttributes->RootDirectory);
 
   /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */
 
-  Status = ObFindObject(ObjectAttributes, &Object, &RemainingPath, CmiKeyType);
-
+  Status = ObFindObject(ObjectAttributes,
+                       &Object,
+                       &RemainingPath,
+                       CmiKeyType);
   if (!NT_SUCCESS(Status))
     {
-      return Status;
+      return(Status);
     }
 
   DPRINT("RemainingPath %wZ\n", &RemainingPath);
@@ -73,7 +75,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
       if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
        {
          ObDereferenceObject(Object);
-         return STATUS_UNSUCCESSFUL;
+         return(STATUS_UNSUCCESSFUL);
        }
 
       if (Disposition)
@@ -112,7 +114,9 @@ NtCreateKey(OUT PHANDLE KeyHandle,
                          (PVOID*)&KeyObject);
 
   if (!NT_SUCCESS(Status))
-    return(Status);
+    {
+      return(Status);
+    }
 
   KeyObject->ParentKey = Object;
 
@@ -125,7 +129,10 @@ NtCreateKey(OUT PHANDLE KeyHandle,
   KeyObject->NumberOfSubKeys = 0;
   KeyObject->SizeOfSubKeys = 0;
   KeyObject->SubKeys = NULL;
-//  KeAcquireSpinLock(&Key->RegistryHive->RegLock, &OldIrql);
+
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   /* add key to subkeys of parent if needed */
   Status = CmiAddSubKey(KeyObject->RegistryHive,
                        KeyObject->ParentKey,
@@ -138,6 +145,7 @@ NtCreateKey(OUT PHANDLE KeyHandle,
 
   if (!NT_SUCCESS(Status))
     {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       ObDereferenceObject(Object);
       return STATUS_UNSUCCESSFUL;
@@ -164,7 +172,9 @@ NtCreateKey(OUT PHANDLE KeyHandle,
     }
 
   CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
-//  KeReleaseSpinLock(&KeyObject->RegistryHive->RegLock, OldIrql);
+
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
 
   ObDereferenceObject(KeyObject);
   ObDereferenceObject(Object);
@@ -199,6 +209,9 @@ NtDeleteKey(IN HANDLE KeyHandle)
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /*  Set the marked for delete bit in the key object  */
@@ -213,6 +226,9 @@ NtDeleteKey(IN HANDLE KeyHandle)
   /* FIXME: I think that ObDeleteHandle should dereference the object  */
   ObDereferenceObject(KeyObject);
 
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
   return STATUS_SUCCESS;
 }
 
@@ -238,13 +254,13 @@ NtEnumerateKey(
   PDATA_CELL pClassData;
 
   DPRINT("KH %x  I %d  KIC %x KI %x  L %d  RL %x\n",
-       KeyHandle,
-       Index,
-         KeyInformationClass,
-       KeyInformation,
-       Length,
-       ResultLength);
-    
+        KeyHandle,
+        Index,
+        KeyInformationClass,
+        KeyInformation,
+        Length,
+        ResultLength);
+
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_ENUMERATE_SUB_KEYS,
@@ -255,62 +271,68 @@ NtEnumerateKey(
   if (!NT_SUCCESS(Status))
     {
       DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
-      return Status;
+      return(Status);
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-    
+
   /* Get pointer to SubKey */
   if (Index >= KeyCell->NumberOfSubKeys)
-         {
-           if (RegistryHive == CmiVolatileHive)
-                   {
-                     ObDereferenceObject (KeyObject);
-                     DPRINT("No more volatile entries\n");
-                     return STATUS_NO_MORE_ENTRIES;
-                   }
-           else
-                   {
-                    ULONG i;
-                    PKEY_OBJECT CurKey = NULL;
-
-                     /* Search volatile keys */
-                     for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
-                             {
-                               CurKey = KeyObject->SubKeys[i];
-                               if (CurKey->RegistryHive == CmiVolatileHive)
-                                                               {
-                                                                 if (Index-- == KeyObject->NumberOfSubKeys)
-                    break;
-                                                               }
-                             }
-                     if(Index >= KeyCell->NumberOfSubKeys)
-                             {
-                               ObDereferenceObject (KeyObject);
-                               DPRINT("No more non-volatile entries\n");
-                               return STATUS_NO_MORE_ENTRIES;
-                             }
-                     SubKeyCell = CurKey->KeyCell;
-                   }
-         }
+    {
+      if (RegistryHive == CmiVolatileHive)
+       {
+         ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+         ObDereferenceObject(KeyObject);
+         DPRINT("No more volatile entries\n");
+         return(STATUS_NO_MORE_ENTRIES);
+       }
+      else
+       {
+         ULONG i;
+         PKEY_OBJECT CurKey = NULL;
+
+         /* Search volatile keys */
+         for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+           {
+             CurKey = KeyObject->SubKeys[i];
+             if (CurKey->RegistryHive == CmiVolatileHive)
+               {
+                 if (Index-- == KeyObject->NumberOfSubKeys)
+                   break;
+               }
+           }
+         if (Index >= KeyCell->NumberOfSubKeys)
+           {
+             ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+             ObDereferenceObject(KeyObject);
+             DPRINT("No more non-volatile entries\n");
+             return(STATUS_NO_MORE_ENTRIES);
+           }
+         SubKeyCell = CurKey->KeyCell;
+       }
+    }
   else
-         {
-           HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
-           SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, 
-                               HashTableBlock, 
-                               Index);
-         }
+    {
+      HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+      SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
+                                           HashTableBlock,
+                                           Index);
+    }
 
   if (SubKeyCell == NULL)
-         {
-           ObDereferenceObject (KeyObject);
-           DPRINT("No more entries\n");
-           return STATUS_NO_MORE_ENTRIES;
-         }
+    {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+      ObDereferenceObject(KeyObject);
+      DPRINT("No more entries\n");
+      return(STATUS_NO_MORE_ENTRIES);
+    }
 
   Status = STATUS_SUCCESS;
   switch (KeyInformationClass)
@@ -417,11 +439,13 @@ NtEnumerateKey(
       break;
     }
   CmiReleaseBlock(RegistryHive, SubKeyCell);
-  ObDereferenceObject (KeyObject);
+
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+  ObDereferenceObject(KeyObject);
 
   DPRINT("Returning status %x\n", Status);
 
-  return  Status;
+  return(Status);
 }
 
 
@@ -444,12 +468,12 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
   PKEY_VALUE_FULL_INFORMATION  ValueFullInformation;
 
   DPRINT("KH %x  I %d  KVIC %x  KVI %x  L %d  RL %x\n",
-       KeyHandle,
-       Index,
-         KeyValueInformationClass,
-       KeyValueInformation,
-       Length,
-       ResultLength);
+        KeyHandle,
+        Index,
+        KeyValueInformationClass,
+        KeyValueInformation,
+        Length,
+        ResultLength);
 
   /*  Verify that the handle is valid and is a registry key  */
   Status = ObReferenceObjectByHandle(KeyHandle,
@@ -464,12 +488,15 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-    
+
   /* Get Value block of interest */
   Status = CmiGetValueFromKeyByIndex(RegistryHive,
                KeyCell,
@@ -478,10 +505,12 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
 
   if (!NT_SUCCESS(Status))
     {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
-  else if (ValueCell != NULL)
+
+  if (ValueCell != NULL)
     {
       switch (KeyValueInformationClass)
         {
@@ -588,6 +617,8 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
     {
       Status = STATUS_UNSUCCESSFUL;
     }
+
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
 
   return Status;
@@ -597,23 +628,22 @@ NtEnumerateValueKey(IN HANDLE KeyHandle,
 NTSTATUS STDCALL
 NtFlushKey(IN HANDLE KeyHandle)
 {
-       NTSTATUS Status;
-       PKEY_OBJECT  KeyObject;
-       PREGISTRY_HIVE  RegistryHive;
-       WCHAR LogName[MAX_PATH];
-       UNICODE_STRING TmpFileName;
-       HANDLE FileHandle;
-       // HANDLE FileHandleLog;
-       OBJECT_ATTRIBUTES ObjectAttributes;
-       // KIRQL  OldIrql;
-       LARGE_INTEGER fileOffset;
-       DWORD * pEntDword;
-       ULONG i;
+  NTSTATUS Status;
+  PKEY_OBJECT  KeyObject;
+  PREGISTRY_HIVE  RegistryHive;
+  WCHAR LogName[MAX_PATH];
+  UNICODE_STRING TmpFileName;
+  HANDLE FileHandle;
+//  HANDLE FileHandleLog;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  LARGE_INTEGER fileOffset;
+  DWORD * pEntDword;
+  ULONG i;
 
   DPRINT("KeyHandle %x\n", KeyHandle);
 
-       /* Verify that the handle is valid and is a registry key */
-       Status = ObReferenceObjectByHandle(KeyHandle,
+  /* Verify that the handle is valid and is a registry key */
+  Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_QUERY_VALUE,
                CmiKeyType,
                UserMode,
@@ -625,19 +655,22 @@ NtFlushKey(IN HANDLE KeyHandle)
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   RegistryHive = KeyObject->RegistryHive;
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
+
   /* Then write changed blocks in .log */
   wcscpy(LogName,RegistryHive->Filename.Buffer);
   wcscat(LogName,L".log");
   RtlInitUnicodeString (&TmpFileName, LogName);
   InitializeObjectAttributes(&ObjectAttributes,
-               &TmpFileName,
-               0,
-               NULL,
-               NULL);
+                            &TmpFileName,
+                            0,
+                            NULL,
+                            NULL);
 
 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
    so we can't create log file
@@ -721,28 +754,28 @@ END FIXME*/
                      NULL,
                      0,
                      FILE_SYNCHRONOUS_IO_NONALERT);
-
   if (!NT_SUCCESS(Status))
     {
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
 
   RegistryHive->HiveHeader->Version++;
 
-  Status = ZwWriteFile(FileHandle, 
-               0,
-    0,
-    0,
-    0, 
-               RegistryHive->HiveHeader, 
-               sizeof(HIVE_HEADER), 
-               0,
-    0);
-
+  Status = ZwWriteFile(FileHandle,
+                      0,
+                      0,
+                      0,
+                      0,
+                      RegistryHive->HiveHeader,
+                      sizeof(HIVE_HEADER),
+                      0,
+                      0);
   if (!NT_SUCCESS(Status))
     {
       ZwClose(FileHandle);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
@@ -750,35 +783,33 @@ END FIXME*/
   /* Update changed blocks in file */
   fileOffset.u.HighPart = 0;
   for (i = 0; i < RegistryHive->BlockListSize ; i++)
-  {
-    if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
+    {
+      if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
            > RegistryHive->HiveHeader->DateModified.dwHighDateTime
-      || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
+         || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
                == RegistryHive->HiveHeader->DateModified.dwHighDateTime
-          && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
-               > RegistryHive->HiveHeader->DateModified.dwLowDateTime
-         )
-       )
+             && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
+                > RegistryHive->HiveHeader->DateModified.dwLowDateTime))
+       {
+         fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096;
+         Status = NtWriteFile(FileHandle,
+                              0,
+                              0,
+                              0,
+                              0,
+                              RegistryHive->BlockList[i],
+                              RegistryHive->BlockList[i]->BlockSize,
+                              &fileOffset,
+                              0);
+         if (!NT_SUCCESS(Status))
            {
-             fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096;
-             Status = NtWriteFile(FileHandle, 
-                                       0,
-               0,
-               0,
-               0, 
-                                       RegistryHive->BlockList[i],
-                                       RegistryHive->BlockList[i]->BlockSize ,
-                                       &fileOffset,
-               0);
-
-                         if (!NT_SUCCESS(Status))
-                           {
-                             ZwClose(FileHandle);
-                             ObDereferenceObject(KeyObject);
-                             return Status;
-                           }
+             ZwClose(FileHandle);
+             ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+             ObDereferenceObject(KeyObject);
+             return(Status);
            }
-  }
+       }
+    }
 
   /* Change version in header */
   RegistryHive->HiveHeader->VersionOld = RegistryHive->HiveHeader->Version;
@@ -794,25 +825,26 @@ END FIXME*/
 
   /* Write new header */
   fileOffset.u.LowPart = 0;
-  Status = ZwWriteFile(FileHandle, 
-               0,
-    0,
-    0,
-    0, 
-               RegistryHive->HiveHeader, 
-               sizeof(HIVE_HEADER), 
-               &fileOffset,
-    0);
+  Status = ZwWriteFile(FileHandle,
+                      0,
+                      0,
+                      0,
+                      0,
+                      RegistryHive->HiveHeader,
+                      sizeof(HIVE_HEADER),
+                      &fileOffset,
+                      0);
 
   if (!NT_SUCCESS(Status))
     {
       ZwClose(FileHandle);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return Status;
     }
 
   ZwClose(FileHandle);
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
   return STATUS_SUCCESS;
 }
@@ -893,12 +925,12 @@ NtQueryKey(IN     HANDLE KeyHandle,
   NTSTATUS Status;
 
   DPRINT("KH %x  KIC %x  KI %x  L %d  RL %x\n",
-       KeyHandle,
-    KeyInformationClass,
-       KeyInformation,
-    Length,
-    ResultLength);
-    
+        KeyHandle,
+        KeyInformationClass,
+        KeyInformation,
+        Length,
+        ResultLength);
+
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle(KeyHandle,
                KEY_READ,
@@ -906,12 +938,14 @@ NtQueryKey(IN     HANDLE KeyHandle,
                UserMode,
                (PVOID *) &KeyObject,
                NULL);
-
   if (!NT_SUCCESS(Status))
     {
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
@@ -1023,11 +1057,13 @@ NtQueryKey(IN   HANDLE KeyHandle,
       break;
     }
 
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
 
   return Status;
 }
 
+
 NTSTATUS STDCALL
 NtQueryValueKey(IN HANDLE KeyHandle,
        IN PUNICODE_STRING ValueName,
@@ -1067,22 +1103,27 @@ NtQueryValueKey(IN HANDLE KeyHandle,
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
   KeyCell = KeyObject->KeyCell;
   RegistryHive = KeyObject->RegistryHive;
-  /* Get Value block of interest */
-  Status = CmiScanKeyForValue(RegistryHive, 
-               KeyCell,
-               ValueName2,
-               &ValueCell,NULL);
 
+  /* Get Value block of interest */
+  Status = CmiScanKeyForValue(RegistryHive,
+                             KeyCell,
+                             ValueName2,
+                             &ValueCell,
+                             NULL);
   if (!NT_SUCCESS(Status))
     {
       DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
-      return Status;
+      return(Status);
     }
   else if (ValueCell != NULL)
     {
@@ -1165,21 +1206,21 @@ NtQueryValueKey(IN HANDLE KeyHandle,
               mbstowcs(ValueFullInformation->Name, ValueCell->Name,ValueCell->NameSize*2);
               ValueFullInformation->Name[ValueCell->NameSize] = 0;
               if (ValueCell->DataSize > 0)
-                     {
-                       DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                         DataCell->Data, 
-                         ValueCell->DataSize & LONG_MAX);
-                       CmiReleaseBlock(RegistryHive, DataCell);
-                     }
+                {
+                  DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                                + ValueFullInformation->DataOffset,
+                                DataCell->Data,
+                                ValueCell->DataSize & LONG_MAX);
+                  CmiReleaseBlock(RegistryHive, DataCell);
+                }
               else
-                     {
-                       RtlCopyMemory((PCHAR) ValueFullInformation
-                                     + ValueFullInformation->DataOffset,
-                    &ValueCell->DataOffset, 
-                    ValueCell->DataSize & LONG_MAX);
-                     }
+                {
+                  RtlCopyMemory((PCHAR) ValueFullInformation
+                                + ValueFullInformation->DataOffset,
+                                &ValueCell->DataOffset,
+                  ValueCell->DataSize & LONG_MAX);
+                }
             }
           break;
         }
@@ -1189,8 +1230,9 @@ NtQueryValueKey(IN HANDLE KeyHandle,
       Status = STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
-  
+
   return Status;
 }
 
@@ -1214,7 +1256,6 @@ NtSetValueKey(IN HANDLE KeyHandle,
   PDATA_CELL NewDataCell;
   PHBIN pBin;
   ULONG DesiredAccess;
-// KIRQL  OldIrql;
 
   DPRINT("KeyHandle %x  ValueName %S  Type %d\n",
     KeyHandle, ValueName? ValueName->Buffer : NULL, Type);
@@ -1236,6 +1277,9 @@ NtSetValueKey(IN HANDLE KeyHandle,
   if (!NT_SUCCESS(Status))
     return(Status);
 
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to key cell */
@@ -1250,12 +1294,11 @@ NtSetValueKey(IN HANDLE KeyHandle,
     {
       DPRINT1("Value not found. Status 0x%X\n", Status);
 
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return(Status);
     }
 
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
-
   if (ValueCell == NULL)
     {
       Status = CmiAddValueToKey(RegistryHive,
@@ -1269,6 +1312,7 @@ NtSetValueKey(IN HANDLE KeyHandle,
     {
       DPRINT1("Cannot add value. Status 0x%X\n", Status);
 
+      ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
       ObDereferenceObject(KeyObject);
       return(Status);
     }
@@ -1338,8 +1382,7 @@ NtSetValueKey(IN HANDLE KeyHandle,
        }
     }
 
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
-
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
   ObDereferenceObject(KeyObject);
 
   DPRINT("Return Status 0x%X\n", Status);
@@ -1350,14 +1393,11 @@ NtSetValueKey(IN HANDLE KeyHandle,
 
 NTSTATUS STDCALL
 NtDeleteValueKey(IN HANDLE KeyHandle,
-  IN PUNICODE_STRING ValueName)
+                IN PUNICODE_STRING ValueName)
 {
-  PREGISTRY_HIVE RegistryHive;
   CHAR ValueName2[MAX_PATH];
   PKEY_OBJECT KeyObject;
-  PKEY_CELL KeyCell;
   NTSTATUS Status;
-//  KIRQL  OldIrql;
 
   wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1);
   ValueName2[ValueName->Length>>1] = 0;
@@ -1369,20 +1409,23 @@ NtDeleteValueKey(IN HANDLE KeyHandle,
                UserMode,
                (PVOID *)&KeyObject,
                NULL);
-
   if (!NT_SUCCESS(Status))
     {
       return Status;
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
-  /* Get pointer to KeyCell */
-  KeyCell = KeyObject->KeyCell;
-  RegistryHive = KeyObject->RegistryHive;
-//  KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql);
-  Status = CmiDeleteValueFromKey(RegistryHive, KeyCell, ValueName2);
-//  KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql);
+  Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
+                                KeyObject->KeyCell,
+                                ValueName2);
+
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
   ObDereferenceObject(KeyObject);
 
   return Status;
@@ -1425,11 +1468,11 @@ NtNotifyChangeKey(
 
 NTSTATUS STDCALL
 NtQueryMultipleValueKey(IN HANDLE KeyHandle,
-       IN OUT PKEY_VALUE_ENTRY ValueList,
-       IN ULONG NumberOfValues,
-       OUT PVOID Buffer,
-       IN OUT PULONG Length,
-       OUT PULONG ReturnLength)
+                       IN OUT PKEY_VALUE_ENTRY ValueList,
+                       IN ULONG NumberOfValues,
+                       OUT PVOID Buffer,
+                       IN OUT PULONG Length,
+                       OUT PULONG ReturnLength)
 {
   PREGISTRY_HIVE RegistryHive;
   UCHAR ValueName[MAX_PATH];
@@ -1455,6 +1498,9 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle,
       return(Status);
     }
 
+  /* Acquire hive lock */
+  ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+
   VERIFY_KEY_OBJECT(KeyObject);
 
   /* Get pointer to KeyCell */
@@ -1528,11 +1574,14 @@ NtQueryMultipleValueKey(IN HANDLE KeyHandle,
 
   *ReturnLength = BufferLength;
 
+  /* Release hive lock */
+  ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+
   ObDereferenceObject(KeyObject);
 
   DPRINT("Return Status 0x%X\n", Status);
 
-  return Status;
+  return(Status);
 }
 
 
index 1ae26f7..4587dc2 100644 (file)
@@ -483,19 +483,17 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
   ULONG CreateDisposition;
   IO_STATUS_BLOCK IoSB;
   HANDLE FileHandle;
-  DWORD FreeOffset;
+  ULONG FreeOffset;
   NTSTATUS Status;
-  //BOOLEAN Success;
   PHBIN tmpBin;
   ULONG i, j;
 
-  IO_STATUS_BLOCK Iosb;
-
   DPRINT("CmiInitPermanentRegistryHive(%p, %S, %d) - Entered.\n", RegistryHive, Filename, CreateNew);
 
   /* Duplicate Filename */
   Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename);
-  if (!NT_SUCCESS(Status)) {
+  if (!NT_SUCCESS(Status))
+  {
     DPRINT("CmiInitPermanentRegistryHive() - Failed 1.\n");
     return Status;
   }
@@ -512,27 +510,32 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
     CreateDisposition = FILE_OPEN;
 
   Status = NtCreateFile(&FileHandle,
-               FILE_ALL_ACCESS,
-               &ObjectAttributes,
-               &IoSB,
-               NULL,
-               FILE_ATTRIBUTE_NORMAL,
-               0,
-               CreateDisposition,
-               FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
-               NULL,
-               0);
-
-  if ((CreateNew) && (IoSB.Information == FILE_CREATED))
+                       FILE_ALL_ACCESS,
+                       &ObjectAttributes,
+                       &IoSB,
+                       NULL,
+                       FILE_ATTRIBUTE_NORMAL,
+                       0,
+                       CreateDisposition,
+                       FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+                       NULL,
+                       0);
+  if (!NT_SUCCESS(Status))
     {
-      Status = CmiCreateNewRegFile(FileHandle);
+      RtlFreeUnicodeString(&RegistryHive->Filename);
+      DPRINT1("NtCreateFile() failed (Status %lx)\n", Status);
+      return(Status);
     }
 
-  if (!NT_SUCCESS(Status))
+  if ((CreateNew) && (IoSB.Information == FILE_CREATED))
     {
-      RtlFreeUnicodeString(&RegistryHive->Filename);
-      DPRINT("CmiCreateNewRegFile() - Failed with status %x.\n", Status);
-      return Status;
+      Status = CmiCreateNewRegFile(FileHandle);
+      if (!NT_SUCCESS(Status))
+       {
+         RtlFreeUnicodeString(&RegistryHive->Filename);
+         DPRINT1("CmiCreateNewRegFile() - Failed with status %x.\n", Status);
+         return(Status);
+       }
     }
 
   Status = ObReferenceObjectByHandle(FileHandle,
@@ -546,7 +549,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
 
   if (!NT_SUCCESS(Status))
     {
-      ZwClose(FileHandle);
+      NtClose(FileHandle);
       RtlFreeUnicodeString(&RegistryHive->Filename);
       DPRINT("CmiInitPermanentRegistryHive() - ObReferenceObjectByHandle Failed with status %x.\n", Status);
       return Status;
@@ -555,12 +558,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
   FileOffset.u.HighPart = 0;
   FileOffset.u.LowPart = 0;
   DPRINT("    Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, sizeof(HIVE_HEADER), RegistryHive->HiveHeader);
-  Status = ZwReadFile(FileHandle,
+  Status = NtReadFile(FileHandle,
                      0,
                      0,
                      0,
-//                   0,
-              &Iosb,
+                     &IoSB,
                      RegistryHive->HiveHeader,
                      sizeof(HIVE_HEADER),
                      &FileOffset,
@@ -576,11 +578,11 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
       return Status;
     }
 
-  Status = ZwQueryInformationFile(FileHandle,
-    &IoSB,
-    &fsi,
-    sizeof(fsi),
-    FileStandardInformation);
+  Status = NtQueryInformationFile(FileHandle,
+                                 &IoSB,
+                                 &fsi,
+                                 sizeof(fsi),
+                                 FileStandardInformation);
 
   assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
 
@@ -600,13 +602,16 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
   RegistryHive->FileSize = fsi.EndOfFile.u.LowPart;
 #ifdef WIN32_REGDBG
 //  assert(RegistryHive->FileSize);
-  if (RegistryHive->FileSize) {
-  RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
-  } else {
-      ObDereferenceObject(RegistryHive->FileObject);
-      RtlFreeUnicodeString(&RegistryHive->Filename);
-      DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
-      return STATUS_INSUFFICIENT_RESOURCES;
+  if (RegistryHive->FileSize)
+  {
+    RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
+  }
+  else
+  {
+    ObDereferenceObject(RegistryHive->FileObject);
+    RtlFreeUnicodeString(&RegistryHive->Filename);
+    DPRINT("CmiInitPermanentRegistryHive() - Failed, zero length hive file.\n");
+    return STATUS_INSUFFICIENT_RESOURCES;
   }
 #else
   RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1;
@@ -670,19 +675,19 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
   FileOffset.u.LowPart = 4096;
 
   DPRINT("    Attempting to ZwReadFile(%d) for %d bytes into %p\n", FileHandle, RegistryHive->FileSize - 4096, (PVOID)RegistryHive->BlockList[0]);
-  Status = ZwReadFile(FileHandle,
+  Status = NtReadFile(FileHandle,
                      0,
                      0,
                      0,
-//                   0,
-              &Iosb,
+                     &IoSB,
                      (PVOID) RegistryHive->BlockList[0],
                      RegistryHive->FileSize - 4096,
-              &FileOffset,
-              0);
+                     &FileOffset,
+                     0);
 
   assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status));
 
+  NtClose(FileHandle);
 #endif
 
   RegistryHive->FreeListSize = 0;
@@ -698,7 +703,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
        {
          DPRINT("Bad BlockId %x, offset %x\n", tmpBin->BlockId, BlockOffset);
          //KeBugCheck(0);
-      return STATUS_INSUFFICIENT_RESOURCES;
+         return STATUS_INSUFFICIENT_RESOURCES;
        }
 
       assertmsg((tmpBin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin->BlockSize));
@@ -741,7 +746,7 @@ CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive,
 
   DPRINT("CmiInitPermanentRegistryHive(%p, %S, %d) - Finished.\n", RegistryHive, Filename, CreateNew);
 
-  return STATUS_SUCCESS;
+  return(STATUS_SUCCESS);
 }
 
 
@@ -773,6 +778,7 @@ CmiCreateRegistryHive(PWSTR Filename,
   BOOLEAN CreateNew)
 {
   PREGISTRY_HIVE Hive;
+  KIRQL oldlvl;
   NTSTATUS Status;
 
   DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename);
@@ -781,7 +787,7 @@ CmiCreateRegistryHive(PWSTR Filename,
 
   Hive = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_HIVE));
   if (Hive == NULL)
-    return STATUS_INSUFFICIENT_RESOURCES;
+    return(STATUS_INSUFFICIENT_RESOURCES);
 
   DPRINT("Hive %x\n", Hive);
 
@@ -793,7 +799,7 @@ CmiCreateRegistryHive(PWSTR Filename,
   if (Hive->HiveHeader == NULL)
     {
       ExFreePool(Hive);
-      return STATUS_INSUFFICIENT_RESOURCES;
+      return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
   if (Filename != NULL)
@@ -812,8 +818,13 @@ CmiCreateRegistryHive(PWSTR Filename,
       return(Status);
     }
 
-  KeInitializeSemaphore(&Hive->RegSem, 1, 1);
-  
+  ExInitializeResourceLite(&Hive->HiveResource);
+
+  /* Add the new hive to the hive list */
+  KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
+  InsertHeadList(&CmiHiveListHead, &Hive->HiveList);
+  KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
+
   VERIFY_REGISTRY_HIVE(Hive);
 
   *RegistryHive = Hive;
@@ -824,6 +835,30 @@ CmiCreateRegistryHive(PWSTR Filename,
 }
 
 
+NTSTATUS
+CmiRemoveRegistryHive(PREGISTRY_HIVE RegistryHive)
+{
+  KIRQL oldlvl;
+
+  /* Remove hive from hive list */
+  KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
+  RemoveEntryList(&RegistryHive->HiveList);
+  KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
+
+
+  /* FIXME: Remove attached keys and values */
+
+
+  /* Release hive header */
+  ExFreePool(RegistryHive->HiveHeader);
+
+  /* Release hive */
+  ExFreePool(RegistryHive);
+
+  return(STATUS_SUCCESS);
+}
+
+
 ULONG
 CmiGetMaxNameLength(PREGISTRY_HIVE  RegistryHive,
   PKEY_CELL  KeyCell)
index e52439e..2d002d1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: registry.c,v 1.77 2002/11/13 05:18:03 robd Exp $
+/* $Id: registry.c,v 1.78 2002/11/26 15:31:41 ekohl Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -33,6 +33,9 @@ POBJECT_TYPE  CmiKeyType = NULL;
 PREGISTRY_HIVE  CmiVolatileHive = NULL;
 KSPIN_LOCK  CmiKeyListLock;
 
+LIST_ENTRY CmiHiveListHead;
+KSPIN_LOCK CmiHiveListLock;
+
 static PKEY_OBJECT  CmiRootKey = NULL;
 static PKEY_OBJECT  CmiMachineKey = NULL;
 static PKEY_OBJECT  CmiUserKey = NULL;
@@ -42,6 +45,7 @@ static GENERIC_MAPPING CmiKeyMapping =
        {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
 
 
+
 VOID
 CmiCheckKey(BOOLEAN Verbose,
   HANDLE Key);
@@ -271,11 +275,15 @@ CmInitializeRegistry(VOID)
   CmiKeyType->DuplicationNotify = NULL;
   RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
 
+  /* Initialize the hive list */
+  InitializeListHead(&CmiHiveListHead);
+  KeInitializeSpinLock(&CmiHiveListLock);
+
   /*  Build volatile registry store  */
   Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE);
   assert(NT_SUCCESS(Status));
 
-  /* Build the Root Key Object */
+  /* Create '\Registry' key. */
   RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME);
   InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
   Status = ObCreateObject(&RootKeyHandle,
@@ -307,7 +315,7 @@ CmInitializeRegistry(VOID)
 
   /* Create initial predefined symbolic links */
 
-  /* HKEY_LOCAL_MACHINE */
+  /* Create '\Registry\Machine' key. */
   Status = ObCreateObject(&KeyHandle,
     STANDARD_RIGHTS_REQUIRED,
     NULL,
@@ -334,7 +342,7 @@ CmInitializeRegistry(VOID)
   CmiAddKeyToList(CmiRootKey, NewKey);
   CmiMachineKey = NewKey;
 
-  /* HKEY_USERS */
+  /* Create '\Registry\User' key. */
   Status = ObCreateObject(&KeyHandle,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
@@ -361,7 +369,7 @@ CmInitializeRegistry(VOID)
        CmiAddKeyToList(CmiRootKey, NewKey);
        CmiUserKey = NewKey;
 
-  /* Create '\\Registry\\Machine\\HARDWARE' key. */
+  /* Create '\Registry\Machine\HARDWARE' key. */
   Status = ObCreateObject(&KeyHandle,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
@@ -388,7 +396,7 @@ CmInitializeRegistry(VOID)
   CmiAddKeyToList(CmiMachineKey, NewKey);
   CmiHardwareKey = NewKey;
 
-  /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */
+  /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
   Status = ObCreateObject(&KeyHandle,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
@@ -414,7 +422,7 @@ CmInitializeRegistry(VOID)
   memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION"));
   CmiAddKeyToList(CmiHardwareKey, NewKey);
 
-  /* Create '\\Registry\\Machine\\HARDWARE\\DEVICEMAP' key. */
+  /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
   Status = ObCreateObject(&KeyHandle,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
@@ -440,7 +448,7 @@ CmInitializeRegistry(VOID)
   memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP"));
   CmiAddKeyToList(CmiHardwareKey,NewKey);
 
-  /* Create '\\Registry\\Machine\\HARDWARE\\RESOURCEMAP' key. */
+  /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
   Status = ObCreateObject(&KeyHandle,
                STANDARD_RIGHTS_REQUIRED,
                NULL,
@@ -477,7 +485,9 @@ CmInit2(PCHAR CommandLine)
   PCHAR p1, p2;
   ULONG PiceStart;
 
-  /* FIXME: Store current command line */
+  /* FIXME: Store system start options */
+
+
 
   /* Create the 'CurrentControlSet' link. */
   CmiCreateCurrentControlSetLink();
@@ -655,9 +665,9 @@ CmiConnectHive(PWSTR FileName,
 
   if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
     {
-      /* FIXME: Cleanup from CmiCreateRegistryHive() */
       DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
       ZwClose(NewKey);
+      CmiRemoveRegistryHive(RegistryHive);
       return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
@@ -666,11 +676,11 @@ CmiConnectHive(PWSTR FileName,
 
   if ((NewKey->Name == NULL) && (strlen(KeyName) != 0))
     {
-      /* FIXME: Cleanup from CmiCreateRegistryHive() */
       DPRINT("strlen(KeyName) %d\n", strlen(KeyName));
       if (NewKey->SubKeys != NULL)
        ExFreePool(NewKey->SubKeys);
       ZwClose(NewKey);
+      CmiRemoveRegistryHive(RegistryHive);
       return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
@@ -729,39 +739,163 @@ CmiInitializeHive(PWSTR FileName,
 NTSTATUS
 CmiInitHives(BOOLEAN SetUpBoot)
 {
+  PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  UNICODE_STRING ValueName;
+  HANDLE KeyHandle;
+
   NTSTATUS Status;
 
+  WCHAR ConfigPath[MAX_PATH];
+
+  ULONG BufferSize;
+  ULONG ResultSize;
+  PWSTR EndPtr;
+
+
   DPRINT("CmiInitHives() called\n");
 
+  if (SetUpBoot == TRUE)
+  {
+    RtlInitUnicodeStringFromLiteral(&KeyName,
+                                   L"\\Registry\\Machine\\HARDWARE");
+    InitializeObjectAttributes(&ObjectAttributes,
+                              &KeyName,
+                              OBJ_CASE_INSENSITIVE,
+                              NULL,
+                              NULL);
+    Status =  NtOpenKey(&KeyHandle,
+                       KEY_ALL_ACCESS,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
+      return(Status);
+    }
+
+    RtlInitUnicodeStringFromLiteral(&ValueName,
+                                   L"InstallPath");
+
+    BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
+    ValueInfo = ExAllocatePool(PagedPool,
+                              BufferSize);
+    if (ValueInfo == NULL)
+    {
+      NtClose(KeyHandle);
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+    Status = NtQueryValueKey(KeyHandle,
+                            &ValueName,
+                            KeyValuePartialInformation,
+                            ValueInfo,
+                            BufferSize,
+                            &ResultSize);
+    NtClose(KeyHandle);
+    if (ValueInfo == NULL)
+    {
+      ExFreePool(ValueInfo);
+      return(Status);
+    }
+
+    RtlCopyMemory(ConfigPath,
+                 ValueInfo->Data,
+                 ValueInfo->DataLength);
+    ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0;
+    ExFreePool(ValueInfo);
+  }
+  else
+  {
+    wcscpy(ConfigPath, L"\\SystemRoot\\system32\\config");
+  }
+  DPRINT1("ConfigPath: %S\n", ConfigPath);
+
+  EndPtr = ConfigPath + wcslen(ConfigPath);
+
   CmiDoVerify = TRUE;
 
-  /* FIXME: Delete temporary \Registry\Machine\System */
+  /* FIXME: Save boot log */
+
+  /* FIXME: Rename \Registry\Machine\System */
 
   /* Connect the SYSTEM hive */
-  /* FIXME: Don't overwrite the existing 'System' hive yet */
-//  Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey);
+//  Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey, SetUpBoot);
 //  assert(NT_SUCCESS(Status));
 
+  /* FIXME: Synchronize old and new system hive (??) */
+
+  /* FIXME: Delete old system hive */
+
   /* Connect the SOFTWARE hive */
-  Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey, SetUpBoot);
+  wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
+  DPRINT1("ConfigPath: %S\n", ConfigPath);
+
+//  Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey, SetUpBoot);
+  Status = CmiInitializeHive(ConfigPath,
+                            REG_SOFTWARE_KEY_NAME,
+                            "Software",
+                            CmiMachineKey,
+                            SetUpBoot);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+  }
   //assert(NT_SUCCESS(Status));
 
   /* Connect the SAM hive */
-  Status = CmiInitializeHive(SAM_REG_FILE,REG_SAM_KEY_NAME, "Sam", CmiMachineKey, SetUpBoot);
+  wcscpy(EndPtr, REG_SAM_FILE_NAME);
+  DPRINT1("ConfigPath: %S\n", ConfigPath);
+
+//  Status = CmiInitializeHive(SAM_REG_FILE, REG_SAM_KEY_NAME, "Sam", CmiMachineKey, SetUpBoot);
+  Status = CmiInitializeHive(ConfigPath,
+                            REG_SAM_KEY_NAME,
+                            "Sam",
+                            CmiMachineKey,
+                            SetUpBoot);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+  }
   //assert(NT_SUCCESS(Status));
 
   /* Connect the SECURITY hive */
-  Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey, SetUpBoot);
+  wcscpy(EndPtr, REG_SEC_FILE_NAME);
+  DPRINT1("ConfigPath: %S\n", ConfigPath);
+//  Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey, SetUpBoot);
+  Status = CmiInitializeHive(ConfigPath,
+                            REG_SEC_KEY_NAME,
+                            "Security",
+                            CmiMachineKey,
+                            SetUpBoot);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+  }
   //assert(NT_SUCCESS(Status));
 
   /* Connect the DEFAULT hive */
-  Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey, SetUpBoot);
+  wcscpy(EndPtr, REG_USER_FILE_NAME);
+  DPRINT1("ConfigPath: %S\n", ConfigPath);
+
+//  Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey, SetUpBoot);
+  Status = CmiInitializeHive(ConfigPath,
+                            REG_USER_KEY_NAME,
+                            ".Default",
+                            CmiUserKey,
+                            SetUpBoot);
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+  }
   //assert(NT_SUCCESS(Status));
 
   /* FIXME : initialize standards symbolic links */
 
 //  CmiCheckRegistry(TRUE);
 
+  /* FIXME: Start automatic hive syncronization */
+
   DPRINT("CmiInitHives() done\n");
 
   return(STATUS_SUCCESS);
@@ -771,7 +905,41 @@ CmiInitHives(BOOLEAN SetUpBoot)
 VOID
 CmShutdownRegistry(VOID)
 {
-  DPRINT("CmShutdownRegistry() called\n");
+  PREGISTRY_HIVE Hive;
+  PLIST_ENTRY Entry;
+  KIRQL oldlvl;
+
+  DPRINT1("CmShutdownRegistry() called\n");
+
+  /* FIXME: Stop automatic hive syncronization */
+
+  KeAcquireSpinLock(&CmiHiveListLock,&oldlvl);
+  Entry = CmiHiveListHead.Flink;
+  while (Entry != &CmiHiveListHead)
+  {
+    Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
+
+    if (Hive->Flags & HIVE_VOLATILE)
+    {
+      DPRINT1("Volatile hive\n");
+    }
+    else
+    {
+      DPRINT1("Flush non-volatile hive '%wZ'\n", &Hive->Filename);
+
+      /* Flush non-volatile hive */
+
+      /* Dereference file */
+      ObDereferenceObject(Hive->FileObject);
+      Hive->FileObject = NULL;
+    }
+
+    Entry = Entry->Flink;
+  }
+  KeReleaseSpinLock(&CmiHiveListLock,oldlvl);
+
+DPRINT1("  *** System stopped ***\n");
+for (;;);
 
   /* Note:
    *   Don't call UNIMPLEMENTED() here since this function is
index 13063df..9678f62 100644 (file)
@@ -190,7 +190,7 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
     ParamTable[1].DefaultType = REG_MULTI_SZ;
 
     Status = RtlQueryRegistryValues(
-                  IN ULONG RelativeTo = RTL_REGISTRY_ABSOLUTE,
+               IN ULONG RelativeTo = RTL_REGISTRY_ABSOLUTE,
                IN PWSTR Path = Path,
                IN PRTL_QUERY_REGISTRY_TABLE QueryTable = ParamTable,
                IN PVOID Context = NULL,