[USETUP] More code for updating/repairing the registry. Fix the name of the txtsetup...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 22 Jun 2017 00:38:32 +0000 (00:38 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 24 Oct 2018 23:00:43 +0000 (01:00 +0200)
[BOOTDATA] Add needed entries in txtsetup.sif for registry upgrade.

svn path=/branches/setup_improvements/; revision=75162
svn path=/branches/setup_improvements/; revision=75226

base/setup/usetup/registry.c
base/setup/usetup/registry.h
base/setup/usetup/usetup.c
boot/bootdata/txtsetup.sif

index bb79689..50fbb31 100644 (file)
@@ -750,7 +750,7 @@ CreateRegistryFile(
     InitializeObjectAttributes(&ObjectAttributes,
                                &FileName,
                                OBJ_CASE_INSENSITIVE,
-                               NULL,  // Could have been installpath, etc...
+                               NULL,  // Could have been InstallPath, etc...
                                NULL); // Descriptor
 
     Status = NtCreateFile(&FileHandle,
@@ -902,7 +902,7 @@ VerifyRegistryHive(
 {
     NTSTATUS Status;
     UNICODE_STRING KeyName;
-    OBJECT_ATTRIBUTES KeyObjectAttributes;
+    OBJECT_ATTRIBUTES ObjectAttributes;
 
     /* Try to mount the specified registry hive */
     Status = ConnectRegistry(NULL,
@@ -937,14 +937,14 @@ VerifyRegistryHive(
         DPRINT1("VerifyRegistryHive: Registry hive %S succeeded recovered (Status 0x%08lx)\n", RegistryKey, Status);
 
     /* Unmount the hive */
-    InitializeObjectAttributes(&KeyObjectAttributes,
+    InitializeObjectAttributes(&ObjectAttributes,
                                &KeyName,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL);
 
     RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\USetup_VerifyHive");
-    Status = NtUnloadKey(&KeyObjectAttributes);
+    Status = NtUnloadKey(&ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtUnloadKey(%S, %wZ) failed, Status 0x%08lx\n", RegistryKey, &KeyName, Status);
@@ -998,14 +998,14 @@ C_ASSERT(_countof(SecurityRegistryHives) == NUMBER_OF_SECURITY_REGISTRY_HIVES);
 NTSTATUS
 VerifyRegistryHives(
     IN PUNICODE_STRING InstallPath,
-    OUT PBOOLEAN ShouldUpdateRegistry)
+    OUT PBOOLEAN ShouldRepairRegistry)
 {
     NTSTATUS Status;
     BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
     UINT i;
 
-    /* Suppose first the registry hives do not have to be updated/recreated */
-    *ShouldUpdateRegistry = FALSE;
+    /* Suppose first the registry hives do not have to be fully recreated */
+    *ShouldRepairRegistry = FALSE;
 
     /* Acquire restore privilege */
     Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &PrivilegeSet[0]);
@@ -1033,7 +1033,7 @@ VerifyRegistryHives(
         {
             DPRINT1("Registry hive '%S' needs repair!\n", RegistryHives[i].HiveName);
             RegistryHives[i].State = Repair;
-            *ShouldUpdateRegistry = TRUE;
+            *ShouldRepairRegistry = TRUE;
         }
         else
         {
@@ -1145,14 +1145,14 @@ RegInitializeRegistry(
         {
             DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryHives[i].HiveName, Status);
             /* Exit prematurely here.... */
-            /* That is now done, clean everything up! */
+            /* That is now done, remove the proto-hive */
             NtDeleteKey(KeyHandle);
             NtClose(KeyHandle);
             goto Quit;
         }
     }
 
-    /* That is now done, clean everything up! */
+    /* That is now done, remove the proto-hive */
     NtDeleteKey(KeyHandle);
     NtClose(KeyHandle);
 
@@ -1238,7 +1238,7 @@ RegInitializeRegistry(
         }
         else
         {
-            /* Create *DUMMY* volatile hives just to make the update procedure work */
+            /* Create *DUMMY* volatile hives just to make the update procedure working */
 
             RtlInitUnicodeString(&KeyName, RegistryHives[i].RegSymLink);
             InitializeObjectAttributes(&ObjectAttributes,
@@ -1385,23 +1385,14 @@ RegCleanupRegistry(
     IN PUNICODE_STRING InstallPath)
 {
     NTSTATUS Status;
+    HANDLE KeyHandle;
     UNICODE_STRING KeyName;
-    OBJECT_ATTRIBUTES KeyObjectAttributes;
+    OBJECT_ATTRIBUTES ObjectAttributes;
     BOOLEAN PrivilegeSet[2] = {FALSE, FALSE};
     UINT i;
     WCHAR SrcPath[MAX_PATH];
     WCHAR DstPath[MAX_PATH];
 
-    for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
-    {
-        if (RootKeys[i].Handle)
-        {
-            NtFlushKey(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))
@@ -1421,20 +1412,68 @@ RegCleanupRegistry(
         return;
     }
 
-    InitializeObjectAttributes(&KeyObjectAttributes,
-                               &KeyName,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
+    /*
+     * Note that we don't need to explicitly remove the symlinks we have created
+     * since they are created volatile, inside registry keys that will be however
+     * removed explictly in the following.
+     */
 
     for (i = 0; i < ARRAYSIZE(RegistryHives); ++i)
     {
         if (RegistryHives[i].State != Create && RegistryHives[i].State != Repair)
-            continue;
+        {
+            RtlInitUnicodeString(&KeyName, RegistryHives[i].RegSymLink);
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &KeyName,
+                                       OBJ_CASE_INSENSITIVE,
+                                       RootKeys[GetPredefKeyIndex(RegistryHives[i].PredefKeyHandle)].Handle,
+                                       NULL);
+            KeyHandle = NULL;
+            Status = NtOpenKey(&KeyHandle,
+                               DELETE,
+                               &ObjectAttributes);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("NtOpenKey(%wZ) failed, Status 0x%08lx\n", &KeyName, Status);
+                // return;
+            }
+
+            NtDeleteKey(KeyHandle);
+            NtClose(KeyHandle);
+        }
+        else
+        {
+            RtlInitUnicodeString(&KeyName, RegistryHives[i].HiveRegistryPath);
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &KeyName,
+                                       OBJ_CASE_INSENSITIVE,
+                                       NULL,
+                                       NULL);
+            // Status = NtUnloadKey(&ObjectAttributes);
+            Status = NtUnloadKey2(&ObjectAttributes, 1 /* REG_FORCE_UNLOAD */);
+            DPRINT1("Unmounting '%S' %s\n", RegistryHives[i].HiveRegistryPath, NT_SUCCESS(Status) ? "succeeded" : "failed");
 
-        RtlInitUnicodeString(&KeyName, RegistryHives[i].HiveRegistryPath);
-        Status = NtUnloadKey(&KeyObjectAttributes);
-        DPRINT1("Unmounting '%S' %s\n", RegistryHives[i].HiveRegistryPath, NT_SUCCESS(Status) ? "succeeded" : "failed");
+            /* Switch the hive state to 'Update' */
+            RegistryHives[i].State = Update;
+        }
+    }
+
+    /*
+     * FIXME: Once force-unloading keys is correctly fixed, I'll fix
+     * this code that closes some of the registry keys that were opened
+     * inside the hives we've just unmounted above...
+     */
+
+    /* Remove the registry root keys */
+    for (i = 0; i < ARRAYSIZE(RootKeys); ++i)
+    {
+        if (RootKeys[i].Handle)
+        {
+            /**/NtFlushKey(RootKeys[i].Handle);/**/ // FIXME: Why does it hang? Answer: because we have some problems in CMAPI!
+            NtDeleteKey(RootKeys[i].Handle);
+            NtClose(RootKeys[i].Handle);
+            RootKeys[i].Handle = NULL;
+        }
     }
 
     //
@@ -1465,6 +1504,7 @@ RegCleanupRegistry(
     RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, PrivilegeSet[0], FALSE, &PrivilegeSet[0]);
 }
 
+
 VOID
 SetDefaultPagefile(
     WCHAR Drive)
index cae50e8..0548061 100644 (file)
@@ -46,7 +46,7 @@ ImportRegistryFile(
 NTSTATUS
 VerifyRegistryHives(
     IN PUNICODE_STRING InstallPath,
-    OUT PBOOLEAN ShouldUpdateRegistry);
+    OUT PBOOLEAN ShouldRepairRegistry);
 
 NTSTATUS
 RegInitializeRegistry(
index 80d6345..a8e7267 100644 (file)
@@ -4079,32 +4079,32 @@ RegistryPage(PINPUT_RECORD Ir)
     PWSTR Action;
     PWSTR File;
     PWSTR Section;
+    BOOLEAN Success;
+    BOOLEAN ShouldRepairRegistry = FALSE;
     BOOLEAN Delete;
 
     MUIDisplayPage(REGISTRY_PAGE);
 
     if (RepairUpdateFlag)
     {
-        BOOLEAN ShouldUpdateRegistry = FALSE;
-
         DPRINT1("TODO: Updating / repairing the registry is not completely implemented yet!\n");
 
         /* Verify the registry hives and check whether we need to update or repair any of them */
-        Status = VerifyRegistryHives(&DestinationPath, &ShouldUpdateRegistry);
+        Status = VerifyRegistryHives(&DestinationPath, &ShouldRepairRegistry);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status);
-            ShouldUpdateRegistry = FALSE;
-        }
-        if (!ShouldUpdateRegistry)
-        {
-            DPRINT1("No need to update the registry\n");
-            // return SUCCESS_PAGE;
-            goto Quit;
+            ShouldRepairRegistry = FALSE;
         }
+        if (!ShouldRepairRegistry)
+            DPRINT1("No need to repair the registry\n");
     }
 
-    /* Initialize the registry and setup the default installation hives */
+DoUpdate:
+    /* Update the registry */
+    CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
+
+    /* Initialize the registry and setup the registry hives */
     Status = RegInitializeRegistry(&DestinationPath);
     if (!NT_SUCCESS(Status))
     {
@@ -4124,14 +4124,41 @@ RegistryPage(PINPUT_RECORD Ir)
         return QUIT_PAGE;
     }
 
-    /* Update registry */
-    CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
+    if (!RepairUpdateFlag || ShouldRepairRegistry)
+    {
+        /*
+         * We fully setup the hives, in case we are doing a fresh installation
+         * (RepairUpdateFlag == FALSE), or in case we are doing an update
+         * (RepairUpdateFlag == TRUE) BUT we have some registry hives to
+         * "repair" (aka. recreate: ShouldRepairRegistry == TRUE).
+         */
+
+        Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Fresh", NULL, &InfContext);       // Windows-compatible
+        if (!Success)
+            Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext); // ReactOS-specific
 
-    if (!SetupFindFirstLineW(SetupInf, L"HiveInfs.Install", NULL, &InfContext))
+        if (!Success)
+        {
+            DPRINT1("SetupFindFirstLine() failed\n");
+            MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
+            goto Cleanup;
+        }
+    }
+    else // if (RepairUpdateFlag && !ShouldRepairRegistry)
     {
-        DPRINT1("SetupFindFirstLine() failed\n");
-        MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
+        /*
+         * In case we are doing an update (RepairUpdateFlag == TRUE) and
+         * NO registry hives need a repair (ShouldRepairRegistry == FALSE),
+         * we only update the hives.
+         */
+
+        Success = SetupFindFirstLineW(SetupInf, L"HiveInfs.Upgrade", NULL, &InfContext);
+        if (!Success)
+        {
+            /* Nothing to do for update! */
+            DPRINT1("No update needed for the registry!\n");
+            goto Cleanup;
+        }
     }
 
     do
@@ -4150,7 +4177,10 @@ RegistryPage(PINPUT_RECORD Ir)
         else if (!_wcsicmp(Action, L"DelReg"))
             Delete = TRUE;
         else
+        {
+            DPRINT1("Unrecognized registry INF action '%S'\n", Action);
             continue;
+        }
 
         CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
 
@@ -4162,62 +4192,67 @@ RegistryPage(PINPUT_RECORD Ir)
         }
     } while (SetupFindNextLine(&InfContext, &InfContext));
 
-    /* Update display registry settings */
-    CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
-    if (!ProcessDisplayRegistry(SetupInf, DisplayList))
+    if (!RepairUpdateFlag || ShouldRepairRegistry)
     {
-        MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
-    }
+        /* See the explanation for this test above */
 
-    /* Set the locale */
-    CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
-    if (!ProcessLocaleRegistry(LanguageList))
-    {
-        MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
-    }
+        /* Update display registry settings */
+        CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYETTINGSUPDATE));
+        if (!ProcessDisplayRegistry(SetupInf, DisplayList))
+        {
+            MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, Ir, POPUP_WAIT_ENTER);
+            goto Cleanup;
+        }
 
-    /* Add keyboard layouts */
-    CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
-    if (!AddKeyboardLayouts())
-    {
-        MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
-    }
+        /* Set the locale */
+        CONSOLE_SetStatusText(MUIGetString(STRING_LOCALESETTINGSUPDATE));
+        if (!ProcessLocaleRegistry(LanguageList))
+        {
+            MUIDisplayError(ERROR_UPDATE_LOCALESETTINGS, Ir, POPUP_WAIT_ENTER);
+            goto Cleanup;
+        }
 
-    /* Set GeoID */
-    if (!SetGeoID(MUIGetGeoID()))
-    {
-        MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
-    }
+        /* Add keyboard layouts */
+        CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
+        if (!AddKeyboardLayouts())
+        {
+            MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
+            goto Cleanup;
+        }
 
-    if (!IsUnattendedSetup)
-    {
-        /* Update keyboard layout settings */
-        CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
-        if (!ProcessKeyboardLayoutRegistry(LayoutList))
+        /* Set GeoID */
+        if (!SetGeoID(MUIGetGeoID()))
         {
-            MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
+            MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
             goto Cleanup;
         }
-    }
 
-    /* Add codepage information to registry */
-    CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
-    if (!AddCodePage())
-    {
-        MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
-        goto Cleanup;
-    }
+        if (!IsUnattendedSetup)
+        {
+            /* Update keyboard layout settings */
+            CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
+            if (!ProcessKeyboardLayoutRegistry(LayoutList))
+            {
+                MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
+                goto Cleanup;
+            }
+        }
+
+        /* Add codepage information to registry */
+        CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
+        if (!AddCodePage())
+        {
+            MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
+            goto Cleanup;
+        }
 
-    /* Set the default pagefile entry */
-    SetDefaultPagefile(DestinationDriveLetter);
+        /* Set the default pagefile entry */
+        SetDefaultPagefile(DestinationDriveLetter);
 
-    /* Update the mounted devices list */
-    // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
-    SetMountedDeviceValues(PartitionList);
+        /* Update the mounted devices list */
+        // FIXME: This should technically be done by mountmgr (if AutoMount is enabled)!
+        SetMountedDeviceValues(PartitionList);
+    }
 
 Cleanup:
     //
@@ -4226,7 +4261,18 @@ Cleanup:
     //
     RegCleanupRegistry(&DestinationPath);
 
-Quit:
+    /*
+     * Check whether we were in update/repair mode but we were actually
+     * repairing the registry hives. If so, we have finished repairing them,
+     * and we now reset the flag and run the proper registry update.
+     * Otherwise we have finished the registry update!
+     */
+    if (RepairUpdateFlag && ShouldRepairRegistry)
+    {
+        ShouldRepairRegistry = FALSE;
+        goto DoUpdate;
+    }
+
     if (NT_SUCCESS(Status))
     {
         CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
index ba2db10..f7f44d8 100644 (file)
@@ -524,7 +524,12 @@ Default = "XT-, AT- or extended keyboard (83-105 keys)"
 0000048F = kbdeo.dll
 
 [HiveInfs.Install]
-AddReg=caroots.inf,AddReg
-AddReg=registry.inf,AddReg
+; Called "HiveInfs.Fresh" on Windows
+AddReg = caroots.inf,AddReg
+AddReg = registry.inf,AddReg
+
+[HiveInfs.Upgrade]
+DelReg = registry.inf,DelReg
+AddReg = registry.inf,AddReg
 
 ; EOF