[SETUPLIB][USETUP] Remove the deprecated GenericListHasSingleEntry() function and...
[reactos.git] / base / setup / usetup / usetup.c
index f29935b..46cb244 100644 (file)
@@ -36,9 +36,6 @@
 #define NDEBUG
 #include <debug.h>
 
-// HACK!
-#include <strsafe.h>
-
 
 /* GLOBALS & LOCALS *********************************************************/
 
@@ -59,7 +56,7 @@ static WCHAR DestinationDriveLetter;
 
 /* OTHER Stuff *****/
 
-PWCHAR SelectedLanguageId;
+PCWSTR SelectedLanguageId;
 static WCHAR DefaultLanguage[20];   // Copy of string inside LanguageList
 static WCHAR DefaultKBLayout[20];   // Copy of string inside KeyboardList
 
@@ -417,25 +414,63 @@ UpdateKBLayout(VOID)
         }
     }
 
-    ListEntry = GetFirstListEntry(LayoutList);
-
     /* Search for default layout (if provided) */
     if (pszNewLayout != NULL)
     {
-        while (ListEntry != NULL)
+        for (ListEntry = GetFirstListEntry(LayoutList); ListEntry;
+             ListEntry = GetNextListEntry(ListEntry))
         {
-            if (!wcscmp(pszNewLayout, GetListEntryUserData(ListEntry)))
+            if (!wcscmp(pszNewLayout, ((PGENENTRY)GetListEntryData(ListEntry))->Id))
             {
                 SetCurrentListEntry(LayoutList, ListEntry);
                 break;
             }
-
-            ListEntry = GetNextListEntry(ListEntry);
         }
     }
 }
 
 
+static NTSTATUS
+NTAPI
+GetSettingDescription(
+    IN PGENERIC_LIST_ENTRY Entry,
+    OUT PSTR Buffer,
+    IN SIZE_T cchBufferSize)
+{
+    return RtlStringCchPrintfA(Buffer, cchBufferSize, "%S",
+                               ((PGENENTRY)GetListEntryData(Entry))->Value);
+}
+
+static NTSTATUS
+NTAPI
+GetNTOSInstallationName(
+    IN PGENERIC_LIST_ENTRY Entry,
+    OUT PSTR Buffer,
+    IN SIZE_T cchBufferSize)
+{
+    PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
+    PPARTENTRY PartEntry = NtOsInstall->PartEntry;
+
+    if (PartEntry && PartEntry->DriveLetter)
+    {
+        /* We have retrieved a partition that is mounted */
+        return RtlStringCchPrintfA(Buffer, cchBufferSize,
+                                   "%c:%S  \"%S\"",
+                                   PartEntry->DriveLetter,
+                                   NtOsInstall->PathComponent,
+                                   NtOsInstall->InstallationName);
+    }
+    else
+    {
+        /* We failed somewhere, just show the NT path */
+        return RtlStringCchPrintfA(Buffer, cchBufferSize,
+                                   "%wZ  \"%S\"",
+                                   &NtOsInstall->SystemNtPath,
+                                   NtOsInstall->InstallationName);
+    }
+}
+
+
 /*
  * Displays the LanguagePage.
  *
@@ -452,7 +487,7 @@ static PAGE_NUMBER
 LanguagePage(PINPUT_RECORD Ir)
 {
     GENERIC_LIST_UI ListUi;
-    PWCHAR NewLanguageId;
+    PCWSTR NewLanguageId;
     BOOL RefreshPage = FALSE;
 
     /* Initialize the computer settings list */
@@ -473,18 +508,19 @@ LanguagePage(PINPUT_RECORD Ir)
     SetConsoleCodePage();
     UpdateKBLayout();
 
-    /* If there's just a single language in the list skip
-     * the language selection process altogether! */
-    if (GenericListHasSingleEntry(LanguageList))
+    /*
+     * If there is no language or just a single one in the list,
+     * skip the language selection process altogether.
+     */
+    if (GetNumberOfListEntries(LanguageList) <= 1)
     {
         USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
         return WELCOME_PAGE;
     }
 
-    InitGenericListUi(&ListUi, LanguageList);
+    InitGenericListUi(&ListUi, LanguageList, GetSettingDescription);
     DrawGenericList(&ListUi,
-                    2,
-                    18,
+                    2, 18,
                     xScreen - 3,
                     yScreen - 3);
 
@@ -530,7 +566,10 @@ LanguagePage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)  /* ENTER */
         {
-            SelectedLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
+            ASSERT(GetNumberOfListEntries(LanguageList) >= 1);
+
+            SelectedLanguageId =
+                ((PGENENTRY)GetListEntryData(GetCurrentListEntry(LanguageList)))->Id;
 
             USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
 
@@ -553,7 +592,10 @@ LanguagePage(PINPUT_RECORD Ir)
 
         if (RefreshPage)
         {
-            NewLanguageId = (PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
+            ASSERT(GetNumberOfListEntries(LanguageList) >= 1);
+
+            NewLanguageId =
+                ((PGENENTRY)GetListEntryData(GetCurrentListEntry(LanguageList)))->Id;
 
             if (wcscmp(SelectedLanguageId, NewLanguageId))
             {
@@ -606,6 +648,7 @@ SetupStartPage(PINPUT_RECORD Ir)
     NTSTATUS Status;
     ULONG Error;
     PGENERIC_LIST_ENTRY ListEntry;
+    PCWSTR LocaleId;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
@@ -643,6 +686,8 @@ SetupStartPage(PINPUT_RECORD Ir)
     if (IsUnattendedSetup)
     {
         // TODO: Read options from inf
+        /* Load the hardware, language and keyboard layout lists */
+
         ComputerList = CreateComputerTypeList(SetupInf);
         DisplayList = CreateDisplayDriverList(SetupInf);
         KeyboardList = CreateKeyboardDriverList(SetupInf);
@@ -651,37 +696,35 @@ SetupStartPage(PINPUT_RECORD Ir)
 
         /* new part */
         SelectedLanguageId = DefaultLanguage;
-        wcscpy(SelectedLanguageId, USetupData.LocaleID);
+        wcscpy(DefaultLanguage, USetupData.LocaleID);
         USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
 
         LayoutList = CreateKeyboardLayoutList(SetupInf, SelectedLanguageId, DefaultKBLayout);
 
         /* first we hack LanguageList */
-        ListEntry = GetFirstListEntry(LanguageList);
-        while (ListEntry != NULL)
+        for (ListEntry = GetFirstListEntry(LanguageList); ListEntry;
+             ListEntry = GetNextListEntry(ListEntry))
         {
-            if (!wcsicmp(USetupData.LocaleID, GetListEntryUserData(ListEntry)))
+            LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
+            if (!wcsicmp(USetupData.LocaleID, LocaleId))
             {
-                DPRINT("found %S in LanguageList\n",GetListEntryUserData(ListEntry));
+                DPRINT("found %S in LanguageList\n", LocaleId);
                 SetCurrentListEntry(LanguageList, ListEntry);
                 break;
             }
-
-            ListEntry = GetNextListEntry(ListEntry);
         }
 
         /* now LayoutList */
-        ListEntry = GetFirstListEntry(LayoutList);
-        while (ListEntry != NULL)
+        for (ListEntry = GetFirstListEntry(LayoutList); ListEntry;
+             ListEntry = GetNextListEntry(ListEntry))
         {
-            if (!wcsicmp(USetupData.LocaleID, GetListEntryUserData(ListEntry)))
+            LocaleId = ((PGENENTRY)GetListEntryData(ListEntry))->Id;
+            if (!wcsicmp(USetupData.LocaleID, LocaleId))
             {
-                DPRINT("found %S in LayoutList\n",GetListEntryUserData(ListEntry));
+                DPRINT("found %S in LayoutList\n", LocaleId);
                 SetCurrentListEntry(LayoutList, ListEntry);
                 break;
             }
-
-            ListEntry = GetNextListEntry(ListEntry);
         }
 
         SetConsoleCodePage();
@@ -854,6 +897,11 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
     NtOsInstallsList = CreateNTOSInstallationsList(PartitionList);
     if (!NtOsInstallsList)
         DPRINT1("Failed to get a list of NTOS installations; continue installation...\n");
+
+    /*
+     * If there is no available installation (or just a single one??) that can
+     * be updated in the list, just continue with the regular installation.
+     */
     if (!NtOsInstallsList || GetNumberOfListEntries(NtOsInstallsList) == 0)
     {
         RepairUpdateFlag = FALSE;
@@ -865,14 +913,12 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
 
     MUIDisplayPage(UPGRADE_REPAIR_PAGE);
 
-    InitGenericListUi(&ListUi, NtOsInstallsList);
+    InitGenericListUi(&ListUi, NtOsInstallsList, GetNTOSInstallationName);
     DrawGenericList(&ListUi,
                     2, 23,
                     xScreen - 3,
                     yScreen - 3);
 
-    SaveGenericListState(NtOsInstallsList);
-
     // return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
     while (TRUE)
     {
@@ -904,7 +950,7 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
             }
             case VK_ESCAPE: /* ESC */
             {
-                RestoreGenericListState(NtOsInstallsList);
+                RestoreGenericListUiState(&ListUi);
                 // return nextPage;    // prevPage;
 
                 // return INSTALL_INTRO_PAGE;
@@ -920,7 +966,11 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
             if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'U')  /* U */
             {
                 /* Retrieve the current installation */
-                CurrentInstallation = (PNTOS_INSTALLATION)GetListEntryUserData(GetCurrentListEntry(NtOsInstallsList));
+                ASSERT(GetNumberOfListEntries(NtOsInstallsList) >= 1);
+
+                CurrentInstallation =
+                    (PNTOS_INSTALLATION)GetListEntryData(GetCurrentListEntry(NtOsInstallsList));
+
                 DPRINT1("Selected installation for repair: \"%S\" ; DiskNumber = %d , PartitionNumber = %d\n",
                         CurrentInstallation->InstallationName, CurrentInstallation->DiskNumber, CurrentInstallation->PartitionNumber);
 
@@ -1147,10 +1197,10 @@ DeviceSettingsPage(PINPUT_RECORD Ir)
 
     MUIDisplayPage(DEVICE_SETTINGS_PAGE);
 
-    CONSOLE_SetTextXY(25, 11, GetListEntryText(GetCurrentListEntry(ComputerList)));
-    CONSOLE_SetTextXY(25, 12, GetListEntryText(GetCurrentListEntry(DisplayList)));
-    CONSOLE_SetTextXY(25, 13, GetListEntryText(GetCurrentListEntry(KeyboardList)));
-    CONSOLE_SetTextXY(25, 14, GetListEntryText(GetCurrentListEntry(LayoutList)));
+    DrawGenericListCurrentItem(ComputerList, GetSettingDescription, 25, 11);
+    DrawGenericListCurrentItem(DisplayList , GetSettingDescription, 25, 12);
+    DrawGenericListCurrentItem(KeyboardList, GetSettingDescription, 25, 13);
+    DrawGenericListCurrentItem(LayoutList  , GetSettingDescription, 25, 14);
 
     CONSOLE_InvertTextXY(24, Line, 48, 1);
 
@@ -1261,7 +1311,7 @@ HandleGenericList(PGENERIC_LIST_UI ListUi,
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))  /* ESC */
         {
-            RestoreGenericListState(ListUi->List);
+            RestoreGenericListUiState(ListUi);
             return nextPage;    // Use some "prevPage;" instead?
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
@@ -1293,15 +1343,12 @@ ComputerSettingsPage(PINPUT_RECORD Ir)
     GENERIC_LIST_UI ListUi;
     MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
 
-    InitGenericListUi(&ListUi, ComputerList);
+    InitGenericListUi(&ListUi, ComputerList, GetSettingDescription);
     DrawGenericList(&ListUi,
-                    2,
-                    18,
+                    2, 18,
                     xScreen - 3,
                     yScreen - 3);
 
-    SaveGenericListState(ComputerList);
-
     return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
@@ -1322,15 +1369,12 @@ DisplaySettingsPage(PINPUT_RECORD Ir)
     GENERIC_LIST_UI ListUi;
     MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
 
-    InitGenericListUi(&ListUi, DisplayList);
+    InitGenericListUi(&ListUi, DisplayList, GetSettingDescription);
     DrawGenericList(&ListUi,
-                    2,
-                    18,
+                    2, 18,
                     xScreen - 3,
                     yScreen - 3);
 
-    SaveGenericListState(DisplayList);
-
     return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
@@ -1351,15 +1395,12 @@ KeyboardSettingsPage(PINPUT_RECORD Ir)
     GENERIC_LIST_UI ListUi;
     MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
 
-    InitGenericListUi(&ListUi, KeyboardList);
+    InitGenericListUi(&ListUi, KeyboardList, GetSettingDescription);
     DrawGenericList(&ListUi,
-                    2,
-                    18,
+                    2, 18,
                     xScreen - 3,
                     yScreen - 3);
 
-    SaveGenericListState(KeyboardList);
-
     return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
@@ -1380,15 +1421,12 @@ LayoutSettingsPage(PINPUT_RECORD Ir)
     GENERIC_LIST_UI ListUi;
     MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
 
-    InitGenericListUi(&ListUi, LayoutList);
+    InitGenericListUi(&ListUi, LayoutList, GetSettingDescription);
     DrawGenericList(&ListUi,
-                    2,
-                    18,
+                    2, 18,
                     xScreen - 3,
                     yScreen - 3);
 
-    SaveGenericListState(LayoutList);
-
     return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
@@ -1674,7 +1712,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                 return SELECT_PARTITION_PAGE;
             }
 
-            StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
                     L"\\Device\\Harddisk%lu\\Partition%lu\\",
                     PartitionList->CurrentDisk->DiskNumber,
                     PartitionList->CurrentPartition->PartitionNumber);
@@ -2913,12 +2951,13 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 FormatPartitionPage(PINPUT_RECORD Ir)
 {
-    UNICODE_STRING PartitionRootPath;
-    WCHAR PathBuffer[MAX_PATH];
+    NTSTATUS Status;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
     PFILE_SYSTEM_ITEM SelectedFileSystem;
-    NTSTATUS Status;
+    UNICODE_STRING PartitionRootPath;
+    WCHAR PathBuffer[MAX_PATH];
+    CHAR Buffer[MAX_PATH];
 
 #ifndef NDEBUG
     ULONG Line;
@@ -3002,7 +3041,7 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             }
 
             /* Set PartitionRootPath */
-            StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
                     L"\\Device\\Harddisk%lu\\Partition%lu",
                     DiskEntry->DiskNumber,
                     PartEntry->PartitionNumber);
@@ -3014,7 +3053,38 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             {
                 Status = FormatPartition(&PartitionRootPath,
                                          SelectedFileSystem);
-                if (!NT_SUCCESS(Status))
+                if (Status == STATUS_NOT_SUPPORTED)
+                {
+                    sprintf(Buffer,
+                            "Setup is currently unable to format a partition in %S.\n"
+                            "\n"
+                            "  \x07  Press ENTER to continue Setup.\n"
+                            "  \x07  Press F3 to quit Setup.",
+                            SelectedFileSystem->FileSystem->FileSystemName);
+
+                    PopupError(Buffer,
+                               MUIGetString(STRING_QUITCONTINUE),
+                               NULL, POPUP_WAIT_NONE);
+
+                    while (TRUE)
+                    {
+                        CONSOLE_ConInKey(Ir);
+
+                        if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
+                            Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)  /* F3 */
+                        {
+                            if (ConfirmQuit(Ir))
+                                return QUIT_PAGE;
+                            else
+                                return SELECT_FILE_SYSTEM_PAGE;
+                        }
+                        else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
+                        {
+                            return SELECT_FILE_SYSTEM_PAGE;
+                        }
+                    }
+                }
+                else if (!NT_SUCCESS(Status))
                 {
                     DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
                     MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
@@ -3055,13 +3125,13 @@ FormatPartitionPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 CheckFileSystemPage(PINPUT_RECORD Ir)
 {
+    NTSTATUS Status;
+    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
     PFILE_SYSTEM CurrentFileSystem;
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
     CHAR Buffer[MAX_PATH];
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
-    NTSTATUS Status;
 
     if (PartitionList == NULL)
     {
@@ -3075,7 +3145,7 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     }
 
     /* Set PartitionRootPath */
-    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu",
             DiskEntry->DiskNumber,
             PartEntry->PartitionNumber);
@@ -3097,7 +3167,8 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
         return CHECK_FILE_SYSTEM_PAGE;
     }
 
-    if (CurrentFileSystem->ChkdskFunc == NULL)
+    Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
+    if (Status == STATUS_NOT_SUPPORTED)
     {
         sprintf(Buffer,
                 "Setup is currently unable to check a partition formatted in %S.\n"
@@ -3129,26 +3200,22 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
             }
         }
     }
-    else
+    else if (!NT_SUCCESS(Status))
     {
-        Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
-            // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
-            sprintf(Buffer, "ChkDsk detected some disk errors.\n"
-                    "(Status 0x%08lx).\n", Status);
-            PopupError(Buffer,
-                       // MUIGetString(STRING_REBOOTCOMPUTER),
-                       MUIGetString(STRING_CONTINUE),
-                       Ir, POPUP_WAIT_ENTER);
-
-            // return QUIT_PAGE;
-        }
+        DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
+        // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
+        sprintf(Buffer, "ChkDsk detected some disk errors.\n"
+                "(Status 0x%08lx).\n", Status);
+        PopupError(Buffer,
+                   // MUIGetString(STRING_REBOOTCOMPUTER),
+                   MUIGetString(STRING_CONTINUE),
+                   Ir, POPUP_WAIT_ENTER);
 
-        PartEntry->NeedsCheck = FALSE;
-        return CHECK_FILE_SYSTEM_PAGE;
+        // return QUIT_PAGE;
     }
+
+    PartEntry->NeedsCheck = FALSE;
+    return CHECK_FILE_SYSTEM_PAGE;
 }
 
 
@@ -3166,7 +3233,7 @@ BuildInstallPaths(PWSTR InstallDir,
 
     /* Create 'USetupData.DestinationRootPath' string */
     RtlFreeUnicodeString(&USetupData.DestinationRootPath);
-    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
             DiskEntry->DiskNumber,
             PartEntry->PartitionNumber);
@@ -3183,7 +3250,7 @@ BuildInstallPaths(PWSTR InstallDir,
 /** Equivalent of 'NTOS_INSTALLATION::SystemArcPath' **/
     /* Create 'USetupData.DestinationArcPath' */
     RtlFreeUnicodeString(&USetupData.DestinationArcPath);
-    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
             DiskEntry->BiosDiskNumber,
             PartEntry->PartitionNumber);
@@ -3436,9 +3503,7 @@ AddSectionToCopyQueueCab(HINF InfFile,
     /* Search for the SectionName section */
     if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
     {
-        CHAR Buffer[128];
-        sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
-        PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
+        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
         return FALSE;
     }
 
@@ -3530,9 +3595,7 @@ AddSectionToCopyQueue(HINF InfFile,
     /* Search for the SectionName section */
     if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
     {
-        CHAR Buffer[128];
-        sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
-        PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
+        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
         return FALSE;
     }
 
@@ -3593,8 +3656,8 @@ AddSectionToCopyQueue(HINF InfFile,
             /* Installation path */
             DPRINT("InstallationPath: '%S'\n", DirKeyValue);
 
-            StringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                           USetupData.SourceRootDir.Buffer);
+            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                              USetupData.SourceRootDir.Buffer);
 
             DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
         }
@@ -3603,8 +3666,8 @@ AddSectionToCopyQueue(HINF InfFile,
             /* Absolute path */
             DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
 
-            StringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                           DirKeyValue);
+            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                              DirKeyValue);
 
             DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName);
         }
@@ -3679,7 +3742,7 @@ PrepareCopyPageInfFile(HINF InfFile,
      */
 
     /* Get destination path */
-    StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), USetupData.DestinationPath.Buffer);
+    RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), USetupData.DestinationPath.Buffer);
 
     DPRINT("FullPath(1): '%S'\n", PathBuffer);
 
@@ -3696,13 +3759,9 @@ PrepareCopyPageInfFile(HINF InfFile,
     if (!SetupFindFirstLineW(InfFile, L"Directories", NULL, &DirContext))
     {
         if (SourceCabinet)
-        {
-            MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER);
-        }
+            MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
         else
-        {
-            MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER);
-        }
+            MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
 
         return FALSE;
     }
@@ -3721,8 +3780,8 @@ PrepareCopyPageInfFile(HINF InfFile,
             /* Installation path */
             DPRINT("InstallationPath: '%S'\n", DirKeyValue);
 
-            StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
-                           USetupData.DestinationPath.Buffer);
+            RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
+                              USetupData.DestinationPath.Buffer);
 
             DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
         }
@@ -4042,6 +4101,37 @@ FileCopyPage(PINPUT_RECORD Ir)
 }
 
 
+static VOID
+__cdecl
+RegistryStatus(IN REGISTRY_STATUS RegStatus, ...)
+{
+    /* WARNING: Please keep this lookup table in sync with the resources! */
+    static const UINT StringIDs[] =
+    {
+        STRING_DONE,                    /* Success */
+        STRING_REGHIVEUPDATE,           /* RegHiveUpdate */
+        STRING_IMPORTFILE,              /* ImportRegHive */
+        STRING_DISPLAYSETTINGSUPDATE,   /* DisplaySettingsUpdate */
+        STRING_LOCALESETTINGSUPDATE,    /* LocaleSettingsUpdate */
+        STRING_ADDKBLAYOUTS,            /* KeybLayouts */
+        STRING_KEYBOARDSETTINGSUPDATE,  /* KeybSettingsUpdate */
+        STRING_CODEPAGEINFOUPDATE,      /* CodePageInfoUpdate */
+    };
+
+    va_list args;
+
+    if (RegStatus < ARRAYSIZE(StringIDs))
+    {
+        va_start(args, RegStatus);
+        CONSOLE_SetStatusTextV(MUIGetString(StringIDs[RegStatus]), args);
+        va_end(args);
+    }
+    else
+    {
+        CONSOLE_SetStatusText("Unknown status %d", RegStatus);
+    }
+}
+
 /*
  * Displays the RegistryPage.
  *
@@ -4051,10 +4141,7 @@ FileCopyPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Calls RegInitializeRegistry
- *  Calls ImportRegistryFile
- *  Calls SetDefaultPagefile
- *  Calls SetMountedDeviceValues
+ *  Calls UpdateRegistry
  *
  * RETURNS
  *   Number of the next page.
@@ -4062,226 +4149,30 @@ FileCopyPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 RegistryPage(PINPUT_RECORD Ir)
 {
-    NTSTATUS Status;
-    INFCONTEXT InfContext;
-    PWSTR Action;
-    PWSTR File;
-    PWSTR Section;
-    BOOLEAN Success;
-    BOOLEAN ShouldRepairRegistry = FALSE;
-    BOOLEAN Delete;
+    ULONG Error;
 
     MUIDisplayPage(REGISTRY_PAGE);
 
-    if (RepairUpdateFlag)
-    {
-        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(&USetupData.DestinationPath, &ShouldRepairRegistry);
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status);
-            ShouldRepairRegistry = FALSE;
-        }
-        if (!ShouldRepairRegistry)
-            DPRINT1("No need to repair the registry\n");
-    }
-
-DoUpdate:
-    /* Update the registry */
-    CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
-
-    /* Initialize the registry and setup the registry hives */
-    Status = RegInitializeRegistry(&USetupData.DestinationPath);
-    if (!NT_SUCCESS(Status))
+    Error = UpdateRegistry(SetupInf,
+                           &USetupData,
+                           RepairUpdateFlag,
+                           PartitionList,
+                           DestinationDriveLetter,
+                           SelectedLanguageId,
+                           DisplayList,
+                           LayoutList,
+                           LanguageList,
+                           RegistryStatus);
+    if (Error != ERROR_SUCCESS)
     {
-        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 failed */
-            MUIDisplayError(ERROR_CREATE_HIVE, Ir, POPUP_WAIT_ENTER);
-        }
+        MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
-
-    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 (!Success)
-        {
-            DPRINT1("SetupFindFirstLine() failed\n");
-            MUIDisplayError(ERROR_FIND_REGISTRY, Ir, POPUP_WAIT_ENTER);
-            goto Cleanup;
-        }
-    }
-    else // if (RepairUpdateFlag && !ShouldRepairRegistry)
-    {
-        /*
-         * 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
-    {
-        INF_GetDataField(&InfContext, 0, &Action);
-        INF_GetDataField(&InfContext, 1, &File);
-        INF_GetDataField(&InfContext, 2, &Section);
-
-        DPRINT("Action: %S  File: %S  Section %S\n", Action, File, Section);
-
-        if (Action == NULL)
-        {
-            INF_FreeData(Action);
-            INF_FreeData(File);
-            INF_FreeData(Section);
-            break; // Hackfix
-        }
-
-        if (!_wcsicmp(Action, L"AddReg"))
-            Delete = FALSE;
-        else if (!_wcsicmp(Action, L"DelReg"))
-            Delete = TRUE;
-        else
-        {
-            DPRINT1("Unrecognized registry INF action '%S'\n", Action);
-            INF_FreeData(Action);
-            INF_FreeData(File);
-            INF_FreeData(Section);
-            continue;
-        }
-
-        INF_FreeData(Action);
-
-        CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
-
-        if (!ImportRegistryFile(USetupData.SourcePath.Buffer, File, Section, USetupData.LanguageId, Delete))
-        {
-            DPRINT1("Importing %S failed\n", File);
-            INF_FreeData(File);
-            INF_FreeData(Section);
-            MUIDisplayError(ERROR_IMPORT_HIVE, Ir, POPUP_WAIT_ENTER);
-            goto Cleanup;
-        }
-    } while (SetupFindNextLine(&InfContext, &InfContext));
-
-    if (!RepairUpdateFlag || ShouldRepairRegistry)
-    {
-        /* See the explanation for this test above */
-
-        /* Update display registry settings */
-        CONSOLE_SetStatusText(MUIGetString(STRING_DISPLAYSETTINGSUPDATE));
-        if (!ProcessDisplayRegistry(SetupInf, DisplayList))
-        {
-            MUIDisplayError(ERROR_UPDATE_DISPLAY_SETTINGS, 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;
-        }
-
-        /* Add keyboard layouts */
-        CONSOLE_SetStatusText(MUIGetString(STRING_ADDKBLAYOUTS));
-        if (!AddKeyboardLayouts(SelectedLanguageId))
-        {
-            MUIDisplayError(ERROR_ADDING_KBLAYOUTS, Ir, POPUP_WAIT_ENTER);
-            goto Cleanup;
-        }
-
-        /* Set GeoID */
-        if (!SetGeoID(MUIGetGeoID(SelectedLanguageId)))
-        {
-            MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
-            goto Cleanup;
-        }
-
-        if (!IsUnattendedSetup)
-        {
-            /* Update keyboard layout settings */
-            CONSOLE_SetStatusText(MUIGetString(STRING_KEYBOARDSETTINGSUPDATE));
-            if (!ProcessKeyboardLayoutRegistry(LayoutList, SelectedLanguageId))
-            {
-                MUIDisplayError(ERROR_UPDATE_KBSETTINGS, Ir, POPUP_WAIT_ENTER);
-                goto Cleanup;
-            }
-        }
-
-        /* Add codepage information to registry */
-        CONSOLE_SetStatusText(MUIGetString(STRING_CODEPAGEINFOUPDATE));
-        if (!AddCodePage(SelectedLanguageId))
-        {
-            MUIDisplayError(ERROR_ADDING_CODEPAGE, Ir, POPUP_WAIT_ENTER);
-            goto Cleanup;
-        }
-
-        /* 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);
-    }
-
-Cleanup:
-    //
-    // TODO: Unload all the registry stuff, perform cleanup,
-    // and copy the created hive files into .sav files.
-    //
-    RegCleanupRegistry(&USetupData.DestinationPath);
-
-    /*
-     * 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))
+    else
     {
         CONSOLE_SetStatusText(MUIGetString(STRING_DONE));
         return BOOT_LOADER_PAGE;
     }
-    else
-    {
-        return QUIT_PAGE;
-    }
 }
 
 
@@ -4316,7 +4207,7 @@ BootLoaderPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
     RtlFreeUnicodeString(&USetupData.SystemRootPath);
-    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
             PartitionList->SystemPartition->DiskEntry->DiskNumber,
             PartitionList->SystemPartition->PartitionNumber);
@@ -4532,16 +4423,14 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
-            if (DoesDirExist(NULL, L"\\Device\\Floppy0\\") == FALSE)
-            {
-                MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
-                return BOOT_LOADER_FLOPPY_PAGE;
-            }
-
-            Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath, &USetupData.DestinationArcPath);
+            Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath,
+                                                &USetupData.DestinationArcPath);
             if (!NT_SUCCESS(Status))
             {
-                /* Print error message */
+                if (Status == STATUS_DEVICE_NOT_READY)
+                    MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
+
+                /* TODO: Print error message */
                 return BOOT_LOADER_FLOPPY_PAGE;
             }
 
@@ -4617,7 +4506,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     }
 
     /* Step 2: Write the MBR */
-    StringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
+    RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
             L"\\Device\\Harddisk%d\\Partition0",
             PartitionList->SystemPartition->DiskEntry->DiskNumber);
     Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
@@ -4625,8 +4514,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
                                       DestinationDevicePathBuffer);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
-                Status);
+        DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
         MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }