[USETUP] Implement offline ReactOS registry initialization in USetup (equivalent...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 3 Jun 2017 16:22:42 +0000 (16:22 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 24 Oct 2018 22:57:02 +0000 (00:57 +0200)
The rationale is as follows.

We now have the 1st-stage ReactOS setup running with its own registry SYSTEM hive,
similarly to regular ROS running instances (livecd, regular installation...).

The ReactOS-specific SetInstallPathValue() hack, introduced in a76689e9 (r3794)
and 5f973ce0 (r3795), is removed. This hack told the kernel that, during the setup,
it had to "switch" the used registry hives and instead use the ones of the ROS
installation being prepared.

This was really hackish because this means, mixing between registry settings used only
for the setup running instance, that could use different registry settings
than the ones that should be set for the ROS installation being actually performed.

Also, note that in the case of a 1st-stage GUI setup, consisting in running the
LiveCD + the GUI setup program, this situation would be untenable. Note also that
for people willing to use the Setup*** functions exported by setupapi.dll to parse
the registry INF files to initialize the registry of the ROS installation being
prepared, this would be impossible either.

Hence the need to have offline registry modification functionality.

svn path=/branches/setup_improvements/; revision=74766

base/setup/usetup/mui.c
base/setup/usetup/registry.c
base/setup/usetup/registry.h
base/setup/usetup/settings.c
base/setup/usetup/usetup.c

index 0ddbdfe..a983f0f 100644 (file)
@@ -297,11 +297,11 @@ AddHotkeySettings(
     NTSTATUS Status;
 
     RtlInitUnicodeString(&KeyName,
-                         L"\\Registry\\User\\.DEFAULT\\Keyboard Layout\\Toggle");
+                         L".DEFAULT\\Keyboard Layout\\Toggle");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
 
     Status =  NtCreateKey(&KeyHandle,
@@ -384,17 +384,16 @@ AddKbLayoutsToRegistry(
     ULONG Disposition;
     ULONG uIndex = 0;
     ULONG uCount = 0;
-    WCHAR szKeyName[48] = L"\\Registry\\User\\.DEFAULT\\Keyboard Layout";
+    WCHAR szKeyName[48] = L".DEFAULT\\Keyboard Layout";
     WCHAR szValueName[3 + 1];
     WCHAR szLangID[8 + 1];
 
     // Open the keyboard layout key
-    RtlInitUnicodeString(&KeyName,
-                         szKeyName);
+    RtlInitUnicodeString(&KeyName, szKeyName);
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
 
     Status =  NtCreateKey(&KeyHandle,
@@ -416,7 +415,7 @@ AddKbLayoutsToRegistry(
     KeyName.MaximumLength = sizeof(szKeyName);
     Status = RtlAppendUnicodeToString(&KeyName, L"\\Preload");
 
-    if(!NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlAppend failed! (%lx)\n", Status);
         DPRINT1("String is %wZ\n", &KeyName);
@@ -426,7 +425,7 @@ AddKbLayoutsToRegistry(
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
 
     Status = NtCreateKey(&KeyHandle,
@@ -443,11 +442,11 @@ AddKbLayoutsToRegistry(
         return FALSE;
     }
 
-    RtlInitUnicodeString(&KeyName, L"\\Registry\\User\\.DEFAULT\\Keyboard Layout\\Substitutes");
+    RtlInitUnicodeString(&KeyName, L".DEFAULT\\Keyboard Layout\\Substitutes");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
 
     Status =  NtCreateKey(&SubKeyHandle,
@@ -577,15 +576,15 @@ AddCodepageToRegistry(
 
     // Open the nls codepage key
     RtlInitUnicodeString(&KeyName,
-                         L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
+                         L"SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
                                NULL);
-    Status =  NtOpenKey(&KeyHandle,
-                        KEY_WRITE,
-                        &ObjectAttributes);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_WRITE,
+                       &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
@@ -656,15 +655,15 @@ AddFontsSettingsToRegistry(
     ULONG uIndex = 0;
 
     RtlInitUnicodeString(&KeyName,
-                         L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
+                         L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
                                NULL);
-    Status =  NtOpenKey(&KeyHandle,
-                        KEY_WRITE,
-                        &ObjectAttributes);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_WRITE,
+                       &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
index fc9b127..7fda1c9 100644 (file)
 
 /* FUNCTIONS ****************************************************************/
 
-static
-BOOLEAN
-GetRootKey(
-    PWCHAR Name)
+typedef struct _ROOT_KEY
 {
-    if (!_wcsicmp (Name, L"HKCR"))
-    {
-        wcscpy (Name, L"\\Registry\\Machine\\SOFTWARE\\Classes\\");
-        return TRUE;
-    }
+    PCWSTR Name;
+    PCWSTR MountPoint;
+    HANDLE Handle;
+} ROOT_KEY, *PROOT_KEY;
 
-    if (!_wcsicmp (Name, L"HKCU"))
-    {
-        wcscpy (Name, L"\\Registry\\User\\.DEFAULT\\");
-        return TRUE;
-    }
+ROOT_KEY RootKeys[] =
+{
+    // L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SOFTWARE\\Classes\\"
+    { L"HKCR", L"\\Registry\\Machine\\USetup_SOFTWARE\\Classes\\", NULL },    /* "\\Registry\\Machine\\SOFTWARE\\Classes\\" */  // HKEY_CLASSES_ROOT
+    { L"HKCU", L"\\Registry\\User\\USetup_DEFAULT\\"             , NULL },    /* "\\Registry\\User\\.DEFAULT\\" */              // HKEY_CURRENT_USER
+    { L"HKLM", L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\"  , NULL },    /* "\\Registry\\Machine\\"        */              // HKEY_LOCAL_MACHINE
+    { L"HKU" , L"\\Registry\\Machine\\SYSTEM\\USetup_User\\"     , NULL },    /* "\\Registry\\User\\"           */              // HKEY_USERS
+#if 0
+    { L"HKR", NULL, NULL },
+#endif
+};
 
-    if (!_wcsicmp (Name, L"HKLM"))
-    {
-        wcscpy (Name, L"\\Registry\\Machine\\");
-        return TRUE;
-    }
+#define IsPredefKey(HKey)       \
+    (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
+
+#define GetPredefKeyIndex(HKey) \
+    ((ULONG_PTR)(HKey) & 0x0FFFFFFF)
+
+HANDLE
+GetRootKeyByPredefKey(
+    IN HANDLE KeyHandle,
+    OUT PCWSTR* RootKeyMountPoint OPTIONAL)
+{
+    ULONG_PTR Index = GetPredefKeyIndex(KeyHandle);
+
+    if (!IsPredefKey(KeyHandle))
+        return NULL;
+    if (GetPredefKeyIndex(KeyHandle) >= ARRAYSIZE(RootKeys))
+        return NULL;
 
-    if (!_wcsicmp (Name, L"HKU"))
+    if (RootKeyMountPoint)
+        *RootKeyMountPoint = RootKeys[Index].MountPoint;
+    return RootKeys[Index].Handle;
+}
+
+HANDLE
+GetRootKeyByName(
+    IN PCWSTR RootKeyName,
+    OUT PCWSTR* RootKeyMountPoint OPTIONAL)
+{
+    UCHAR i;
+
+    for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
     {
-        wcscpy (Name, L"\\Registry\\User\\");
-        return TRUE;
+        if (!_wcsicmp(RootKeyName, RootKeys[i].Name))
+        {
+            if (RootKeyMountPoint)
+                *RootKeyMountPoint = RootKeys[i].MountPoint;
+            return RootKeys[i].Handle;
+        }
     }
 
-#if 0
-    if (!_wcsicmp (Name, L"HKR"))
-        return FALSE;
-#endif
-
-    return FALSE;
+    return NULL;
 }
 
 
@@ -481,11 +506,11 @@ registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete)
     UNICODE_STRING Name, Value;
     PUNICODE_STRING ValuePtr;
     UINT Flags;
-    ULONG Length;
     WCHAR Buffer[MAX_INF_STRING_LENGTH];
 
     INFCONTEXT Context;
-    HANDLE KeyHandle;
+    PCWSTR RootKeyName;
+    HANDLE RootKeyHandle, KeyHandle;
     BOOLEAN Ok;
 
     Ok = SetupFindFirstLineW(hInf, Section, NULL, &Context);
@@ -497,15 +522,15 @@ registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete)
         /* get root */
         if (!SetupGetStringFieldW(&Context, 1, Buffer, sizeof(Buffer)/sizeof(WCHAR), NULL))
             continue;
-        if (!GetRootKey (Buffer))
+        RootKeyHandle = GetRootKeyByName(Buffer, &RootKeyName);
+        if (!RootKeyHandle)
             continue;
 
         /* get key */
-        Length = wcslen(Buffer);
-        if (!SetupGetStringFieldW(&Context, 2, Buffer + Length, sizeof(Buffer)/sizeof(WCHAR) - Length, NULL))
+        if (!SetupGetStringFieldW(&Context, 2, Buffer, sizeof(Buffer)/sizeof(WCHAR), NULL))
             *Buffer = 0;
 
-        DPRINT("KeyName: <%S>\n", Buffer);
+        DPRINT("KeyName: <%S\\%S>\n", RootKeyName, Buffer);
 
         /* get flags */
         if (!SetupGetIntField(&Context, 4, (PINT)&Flags))
@@ -517,7 +542,7 @@ registry_callback(HINF hInf, PCWSTR Section, BOOLEAN Delete)
         InitializeObjectAttributes(&ObjectAttributes,
                                    &Name,
                                    OBJ_CASE_INSENSITIVE,
-                                   NULL,
+                                   RootKeyHandle,
                                    NULL);
 
         if (Delete || (Flags & FLG_ADDREG_OVERWRITEONLY))
@@ -621,13 +646,611 @@ ImportRegistryFile(
     return TRUE;
 }
 
+/*
+ * Should be called under privileges
+ */
+// static
+NTSTATUS
+CreateRegistryFile(
+    IN PUNICODE_STRING InstallPath,
+    IN PCWSTR RegistryKey,
+    IN HANDLE ProtoKeyHandle)
+{
+    NTSTATUS Status;
+    HANDLE FileHandle;
+    UNICODE_STRING FileName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    WCHAR PathBuffer[MAX_PATH];
+
+    /* Create the file */
+    CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 3,
+                 InstallPath->Buffer, L"System32\\config", RegistryKey);
+    RtlInitUnicodeString(&FileName, PathBuffer);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL, // Could have been installpath, etc...
+                               NULL);
+
+    Status = NtCreateFile(&FileHandle,
+                          FILE_GENERIC_WRITE,
+                          &ObjectAttributes,
+                          &IoStatusBlock,
+                          NULL,
+                          FILE_ATTRIBUTE_NORMAL,
+                          0,
+                          FILE_OVERWRITE_IF,
+                          FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
+                          NULL,
+                          0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateFile(%wZ) failed, Status 0x%08lx\n", &FileName, Status);
+        return Status;
+    }
+
+    /* Save the selected hive into the file */
+    Status = NtSaveKeyEx(ProtoKeyHandle, FileHandle, REG_LATEST_FORMAT);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtSaveKeyEx(%wZ) failed, Status 0x%08lx\n", &FileName, Status);
+    }
+
+    /* Close the file and return */
+    NtClose(FileHandle);
+    return Status;
+}
+
+static BOOLEAN
+CmpLinkKeyToHive(
+    IN HANDLE RootLinkKeyHandle OPTIONAL,
+    IN PCWSTR LinkKeyName,
+    IN PCWSTR TargetKeyName)
+{
+    static UNICODE_STRING CmSymbolicLinkValueName =
+        RTL_CONSTANT_STRING(L"SymbolicLinkValue");
+
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING KeyName;
+    HANDLE TargetKeyHandle;
+    ULONG Disposition;
+
+    /* Initialize the object attributes */
+    RtlInitUnicodeString(&KeyName, LinkKeyName);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootLinkKeyHandle,
+                               NULL);
+
+    /* Create the link key */
+    Status = NtCreateKey(&TargetKeyHandle,
+                         KEY_SET_VALUE | KEY_CREATE_LINK,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CmpLinkKeyToHive: couldn't create %S, Status = 0x%08lx\n",
+                LinkKeyName, Status);
+        return FALSE;
+    }
+
+    /* Check if the new key was actually created */
+    if (Disposition != REG_CREATED_NEW_KEY)
+    {
+        DPRINT1("CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
+        NtClose(TargetKeyHandle);
+        return FALSE;
+    }
+
+    /* Set the target key name as link target */
+    RtlInitUnicodeString(&KeyName, TargetKeyName);
+    Status = NtSetValueKey(TargetKeyHandle,
+                           &CmSymbolicLinkValueName,
+                           0,
+                           REG_LINK,
+                           KeyName.Buffer,
+                           KeyName.Length);
+
+    /* Close the link key handle */
+    NtClose(TargetKeyHandle);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%08lx\n",
+                TargetKeyName, Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * Should be called under privileges
+ */
+// static
+NTSTATUS
+ConnectRegistry(
+    IN HKEY RootKey OPTIONAL,
+    // IN HANDLE RootDirectory OPTIONAL,
+    IN PUNICODE_STRING InstallPath,
+    IN PCWSTR RegistryKey,
+    // IN PUCHAR Descriptor,
+    // IN ULONG DescriptorLength,
+    IN PCWSTR RegMountPoint)
+{
+    NTSTATUS Status;
+    UNICODE_STRING KeyName, FileName;
+    OBJECT_ATTRIBUTES KeyObjectAttributes;
+    OBJECT_ATTRIBUTES FileObjectAttributes;
+    WCHAR PathBuffer[MAX_PATH];
+
+    RtlInitUnicodeString(&KeyName, RegMountPoint);
+    InitializeObjectAttributes(&KeyObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKey,
+                               NULL);
+
+    CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 3,
+                 InstallPath->Buffer, L"System32\\config", RegistryKey);
+    RtlInitUnicodeString(&FileName, PathBuffer);
+    InitializeObjectAttributes(&FileObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL, // RootDirectory,
+                               NULL);
+
+#if 0
+    IN PCMHIVE HiveToConnect;
+    /*
+     * Add security to the root key.
+     * NOTE: One can implement this using the lpSecurityAttributes
+     * parameter of RegCreateKeyExW.
+     */
+    Status = CmiCreateSecurityKey(&HiveToConnect->Hive,
+                                  HiveToConnect->Hive.BaseBlock->RootCell,
+                                  Descriptor, DescriptorLength);
+    if (!NT_SUCCESS(Status))
+        DPRINT1("Failed to add security for root key '%S'\n", Path);
+#endif
+
+    /* Mount the registry hive in the registry namespace */
+    Status = NtLoadKey(&KeyObjectAttributes, &FileObjectAttributes);
+
+    return Status;
+}
+
+NTSTATUS
+RegInitializeRegistry(
+    IN PUNICODE_STRING InstallPath)
+{
+    NTSTATUS Status;
+    HANDLE KeyHandle;
+    UNICODE_STRING KeyName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
+    ULONG Disposition;
+    UINT i;
+    PCWSTR RegistryKeys[] =
+    {
+        L"SYSTEM",
+        L"SOFTWARE",
+        L"DEFAULT", // L".DEFAULT",
+        // L"SAM",
+        // L"SECURITY",
+        // L"BCD00000000",
+    };
+
+#if 0
+    /* Initialize the current session registry */
+    Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
+        return Status;
+    }
+#endif
+
+    /* Acquire restore privilege */
+    Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status);
+        /* Exit prematurely here.... */
+        return Status;
+    }
+
+    /* Acquire backup privilege */
+    Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[1]);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status);
+        RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
+        /* Exit prematurely here.... */
+        return Status;
+    }
+
+    /*
+     * Create the template proto-hive.
+     *
+     * Use a dummy root key name:
+     * - On 2k/XP/2k3, this is "$$$PROTO.HIV"
+     * - On Vista+, this is "CMI-CreateHive{guid}"
+     * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc
+     * for more information.
+     */
+    RtlInitUnicodeString(&KeyName,
+                         L"\\Registry\\Machine\\SYSTEM\\$$$PROTO.HIV");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               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 to create the proto-hive (Status %lx)\n", Status);
+        goto Quit;
+    }
+    NtFlushKey(KeyHandle);
+
+    for (i = 0; i < ARRAYSIZE(RegistryKeys); ++i)
+    {
+        Status = CreateRegistryFile(InstallPath,
+                                    RegistryKeys[i],
+                                    KeyHandle);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryKeys[i], Status);
+            /* Exit prematurely here.... */
+            /* That is now done, clean everything up! */
+            NtDeleteKey(KeyHandle);
+            NtClose(KeyHandle);
+            goto Quit;
+        }
+    }
+
+    /* That is now done, clean everything up! */
+    NtDeleteKey(KeyHandle);
+    NtClose(KeyHandle);
+
+
+    /*
+     * Prepare the installation roots. Since we cannot create real registry keys
+     * inside the master keys (\Registry, \Registry\Machine or \Registry\User),
+     * we need to perform some SymLink tricks instead.
+     */
+
+    /* Our offline HKLM '\Registry\Machine' is inside '\Registry\Machine\SYSTEM\USetup_Machine' */
+    RtlInitUnicodeString(&KeyName, RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].MountPoint);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    KeyHandle = NULL;
+    Status = NtCreateKey(&KeyHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName, Status);
+        // return Status;
+    }
+    RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle = KeyHandle;
+
+    /* Our offline HKU '\Registry\User' is inside '\Registry\Machine\SYSTEM\USetup_User' */
+    RtlInitUnicodeString(&KeyName, RootKeys[GetPredefKeyIndex(HKEY_USERS)].MountPoint);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    KeyHandle = NULL;
+    Status = NtCreateKey(&KeyHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName, Status);
+        // return Status;
+    }
+    RootKeys[GetPredefKeyIndex(HKEY_USERS)].Handle = KeyHandle;
+
+
+
+    /*
+     * Now properly mount the offline hive files
+     */
+
+    /* Create SYSTEM key */
+    Status =
+    ConnectRegistry(NULL,
+                    InstallPath,
+                    RegistryKeys[0],
+                    // SystemSecurity, sizeof(SystemSecurity),
+                    L"\\Registry\\Machine\\USetup_SYSTEM");
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ConnectRegistry(SYSTEM) failed, Status 0x%08lx\n", Status);
+    }
+
+    /* Create the 'HKLM\SYSTEM' symlink to this key */
+    if (!CmpLinkKeyToHive(RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
+                          L"SYSTEM",
+                          L"\\Registry\\Machine\\USetup_SYSTEM"))
+    {
+        DPRINT1("CmpLinkKeyToHive(SYSTEM) failed!\n");
+    }
+
+
+    /* Create SOFTWARE key */
+    Status =
+    ConnectRegistry(NULL,
+                    InstallPath,
+                    RegistryKeys[1],
+                    // SoftwareSecurity, sizeof(SoftwareSecurity),
+                    L"\\Registry\\Machine\\USetup_SOFTWARE");
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ConnectRegistry(SOFTWARE) failed, Status 0x%08lx\n", Status);
+    }
+
+    /* Create the 'HKLM\Software' symlink to this key */
+    if (!CmpLinkKeyToHive(RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
+                          L"Software",
+                          L"\\Registry\\Machine\\USetup_SOFTWARE"))
+    {
+        DPRINT1("CmpLinkKeyToHive(SOFTWARE) failed!\n");
+    }
+
+
+    /* Create DEFAULT key */
+    Status =
+    ConnectRegistry(NULL,
+                    InstallPath,
+                    RegistryKeys[2],
+                    // SystemSecurity, sizeof(SystemSecurity),
+                    L"\\Registry\\User\\USetup_DEFAULT");
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("ConnectRegistry(DEFAULT) failed, Status 0x%08lx\n", Status);
+    }
+
+    /* Create the 'HKU\.DEFAULT' symlink to this key */
+    if (!CmpLinkKeyToHive(RootKeys[GetPredefKeyIndex(HKEY_USERS)].Handle,
+                          L".DEFAULT",
+                          L"\\Registry\\User\\USetup_DEFAULT"))
+    {
+        DPRINT1("CmpLinkKeyToHive(DEFAULT) failed!\n");
+    }
+
+    /* HKCU is a handle to 'HKU\.DEFAULT' */
+#if 0
+    RtlInitUnicodeString(&KeyName, L".DEFAULT");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKeys[GetPredefKeyIndex(HKEY_USERS)].Handle,
+                               NULL);
+#else
+    RtlInitUnicodeString(&KeyName, RootKeys[GetPredefKeyIndex(HKEY_CURRENT_USER)].MountPoint);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+#endif
+    KeyHandle = NULL;
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_ALL_ACCESS,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &KeyName, Status);
+    }
+    RootKeys[GetPredefKeyIndex(HKEY_CURRENT_USER)].Handle = KeyHandle;
+
+
+    /* HKCR is a handle to 'HKLM\Software\Classes' */
+#if 0
+    RtlInitUnicodeString(&KeyName, L"Software\\Classes");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
+                               NULL);
+#else
+    RtlInitUnicodeString(&KeyName, RootKeys[GetPredefKeyIndex(HKEY_CLASSES_ROOT)].MountPoint);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+#endif
+    KeyHandle = NULL;
+    Status = NtCreateKey(&KeyHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         0,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateKey(%wZ) failed (Status %lx)\n", &KeyName, Status);
+    }
+    else
+    {
+        DPRINT1("NtCreateKey() succeeded to %s the %wZ key (Status %lx)\n",
+                Disposition == REG_CREATED_NEW_KEY ? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
+                &KeyName, Status);
+    }
+    RootKeys[GetPredefKeyIndex(HKEY_CLASSES_ROOT)].Handle = KeyHandle;
+
+
+#if 0
+    /* Create SAM key */
+    ConnectRegistry(NULL,
+                    &SamHive,
+                    // SystemSecurity, sizeof(SystemSecurity),
+                    L"\\Registry\\Machine\\USetup_SAM");
+
+    /* Create SECURITY key */
+    ConnectRegistry(NULL,
+                    &SecurityHive,
+                    // NULL, 0,
+                    L"\\Registry\\Machine\\USetup_SECURITY");
+
+    /* Create BCD key */
+    ConnectRegistry(NULL,
+                    &BcdHive,
+                    // BcdSecurity, sizeof(BcdSecurity),
+                    L"\\Registry\\Machine\\USetup_BCD00000000");
+#endif
+
+    Status = STATUS_SUCCESS;
+
+
+    /* Create the 'HKLM\SYSTEM\ControlSet001' key */
+    // L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SYSTEM\\ControlSet001"
+    RtlInitUnicodeString(&KeyName, L"SYSTEM\\ControlSet001");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
+                               NULL);
+    Status = NtCreateKey(&KeyHandle,
+                         KEY_ALL_ACCESS,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_NON_VOLATILE,
+                         &Disposition);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateKey() failed to create the ControlSet001 key (Status %lx)\n", Status);
+        // return Status;
+    }
+    else
+    {
+        DPRINT1("NtCreateKey() succeeded to %s the ControlSet001 key (Status %lx)\n",
+                Disposition == REG_CREATED_NEW_KEY ? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
+                Status);
+    }
+    NtClose(KeyHandle);
+
+    /* Create the 'HKLM\SYSTEM\CurrentControlSet' symlink */
+    if (!CmpLinkKeyToHive(RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
+                          L"SYSTEM\\CurrentControlSet",
+                          L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SYSTEM\\ControlSet001"))
+    {
+        DPRINT1("CmpLinkKeyToHive(CurrentControlSet) failed!\n");
+    }
+
+
+Quit:
+    /* Remove restore and backup privileges */
+    RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, PrivilegeSet[1], FALSE, &PrivilegeSet[1]);
+    RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
+
+    return Status;
+}
+
+VOID
+RegCleanupRegistry(VOID)
+{
+    NTSTATUS Status;
+    UNICODE_STRING KeyName;
+    OBJECT_ATTRIBUTES KeyObjectAttributes;
+    BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
+    UCHAR i;
+
+    for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
+    {
+        if (RootKeys[i].Handle)
+        {
+            NtClose(RootKeys[i].Handle);
+            RootKeys[i].Handle = NULL;
+        }
+    }
+
+    /* Acquire restore privilege */
+    Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status);
+        /* Exit prematurely here.... */
+        return;
+    }
+
+    /* Acquire backup privilege */
+    Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[1]);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status);
+        RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
+        /* Exit prematurely here.... */
+        return;
+    }
+
+    InitializeObjectAttributes(&KeyObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_SYSTEM");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_SOFTWARE");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\User\\USetup_DEFAULT");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+
+#if 0
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_SAM");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_SECURITY");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_BCD00000000");
+    Status = NtUnloadKey(&KeyObjectAttributes);
+#endif
+
+    /* Remove restore and backup privileges */
+    RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, PrivilegeSet[1], FALSE, &PrivilegeSet[1]);
+    RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
+}
 
 VOID
 SetDefaultPagefile(
     WCHAR Drive)
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
+    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
     UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"PagingFiles");
     WCHAR ValueBuffer[] = L"?:\\pagefile.sys 0 0\0";
     HANDLE KeyHandle;
@@ -636,7 +1259,7 @@ SetDefaultPagefile(
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               RootKeys[GetPredefKeyIndex(HKEY_LOCAL_MACHINE)].Handle,
                                NULL);
     Status = NtOpenKey(&KeyHandle,
                        KEY_ALL_ACCESS,
index 5064bb9..c97d897 100644 (file)
 
 #pragma once
 
+HANDLE
+GetRootKeyByPredefKey(
+    IN HANDLE KeyHandle,
+    OUT PCWSTR* RootKeyMountPoint OPTIONAL);
+
+HANDLE
+GetRootKeyByName(
+    IN PCWSTR RootKeyName,
+    OUT PCWSTR* RootKeyMountPoint OPTIONAL);
+
 BOOLEAN
 ImportRegistryFile(
     PWSTR Filename,
@@ -33,9 +43,12 @@ ImportRegistryFile(
     LCID LocaleId,
     BOOLEAN Delete);
 
-BOOLEAN
-SetInstallPathValue(
-    PUNICODE_STRING InstallPath);
+NTSTATUS
+RegInitializeRegistry(
+    IN PUNICODE_STRING InstallPath);
+
+VOID
+RegCleanupRegistry(VOID);
 
 VOID
 SetDefaultPagefile(
index a6dc2ed..d358f85 100644 (file)
@@ -214,7 +214,7 @@ GetComputerIdentifier(
                                NULL);
 
     Status = NtOpenKey(&ProcessorsKey,
-                       KEY_QUERY_VALUE ,
+                       KEY_QUERY_VALUE,
                        &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
@@ -676,14 +676,17 @@ ProcessDisplayRegistry(
     HINF InfFile,
     PGENERIC_LIST List)
 {
+    NTSTATUS Status;
     PGENERIC_LIST_ENTRY Entry;
     INFCONTEXT Context;
+    PWCHAR Buffer;
     PWCHAR ServiceName;
     ULONG StartValue;
-    NTSTATUS Status;
-    WCHAR RegPath [255];
-    PWCHAR Buffer;
     ULONG Width, Height, Bpp;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING KeyName;
+    HANDLE KeyHandle;
+    WCHAR RegPath[255];
 
     DPRINT("ProcessDisplayRegistry() called\n");
 
@@ -700,7 +703,7 @@ ProcessDisplayRegistry(
         return FALSE;
     }
 
-    /* Enable the right driver */
+    /* Enable the correct driver */
     if (!INF_GetDataField(&Context, 3, &ServiceName))
     {
         DPRINT1("INF_GetDataField() failed\n");
@@ -708,15 +711,31 @@ ProcessDisplayRegistry(
     }
 
     ASSERT(wcslen(ServiceName) < 10);
-    DPRINT("Service name: %S\n", ServiceName);
+    DPRINT1("Service name: '%S'\n", ServiceName);
+
+    swprintf(RegPath, L"System\\CurrentControlSet\\Services\\%s", ServiceName);
+    RtlInitUnicodeString(&KeyName, RegPath);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
+                               NULL);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_SET_VALUE,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
+        return FALSE;
+    }
 
     StartValue = 1;
-    Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
-                                   ServiceName,
+    Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, KeyHandle,
                                    L"Start",
                                    REG_DWORD,
                                    &StartValue,
-                                   sizeof(ULONG));
+                                   sizeof(StartValue));
+    NtClose(KeyHandle);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
@@ -724,7 +743,6 @@ ProcessDisplayRegistry(
     }
 
     /* Set the resolution */
-    swprintf(RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName);
 
     if (!INF_GetDataField(&Context, 4, &Buffer))
     {
@@ -732,57 +750,80 @@ ProcessDisplayRegistry(
         return FALSE;
     }
 
+    swprintf(RegPath,
+             L"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0",
+             ServiceName);
+    DPRINT1("RegPath: '%S'\n", RegPath);
+    RtlInitUnicodeString(&KeyName, RegPath);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
+                               NULL);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_SET_VALUE,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
+        return FALSE;
+    }
+
     Width = wcstoul(Buffer, NULL, 10);
-    Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-                                   RegPath,
+    Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, KeyHandle,
                                    L"DefaultSettings.XResolution",
                                    REG_DWORD,
                                    &Width,
-                                   sizeof(ULONG));
+                                   sizeof(Width));
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
+        NtClose(KeyHandle);
         return FALSE;
     }
 
     if (!INF_GetDataField(&Context, 5, &Buffer))
     {
         DPRINT1("INF_GetDataField() failed\n");
+        NtClose(KeyHandle);
         return FALSE;
     }
 
     Height = wcstoul(Buffer, 0, 0);
-    Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-                                   RegPath,
+    Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, KeyHandle,
                                    L"DefaultSettings.YResolution",
                                    REG_DWORD,
                                    &Height,
-                                   sizeof(ULONG));
+                                   sizeof(Height));
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
+        NtClose(KeyHandle);
         return FALSE;
     }
 
     if (!INF_GetDataField(&Context, 6, &Buffer))
     {
         DPRINT1("INF_GetDataField() failed\n");
+        NtClose(KeyHandle);
         return FALSE;
     }
 
     Bpp = wcstoul(Buffer, 0, 0);
-    Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
-                                   RegPath,
+    Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, KeyHandle,
                                    L"DefaultSettings.BitsPerPel",
                                    REG_DWORD,
                                    &Bpp,
-                                   sizeof(ULONG));
+                                   sizeof(Bpp));
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
+        NtClose(KeyHandle);
         return FALSE;
     }
 
+    NtClose(KeyHandle);
+
     DPRINT("ProcessDisplayRegistry() done\n");
 
     return TRUE;
@@ -814,17 +855,17 @@ ProcessLocaleRegistry(
 
     /* Open the default users locale key */
     RtlInitUnicodeString(&KeyName,
-                         L"\\Registry\\User\\.DEFAULT\\Control Panel\\International");
+                         L".DEFAULT\\Control Panel\\International");
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
 
-    Status =  NtOpenKey(&KeyHandle,
-                        KEY_SET_VALUE,
-                        &ObjectAttributes);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_SET_VALUE,
+                       &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
@@ -832,8 +873,7 @@ ProcessLocaleRegistry(
     }
 
     /* Set default user locale */
-    RtlInitUnicodeString(&ValueName,
-                         L"Locale");
+    RtlInitUnicodeString(&ValueName, L"Locale");
     Status = NtSetValueKey(KeyHandle,
                            &ValueName,
                            0,
@@ -853,17 +893,17 @@ ProcessLocaleRegistry(
 
     /* Open the NLS language key */
     RtlInitUnicodeString(&KeyName,
-                         L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
+                         L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
 
     InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_LOCAL_MACHINE, NULL),
                                NULL);
 
-    Status =  NtOpenKey(&KeyHandle,
-                        KEY_SET_VALUE,
-                        &ObjectAttributes);
+    Status = NtOpenKey(&KeyHandle,
+                       KEY_SET_VALUE,
+                       &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
@@ -871,8 +911,7 @@ ProcessLocaleRegistry(
     }
 
     /* Set default language */
-    RtlInitUnicodeString(&ValueName,
-                         L"Default");
+    RtlInitUnicodeString(&ValueName, L"Default");
     Status = NtSetValueKey(KeyHandle,
                            &ValueName,
                            0,
@@ -887,14 +926,13 @@ ProcessLocaleRegistry(
     }
 
     /* Set install language */
-    RtlInitUnicodeString(&ValueName,
-                         L"InstallLanguage");
-    Status = NtSetValueKey (KeyHandle,
-                            &ValueName,
-                            0,
-                            REG_SZ,
-                            (PVOID)LanguageId,
-                            (wcslen(LanguageId) + 1) * sizeof(WCHAR));
+    RtlInitUnicodeString(&ValueName, L"InstallLanguage");
+    Status = NtSetValueKey(KeyHandle,
+                           &ValueName,
+                           0,
+                           REG_SZ,
+                           (PVOID)LanguageId,
+                           (wcslen(LanguageId) + 1) * sizeof(WCHAR));
     NtClose(KeyHandle);
     if (!NT_SUCCESS(Status))
     {
@@ -1191,22 +1229,18 @@ BOOLEAN
 SetGeoID(
     PWCHAR Id)
 {
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING KeyName;
-    UNICODE_STRING ValueName;
+    UNICODE_STRING Name;
     HANDLE KeyHandle;
-    WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
-    WCHAR szValueName[] = L"Nation";
-    NTSTATUS Status;
 
-    RtlInitUnicodeString(&KeyName,
-                         szKeyName);
+    RtlInitUnicodeString(&Name,
+                         L".DEFAULT\\Control Panel\\International\\Geo");
     InitializeObjectAttributes(&ObjectAttributes,
-                               &KeyName,
+                               &Name,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,
+                               GetRootKeyByPredefKey(HKEY_USERS, NULL),
                                NULL);
-
     Status =  NtOpenKey(&KeyHandle,
                         KEY_SET_VALUE,
                         &ObjectAttributes);
@@ -1216,9 +1250,9 @@ SetGeoID(
         return FALSE;
     }
 
-    RtlInitUnicodeString(&ValueName, szValueName);
+    RtlInitUnicodeString(&Name, L"Nation");
     Status = NtSetValueKey(KeyHandle,
-                           &ValueName,
+                           &Name,
                            0,
                            REG_SZ,
                            (PVOID)Id,
index 9170b23..4eb2558 100644 (file)
@@ -816,9 +816,9 @@ SetupStartPage(PINPUT_RECORD Ir)
         MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
-    DPRINT1("SourcePath: '%wZ'", &SourcePath);
-    DPRINT1("SourceRootPath: '%wZ'", &SourceRootPath);
-    DPRINT1("SourceRootDir: '%wZ'", &SourceRootDir);
+    DPRINT1("SourcePath: '%wZ'\n", &SourcePath);
+    DPRINT1("SourceRootPath: '%wZ'\n", &SourceRootPath);
+    DPRINT1("SourceRootDir: '%wZ'\n", &SourceRootDir);
 
     /* Load txtsetup.sif from install media. */
     CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2, SourcePath.Buffer, L"txtsetup.sif");
@@ -4046,8 +4046,7 @@ FileCopyPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Calls SetInstallPathValue
- *  Calls NtInitializeRegistry
+ *  Calls RegInitializeRegistry
  *  Calls ImportRegistryFile
  *  Calls SetDefaultPagefile
  *  Calls SetMountedDeviceValues
@@ -4074,21 +4073,23 @@ RegistryPage(PINPUT_RECORD Ir)
         return SUCCESS_PAGE;
     }
 
-    /************************ HACK!!!!!!!!!!! *********************************/
-    if (!SetInstallPathValue(&DestinationPath))
-    {
-        DPRINT1("SetInstallPathValue() failed\n");
-        MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-    /************************ HACK!!!!!!!!!!! *********************************/
-
-    /* Create the default hives */
-    Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
+    /* Initialize the registry and setup the default installation hives */
+    Status = RegInitializeRegistry(&DestinationPath);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status);
-        MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
+        DPRINT1("RegInitializeRegistry() failed\n");
+        /********** HACK!!!!!!!!!!! **********/
+        if (Status == STATUS_NOT_IMPLEMENTED)
+        {
+            /* The hack was called, display its corresponding error */
+            MUIDisplayError(ERROR_INITIALIZE_REGISTRY, Ir, POPUP_WAIT_ENTER);
+        }
+        else
+        /*************************************/
+        {
+            /* Something else (correct) failed */
+            MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
+        }
         return QUIT_PAGE;
     }
 
@@ -4098,6 +4099,7 @@ RegistryPage(PINPUT_RECORD Ir)
     if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
     {
         DPRINT1("SetupFindFirstLine() failed\n");
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4132,6 +4134,7 @@ RegistryPage(PINPUT_RECORD Ir)
         {
             DPRINT1("Importing %S failed\n", File);
 
+            RegCleanupRegistry();
             MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
@@ -4141,6 +4144,7 @@ RegistryPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
     if (!ProcessDisplayRegistry(SetupInf, DisplayList))
     {
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4149,6 +4153,7 @@ RegistryPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
     if (!ProcessLocaleRegistry(LanguageList))
     {
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4157,6 +4162,7 @@ RegistryPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
     if (!AddKeyboardLayouts())
     {
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4164,6 +4170,7 @@ RegistryPage(PINPUT_RECORD Ir)
     /* Set GeoID */
     if (!SetGeoID(MUIGetGeoID()))
     {
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4174,6 +4181,7 @@ RegistryPage(PINPUT_RECORD Ir)
         CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
         if (!ProcessKeyboardLayoutRegistry(LayoutList))
         {
+            RegCleanupRegistry();
             MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
@@ -4183,6 +4191,7 @@ RegistryPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
     if (!AddCodePage())
     {
+        RegCleanupRegistry();
         MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
@@ -4193,6 +4202,12 @@ RegistryPage(PINPUT_RECORD Ir)
     /* Update the mounted devices list */
     SetMountedDeviceValues(PartitionList);
 
+    //
+    // TODO: Unload all the registry stuff, perform cleanup,
+    // and copy the created hive files into .sav ones.
+    //
+    RegCleanupRegistry();
+
     CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
 
     return BOOT_LOADER_PAGE;
@@ -4211,8 +4226,7 @@ RegistryPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Calls SetInstallPathValue
- *  Calls NtInitializeRegistry
+ *  Calls RegInitializeRegistry
  *  Calls ImportRegistryFile
  *  Calls SetDefaultPagefile
  *  Calls SetMountedDeviceValues
@@ -4865,12 +4879,10 @@ RunUSetup(VOID)
 
     InfSetHeap(ProcessHeap);
 
-#if 0
     /* Tell the Cm this is a setup boot, and it has to behave accordingly */
     Status = NtInitializeRegistry(CM_BOOT_FLAG_SETUP);
     if (!NT_SUCCESS(Status))
         DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
-#endif
 
     /* Create the PnP thread in suspended state */
     Status = RtlCreateUserThread(NtCurrentProcess(),