update for HEAD-2003050101
[reactos.git] / ntoskrnl / cm / registry.c
index 8b7769e..e354c1f 100644 (file)
@@ -11,9 +11,6 @@
  *                  Created 22/05/98
  */
 
-#ifdef WIN32_REGDBG
-#include "cm_win32.h"
-#else
 #include <ddk/ntddk.h>
 #include <roscfg.h>
 #include <limits.h>
@@ -26,9 +23,8 @@
 #include <internal/debug.h>
 
 #include "cm.h"
-#endif
 
-/*  -------------------------------------------------  File Statics  */
+/* GLOBALS ******************************************************************/
 
 POBJECT_TYPE  CmiKeyType = NULL;
 PREGISTRY_HIVE  CmiVolatileHive = NULL;
@@ -42,11 +38,6 @@ volatile BOOLEAN CmiHiveSyncPending = FALSE;
 KDPC CmiHiveSyncDpc;
 KTIMER CmiHiveSyncTimer;
 
-static PKEY_OBJECT  CmiRootKey = NULL;
-static PKEY_OBJECT  CmiMachineKey = NULL;
-static PKEY_OBJECT  CmiUserKey = NULL;
-static PKEY_OBJECT  CmiHardwareKey = NULL;
-
 static GENERIC_MAPPING CmiKeyMapping =
        {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
 
@@ -260,8 +251,10 @@ CmInitializeRegistry(VOID)
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING RootKeyName;
+  PKEY_OBJECT RootKey;
+  PKEY_OBJECT MachineKey;
+  PKEY_OBJECT UserKey;
   HANDLE RootKeyHandle;
-  PKEY_OBJECT NewKey;
   HANDLE KeyHandle;
   NTSTATUS Status;
 
@@ -280,7 +273,7 @@ CmInitializeRegistry(VOID)
   CmiKeyType->Close = NULL;
   CmiKeyType->Delete = CmiObjectDelete;
   CmiKeyType->Parse = CmiObjectParse;
-  CmiKeyType->Security = NULL;
+  CmiKeyType->Security = CmiObjectSecurity;
   CmiKeyType->QueryName = NULL;
   CmiKeyType->OkayToClose = NULL;
   CmiKeyType->Create = CmiObjectCreate;
@@ -302,192 +295,79 @@ CmInitializeRegistry(VOID)
                STANDARD_RIGHTS_REQUIRED,
                &ObjectAttributes,
                CmiKeyType,
-               (PVOID *) &NewKey);
+               (PVOID *) &RootKey);
   assert(NT_SUCCESS(Status));
-  CmiRootKey = NewKey;
   Status = ObReferenceObjectByHandle(RootKeyHandle,
-    STANDARD_RIGHTS_REQUIRED,
-               CmiKeyType,
-               KernelMode,
-               (PVOID *) &CmiRootKey,
-               NULL);
+                                    STANDARD_RIGHTS_REQUIRED,
+                                    CmiKeyType,
+                                    KernelMode,
+                                    (PVOID *)&RootKey,
+                                    NULL);
   assert(NT_SUCCESS(Status));
-  CmiRootKey->RegistryHive = CmiVolatileHive;
-  NewKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell;
-  NewKey->KeyCell = CmiGetBlock(CmiVolatileHive, NewKey->BlockOffset, NULL);
-  CmiRootKey->Flags = 0;
-  CmiRootKey->NumberOfSubKeys = 0;
-  CmiRootKey->SubKeys = NULL;
-  CmiRootKey->SizeOfSubKeys = 0;
-  CmiRootKey->Name = ExAllocatePool(PagedPool, strlen("Registry"));
-  CmiRootKey->NameSize = strlen("Registry");
-  memcpy(CmiRootKey->Name, "Registry", strlen("Registry"));
+  RootKey->RegistryHive = CmiVolatileHive;
+  RootKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell;
+  RootKey->KeyCell = CmiGetBlock(CmiVolatileHive, RootKey->BlockOffset, NULL);
+  RootKey->Flags = 0;
+  RootKey->NumberOfSubKeys = 0;
+  RootKey->SubKeys = NULL;
+  RootKey->SizeOfSubKeys = 0;
+  RootKey->NameSize = strlen("Registry");
+  RootKey->Name = ExAllocatePool(PagedPool, RootKey->NameSize);
+  RtlCopyMemory(RootKey->Name, "Registry", RootKey->NameSize);
 
   KeInitializeSpinLock(&CmiKeyListLock);
 
-  /* Create initial predefined symbolic links */
-
   /* Create '\Registry\Machine' key. */
   Status = ObCreateObject(&KeyHandle,
-    STANDARD_RIGHTS_REQUIRED,
-    NULL,
-    CmiKeyType,
-    (PVOID*) &NewKey);
+                         STANDARD_RIGHTS_REQUIRED,
+                         NULL,
+                         CmiKeyType,
+                         (PVOID*)&MachineKey);
   assert(NT_SUCCESS(Status));
   Status = CmiAddSubKey(CmiVolatileHive,
-               CmiRootKey,
-               NewKey,
-               L"Machine",
-               wcslen(L"Machine") * sizeof(WCHAR),
-               0,
-               NULL,
-               0);
+                       RootKey,
+                       MachineKey,
+                       L"Machine",
+                       wcslen(L"Machine") * sizeof(WCHAR),
+                       0,
+                       NULL,
+                       0);
   assert(NT_SUCCESS(Status));
-       NewKey->RegistryHive = CmiVolatileHive;
-       NewKey->Flags = 0;
-       NewKey->NumberOfSubKeys = 0;
-       NewKey->SubKeys = NULL;
-       NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-       NewKey->Name = ExAllocatePool(PagedPool, strlen("Machine"));
-       NewKey->NameSize = strlen("Machine");
-       memcpy(NewKey->Name, "Machine", strlen("Machine"));
-  CmiAddKeyToList(CmiRootKey, NewKey);
-  CmiMachineKey = NewKey;
+  MachineKey->RegistryHive = CmiVolatileHive;
+  MachineKey->Flags = 0;
+  MachineKey->NumberOfSubKeys = 0;
+  MachineKey->SubKeys = NULL;
+  MachineKey->SizeOfSubKeys = MachineKey->KeyCell->NumberOfSubKeys;
+  MachineKey->NameSize = strlen("Machine");
+  MachineKey->Name = ExAllocatePool(PagedPool, MachineKey->NameSize);
+  RtlCopyMemory(MachineKey->Name, "Machine", MachineKey->NameSize);
+  CmiAddKeyToList(RootKey, MachineKey);
 
   /* Create '\Registry\User' key. */
   Status = ObCreateObject(&KeyHandle,
-               STANDARD_RIGHTS_REQUIRED,
-               NULL,
-               CmiKeyType,
-               (PVOID*) &NewKey);
-  assert(NT_SUCCESS(Status));
-  Status = CmiAddSubKey(CmiVolatileHive,
-    CmiRootKey,
-    NewKey,
-    L"User",
-    wcslen(L"User") * sizeof(WCHAR),
-    0,
-    NULL,
-    0);
-  assert(NT_SUCCESS(Status));
-       NewKey->RegistryHive = CmiVolatileHive;
-       NewKey->Flags = 0;
-       NewKey->NumberOfSubKeys = 0;
-       NewKey->SubKeys = NULL;
-       NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-       NewKey->Name = ExAllocatePool(PagedPool, strlen("User"));
-       NewKey->NameSize = strlen("User");
-       memcpy(NewKey->Name, "User", strlen("User"));
-       CmiAddKeyToList(CmiRootKey, NewKey);
-       CmiUserKey = NewKey;
-
-  /* Create '\Registry\Machine\HARDWARE' key. */
-  Status = ObCreateObject(&KeyHandle,
-               STANDARD_RIGHTS_REQUIRED,
-               NULL,
-               CmiKeyType,
-               (PVOID*)&NewKey);
-  assert(NT_SUCCESS(Status));
-  Status = CmiAddSubKey(CmiVolatileHive,
-    CmiMachineKey,
-    NewKey,
-    L"HARDWARE",
-    wcslen(L"HARDWARE") * sizeof(WCHAR),
-    0,
-    NULL,
-    0);
-  assert(NT_SUCCESS(Status));
-  NewKey->RegistryHive = CmiVolatileHive;
-  NewKey->Flags = 0;
-  NewKey->NumberOfSubKeys = 0;
-  NewKey->SubKeys = NULL;
-  NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-  NewKey->Name = ExAllocatePool(PagedPool, strlen("HARDWARE"));
-  NewKey->NameSize = strlen("HARDWARE");
-  memcpy(NewKey->Name, "HARDWARE", strlen("HARDWARE"));
-  CmiAddKeyToList(CmiMachineKey, NewKey);
-  CmiHardwareKey = NewKey;
-
-  /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
-  Status = ObCreateObject(&KeyHandle,
-               STANDARD_RIGHTS_REQUIRED,
-               NULL,
-               CmiKeyType,
-               (PVOID*) &NewKey);
-  assert(NT_SUCCESS(Status));
-  Status = CmiAddSubKey(CmiVolatileHive,
-               CmiHardwareKey,
-               NewKey,
-               L"DESCRIPTION",
-               wcslen(L"DESCRIPTION") * sizeof(WCHAR),
-               0,
-               NULL,
-               0);
-  assert(NT_SUCCESS(Status));
-  NewKey->RegistryHive = CmiVolatileHive;
-  NewKey->Flags = 0;
-  NewKey->NumberOfSubKeys = 0;
-  NewKey->SubKeys = NULL;
-  NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-  NewKey->Name = ExAllocatePool(PagedPool, strlen("DESCRIPTION"));
-  NewKey->NameSize = strlen("DESCRIPTION");
-  memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION"));
-  CmiAddKeyToList(CmiHardwareKey, NewKey);
-
-  /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
-  Status = ObCreateObject(&KeyHandle,
-               STANDARD_RIGHTS_REQUIRED,
-               NULL,
-               CmiKeyType,
-               (PVOID*) &NewKey);
-  assert(NT_SUCCESS(Status));
-  Status = CmiAddSubKey(CmiVolatileHive,
-    CmiHardwareKey,
-    NewKey,
-    L"DEVICEMAP",
-               wcslen(L"DEVICEMAP") * sizeof(WCHAR),
-    0,
-    NULL,
-    0);
-  assert(NT_SUCCESS(Status));
-  NewKey->RegistryHive = CmiVolatileHive;
-  NewKey->Flags = 0;
-  NewKey->NumberOfSubKeys = 0;
-  NewKey->SubKeys = NULL;
-  NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-  NewKey->Name = ExAllocatePool(PagedPool, strlen("DEVICEMAP"));
-  NewKey->NameSize = strlen("DEVICEMAP");
-  memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP"));
-  CmiAddKeyToList(CmiHardwareKey,NewKey);
-
-  /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
-  Status = ObCreateObject(&KeyHandle,
-               STANDARD_RIGHTS_REQUIRED,
-               NULL,
-               CmiKeyType,
-               (PVOID*) &NewKey);
+                         STANDARD_RIGHTS_REQUIRED,
+                         NULL,
+                         CmiKeyType,
+                         (PVOID*)&UserKey);
   assert(NT_SUCCESS(Status));
   Status = CmiAddSubKey(CmiVolatileHive,
-               CmiHardwareKey,
-               NewKey,
-               L"RESOURCEMAP",
-               wcslen(L"RESOURCEMAP") * sizeof(WCHAR),
-               0,
-               NULL,
-               0);
+                       RootKey,
+                       UserKey,
+                       L"User",
+                       wcslen(L"User") * sizeof(WCHAR),
+                       0,
+                       NULL,
+                       0);
   assert(NT_SUCCESS(Status));
-  NewKey->RegistryHive = CmiVolatileHive;
-  NewKey->Flags = 0;
-  NewKey->NumberOfSubKeys = 0;
-  NewKey->SubKeys = NULL;
-  NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-  NewKey->Name = ExAllocatePool(PagedPool, strlen("RESOURCEMAP"));
-  NewKey->NameSize = strlen("RESOURCEMAP");
-  memcpy(NewKey->Name, "RESOURCEMAP", strlen("RESOURCEMAP"));
-  CmiAddKeyToList(CmiHardwareKey, NewKey);
-
-  /* FIXME: create remaining structure needed for default handles  */
-  /* FIXME: load volatile registry data from ROSDTECT  */
+  UserKey->RegistryHive = CmiVolatileHive;
+  UserKey->Flags = 0;
+  UserKey->NumberOfSubKeys = 0;
+  UserKey->SubKeys = NULL;
+  UserKey->SizeOfSubKeys = UserKey->KeyCell->NumberOfSubKeys;
+  UserKey->NameSize = strlen("User");
+  UserKey->Name = ExAllocatePool(PagedPool, UserKey->NameSize);
+  RtlCopyMemory(UserKey->Name, "User", UserKey->NameSize);
+  CmiAddKeyToList(RootKey, UserKey);
 }
 
 
@@ -504,12 +384,10 @@ CmInit2(PCHAR CommandLine)
 
   /* Create the 'CurrentControlSet' link. */
   Status = CmiCreateCurrentControlSetLink();
-#ifndef WIN32_REGDBG
   if (!NT_SUCCESS(Status))
     {
       KeBugCheck(CONFIG_INITIALIZATION_FAILED);
     }
-#endif
 
   /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
   PiceStart = 4;
@@ -532,7 +410,7 @@ CmInit2(PCHAR CommandLine)
        }
       p1 = p2;
     }
-#ifndef WIN32_REGDBG
+
   Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
                                 L"\\Pice",
                                 L"Start",
@@ -543,7 +421,6 @@ CmInit2(PCHAR CommandLine)
     {
       KeBugCheck(CONFIG_INITIALIZATION_FAILED);
     }
-#endif
 }
 
 
@@ -603,7 +480,7 @@ CmiCreateCurrentControlSetLink(VOID)
   DPRINT("Link target '%S'\n", TargetNameBuffer);
 
   RtlInitUnicodeStringFromLiteral(&LinkName,
-                      L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
+                                 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
   InitializeObjectAttributes(&ObjectAttributes,
                             &LinkName,
                             OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
@@ -623,7 +500,7 @@ CmiCreateCurrentControlSetLink(VOID)
     }
 
   RtlInitUnicodeStringFromLiteral(&LinkValue,
-                      L"SymbolicLinkValue");
+                                 L"SymbolicLinkValue");
   Status = NtSetValueKey(KeyHandle,
                         &LinkValue,
                         0,
@@ -642,33 +519,53 @@ CmiCreateCurrentControlSetLink(VOID)
 
 
 NTSTATUS
-CmiConnectHive(PWSTR FileName,
-  PWSTR FullName,
-  PCHAR KeyName,
-  PKEY_OBJECT Parent,
-  BOOLEAN CreateNew)
+CmiConnectHive(PREGISTRY_HIVE RegistryHive,
+              PUNICODE_STRING KeyName)
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
-  PREGISTRY_HIVE RegistryHive = NULL;
-  UNICODE_STRING uKeyName;
+  UNICODE_STRING ParentKeyName;
+  PKEY_OBJECT ParentKey;
   PKEY_OBJECT NewKey;
   HANDLE KeyHandle;
   NTSTATUS Status;
+  PWSTR SubName;
 
-  DPRINT("CmiConnectHive(%S, %S, %s, %p, %d) - Called.\n", FileName, FullName, KeyName, Parent, CreateNew);
+  DPRINT("CmiConnectHive(%p, %wZ) called.\n",
+        RegistryHive, KeyName);
 
-  Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew);
-  if (!NT_SUCCESS(Status))
+  SubName = wcsrchr (KeyName->Buffer, L'\\');
+  if (SubName == NULL)
     {
-      DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
-      KeBugCheck(0);
-      return(Status);
+      return STATUS_UNSUCCESSFUL;
     }
 
-  RtlInitUnicodeString(&uKeyName, FullName);
+  ParentKeyName.Length = (USHORT)(SubName - KeyName->Buffer) * sizeof(WCHAR);
+  ParentKeyName.MaximumLength = ParentKeyName.Length + sizeof(WCHAR);
+  ParentKeyName.Buffer = ExAllocatePool (NonPagedPool,
+                                        ParentKeyName.MaximumLength);
+  RtlCopyMemory (ParentKeyName.Buffer,
+                KeyName->Buffer,
+                ParentKeyName.Length);
+  ParentKeyName.Buffer[ParentKeyName.Length / sizeof(WCHAR)] = 0;
+  SubName++;
+
+  Status = ObReferenceObjectByName (&ParentKeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   STANDARD_RIGHTS_REQUIRED,
+                                   CmiKeyType,
+                                   KernelMode,
+                                   NULL,
+                                   (PVOID*)&ParentKey);
+  RtlFreeUnicodeString (&ParentKeyName);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
+      return Status;
+    }
 
   InitializeObjectAttributes(&ObjectAttributes,
-                            &uKeyName,
+                            KeyName,
                             0,
                             NULL,
                             NULL);
@@ -680,10 +577,9 @@ CmiConnectHive(PWSTR FileName,
                          (PVOID*)&NewKey);
   if (!NT_SUCCESS(Status))
     {
-      DPRINT1("ObCreateObject() failed (Status %lx)\n", Status);
-      KeBugCheck(0);
-      CmiRemoveRegistryHive(RegistryHive);
-      return(Status);
+      DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
+      ObDereferenceObject (ParentKey);
+      return Status;
     }
 
   NewKey->RegistryHive = RegistryHive;
@@ -692,32 +588,36 @@ CmiConnectHive(PWSTR FileName,
   NewKey->Flags = 0;
   NewKey->NumberOfSubKeys = 0;
   NewKey->SubKeys = ExAllocatePool(PagedPool,
-  NewKey->KeyCell->NumberOfSubKeys * sizeof(DWORD));
+  NewKey->KeyCell->NumberOfSubKeys * sizeof(ULONG));
 
   if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
     {
       DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
-      ZwClose(NewKey);
-      CmiRemoveRegistryHive(RegistryHive);
+      NtClose(NewKey);
+      ObDereferenceObject (ParentKey);
       return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
   NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
-  NewKey->Name = ExAllocatePool(PagedPool, strlen(KeyName));
+  NewKey->NameSize = wcslen (SubName);
+  NewKey->Name = ExAllocatePool(PagedPool, NewKey->NameSize);
 
-  if ((NewKey->Name == NULL) && (strlen(KeyName) != 0))
+  if ((NewKey->Name == NULL) && (NewKey->NameSize != 0))
     {
-      DPRINT("strlen(KeyName) %d\n", strlen(KeyName));
+      DPRINT("NewKey->NameSize %d\n", NewKey->NameSize);
       if (NewKey->SubKeys != NULL)
        ExFreePool(NewKey->SubKeys);
-      ZwClose(NewKey);
-      CmiRemoveRegistryHive(RegistryHive);
+      NtClose(KeyHandle);
+      ObDereferenceObject (ParentKey);
       return(STATUS_INSUFFICIENT_RESOURCES);
     }
 
-  NewKey->NameSize = strlen(KeyName);
-  memcpy(NewKey->Name, KeyName, strlen(KeyName));
-  CmiAddKeyToList(Parent, NewKey);
+  wcstombs (NewKey->Name,
+           SubName,
+           NewKey->NameSize);
+
+  CmiAddKeyToList (ParentKey, NewKey);
+  ObDereferenceObject (ParentKey);
 
   VERIFY_KEY_OBJECT(NewKey);
 
@@ -725,53 +625,138 @@ CmiConnectHive(PWSTR FileName,
 }
 
 
+static NTSTATUS
+CmiInitializeSystemHive (PWSTR FileName,
+                        PUNICODE_STRING KeyName)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING ControlSetKeyName;
+  UNICODE_STRING ControlSetLinkName;
+  UNICODE_STRING ControlSetValueName;
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  PREGISTRY_HIVE RegistryHive;
+
+  Status = CmiCreateRegistryHive (FileName,
+                                 &RegistryHive,
+                                 TRUE);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
+      return Status;
+    }
+
+  Status = CmiConnectHive (RegistryHive,
+                          KeyName);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
+      CmiRemoveRegistryHive (RegistryHive);
+      return Status;
+    }
+
+  /* Create 'ControlSet001' key */
+  RtlInitUnicodeStringFromLiteral (&ControlSetKeyName,
+                                  L"\\Registry\\Machine\\SYSTEM\\ControlSet001");
+  InitializeObjectAttributes (&ObjectAttributes,
+                             &ControlSetKeyName,
+                             OBJ_CASE_INSENSITIVE,
+                             NULL,
+                             NULL);
+  Status = NtCreateKey (&KeyHandle,
+                       KEY_ALL_ACCESS,
+                       &ObjectAttributes,
+                       0,
+                       NULL,
+                       REG_OPTION_NON_VOLATILE,
+                       NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status);
+      return Status;
+    }
+  NtClose (KeyHandle);
+
+  /* Link 'CurrentControlSet' to 'ControlSet001' key */
+  RtlInitUnicodeStringFromLiteral (&ControlSetLinkName,
+                                  L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
+  InitializeObjectAttributes (&ObjectAttributes,
+                             &ControlSetLinkName,
+                             OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
+                             NULL,
+                             NULL);
+  Status = NtCreateKey (&KeyHandle,
+                       KEY_ALL_ACCESS | KEY_CREATE_LINK,
+                       &ObjectAttributes,
+                       0,
+                       NULL,
+                       REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+                       NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status);
+      return Status;
+    }
+
+  RtlInitUnicodeStringFromLiteral (&ControlSetValueName,
+                                  L"SymbolicLinkValue");
+  Status = NtSetValueKey (KeyHandle,
+                         &ControlSetValueName,
+                         0,
+                         REG_LINK,
+                         (PVOID)ControlSetKeyName.Buffer,
+                         ControlSetKeyName.Length);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status);
+    }
+  NtClose (KeyHandle);
+
+  return STATUS_SUCCESS;
+}
+
+
 NTSTATUS
 CmiInitializeHive(PWSTR FileName,
-  PWSTR FullName,
-  PCHAR KeyName,
-  PKEY_OBJECT Parent,
-  BOOLEAN CreateNew)
+                 PUNICODE_STRING KeyName,
+                 BOOLEAN CreateNew)
 {
+  PREGISTRY_HIVE RegistryHive;
   NTSTATUS Status;
 
   DPRINT("CmiInitializeHive(%s) called\n", KeyName);
 
-  /* Try to connect the hive */
-  //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE);
-  Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew);
+  Status = CmiCreateRegistryHive(FileName,
+                                &RegistryHive,
+                                CreateNew);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status);
+
+      /* FIXME: Try to load the backup hive */
 
+      KeBugCheck(0);
+      return(Status);
+    }
+
+  /* Connect the hive */
+  Status = CmiConnectHive(RegistryHive,
+                         KeyName);
   if (!NT_SUCCESS(Status))
     {
-#if 0
-#ifdef WIN32_REGDBG
-      WCHAR AltFileName[MAX_PATH];
-
-      CPRINT("WARNING! Registry file %S not found\n", FileName);
-      //DPRINT("Status %.08x\n", Status);
-
-      wcscpy(AltFileName, FileName);
-      wcscat(AltFileName, L".alt");
-
-      DPRINT("Attempting to connect the alternative hive %S\n", AltFileName);
-      /* Try to connect the alternative hive */
-      Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE);
-
-      if (!NT_SUCCESS(Status)) {
-             CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName);
-           //DPRINT("Status %.08x\n", Status);
-         }
-#endif
-#endif
+      DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status);
+      CmiRemoveRegistryHive(RegistryHive);
+      return(Status);
     }
 
   DPRINT("CmiInitializeHive() done\n");
 
-  return(Status);
+  return(STATUS_SUCCESS);
 }
 
 
 NTSTATUS
-CmiInitHives(BOOLEAN SetUpBoot)
+CmiInitHives(BOOLEAN SetupBoot)
 {
   PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
   OBJECT_ATTRIBUTES ObjectAttributes;
@@ -790,59 +775,59 @@ CmiInitHives(BOOLEAN SetUpBoot)
 
   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))
+  if (SetupBoot == TRUE)
     {
-      DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
-      return(Status);
-    }
+      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");
+      RtlInitUnicodeStringFromLiteral(&ValueName,
+                                     L"InstallPath");
 
-    BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
-    ValueInfo = ExAllocatePool(PagedPool,
-                              BufferSize);
-    if (ValueInfo == NULL)
-    {
+      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);
-      return(STATUS_INSUFFICIENT_RESOURCES);
-    }
+      if (ValueInfo == NULL)
+       {
+         ExFreePool(ValueInfo);
+         return(Status);
+       }
 
-    Status = NtQueryValueKey(KeyHandle,
-                            &ValueName,
-                            KeyValuePartialInformation,
-                            ValueInfo,
-                            BufferSize,
-                            &ResultSize);
-    NtClose(KeyHandle);
-    if (ValueInfo == NULL)
-    {
+      RtlCopyMemory(ConfigPath,
+                   ValueInfo->Data,
+                   ValueInfo->DataLength);
+      ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0;
       ExFreePool(ValueInfo);
-      return(Status);
     }
-
-    RtlCopyMemory(ConfigPath,
-                 ValueInfo->Data,
-                 ValueInfo->DataLength);
-    ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = (WCHAR)0;
-    ExFreePool(ValueInfo);
-  }
   else
-  {
-    wcscpy(ConfigPath, L"\\SystemRoot");
-  }
+    {
+      wcscpy(ConfigPath, L"\\SystemRoot");
+    }
   wcscat(ConfigPath, L"\\system32\\config");
 
   DPRINT("ConfigPath: %S\n", ConfigPath);
@@ -853,76 +838,82 @@ CmiInitHives(BOOLEAN SetUpBoot)
 
   /* FIXME: Save boot log */
 
-  /* FIXME: Rename \Registry\Machine\System */
-
-  /* Connect the SYSTEM hive */
-//  Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey, SetUpBoot);
-//  assert(NT_SUCCESS(Status));
-
-  /* FIXME: Synchronize old and new system hive (??) */
+  /* Connect the SYSTEM hive only if it has been created */
+  if (SetupBoot == TRUE)
+    {
+      wcscpy(EndPtr, REG_SYSTEM_FILE_NAME);
+      DPRINT ("ConfigPath: %S\n", ConfigPath);
 
-  /* FIXME: Delete old system hive */
+      RtlInitUnicodeString (&KeyName,
+                           REG_SYSTEM_KEY_NAME);
+      Status = CmiInitializeSystemHive (ConfigPath,
+                                       &KeyName);
+      if (!NT_SUCCESS(Status))
+       {
+         DPRINT1("CmiInitializeSystemHive() failed (Status %lx)\n", Status);
+         return(Status);
+       }
+    }
 
   /* Connect the SOFTWARE hive */
   wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
-  DPRINT1("ConfigPath: %S\n", ConfigPath);
+  DPRINT ("ConfigPath: %S\n", ConfigPath);
 
+  RtlInitUnicodeString (&KeyName,
+                       REG_SOFTWARE_KEY_NAME);
   Status = CmiInitializeHive(ConfigPath,
-                            REG_SOFTWARE_KEY_NAME,
-                            "Software",
-                            CmiMachineKey,
-                            SetUpBoot);
+                            &KeyName,
+                            SetupBoot);
   if (!NT_SUCCESS(Status))
-  {
-    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
-    return(Status);
-  }
+    {
+      DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+      return(Status);
+    }
 
   /* Connect the SAM hive */
   wcscpy(EndPtr, REG_SAM_FILE_NAME);
-  DPRINT1("ConfigPath: %S\n", ConfigPath);
+  DPRINT ("ConfigPath: %S\n", ConfigPath);
 
+  RtlInitUnicodeString (&KeyName,
+                       REG_SAM_KEY_NAME);
   Status = CmiInitializeHive(ConfigPath,
-                            REG_SAM_KEY_NAME,
-                            "Sam",
-                            CmiMachineKey,
-                            SetUpBoot);
+                            &KeyName,
+                            SetupBoot);
   if (!NT_SUCCESS(Status))
-  {
-    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
-    return(Status);
-  }
+    {
+      DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+      return(Status);
+    }
 
   /* Connect the SECURITY hive */
   wcscpy(EndPtr, REG_SEC_FILE_NAME);
-  DPRINT1("ConfigPath: %S\n", ConfigPath);
+  DPRINT ("ConfigPath: %S\n", ConfigPath);
+
+  RtlInitUnicodeString (&KeyName,
+                       REG_SEC_KEY_NAME);
   Status = CmiInitializeHive(ConfigPath,
-                            REG_SEC_KEY_NAME,
-                            "Security",
-                            CmiMachineKey,
-                            SetUpBoot);
+                            &KeyName,
+                            SetupBoot);
   if (!NT_SUCCESS(Status))
-  {
-    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
-    return(Status);
-  }
+    {
+      DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+      return(Status);
+    }
 
   /* Connect the DEFAULT hive */
   wcscpy(EndPtr, REG_USER_FILE_NAME);
-  DPRINT1("ConfigPath: %S\n", ConfigPath);
+  DPRINT ("ConfigPath: %S\n", ConfigPath);
 
+  RtlInitUnicodeString (&KeyName,
+                       REG_USER_KEY_NAME);
   Status = CmiInitializeHive(ConfigPath,
-                            REG_USER_KEY_NAME,
-                            ".Default",
-                            CmiUserKey,
-                            SetUpBoot);
+                            &KeyName,
+                            SetupBoot);
   if (!NT_SUCCESS(Status))
-  {
-    DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
-    return(Status);
-  }
-
-  /* FIXME : initialize standards symbolic links */
+    {
+      DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
+      return(Status);
+    }
 
 //  CmiCheckRegistry(TRUE);
 
@@ -958,7 +949,7 @@ CmShutdownRegistry(VOID)
     {
       Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
 
-      if (IsPermanentHive(Hive))
+      if (!IsVolatileHive(Hive))
        {
          /* Acquire hive resource exclusively */
          ExAcquireResourceExclusiveLite(&Hive->HiveResource,
@@ -967,10 +958,6 @@ CmShutdownRegistry(VOID)
          /* Flush non-volatile hive */
          CmiFlushRegistryHive(Hive);
 
-         /* Dereference file */
-         ObDereferenceObject(Hive->FileObject);
-         Hive->FileObject = NULL;
-
          /* Release hive resource */
          ExReleaseResourceLite(&Hive->HiveResource);
        }
@@ -991,7 +978,7 @@ CmiHiveSyncRoutine(PVOID DeferredContext)
   PREGISTRY_HIVE Hive;
   PLIST_ENTRY Entry;
 
-  DPRINT1("CmiHiveSyncRoutine() called\n");
+  DPRINT("CmiHiveSyncRoutine() called\n");
 
   CmiHiveSyncPending = FALSE;
 
@@ -1003,7 +990,7 @@ CmiHiveSyncRoutine(PVOID DeferredContext)
     {
       Hive = CONTAINING_RECORD(Entry, REGISTRY_HIVE, HiveList);
 
-      if (IsPermanentHive(Hive))
+      if (!IsVolatileHive(Hive))
        {
          /* Acquire hive resource exclusively */
          ExAcquireResourceExclusiveLite(&Hive->HiveResource,
@@ -1024,6 +1011,8 @@ CmiHiveSyncRoutine(PVOID DeferredContext)
 
   DPRINT("DeferredContext %x\n", DeferredContext);
   ExFreePool(DeferredContext);
+
+  DPRINT("CmiHiveSyncRoutine() done\n");
 }