[NDK][NTOS] Add global definition of INIT_FUNCTION/INIT_SECTION (#779)
[reactos.git] / ntoskrnl / config / cmsysini.c
index a191797..d672ead 100644 (file)
@@ -29,6 +29,7 @@ BOOLEAN CmpSpecialBootCondition;
 BOOLEAN CmpNoWrite;
 BOOLEAN CmpWasSetupBoot;
 BOOLEAN CmpProfileLoaded;
+BOOLEAN CmpNoVolatileCreates;
 ULONG CmpTraceLevel = 0;
 
 extern LONG CmpFlushStarveWriters;
@@ -39,26 +40,27 @@ extern BOOLEAN CmFirstTime;
 BOOLEAN
 NTAPI
 CmpLinkKeyToHive(
-    _In_z_ PWSTR LinkKeyName,
-    _In_z_ PWSTR TargetKeyName)
+    _In_z_ PCWSTR LinkKeyName,
+    _In_z_ PCWSTR TargetKeyName)
 {
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING LinkKeyName_U;
-    HANDLE TargetKeyHandle;
+    UNICODE_STRING KeyName;
+    HANDLE LinkKeyHandle;
     ULONG Disposition;
-    NTSTATUS Status;
+
     PAGED_CODE();
 
     /* Initialize the object attributes */
-    RtlInitUnicodeString(&LinkKeyName_U, LinkKeyName);
+    RtlInitUnicodeString(&KeyName, LinkKeyName);
     InitializeObjectAttributes(&ObjectAttributes,
-                               &LinkKeyName_U,
+                               &KeyName,
                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
 
     /* Create the link key */
-    Status = ZwCreateKey(&TargetKeyHandle,
+    Status = ZwCreateKey(&LinkKeyHandle,
                          KEY_CREATE_LINK,
                          &ObjectAttributes,
                          0,
@@ -67,7 +69,7 @@ CmpLinkKeyToHive(
                          &Disposition);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("CM: CmpLinkKeyToHive: couldn't create %S Status = 0x%lx\n",
+        DPRINT1("CM: CmpLinkKeyToHive: couldn't create %S, Status = 0x%lx\n",
                 LinkKeyName, Status);
         return FALSE;
     }
@@ -76,25 +78,26 @@ CmpLinkKeyToHive(
     if (Disposition != REG_CREATED_NEW_KEY)
     {
         DPRINT1("CM: CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
-        ZwClose(TargetKeyHandle);
+        ZwClose(LinkKeyHandle);
         return FALSE;
     }
 
     /* Set the target key name as link target */
-    Status = ZwSetValueKey(TargetKeyHandle,
+    RtlInitUnicodeString(&KeyName, TargetKeyName);
+    Status = ZwSetValueKey(LinkKeyHandle,
                            &CmSymbolicLinkValueName,
                            0,
                            REG_LINK,
-                           TargetKeyName,
-                           wcslen(TargetKeyName) * sizeof(WCHAR));
+                           KeyName.Buffer,
+                           KeyName.Length);
 
     /* Close the link key handle */
-    ObCloseHandle(TargetKeyHandle, KernelMode);
+    ObCloseHandle(LinkKeyHandle, KernelMode);
 
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("CM: CmpLinkKeyToHive: couldn't create symbolic link for %S\n",
-                TargetKeyName);
+        DPRINT1("CM: CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%lx\n",
+                TargetKeyName, Status);
         return FALSE;
     }
 
@@ -262,7 +265,7 @@ CmpQueryKeyName(IN PVOID ObjectBody,
                       BytesToCopy);
 
         /* Null terminate it */
-        ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = 0;
+        ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = UNICODE_NULL;
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -349,7 +352,7 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName,
     }
 
     /* Initialize the hive */
-    Status = CmpInitializeHive((PCMHIVE*)&NewHive,
+    Status = CmpInitializeHive(&NewHive,
                                Operation,
                                HiveFlags,
                                FileType,
@@ -370,9 +373,6 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName,
     /* Success, return hive */
     *Hive = NewHive;
 
-    /* HACK: ROS: Init root key cell and prepare the hive */
-    if (Operation == HINIT_CREATE) CmCreateRootNode(&NewHive->Hive, L"");
-
     /* Duplicate the hive name */
     NewHive->FileFullPath.Buffer = ExAllocatePoolWithTag(PagedPool,
                                                          HiveName->Length,
@@ -384,22 +384,23 @@ CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName,
                       HiveName->Buffer,
                       HiveName->Length);
         NewHive->FileFullPath.Length = HiveName->Length;
-        NewHive->FileFullPath.MaximumLength = HiveName->MaximumLength;
+        NewHive->FileFullPath.MaximumLength = HiveName->Length;
     }
 
     /* Return success */
     return STATUS_SUCCESS;
 }
 
+INIT_FUNCTION
 NTSTATUS
 NTAPI
-INIT_FUNCTION
 CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE KeyHandle;
     UNICODE_STRING KeyName, ValueName = { 0, 0, NULL };
-    HANDLE KeyHandle = NULL;
-    NTSTATUS Status;
+
     ASSERT(LoaderBlock != NULL);
 
     /* Setup attributes for loader options */
@@ -412,9 +413,10 @@ CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                                NULL,
                                NULL);
     Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes);
-    if (!NT_SUCCESS(Status)) goto Quickie;
+    if (!NT_SUCCESS(Status))
+        return Status;
 
-    /* Key opened, now write to the key */
+    /* Setup the value for the system start options */
     RtlInitUnicodeString(&KeyName, L"SystemStartOptions");
     Status = NtSetValueKey(KeyHandle,
                            &KeyName,
@@ -422,9 +424,10 @@ CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                            REG_SZ,
                            CmpLoadOptions.Buffer,
                            CmpLoadOptions.Length);
-    if (!NT_SUCCESS(Status)) goto Quickie;
+    if (!NT_SUCCESS(Status))
+        goto Quit;
 
-    /* Setup value name for system boot device in ARC format */
+    /* Setup the value for the system boot device in ARC format */
     RtlInitUnicodeString(&KeyName, L"SystemBootDevice");
     RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->ArcBootDeviceName);
     Status = NtSetValueKey(KeyHandle,
@@ -434,20 +437,90 @@ CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
                            ValueName.Buffer,
                            ValueName.Length);
 
-Quickie:
-    /* Free the buffers */
+    /* Free the temporary string */
     RtlFreeUnicodeString(&ValueName);
 
+Quit:
     /* Close the key and return */
-    if (KeyHandle) NtClose(KeyHandle);
+    NtClose(KeyHandle);
+    return Status;
+}
+
+INIT_FUNCTION
+static
+NTSTATUS
+CmpCreateHardwareProfile(HANDLE ControlSetHandle)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING KeyName;
+    HANDLE ProfilesHandle = NULL;
+    HANDLE ProfileHandle = NULL;
+    ULONG Disposition;
+    NTSTATUS Status;
+
+    DPRINT("CmpCreateHardwareProfile()\n");
+
+    /* Create the Hardware Profiles key */
+    RtlInitUnicodeString(&KeyName, L"Hardware Profiles");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               ControlSetHandle,
+                               NULL);
+    Status = NtCreateKey(&ProfilesHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Creating the Hardware Profile key failed\n");
+        goto done;
+    }
 
-    /* Return the status */
-    return (ExpInTextModeSetup ? STATUS_SUCCESS : Status);
+    /* Sanity check */
+    ASSERT(Disposition == REG_CREATED_NEW_KEY);
+
+    /* Create the 0000 key */
+    RtlInitUnicodeString(&KeyName, L"0000");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               ProfilesHandle,
+                               NULL);
+    Status = NtCreateKey(&ProfileHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Creating the Hardware Profile\\0000 key failed\n");
+        goto done;
+    }
+
+    /* Sanity check */
+    ASSERT(Disposition == REG_CREATED_NEW_KEY);
+
+done:
+    if (ProfilesHandle)
+        NtClose(ProfilesHandle);
+
+    if (ProfileHandle)
+        NtClose(ProfileHandle);
+
+    DPRINT("CmpCreateHardwareProfile() done\n");
+
+    return Status;
 }
 
+INIT_FUNCTION
 NTSTATUS
 NTAPI
-INIT_FUNCTION
 CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
     UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB");
@@ -457,75 +530,88 @@ CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     OBJECT_ATTRIBUTES ObjectAttributes;
     CHAR ValueInfoBuffer[128];
     PKEY_VALUE_FULL_INFORMATION ValueInfo;
-    CHAR Buffer[128];
     WCHAR UnicodeBuffer[128];
-    HANDLE SelectHandle, KeyHandle, ConfigHandle = NULL, ProfileHandle = NULL;
+    HANDLE SelectHandle = NULL;
+    HANDLE KeyHandle = NULL;
+    HANDLE ConfigHandle = NULL;
+    HANDLE ProfileHandle = NULL;
     HANDLE ParentHandle = NULL;
     ULONG ControlSet, HwProfile;
-    ANSI_STRING TempString;
     NTSTATUS Status;
     ULONG ResultLength, Disposition;
     PLOADER_PARAMETER_EXTENSION LoaderExtension;
     PAGED_CODE();
 
-    /* Open the select key */
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &SelectName,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-    Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
+    /* ReactOS Hack: Hard-code current to 001 for SetupLdr */
+    if (LoaderBlock->RegistryBase == NULL)
     {
-        /* ReactOS Hack: Hard-code current to 001 for SetupLdr */
-        if (!LoaderBlock->RegistryBase)
+        /* Build the ControlSet001 key */
+        RtlInitUnicodeString(&KeyName,
+                             L"\\Registry\\Machine\\System\\ControlSet001");
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &KeyName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+        Status = NtCreateKey(&KeyHandle,
+                             KEY_ALL_ACCESS,
+                             &ObjectAttributes,
+                             0,
+                             NULL,
+                             0,
+                             &Disposition);
+        if (!NT_SUCCESS(Status))
         {
-            /* Build the ControlSet001 key */
-            RtlInitUnicodeString(&KeyName,
-                                 L"\\Registry\\Machine\\System\\ControlSet001");
-            InitializeObjectAttributes(&ObjectAttributes,
-                                       &KeyName,
-                                       OBJ_CASE_INSENSITIVE,
-                                       NULL,
-                                       NULL);
-            Status = NtCreateKey(&KeyHandle,
-                                 KEY_ALL_ACCESS,
-                                 &ObjectAttributes,
-                                 0,
-                                 NULL,
-                                 0,
-                                 &Disposition);
-            if (!NT_SUCCESS(Status)) return Status;
-
-            /* Don't need the handle */
-            ZwClose(KeyHandle);
+            DPRINT1("Failed to create ControlSet001 key: 0x%lx\n", Status);
+            goto Cleanup;
+        }
 
-            /* Use hard-coded setting */
-            ControlSet = 1;
-            goto UseSet;
+        /* Create the Hardware Profile keys */
+        Status = CmpCreateHardwareProfile(KeyHandle);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to create Hardware profile keys: 0x%lx\n", Status);
+            goto Cleanup;
         }
 
-        /* Fail for real boots */
-        return Status;
+        /* Use hard-coded setting */
+        ControlSet = 1;
     }
+    else
+    {
+        /* Open the select key */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &SelectName,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
+        Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to open select key: 0x%lx\n", Status);
+            goto Cleanup;
+        }
 
-    /* Open the current value */
-    RtlInitUnicodeString(&KeyName, L"Current");
-    Status = NtQueryValueKey(SelectHandle,
-                             &KeyName,
-                             KeyValueFullInformation,
-                             ValueInfoBuffer,
-                             sizeof(ValueInfoBuffer),
-                             &ResultLength);
-    NtClose(SelectHandle);
-    if (!NT_SUCCESS(Status)) return Status;
+        /* Open the current value */
+        RtlInitUnicodeString(&KeyName, L"Current");
+        Status = NtQueryValueKey(SelectHandle,
+                                 &KeyName,
+                                 KeyValueFullInformation,
+                                 ValueInfoBuffer,
+                                 sizeof(ValueInfoBuffer),
+                                 &ResultLength);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to open the Current value: 0x%lx\n", Status);
+            goto Cleanup;
+        }
 
-    /* Get the actual value pointer, and get the control set ID */
-    ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
-    ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+        /* Get the actual value pointer, and get the control set ID */
+        ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
+        ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+    }
 
     /* Create the current control set key */
-UseSet:
     RtlInitUnicodeString(&KeyName,
                          L"\\Registry\\Machine\\System\\CurrentControlSet");
     InitializeObjectAttributes(&ObjectAttributes,
@@ -540,21 +626,20 @@ UseSet:
                          NULL,
                          REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
                          &Disposition);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+        goto Cleanup;
 
     /* Sanity check */
     ASSERT(Disposition == REG_CREATED_NEW_KEY);
 
-    /* Initialize the symbolic link name */
-    sprintf(Buffer,
-            "\\Registry\\Machine\\System\\ControlSet%03ld",
-            ControlSet);
-    RtlInitAnsiString(&TempString, Buffer);
+    /* Initialize the target link name */
+    Status = RtlStringCbPrintfW(UnicodeBuffer, sizeof(UnicodeBuffer),
+                                L"\\Registry\\Machine\\System\\ControlSet%03ld",
+                                ControlSet);
+    if (!NT_SUCCESS(Status))
+        goto Cleanup;
 
-    /* Create a Unicode string out of it */
-    KeyName.MaximumLength = sizeof(UnicodeBuffer);
-    KeyName.Buffer = UnicodeBuffer;
-    Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
+    RtlInitUnicodeString(&KeyName, UnicodeBuffer);
 
     /* Set the value */
     Status = NtSetValueKey(KeyHandle,
@@ -563,7 +648,8 @@ UseSet:
                            REG_LINK,
                            KeyName.Buffer,
                            KeyName.Length);
-    if (!NT_SUCCESS(Status)) return Status;
+    if (!NT_SUCCESS(Status))
+        goto Cleanup;
 
     /* Get the configuration database key */
     InitializeObjectAttributes(&ObjectAttributes,
@@ -572,33 +658,44 @@ UseSet:
                                KeyHandle,
                                NULL);
     Status = NtOpenKey(&ConfigHandle, KEY_READ, &ObjectAttributes);
-    NtClose(KeyHandle);
 
     /* Check if we don't have one */
     if (!NT_SUCCESS(Status))
     {
         /* Cleanup and exit */
-        ConfigHandle = 0;
+        Status = STATUS_SUCCESS;
         goto Cleanup;
     }
 
-    /* Now get the current config */
-    RtlInitUnicodeString(&KeyName, L"CurrentConfig");
-    Status = NtQueryValueKey(ConfigHandle,
-                             &KeyName,
-                             KeyValueFullInformation,
-                             ValueInfoBuffer,
-                             sizeof(ValueInfoBuffer),
-                             &ResultLength);
+    /* ReactOS Hack: Hard-code current to 001 for SetupLdr */
+    if (LoaderBlock->RegistryBase == NULL)
+    {
+        HwProfile = 0;
+    }
+    else
+    {
+        /* Now get the current config */
+        RtlInitUnicodeString(&KeyName, L"CurrentConfig");
+        Status = NtQueryValueKey(ConfigHandle,
+                                 &KeyName,
+                                 KeyValueFullInformation,
+                                 ValueInfoBuffer,
+                                 sizeof(ValueInfoBuffer),
+                                 &ResultLength);
 
-    /* Set pointer to buffer */
-    ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
+        /* Set pointer to buffer */
+        ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer;
 
-    /* Check if we failed or got a non DWORD-value */
-    if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD)) goto Cleanup;
+        /* Check if we failed or got a non DWORD-value */
+        if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD))
+        {
+            Status = STATUS_SUCCESS;
+            goto Cleanup;
+        }
 
-    /* Get the hadware profile */
-    HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+        /* Get the hadware profile */
+        HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+    }
 
     /* Open the hardware profile key */
     RtlInitUnicodeString(&KeyName,
@@ -613,21 +710,14 @@ UseSet:
     if (!NT_SUCCESS(Status))
     {
         /* Exit and clean up */
-        ParentHandle = 0;
+        Status = STATUS_SUCCESS;
         goto Cleanup;
     }
 
     /* Build the profile name */
-    sprintf(Buffer, "%04ld", HwProfile);
-    RtlInitAnsiString(&TempString, Buffer);
-
-    /* Convert it to Unicode */
-    KeyName.MaximumLength = sizeof(UnicodeBuffer);
-    KeyName.Buffer = UnicodeBuffer;
-    Status = RtlAnsiStringToUnicodeString(&KeyName,
-                                          &TempString,
-                                          FALSE);
-    ASSERT(Status == STATUS_SUCCESS);
+    RtlStringCbPrintfW(UnicodeBuffer, sizeof(UnicodeBuffer),
+                       L"%04ld", HwProfile);
+    RtlInitUnicodeString(&KeyName, UnicodeBuffer);
 
     /* Open the associated key */
     InitializeObjectAttributes(&ObjectAttributes,
@@ -641,7 +731,7 @@ UseSet:
     if (!NT_SUCCESS (Status))
     {
         /* Cleanup and exit */
-        ProfileHandle = 0;
+        Status = STATUS_SUCCESS;
         goto Cleanup;
     }
 
@@ -674,19 +764,11 @@ UseSet:
         ASSERT(Disposition == REG_CREATED_NEW_KEY);
 
         /* Create the profile name */
-        sprintf(Buffer,
-                "\\Registry\\Machine\\System\\CurrentControlSet\\"
-                "Hardware Profiles\\%04ld",
-                HwProfile);
-        RtlInitAnsiString(&TempString, Buffer);
-
-        /* Convert it to Unicode */
-        KeyName.MaximumLength = sizeof(UnicodeBuffer);
-        KeyName.Buffer = UnicodeBuffer;
-        Status = RtlAnsiStringToUnicodeString(&KeyName,
-                                              &TempString,
-                                              FALSE);
-        ASSERT(STATUS_SUCCESS == Status);
+        RtlStringCbPrintfW(UnicodeBuffer, sizeof(UnicodeBuffer),
+                           L"\\Registry\\Machine\\System\\CurrentControlSet\\"
+                           L"Hardware Profiles\\%04ld",
+                           HwProfile);
+        RtlInitUnicodeString(&KeyName, UnicodeBuffer);
 
         /* Set it */
         Status = NtSetValueKey(KeyHandle,
@@ -695,17 +777,20 @@ UseSet:
                                REG_LINK,
                                KeyName.Buffer,
                                KeyName.Length);
-        NtClose(KeyHandle);
     }
 
-    /* Close every opened handle */
+    Status = STATUS_SUCCESS;
+
 Cleanup:
+    /* Close every opened handle */
+    if (SelectHandle) NtClose(SelectHandle);
+    if (KeyHandle) NtClose(KeyHandle);
     if (ConfigHandle) NtClose(ConfigHandle);
     if (ProfileHandle) NtClose(ProfileHandle);
     if (ParentHandle) NtClose(ParentHandle);
 
-    /* Return success */
-    return STATUS_SUCCESS;
+    DPRINT("CmpCreateControlSet() done\n");
+    return Status;
 }
 
 NTSTATUS
@@ -774,21 +859,22 @@ CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName,
     return STATUS_SUCCESS;
 }
 
+INIT_FUNCTION
 BOOLEAN
 NTAPI
-INIT_FUNCTION
 CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
+    static const UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM");
     PVOID HiveBase;
     ANSI_STRING LoadString;
     PVOID Buffer;
     ULONG Length;
     NTSTATUS Status;
-    BOOLEAN Allocate;
     UNICODE_STRING KeyName;
     PCMHIVE SystemHive = NULL;
-    UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM");
     PSECURITY_DESCRIPTOR SecurityDescriptor;
+    BOOLEAN Success;
+
     PAGED_CODE();
 
     /* Setup the ansi string */
@@ -807,58 +893,45 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     RtlInitEmptyUnicodeString(&CmpLoadOptions, Buffer, (USHORT)Length);
 
     /* Add the load options and null-terminate */
-    RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE);
+    Status = RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        return FALSE;
+    }
+
     CmpLoadOptions.Buffer[LoadString.Length] = UNICODE_NULL;
     CmpLoadOptions.Length += sizeof(WCHAR);
 
     /* Get the System Hive base address */
     HiveBase = LoaderBlock->RegistryBase;
-    if (HiveBase)
-    {
-        /* Import it */
-        Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
-                                   HINIT_MEMORY,
-                                   HIVE_NOLAZYFLUSH,
-                                   HFILE_TYPE_LOG,
-                                   HiveBase,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &HiveName,
-                                   2);
-        if (!NT_SUCCESS(Status)) return FALSE;
-
-        /* Set the hive filename */
-        RtlCreateUnicodeString(&SystemHive->FileFullPath,
-                               L"\\SystemRoot\\System32\\Config\\SYSTEM");
 
-        /* We imported, no need to create a new hive */
-        Allocate = FALSE;
-
-        /* Manually set the hive as volatile, if in Live CD mode */
-        if (CmpShareSystemHives) SystemHive->Hive.HiveFlags = HIVE_VOLATILE;
-    }
-    else
+    Status = CmpInitializeHive(&SystemHive,
+                               HiveBase ? HINIT_MEMORY : HINIT_CREATE,
+                               HIVE_NOLAZYFLUSH,
+                               HFILE_TYPE_LOG,
+                               HiveBase,
+                               NULL,
+                               NULL,
+                               NULL,
+                               &HiveName,
+                               HiveBase ? 2 : 0);
+    if (!NT_SUCCESS(Status))
     {
-        /* Create it */
-        Status = CmpInitializeHive(&SystemHive,
-                                   HINIT_CREATE,
-                                   HIVE_NOLAZYFLUSH,
-                                   HFILE_TYPE_LOG,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &HiveName,
-                                   0);
-        if (!NT_SUCCESS(Status)) return FALSE;
+        return FALSE;
+    }
 
-        /* Set the hive filename */
-        RtlCreateUnicodeString(&SystemHive->FileFullPath,
-                               L"\\SystemRoot\\System32\\Config\\SYSTEM");
+    /* Set the hive filename */
+    Success = RtlCreateUnicodeString(&SystemHive->FileFullPath,
+                                     L"\\SystemRoot\\System32\\Config\\SYSTEM");
+    if (!Success)
+    {
+        return FALSE;
+    }
 
-        /* Tell CmpLinkHiveToMaster to allocate a hive */
-        Allocate = TRUE;
+    /* Manually set the hive as volatile, if in Live CD mode */
+    if (HiveBase && CmpShareSystemHives)
+    {
+        SystemHive->Hive.HiveFlags = HIVE_VOLATILE;
     }
 
     /* Save the boot type */
@@ -884,27 +957,28 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     SecurityDescriptor = CmpHiveRootSecurityDescriptor();
 
     /* Attach it to the system key */
+    /* Let CmpLinkHiveToMaster allocate a new hive if we got none from the LoaderBlock. */
     RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\SYSTEM");
     Status = CmpLinkHiveToMaster(&KeyName,
                                  NULL,
-                                 (PCMHIVE)SystemHive,
-                                 Allocate,
+                                 SystemHive,
+                                 !HiveBase,
                                  SecurityDescriptor);
 
     /* Free the security descriptor */
-    ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
+    ExFreePoolWithTag(SecurityDescriptor, TAG_CMSD);
     if (!NT_SUCCESS(Status)) return FALSE;
 
     /* Add the hive to the hive list */
-    CmpMachineHiveList[3].CmHive = (PCMHIVE)SystemHive;
+    CmpMachineHiveList[3].CmHive = SystemHive;
 
     /* Success! */
     return TRUE;
 }
 
+INIT_FUNCTION
 NTSTATUS
 NTAPI
-INIT_FUNCTION
 CmpCreateObjectTypes(VOID)
 {
     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
@@ -936,16 +1010,15 @@ CmpCreateObjectTypes(VOID)
     return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType);
 }
 
+INIT_FUNCTION
 BOOLEAN
 NTAPI
-INIT_FUNCTION
 CmpCreateRootNode(IN PHHIVE Hive,
                   IN PCWSTR Name,
                   OUT PHCELL_INDEX Index)
 {
     UNICODE_STRING KeyName;
     PCM_KEY_NODE KeyCell;
-    LARGE_INTEGER SystemTime;
     PAGED_CODE();
 
     /* Initialize the node name and allocate it */
@@ -963,10 +1036,9 @@ CmpCreateRootNode(IN PHHIVE Hive,
     if (!KeyCell) return FALSE;
 
     /* Setup the cell */
-    KeyCell->Signature = (USHORT)CM_KEY_NODE_SIGNATURE;
+    KeyCell->Signature = CM_KEY_NODE_SIGNATURE;
     KeyCell->Flags = KEY_HIVE_ENTRY | KEY_NO_DELETE;
-    KeQuerySystemTime(&SystemTime);
-    KeyCell->LastWriteTime = SystemTime;
+    KeQuerySystemTime(&KeyCell->LastWriteTime);
     KeyCell->Parent = HCELL_NIL;
     KeyCell->SubKeyCounts[Stable] = 0;
     KeyCell->SubKeyCounts[Volatile] = 0;
@@ -983,23 +1055,20 @@ CmpCreateRootNode(IN PHHIVE Hive,
     KeyCell->MaxValueDataLen = 0;
 
     /* Copy the name (this will also set the length) */
-    KeyCell->NameLength = CmpCopyName(Hive, (PWCHAR)KeyCell->Name, &KeyName);
+    KeyCell->NameLength = CmpCopyName(Hive, KeyCell->Name, &KeyName);
 
-    /* Check if the name was compressed */
+    /* Check if the name was compressed and set the flag if so */
     if (KeyCell->NameLength < KeyName.Length)
-    {
-        /* Set the flag */
         KeyCell->Flags |= KEY_COMP_NAME;
-    }
 
     /* Return success */
     HvReleaseCell(Hive, *Index);
     return TRUE;
 }
 
+INIT_FUNCTION
 BOOLEAN
 NTAPI
-INIT_FUNCTION
 CmpCreateRegistryRoot(VOID)
 {
     UNICODE_STRING KeyName;
@@ -1026,7 +1095,7 @@ CmpCreateRegistryRoot(VOID)
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
-                               NULL);
+                               SecurityDescriptor);
     Status = ObCreateObject(KernelMode,
                             CmpKeyObjectType,
                             &ObjectAttributes,
@@ -1036,7 +1105,7 @@ CmpCreateRegistryRoot(VOID)
                             0,
                             0,
                             (PVOID*)&RootKey);
-    ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
+    ExFreePoolWithTag(SecurityDescriptor, TAG_CMSD);
     if (!NT_SUCCESS(Status)) return FALSE;
 
     /* Sanity check, and get the key cell */
@@ -1097,78 +1166,35 @@ CmpCreateRegistryRoot(VOID)
     return TRUE;
 }
 
-NTSTATUS
-NTAPI
-CmpGetRegistryPath(IN PWCHAR ConfigPath)
+static NTSTATUS
+CmpGetRegistryPath(OUT PWCHAR ConfigPath)
 {
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    NTSTATUS Status;
-    HANDLE KeyHandle;
-    PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
-    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE");
-    UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath");
-    ULONG BufferSize, ResultSize;
+    /* Just use default path */
+    wcscpy(ConfigPath, L"\\SystemRoot");
 
     /* Check if we are booted in setup */
-    if (ExpInTextModeSetup)
+    if (!ExpInTextModeSetup)
     {
-        /* Setup the object attributes */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   &KeyName,
-                                   OBJ_CASE_INSENSITIVE,
-                                   NULL,
-                                   NULL);
-        /* Open the key */
-        Status =  ZwOpenKey(&KeyHandle,
-                            KEY_ALL_ACCESS,
-                            &ObjectAttributes);
-        if (!NT_SUCCESS(Status)) return Status;
-
-        /* Allocate the buffer */
-        BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
-        ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_CM);
-        if (!ValueInfo)
-        {
-            /* Fail */
-            ZwClose(KeyHandle);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        /* Query the value */
-        Status = ZwQueryValueKey(KeyHandle,
-                                 &ValueName,
-                                 KeyValuePartialInformation,
-                                 ValueInfo,
-                                 BufferSize,
-                                 &ResultSize);
-        ZwClose(KeyHandle);
-        if (!NT_SUCCESS(Status))
-        {
-            /* Fail */
-            ExFreePoolWithTag(ValueInfo, TAG_CM);
-            return Status;
-        }
-
-        /* Copy the config path and null-terminate it */
-        RtlCopyMemory(ConfigPath,
-                      ValueInfo->Data,
-                      ValueInfo->DataLength);
-        ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = UNICODE_NULL;
-        ExFreePoolWithTag(ValueInfo, TAG_CM);
+        /* Add registry path */
+#if 0
+        ResultSize = wcslen(ConfigPath);
+        if (ResultSize && ConfigPath[ResultSize - 1] == L'\\')
+            ConfigPath[ResultSize - 1] = UNICODE_NULL;
+#endif
+        wcscat(ConfigPath, L"\\System32\\Config\\");
     }
     else
     {
-        /* Just use default path */
-        wcscpy(ConfigPath, L"\\SystemRoot");
+        wcscat(ConfigPath, L"\\");
     }
 
-    /* Add registry path */
-    wcscat(ConfigPath, L"\\System32\\Config\\");
+    DPRINT1("CmpGetRegistryPath: ConfigPath = '%S'\n", ConfigPath);
 
     /* Done */
     return STATUS_SUCCESS;
 }
 
+_Function_class_(KSTART_ROUTINE)
 VOID
 NTAPI
 CmpLoadHiveThread(IN PVOID StartContext)
@@ -1177,7 +1203,6 @@ CmpLoadHiveThread(IN PVOID StartContext)
     UNICODE_STRING TempName, FileName, RegName;
     ULONG i, ErrorResponse, WorkerCount, Length;
     USHORT FileStart;
-    //ULONG RegStart;
     ULONG PrimaryDisposition, SecondaryDisposition, ClusterSize;
     PCMHIVE CmHive;
     HANDLE PrimaryHandle = NULL, LogHandle = NULL;
@@ -1193,36 +1218,35 @@ CmpLoadHiveThread(IN PVOID StartContext)
     CmpMachineHiveList[i].ThreadStarted = TRUE;
 
     /* Build the file name and registry name strings */
-    RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);
-    RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);
+    RtlInitEmptyUnicodeString(&FileName, FileBuffer, sizeof(FileBuffer));
+    RtlInitEmptyUnicodeString(&RegName, RegBuffer, sizeof(RegBuffer));
 
     /* Now build the system root path */
     CmpGetRegistryPath(ConfigPath);
     RtlInitUnicodeString(&TempName, ConfigPath);
-    RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
+    RtlAppendUnicodeStringToString(&FileName, &TempName);
     FileStart = FileName.Length;
 
     /* And build the registry root path */
     RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");
-    RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
-    //RegStart = RegName.Length;
+    RtlAppendUnicodeStringToString(&RegName, &TempName);
 
     /* Build the base name */
     RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);
-    RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
+    RtlAppendUnicodeStringToString(&RegName, &TempName);
 
     /* Check if this is a child of the root */
-    if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')
+    if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
     {
         /* Then setup the whole name */
         RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
-        RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
+        RtlAppendUnicodeStringToString(&RegName, &TempName);
     }
 
     /* Now add the rest of the file name */
     RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
     FileName.Length = FileStart;
-    RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
+    RtlAppendUnicodeStringToString(&FileName, &TempName);
     if (!CmpMachineHiveList[i].CmHive)
     {
         /* We need to allocate a new hive structure */
@@ -1235,9 +1259,12 @@ CmpLoadHiveThread(IN PVOID StartContext)
                                      &CmpMachineHiveList[i].Allocate,
                                      0);
         if (!(NT_SUCCESS(Status)) ||
-            (!(CmHive->FileHandles[HFILE_TYPE_LOG]) && !(CmpMiniNTBoot))) // HACK
+            (!(CmpShareSystemHives) && !(CmHive->FileHandles[HFILE_TYPE_LOG])))
         {
-            /* We failed or couldn't get a log file, raise a hard error */
+            /*
+             * We failed, or could not get a log file (unless
+             * the hive is shared), raise a hard error.
+             */
             ErrorParameters = &FileName;
             NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE,
                              1,
@@ -1295,15 +1322,19 @@ CmpLoadHiveThread(IN PVOID StartContext)
             Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE;
 
             /* Check if the cluster size doesn't match */
-            if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE);
+            if (CmHive->Hive.Cluster != ClusterSize)
+            {
+                DPRINT1("FIXME: Support for CmHive->Hive.Cluster (%lu) != ClusterSize (%lu) is unimplemented!\n",
+                        CmHive->Hive.Cluster, ClusterSize);
+            }
 
             /* Set the file size */
-            DPRINT("FIXME: Should set file size: %lx\n", Length);
+            DPRINT("FIXME: Should set file size: %lu\n", Length);
             //if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length))
-            {
+            //{
                 /* This shouldn't fail */
                 //ASSERT(FALSE);
-            }
+            //}
 
             /* Another thing we don't support is NTLDR-recovery */
             if (CmHive->Hive.BaseBlock->BootRecover) ASSERT(FALSE);
@@ -1331,7 +1362,7 @@ CmpLoadHiveThread(IN PVOID StartContext)
 
 VOID
 NTAPI
-CmpInitializeHiveList(IN USHORT Flag)
+CmpInitializeHiveList(VOID)
 {
     WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH];
     UNICODE_STRING TempName, FileName, RegName;
@@ -1346,17 +1377,17 @@ CmpInitializeHiveList(IN USHORT Flag)
     CmpNoWrite = FALSE;
 
     /* Build the file name and registry name strings */
-    RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);
-    RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);
+    RtlInitEmptyUnicodeString(&FileName, FileBuffer, sizeof(FileBuffer));
+    RtlInitEmptyUnicodeString(&RegName, RegBuffer, sizeof(RegBuffer));
 
     /* Now build the system root path */
     CmpGetRegistryPath(ConfigPath);
     RtlInitUnicodeString(&TempName, ConfigPath);
-    RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
+    RtlAppendUnicodeStringToString(&FileName, &TempName);
 
     /* And build the registry root path */
     RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");
-    RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
+    RtlAppendUnicodeStringToString(&RegName, &TempName);
     RegStart = RegName.Length;
 
     /* Setup the event to synchronize workers */
@@ -1371,9 +1402,13 @@ CmpInitializeHiveList(IN USHORT Flag)
     /* Loop every hive we care about */
     for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++)
     {
-        /* Make sure the list is setup */
+        /* Make sure the list is set up */
         ASSERT(CmpMachineHiveList[i].Name != NULL);
 
+        /* Load the hive as volatile, if in LiveCD mode */
+        if (CmpShareSystemHives)
+            CmpMachineHiveList[i].HHiveFlags |= HIVE_VOLATILE;
+
         /* Create a thread to handle this hive */
         Status = PsCreateSystemThread(&Thread,
                                       THREAD_ALL_ACCESS,
@@ -1424,14 +1459,14 @@ CmpInitializeHiveList(IN USHORT Flag)
             /* Build the base name */
             RegName.Length = RegStart;
             RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);
-            RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
+            RtlAppendUnicodeStringToString(&RegName, &TempName);
 
             /* Check if this is a child of the root */
-            if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')
+            if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == OBJ_NAME_PATH_SEPARATOR)
             {
                 /* Then setup the whole name */
                 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
-                RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
+                RtlAppendUnicodeStringToString(&RegName, &TempName);
             }
 
             /* Now link the hive to its master */
@@ -1463,20 +1498,22 @@ CmpInitializeHiveList(IN USHORT Flag)
     }
 
     /* Get rid of the SD */
-    ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
+    ExFreePoolWithTag(SecurityDescriptor, TAG_CMSD);
 
     /* Link SECURITY to SAM */
     CmpLinkKeyToHive(L"\\Registry\\Machine\\Security\\SAM",
                      L"\\Registry\\Machine\\SAM\\SAM");
 
     /* Link S-1-5-18 to .Default */
+    CmpNoVolatileCreates = FALSE;
     CmpLinkKeyToHive(L"\\Registry\\User\\S-1-5-18",
                      L"\\Registry\\User\\.Default");
+    CmpNoVolatileCreates = TRUE;
 }
 
+INIT_FUNCTION
 BOOLEAN
 NTAPI
-INIT_FUNCTION
 CmInitSystem1(VOID)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -1530,7 +1567,7 @@ CmInitSystem1(VOID)
     }
 
     /* Build the master hive */
-    Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive,
+    Status = CmpInitializeHive(&CmiVolatileHive,
                                HINIT_CREATE,
                                HIVE_VOLATILE,
                                HFILE_TYPE_PRIMARY,
@@ -1556,7 +1593,7 @@ CmInitSystem1(VOID)
     /* Create the default security descriptor */
     SecurityDescriptor = CmpHiveRootSecurityDescriptor();
 
-    /* Create '\Registry\Machine' key. */
+    /* Create '\Registry\Machine' key */
     RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
@@ -1579,7 +1616,7 @@ CmInitSystem1(VOID)
     /* Close the handle */
     NtClose(KeyHandle);
 
-    /* Create '\Registry\User' key. */
+    /* Create '\Registry\User' key */
     RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\USER");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
@@ -1602,6 +1639,9 @@ CmInitSystem1(VOID)
     /* Close the handle */
     NtClose(KeyHandle);
 
+    /* After this point, do not allow creating keys in the master hive */
+    CmpNoVolatileCreates = TRUE;
+
     /* Initialize the system hive */
     if (!CmpInitializeSystemHive(KeLoaderBlock))
     {
@@ -1609,7 +1649,7 @@ CmInitSystem1(VOID)
         KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0);
     }
 
-    /* Create the 'CurrentControlSet' link. */
+    /* Create the 'CurrentControlSet' link */
     Status = CmpCreateControlSet(KeLoaderBlock);
     if (!NT_SUCCESS(Status))
     {
@@ -1618,7 +1658,7 @@ CmInitSystem1(VOID)
     }
 
     /* Create the hardware hive */
-    Status = CmpInitializeHive((PCMHIVE*)&HardwareHive,
+    Status = CmpInitializeHive(&HardwareHive,
                                HINIT_CREATE,
                                HIVE_VOLATILE,
                                HFILE_TYPE_PRIMARY,
@@ -1635,13 +1675,13 @@ CmInitSystem1(VOID)
     }
 
     /* Add the hive to the hive list */
-    CmpMachineHiveList[0].CmHive = (PCMHIVE)HardwareHive;
+    CmpMachineHiveList[0].CmHive = HardwareHive;
 
     /* Attach it to the machine key */
     RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE");
     Status = CmpLinkHiveToMaster(&KeyName,
                                  NULL,
-                                 (PCMHIVE)HardwareHive,
+                                 HardwareHive,
                                  TRUE,
                                  SecurityDescriptor);
     if (!NT_SUCCESS(Status))
@@ -1654,7 +1694,7 @@ CmInitSystem1(VOID)
     CmpAddToHiveFileList(HardwareHive);
 
     /* Free the security descriptor */
-    ExFreePoolWithTag(SecurityDescriptor, TAG_CM);
+    ExFreePoolWithTag(SecurityDescriptor, TAG_CMSD);
 
     /* Fill out the Hardware key with the ARC Data from the Loader */
     Status = CmpInitializeHardwareConfiguration(KeLoaderBlock);
@@ -1687,9 +1727,9 @@ CmInitSystem1(VOID)
     return TRUE;
 }
 
+INIT_FUNCTION
 VOID
 NTAPI
-INIT_FUNCTION
 CmpFreeDriverList(IN PHHIVE Hive,
                   IN PLIST_ENTRY DriverList)
 {
@@ -1736,9 +1776,9 @@ CmpFreeDriverList(IN PHHIVE Hive,
     }
 }
 
+INIT_FUNCTION
 PUNICODE_STRING*
 NTAPI
-INIT_FUNCTION
 CmGetSystemDriverList(VOID)
 {
     LIST_ENTRY DriverList;
@@ -1822,11 +1862,21 @@ CmGetSystemDriverList(VOID)
         /* Get the entry */
         DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link);
 
-        /* Allocate the path for the caller and duplicate the registry path */
+        /* Allocate the path for the caller */
         ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING));
-        RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-                                  &DriverEntry->RegistryPath,
-                                  ServicePath[i]);
+        if (!ServicePath[i])
+        {
+            KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
+        }
+
+        /* Duplicate the registry path */
+        Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                           &DriverEntry->RegistryPath,
+                                           ServicePath[i]);
+        if (!NT_SUCCESS(Status))
+        {
+            KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
+        }
     }
 
     /* Terminate the list */
@@ -2014,14 +2064,14 @@ CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1,
     /* Get hash indexes */
     Index1 = GET_HASH_INDEX(ConvKey1);
     Index2 = GET_HASH_INDEX(ConvKey2);
-    ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey2).Owner == KeGetCurrentThread()) ||
+    ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey2)->Owner == KeGetCurrentThread()) ||
            (CmpTestRegistryLockExclusive()));
 
     /* See which one is highest */
     if (Index1 < Index2)
     {
         /* Grab them in the proper order */
-        ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1).Owner == KeGetCurrentThread()) ||
+        ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1)->Owner == KeGetCurrentThread()) ||
                (CmpTestRegistryLockExclusive()));
         CmpReleaseKcbLockByKey(ConvKey2);
         CmpReleaseKcbLockByKey(ConvKey1);
@@ -2031,7 +2081,7 @@ CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1,
         /* Release the first one first, then the second */
         if (Index1 != Index2)
         {
-            ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1).Owner == KeGetCurrentThread()) ||
+            ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1)->Owner == KeGetCurrentThread()) ||
                    (CmpTestRegistryLockExclusive()));
             CmpReleaseKcbLockByKey(ConvKey1);
         }
@@ -2045,7 +2095,6 @@ CmShutdownSystem(VOID)
 {
     PLIST_ENTRY ListEntry;
     PCMHIVE Hive;
-    ULONG i;
 
     /* Kill the workers */
     if (!CmFirstTime) CmpShutdownWorkers();
@@ -2060,14 +2109,7 @@ CmShutdownSystem(VOID)
     {
         Hive = CONTAINING_RECORD(ListEntry, CMHIVE, HiveList);
 
-        for (i = 0; i < HFILE_TYPE_MAX; i++)
-        {
-            if (Hive->FileHandles[i] != NULL)
-            {
-                ZwClose(Hive->FileHandles[i]);
-                Hive->FileHandles[i] = NULL;
-            }
-        }
+        CmpCloseHiveFiles(Hive);
 
         ListEntry = ListEntry->Flink;
     }
@@ -2079,27 +2121,30 @@ VOID
 NTAPI
 CmpSetVersionData(VOID)
 {
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
     UNICODE_STRING ValueName;
     UNICODE_STRING ValueData;
+    ANSI_STRING TempString;
     HANDLE SoftwareKeyHandle = NULL;
     HANDLE MicrosoftKeyHandle = NULL;
     HANDLE WindowsNtKeyHandle = NULL;
     HANDLE CurrentVersionKeyHandle = NULL;
-    WCHAR Buffer[128];
-    NTSTATUS Status;
+    WCHAR Buffer[128]; // Buffer large enough to contain a full ULONG in decimal
+                       // representation, and the full 'CurrentType' string.
 
-    /* Open the 'CurrentVersion' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"\\REGISTRY\\MACHINE\\SOFTWARE");
+    /*
+     * Open the 'HKLM\Software\Microsoft\Windows NT\CurrentVersion' key
+     * (create the intermediate subkeys if needed).
+     */
 
+    RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SOFTWARE");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
-                               OBJ_CASE_INSENSITIVE,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
-
     Status = NtCreateKey(&SoftwareKeyHandle,
                          KEY_CREATE_SUB_KEY,
                          &ObjectAttributes,
@@ -2113,16 +2158,12 @@ CmpSetVersionData(VOID)
         return;
     }
 
-    /* Open the 'CurrentVersion' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Microsoft");
-
+    RtlInitUnicodeString(&KeyName, L"Microsoft");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
-                               OBJ_CASE_INSENSITIVE,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                SoftwareKeyHandle,
                                NULL);
-
     Status = NtCreateKey(&MicrosoftKeyHandle,
                          KEY_CREATE_SUB_KEY,
                          &ObjectAttributes,
@@ -2133,19 +2174,15 @@ CmpSetVersionData(VOID)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
-        goto done;
+        goto Quit;
     }
 
-    /* Open the 'CurrentVersion' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"Windows NT");
-
+    RtlInitUnicodeString(&KeyName, L"Windows NT");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
-                               OBJ_CASE_INSENSITIVE,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                MicrosoftKeyHandle,
                                NULL);
-
     Status = NtCreateKey(&WindowsNtKeyHandle,
                          KEY_CREATE_SUB_KEY,
                          &ObjectAttributes,
@@ -2156,19 +2193,15 @@ CmpSetVersionData(VOID)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
-        goto done;
+        goto Quit;
     }
 
-    /* Open the 'CurrentVersion' key */
-    RtlInitUnicodeString(&KeyName,
-                         L"CurrentVersion");
-
+    RtlInitUnicodeString(&KeyName, L"CurrentVersion");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
-                               OBJ_CASE_INSENSITIVE,
+                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                WindowsNtKeyHandle,
                                NULL);
-
     Status = NtCreateKey(&CurrentVersionKeyHandle,
                          KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
                          &ObjectAttributes,
@@ -2179,30 +2212,60 @@ CmpSetVersionData(VOID)
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status);
-        goto done;
+        goto Quit;
     }
 
-    /* Set the 'CurrentType' value */
-    RtlInitUnicodeString(&ValueName,
-                         L"CurrentType");
+    /* Set the 'CurrentVersion' value */
+    RtlInitUnicodeString(&ValueName, L"CurrentVersion");
+    NtSetValueKey(CurrentVersionKeyHandle,
+                  &ValueName,
+                  0,
+                  REG_SZ,
+                  CmVersionString.Buffer,
+                  CmVersionString.Length + sizeof(WCHAR));
 
+    /* Set the 'CurrentBuildNumber' value */
+    RtlInitUnicodeString(&ValueName, L"CurrentBuildNumber");
+    RtlInitEmptyUnicodeString(&ValueData, Buffer, sizeof(Buffer));
+    RtlIntegerToUnicodeString(NtBuildNumber & 0xFFFF, 10, &ValueData);
+    NtSetValueKey(CurrentVersionKeyHandle,
+                  &ValueName,
+                  0,
+                  REG_SZ,
+                  ValueData.Buffer,
+                  ValueData.Length + sizeof(WCHAR));
+
+    /* Set the 'BuildLab' value */
+    RtlInitUnicodeString(&ValueName, L"BuildLab");
+    RtlInitAnsiString(&TempString, NtBuildLab);
+    Status = RtlAnsiStringToUnicodeString(&ValueData, &TempString, FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        NtSetValueKey(CurrentVersionKeyHandle,
+                      &ValueName,
+                      0,
+                      REG_SZ,
+                      ValueData.Buffer,
+                      ValueData.Length + sizeof(WCHAR));
+    }
+
+    /* Set the 'CurrentType' value */
+    RtlInitUnicodeString(&ValueName, L"CurrentType");
+    RtlStringCbPrintfW(Buffer, sizeof(Buffer),
+                       L"%s %s",
 #ifdef CONFIG_SMP
-    wcscpy(Buffer, L"Multiprocessor");
+                       L"Multiprocessor"
 #else
-    wcscpy(Buffer, L"Uniprocessor");
+                       L"Uniprocessor"
 #endif
-
-    wcscat(Buffer, L" ");
-
+                       ,
 #if (DBG == 1)
-    wcscat(Buffer, L"Checked");
+                       L"Checked"
 #else
-    wcscat(Buffer, L"Free");
+                       L"Free"
 #endif
-
-    RtlInitUnicodeString(&ValueData,
-                         Buffer);
-
+                       );
+    RtlInitUnicodeString(&ValueData, Buffer);
     NtSetValueKey(CurrentVersionKeyHandle,
                   &ValueName,
                   0,
@@ -2210,7 +2273,50 @@ CmpSetVersionData(VOID)
                   ValueData.Buffer,
                   ValueData.Length + sizeof(WCHAR));
 
-done:;
+    /* Set the 'CSDVersion' value */
+    RtlInitUnicodeString(&ValueName, L"CSDVersion");
+    if (CmCSDVersionString.Length != 0)
+    {
+        NtSetValueKey(CurrentVersionKeyHandle,
+                      &ValueName,
+                      0,
+                      REG_SZ,
+                      CmCSDVersionString.Buffer,
+                      CmCSDVersionString.Length + sizeof(WCHAR));
+    }
+    else
+    {
+        NtDeleteValueKey(CurrentVersionKeyHandle, &ValueName);
+    }
+
+    /* Set the 'CSDBuildNumber' value */
+    RtlInitUnicodeString(&ValueName, L"CSDBuildNumber");
+    if (CmNtSpBuildNumber != 0)
+    {
+        RtlInitEmptyUnicodeString(&ValueData, Buffer, sizeof(Buffer));
+        RtlIntegerToUnicodeString(CmNtSpBuildNumber, 10, &ValueData);
+        NtSetValueKey(CurrentVersionKeyHandle,
+                      &ValueName,
+                      0,
+                      REG_SZ,
+                      ValueData.Buffer,
+                      ValueData.Length + sizeof(WCHAR));
+    }
+    else
+    {
+        NtDeleteValueKey(CurrentVersionKeyHandle, &ValueName);
+    }
+
+    /* Set the 'SystemRoot' value */
+    RtlInitUnicodeString(&ValueName, L"SystemRoot");
+    NtSetValueKey(CurrentVersionKeyHandle,
+                  &ValueName,
+                  0,
+                  REG_SZ,
+                  NtSystemRoot.Buffer,
+                  NtSystemRoot.Length + sizeof(WCHAR));
+
+Quit:
     /* Close the keys */
     if (CurrentVersionKeyHandle != NULL)
         NtClose(CurrentVersionKeyHandle);