[USETUP] Reshuffle a bit the main-function of USetup.
[reactos.git] / base / setup / usetup / usetup.c
index d29f15d..9170b23 100644 (file)
@@ -21,8 +21,7 @@
  * PROJECT:         ReactOS text-mode setup
  * FILE:            base/setup/usetup/usetup.c
  * PURPOSE:         Text-mode setup
- * PROGRAMMER:      Eric Kohl
- *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
  *                  HervĂ© Poussineau (hpoussin@reactos.org)
  */
 
 #define NDEBUG
 #include <debug.h>
 
+// HACK!
+#include <strsafe.h>
+
 
 /* GLOBALS ******************************************************************/
 
 HANDLE ProcessHeap;
-UNICODE_STRING SourceRootPath;
-UNICODE_STRING SourceRootDir;
-UNICODE_STRING SourcePath;
+static UNICODE_STRING SourceRootPath;
+static UNICODE_STRING SourceRootDir;
+/* static */ UNICODE_STRING SourcePath;
 BOOLEAN IsUnattendedSetup = FALSE;
 LONG UnattendDestinationDiskNumber;
 LONG UnattendDestinationPartitionNumber;
@@ -59,7 +61,11 @@ WCHAR DefaultLanguage[20];
 WCHAR DefaultKBLayout[20];
 BOOLEAN RepairUpdateFlag = FALSE;
 HANDLE hPnpThread = INVALID_HANDLE_VALUE;
+
 PPARTLIST PartitionList = NULL;
+PPARTENTRY TempPartition = NULL;
+FORMATMACHINESTATE FormatState = Start;
+
 
 /* LOCALS *******************************************************************/
 
@@ -87,6 +93,7 @@ static UNICODE_STRING DestinationPath;
 static UNICODE_STRING DestinationArcPath;
 static UNICODE_STRING DestinationRootPath;
 
+// FIXME: Is it really useful?? Just used for SetDefaultPagefile...
 static WCHAR DestinationDriveLetter;
 
 static HINF SetupInf;
@@ -414,7 +421,7 @@ ConfirmQuit(PINPUT_RECORD Ir)
 }
 
 
-VOID
+static VOID
 CheckUnattendedSetup(VOID)
 {
     WCHAR UnattendInfPath[MAX_PATH];
@@ -424,15 +431,14 @@ CheckUnattendedSetup(VOID)
     INT IntValue;
     PWCHAR Value;
 
-    if (DoesFileExist(SourcePath.Buffer, L"unattend.inf") == FALSE)
+    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2, SourcePath.Buffer, L"unattend.inf");
+
+    if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
     {
-        DPRINT("Does not exist: %S\\%S\n", SourcePath.Buffer, L"unattend.inf");
+        DPRINT("Does not exist: %S\n", UnattendInfPath);
         return;
     }
 
-    wcscpy(UnattendInfPath, SourcePath.Buffer);
-    wcscat(UnattendInfPath, L"\\unattend.inf");
-
     /* Load 'unattend.inf' from install media. */
     UnattendInf = SetupOpenInfFileW(UnattendInfPath,
                                     NULL,
@@ -524,7 +530,7 @@ CheckUnattendedSetup(VOID)
         return;
     }
 
-    UnattendDestinationPartitionNumber = IntValue;
+    UnattendDestinationPartitionNumber = (LONG)IntValue;
 
     /* Search for 'InstallationDirectory' in the 'Unattend' section */
     if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"InstallationDirectory", &Context))
@@ -578,7 +584,7 @@ CheckUnattendedSetup(VOID)
         if (INF_GetData(&Context, NULL, &Value))
         {
             LONG Id = wcstol(Value, NULL, 16);
-            swprintf(LocaleID,L"%08lx", Id);
+            swprintf(LocaleID, L"%08lx", Id);
        }
     }
 
@@ -588,7 +594,7 @@ CheckUnattendedSetup(VOID)
 }
 
 
-VOID
+static VOID
 UpdateKBLayout(VOID)
 {
     PGENERIC_LIST_ENTRY ListEntry;
@@ -628,7 +634,7 @@ UpdateKBLayout(VOID)
 /*
  * Displays the LanguagePage.
  *
- * Next pages: IntroPage, QuitPage
+ * Next pages: WelcomePage, QuitPage
  *
  * SIDEEFFECTS
  *  Init SelectedLanguageId
@@ -640,6 +646,7 @@ UpdateKBLayout(VOID)
 static PAGE_NUMBER
 LanguagePage(PINPUT_RECORD Ir)
 {
+    GENERIC_LIST_UI ListUi;
     PWCHAR NewLanguageId;
     BOOL RefreshPage = FALSE;
 
@@ -647,11 +654,10 @@ LanguagePage(PINPUT_RECORD Ir)
     if (LanguageList == NULL)
     {
         LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
-
         if (LanguageList == NULL)
         {
            PopupError("Setup failed to initialize available translations", NULL, NULL, POPUP_WAIT_NONE);
-           return INTRO_PAGE;
+           return WELCOME_PAGE;
         }
     }
 
@@ -665,16 +671,17 @@ LanguagePage(PINPUT_RECORD Ir)
     if (GenericListHasSingleEntry(LanguageList))
     {
         LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
-        return INTRO_PAGE;
+        return WELCOME_PAGE;
     }
 
-    DrawGenericList(LanguageList,
+    InitGenericListUi(&ListUi, LanguageList);
+    DrawGenericList(&ListUi,
                     2,
                     18,
                     xScreen - 3,
                     yScreen - 3);
 
-    ScrollToPositionGenericList(LanguageList, GetDefaultLanguageIndex());
+    ScrollToPositionGenericList(&ListUi, GetDefaultLanguageIndex());
 
     MUIDisplayPage(LANGUAGE_PAGE);
 
@@ -685,25 +692,25 @@ LanguagePage(PINPUT_RECORD Ir)
         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN))  /* DOWN */
         {
-            ScrollDownGenericList(LanguageList);
+            ScrollDownGenericList(&ListUi);
             RefreshPage = TRUE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP))  /* UP */
         {
-            ScrollUpGenericList(LanguageList);
+            ScrollUpGenericList(&ListUi);
             RefreshPage = TRUE;
         }
         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT))  /* PAGE DOWN */
         {
-            ScrollPageDownGenericList(LanguageList);
+            ScrollPageDownGenericList(&ListUi);
             RefreshPage = TRUE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR))  /* PAGE UP */
         {
-            ScrollPageUpGenericList(LanguageList);
+            ScrollPageUpGenericList(&ListUi);
             RefreshPage = TRUE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
@@ -712,7 +719,7 @@ LanguagePage(PINPUT_RECORD Ir)
             if (ConfirmQuit(Ir) != FALSE)
                 return QUIT_PAGE;
             else
-                RedrawGenericList(LanguageList);
+                RedrawGenericList(&ListUi);
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)  /* ENTER */
         {
@@ -728,12 +735,12 @@ LanguagePage(PINPUT_RECORD Ir)
             /* Load the font */
             SetConsoleCodePage();
 
-            return INTRO_PAGE;
+            return WELCOME_PAGE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
         {
             /* a-z */
-            GenericListKeyPress(LanguageList, Ir->Event.KeyEvent.uChar.AsciiChar);
+            GenericListKeyPress(&ListUi, Ir->Event.KeyEvent.uChar.AsciiChar);
             RefreshPage = TRUE;
         }
 
@@ -759,7 +766,7 @@ LanguagePage(PINPUT_RECORD Ir)
         }
     }
 
-    return INTRO_PAGE;
+    return WELCOME_PAGE;
 }
 
 
@@ -789,63 +796,32 @@ LanguagePage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 SetupStartPage(PINPUT_RECORD Ir)
 {
-    //SYSTEM_DEVICE_INFORMATION Sdi;
     NTSTATUS Status;
     WCHAR FileNameBuffer[MAX_PATH];
     INFCONTEXT Context;
     PWCHAR Value;
     UINT ErrorLine;
-    //ULONG ReturnSize;
     PGENERIC_LIST_ENTRY ListEntry;
     INT IntValue;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-#if 0
-    /* Check whether a harddisk is available */
-    Status = NtQuerySystemInformation(SystemDeviceInformation,
-                                      &Sdi,
-                                      sizeof(SYSTEM_DEVICE_INFORMATION),
-                                      &ReturnSize);
-
-    if (!NT_SUCCESS(Status))
-    {
-        CONSOLE_PrintTextXY(6, 15, "NtQuerySystemInformation() failed (Status 0x%08lx)", Status);
-        MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    if (Sdi.NumberOfDisks == 0)
-    {
-        MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-#endif
-
     /* Get the source path and source root path */
     Status = GetSourcePaths(&SourcePath,
                             &SourceRootPath,
                             &SourceRootDir);
-
     if (!NT_SUCCESS(Status))
     {
         CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", Status);
         MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
-#if 0
-    else
-    {
-        CONSOLE_PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath);
-        CONSOLE_PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath);
-        CONSOLE_PrintTextXY(6, 17, "SourceRootDir: '%wZ'", &SourceRootDir);
-    }
-#endif
+    DPRINT1("SourcePath: '%wZ'", &SourcePath);
+    DPRINT1("SourceRootPath: '%wZ'", &SourceRootPath);
+    DPRINT1("SourceRootDir: '%wZ'", &SourceRootDir);
 
     /* Load txtsetup.sif from install media. */
-    wcscpy(FileNameBuffer, SourcePath.Buffer);
-    wcscat(FileNameBuffer, L"\\txtsetup.sif");
-
+    CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2, SourcePath.Buffer, L"txtsetup.sif");
     SetupInf = SetupOpenInfFileW(FileNameBuffer,
                                  NULL,
                                  INF_STYLE_WIN4,
@@ -895,7 +871,7 @@ SetupStartPage(PINPUT_RECORD Ir)
 
     RequiredPartitionDiskSpace = (ULONG)IntValue;
 
-    /* Start PnP thread */
+    /* Start the PnP thread */
     if (hPnpThread != INVALID_HANDLE_VALUE)
     {
         NtResumeThread(hPnpThread, NULL);
@@ -906,8 +882,7 @@ SetupStartPage(PINPUT_RECORD Ir)
 
     if (IsUnattendedSetup)
     {
-        //TODO
-        //read options from inf
+        // TODO: Read options from inf
         ComputerList = CreateComputerTypeList(SetupInf);
         DisplayList = CreateDisplayDriverList(SetupInf);
         KeyboardList = CreateKeyboardDriverList(SetupInf);
@@ -915,12 +890,11 @@ SetupStartPage(PINPUT_RECORD Ir)
         LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
 
         /* new part */
-        wcscpy(SelectedLanguageId,LocaleID);
+        wcscpy(SelectedLanguageId, LocaleID);
         LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
 
         /* first we hack LanguageList */
         ListEntry = GetFirstListEntry(LanguageList);
-
         while (ListEntry != NULL)
         {
             if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
@@ -935,7 +909,6 @@ SetupStartPage(PINPUT_RECORD Ir)
 
         /* now LayoutList */
         ListEntry = GetFirstListEntry(LayoutList);
-
         while (ListEntry != NULL)
         {
             if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
@@ -958,7 +931,7 @@ SetupStartPage(PINPUT_RECORD Ir)
 
 
 /*
- * Displays the IntroPage.
+ * Displays the WelcomePage.
  *
  * Next pages:
  *  InstallIntroPage (default)
@@ -970,9 +943,9 @@ SetupStartPage(PINPUT_RECORD Ir)
  *   Number of the next page.
  */
 static PAGE_NUMBER
-IntroPage(PINPUT_RECORD Ir)
+WelcomePage(PINPUT_RECORD Ir)
 {
-    MUIDisplayPage(START_PAGE);
+    MUIDisplayPage(WELCOME_PAGE);
 
     while (TRUE)
     {
@@ -994,13 +967,13 @@ IntroPage(PINPUT_RECORD Ir)
         {
             return REPAIR_INTRO_PAGE;
         }
-        else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* R */
+        else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'L') /* L */
         {
             return LICENSE_PAGE;
         }
     }
 
-    return INTRO_PAGE;
+    return WELCOME_PAGE;
 }
 
 
@@ -1008,7 +981,7 @@ IntroPage(PINPUT_RECORD Ir)
  * Displays the License page.
  *
  * Next page:
- *  IntroPage (default)
+ *  WelcomePage (default)
  *
  * RETURNS
  *   Number of the next page.
@@ -1024,7 +997,7 @@ LicensePage(PINPUT_RECORD Ir)
 
         if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)  /* ENTER */
         {
-            return INTRO_PAGE;
+            return WELCOME_PAGE;
         }
     }
 
@@ -1069,7 +1042,7 @@ RepairIntroPage(PINPUT_RECORD Ir)
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))  /* ESC */
         {
-            return INTRO_PAGE;
+            return WELCOME_PAGE;
         }
     }
 
@@ -1091,8 +1064,6 @@ RepairIntroPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 InstallIntroPage(PINPUT_RECORD Ir)
 {
-    MUIDisplayPage(INSTALL_INTRO_PAGE);
-
     if (RepairUpdateFlag)
     {
         //return SELECT_PARTITION_PAGE;
@@ -1100,9 +1071,9 @@ InstallIntroPage(PINPUT_RECORD Ir)
     }
 
     if (IsUnattendedSetup)
-    {
         return SELECT_PARTITION_PAGE;
-    }
+
+    MUIDisplayPage(INSTALL_INTRO_PAGE);
 
     while (TRUE)
     {
@@ -1131,19 +1102,20 @@ InstallIntroPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 ScsiControllerPage(PINPUT_RECORD Ir)
 {
-    SetTextXY(6, 8, "Setup detected the following mass storage devices:");
+    // MUIDisplayPage(SCSI_CONTROLLER_PAGE);
+
+    CONSOLE_SetTextXY(6, 8, "Setup detected the following mass storage devices:");
 
     /* FIXME: print loaded mass storage driver descriptions */
 #if 0
-    SetTextXY(8, 10, "TEST device");
+    CONSOLE_SetTextXY(8, 10, "TEST device");
 #endif
 
-
-    SetStatusText("   ENTER = Continue   F3 = Quit");
+    CONSOLE_SetStatusText("   ENTER = Continue   F3 = Quit");
 
     while (TRUE)
     {
-        ConInKey(Ir);
+        CONSOLE_ConInKey(Ir);
 
         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
@@ -1161,6 +1133,38 @@ ScsiControllerPage(PINPUT_RECORD Ir)
 
     return SCSI_CONTROLLER_PAGE;
 }
+
+static PAGE_NUMBER
+OemDriverPage(PINPUT_RECORD Ir)
+{
+    // MUIDisplayPage(OEM_DRIVER_PAGE);
+
+    CONSOLE_SetTextXY(6, 8, "This is the OEM driver page!");
+
+    /* FIXME: Implement!! */
+
+    CONSOLE_SetStatusText("   ENTER = Continue   F3 = Quit");
+
+    while (TRUE)
+    {
+        CONSOLE_ConInKey(Ir);
+
+        if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+            (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
+        {
+            if (ConfirmQuit(Ir) == TRUE)
+                return QUIT_PAGE;
+
+            break;
+        }
+        else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+        {
+            return DEVICE_SETTINGS_PAGE;
+        }
+    }
+
+    return OEM_DRIVER_PAGE;
+}
 #endif
 
 
@@ -1189,7 +1193,6 @@ static PAGE_NUMBER
 DeviceSettingsPage(PINPUT_RECORD Ir)
 {
     static ULONG Line = 16;
-    MUIDisplayPage(DEVICE_SETTINGS_PAGE);
 
     /* Initialize the computer settings list */
     if (ComputerList == NULL)
@@ -1236,20 +1239,20 @@ DeviceSettingsPage(PINPUT_RECORD Ir)
         }
     }
 
-    MUIDisplayPage(DEVICE_SETTINGS_PAGE);
+    if (RepairUpdateFlag)
+        return SELECT_PARTITION_PAGE;
 
+    // if (IsUnattendedSetup)
+        // return SELECT_PARTITION_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))));
+    MUIDisplayPage(DEVICE_SETTINGS_PAGE);
 
-    CONSOLE_InvertTextXY(24, Line, 48, 1);
+    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)));
 
-    if (RepairUpdateFlag)
-    {
-        return SELECT_PARTITION_PAGE;
-    }
+    CONSOLE_InvertTextXY(24, Line, 48, 1);
 
     while (TRUE)
     {
@@ -1319,7 +1322,7 @@ DeviceSettingsPage(PINPUT_RECORD Ir)
  * Ir: The PINPUT_RECORD
  */
 static PAGE_NUMBER
-HandleGenericList(PGENERIC_LIST GenericList,
+HandleGenericList(PGENERIC_LIST_UI ListUi,
                   PAGE_NUMBER nextPage,
                   PINPUT_RECORD Ir)
 {
@@ -1330,36 +1333,36 @@ HandleGenericList(PGENERIC_LIST GenericList,
         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN))  /* DOWN */
         {
-            ScrollDownGenericList(GenericList);
+            ScrollDownGenericList(ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP))  /* UP */
         {
-            ScrollUpGenericList(GenericList);
+            ScrollUpGenericList(ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_NEXT))  /* PAGE DOWN */
         {
-            ScrollPageDownGenericList(GenericList);
+            ScrollPageDownGenericList(ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_PRIOR))  /* PAGE UP */
         {
-            ScrollPageUpGenericList(GenericList);
+            ScrollPageUpGenericList(ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))  /* F3 */
         {
             if (ConfirmQuit(Ir) != FALSE)
                 return QUIT_PAGE;
-
-            continue;
+            else
+                RedrawGenericList(ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))  /* ESC */
         {
-            RestoreGenericListState(GenericList);
-            return nextPage;
+            RestoreGenericListState(ListUi->List);
+            return nextPage;    // Use some "prevPage;" instead?
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
         {
@@ -1368,7 +1371,7 @@ HandleGenericList(PGENERIC_LIST GenericList,
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar > 0x60) && (Ir->Event.KeyEvent.uChar.AsciiChar < 0x7b))
         {
             /* a-z */
-            GenericListKeyPress(GenericList, Ir->Event.KeyEvent.uChar.AsciiChar);
+            GenericListKeyPress(ListUi, Ir->Event.KeyEvent.uChar.AsciiChar);
         }
     }
 }
@@ -1387,9 +1390,11 @@ HandleGenericList(PGENERIC_LIST GenericList,
 static PAGE_NUMBER
 ComputerSettingsPage(PINPUT_RECORD Ir)
 {
+    GENERIC_LIST_UI ListUi;
     MUIDisplayPage(COMPUTER_SETTINGS_PAGE);
 
-    DrawGenericList(ComputerList,
+    InitGenericListUi(&ListUi, ComputerList);
+    DrawGenericList(&ListUi,
                     2,
                     18,
                     xScreen - 3,
@@ -1397,10 +1402,10 @@ ComputerSettingsPage(PINPUT_RECORD Ir)
 
     SaveGenericListState(ComputerList);
 
-    return HandleGenericList(ComputerList, DEVICE_SETTINGS_PAGE, Ir);
+    return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
+
+
 /*
  * Displays the DisplaySettingsPage.
  *
@@ -1414,9 +1419,11 @@ ComputerSettingsPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 DisplaySettingsPage(PINPUT_RECORD Ir)
 {
+    GENERIC_LIST_UI ListUi;
     MUIDisplayPage(DISPLAY_SETTINGS_PAGE);
 
-    DrawGenericList(DisplayList,
+    InitGenericListUi(&ListUi, DisplayList);
+    DrawGenericList(&ListUi,
                     2,
                     18,
                     xScreen - 3,
@@ -1424,7 +1431,7 @@ DisplaySettingsPage(PINPUT_RECORD Ir)
 
     SaveGenericListState(DisplayList);
 
-    return HandleGenericList(DisplayList, DEVICE_SETTINGS_PAGE, Ir);
+    return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
 
@@ -1441,9 +1448,11 @@ DisplaySettingsPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 KeyboardSettingsPage(PINPUT_RECORD Ir)
 {
+    GENERIC_LIST_UI ListUi;
     MUIDisplayPage(KEYBOARD_SETTINGS_PAGE);
 
-    DrawGenericList(KeyboardList,
+    InitGenericListUi(&ListUi, KeyboardList);
+    DrawGenericList(&ListUi,
                     2,
                     18,
                     xScreen - 3,
@@ -1451,7 +1460,7 @@ KeyboardSettingsPage(PINPUT_RECORD Ir)
 
     SaveGenericListState(KeyboardList);
 
-    return HandleGenericList(KeyboardList, DEVICE_SETTINGS_PAGE, Ir);
+    return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
 
@@ -1468,9 +1477,11 @@ KeyboardSettingsPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 LayoutSettingsPage(PINPUT_RECORD Ir)
 {
+    GENERIC_LIST_UI ListUi;
     MUIDisplayPage(LAYOUT_SETTINGS_PAGE);
 
-    DrawGenericList(LayoutList,
+    InitGenericListUi(&ListUi, LayoutList);
+    DrawGenericList(&ListUi,
                     2,
                     18,
                     xScreen - 3,
@@ -1478,7 +1489,7 @@ LayoutSettingsPage(PINPUT_RECORD Ir)
 
     SaveGenericListState(LayoutList);
 
-    return HandleGenericList(LayoutList, DEVICE_SETTINGS_PAGE, Ir);
+    return HandleGenericList(&ListUi, DEVICE_SETTINGS_PAGE, Ir);
 }
 
 
@@ -1517,7 +1528,6 @@ IsDiskSizeValid(PPARTENTRY PartEntry)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Init DestinationDriveLetter (only if unattended or not free space is selected)
  *  Set InstallShortcut (only if not unattended + free space is selected)
  *
  * RETURNS
@@ -1526,19 +1536,16 @@ IsDiskSizeValid(PPARTENTRY PartEntry)
 static PAGE_NUMBER
 SelectPartitionPage(PINPUT_RECORD Ir)
 {
+    PARTLIST_UI ListUi;
     ULONG Error;
 
-    MUIDisplayPage(SELECT_PARTITION_PAGE);
-
     if (PartitionList == NULL)
     {
-        PartitionList = CreatePartitionList(2,
-                                            23,
-                                            xScreen - 3,
-                                            yScreen - 3);
+        PartitionList = CreatePartitionList();
         if (PartitionList == NULL)
         {
             /* FIXME: show an error dialog */
+            MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
         else if (IsListEmpty(&PartitionList->DiskListHead))
@@ -1546,9 +1553,19 @@ SelectPartitionPage(PINPUT_RECORD Ir)
             MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
+
+        TempPartition = NULL;
+        FormatState = Start;
     }
 
-    DrawPartitionList(PartitionList);
+    MUIDisplayPage(SELECT_PARTITION_PAGE);
+
+    InitPartitionListUi(&ListUi, PartitionList,
+                        2,
+                        23,
+                        xScreen - 3,
+                        yScreen - 3);
+    DrawPartitionList(&ListUi);
 
     if (IsUnattendedSetup)
     {
@@ -1569,6 +1586,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                                            TRUE);
                 }
 
+// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
                 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
                 {
                     MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
@@ -1576,13 +1594,14 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                     return SELECT_PARTITION_PAGE; /* let the user select another partition */
                 }
 
-                DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
-
                 return SELECT_FILE_SYSTEM_PAGE;
             }
         }
         else
         {
+            DrawPartitionList(&ListUi);
+
+// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
             if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
@@ -1590,8 +1609,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
 
-            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
-
             return SELECT_FILE_SYSTEM_PAGE;
         }
     }
@@ -1605,32 +1622,32 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (PartitionList->CurrentPartition->LogicalPartition)
         {
-             if (PartitionList->CurrentPartition->IsPartitioned)
-             {
-                 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
-             }
-             else
-             {
-                 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL));
-             }
+            if (PartitionList->CurrentPartition->IsPartitioned)
+            {
+                CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
+            }
+            else
+            {
+                CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATELOGICAL));
+            }
         }
         else
         {
-             if (PartitionList->CurrentPartition->IsPartitioned)
-             {
-                 if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
-                 {
-                     CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
-                 }
-                 else
-                 {
-                     CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
-                 }
-             }
-             else
-             {
-                 CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
-             }
+            if (PartitionList->CurrentPartition->IsPartitioned)
+            {
+                if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
+                {
+                    CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
+                }
+                else
+                {
+                    CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLDELETEPARTITION));
+                }
+            }
+            else
+            {
+                CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
+            }
         }
 
         CONSOLE_ConInKey(Ir);
@@ -1650,19 +1667,17 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN))  /* DOWN */
         {
-            if (ScrollDownPartitionList(PartitionList))
-                DrawPartitionList(PartitionList);
+            ScrollDownPartitionList(&ListUi);
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP))  /* UP */
         {
-            if (ScrollUpPartitionList(PartitionList))
-                DrawPartitionList(PartitionList);
+            ScrollUpPartitionList(&ListUi);
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN)  /* ENTER */
         {
             if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
-                continue; //return SELECT_PARTITION_PAGE;
+                continue; // return SELECT_PARTITION_PAGE;
 
             if (PartitionList->CurrentPartition == NULL ||
                 PartitionList->CurrentPartition->IsPartitioned == FALSE)
@@ -1688,8 +1703,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
 
-            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
-
             return SELECT_FILE_SYSTEM_PAGE;
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P')  /* P */
@@ -2003,25 +2016,27 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
     if (DiskEntry->DriverName.Length > 0)
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDINFOPARTCREATE),
+                            MUIGetString(STRING_HDINFOPARTCREATE_1),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
     else
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDDINFOUNK1),
+                            MUIGetString(STRING_HDINFOPARTCREATE_2),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
-                            DiskEntry->Id);
+                            DiskEntry->Id,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
@@ -2160,25 +2175,27 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
     if (DiskEntry->DriverName.Length > 0)
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDINFOPARTCREATE),
+                            MUIGetString(STRING_HDINFOPARTCREATE_1),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
     else
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDDINFOUNK1),
+                            MUIGetString(STRING_HDINFOPARTCREATE_2),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
-                            DiskEntry->Id);
+                            DiskEntry->Id,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
@@ -2316,25 +2333,27 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
     if (DiskEntry->DriverName.Length > 0)
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDINFOPARTCREATE),
+                            MUIGetString(STRING_HDINFOPARTCREATE_1),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
     else
     {
         CONSOLE_PrintTextXY(6, 10,
-                            MUIGetString(STRING_HDDINFOUNK1),
+                            MUIGetString(STRING_HDINFOPARTCREATE_2),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
-                            DiskEntry->Id);
+                            DiskEntry->Id,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
@@ -2553,25 +2572,27 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     if (DiskEntry->DriverName.Length > 0)
     {
         CONSOLE_PrintTextXY(6, 12,
-                            MUIGetString(STRING_HDINFOPARTDELETE),
+                            MUIGetString(STRING_HDINFOPARTDELETE_1),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
     else
     {
         CONSOLE_PrintTextXY(6, 12,
-                            MUIGetString(STRING_HDDINFOUNK3),
+                            MUIGetString(STRING_HDINFOPARTDELETE_2),
                             DiskSize,
                             Unit,
                             DiskEntry->DiskNumber,
                             DiskEntry->Port,
                             DiskEntry->Bus,
-                            DiskEntry->Id);
+                            DiskEntry->Id,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
 
     while (TRUE)
@@ -2642,106 +2663,105 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         return QUIT_PAGE;
     }
 
-    /*** HACK! ***/
-    if (FileSystemList == NULL)
-    {
-        FileSystemList = CreateFileSystemList(6, 26, PartitionList->CurrentPartition->New, L"FAT");
-        if (FileSystemList == NULL)
-        {
-            /* FIXME: show an error dialog */
-            return QUIT_PAGE;
-        }
-
-        /* FIXME: Add file systems to list */
-    }
-
     /* Find or set the active system partition */
-    CheckActiveSystemPartition(PartitionList, FileSystemList);
-
-    if (PartitionList->SystemDisk == NULL ||
-        PartitionList->SystemPartition == NULL)
+    CheckActiveSystemPartition(PartitionList);
+    if (PartitionList->SystemPartition == NULL)
     {
         /* FIXME: show an error dialog */
+        //
+        // Error dialog should say that we cannot find a suitable
+        // system partition and create one on the system. At this point,
+        // it may be nice to ask the user whether he wants to continue,
+        // or use an external drive as the system drive/partition
+        // (e.g. floppy, USB drive, etc...)
+        //
         return QUIT_PAGE;
     }
 
-    PreviousFormatState = PartitionList->FormatState;
-    switch (PartitionList->FormatState)
+    PreviousFormatState = FormatState;
+    switch (FormatState)
     {
         case Start:
+        {
             if (PartitionList->CurrentPartition != PartitionList->SystemPartition)
             {
-                PartitionList->TempDisk = PartitionList->SystemDisk;
-                PartitionList->TempPartition = PartitionList->SystemPartition;
-                PartitionList->TempPartition->NeedsCheck = TRUE;
+                TempPartition = PartitionList->SystemPartition;
+                TempPartition->NeedsCheck = TRUE;
 
-                PartitionList->FormatState = FormatSystemPartition;
+                FormatState = FormatSystemPartition;
                 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
             }
             else
             {
-                PartitionList->TempDisk = PartitionList->CurrentDisk;
-                PartitionList->TempPartition = PartitionList->CurrentPartition;
-                PartitionList->TempPartition->NeedsCheck = TRUE;
+                TempPartition = PartitionList->CurrentPartition;
+                TempPartition->NeedsCheck = TRUE;
 
-                PartitionList->FormatState = FormatInstallPartition;
+                FormatState = FormatInstallPartition;
                 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
             }
             break;
+        }
 
         case FormatSystemPartition:
-            PartitionList->TempDisk = PartitionList->CurrentDisk;
-            PartitionList->TempPartition = PartitionList->CurrentPartition;
-            PartitionList->TempPartition->NeedsCheck = TRUE;
+        {
+            TempPartition = PartitionList->CurrentPartition;
+            TempPartition->NeedsCheck = TRUE;
 
-            PartitionList->FormatState = FormatInstallPartition;
+            FormatState = FormatInstallPartition;
             DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
             break;
+        }
 
         case FormatInstallPartition:
+        {
             if (GetNextUnformattedPartition(PartitionList,
-                                            &PartitionList->TempDisk,
-                                            &PartitionList->TempPartition))
+                                            NULL,
+                                            &TempPartition))
             {
-                PartitionList->FormatState = FormatOtherPartition;
-                PartitionList->TempPartition->NeedsCheck = TRUE;
+                FormatState = FormatOtherPartition;
+                TempPartition->NeedsCheck = TRUE;
                 DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
             }
             else
             {
-                PartitionList->FormatState = FormatDone;
+                FormatState = FormatDone;
                 DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
                 return CHECK_FILE_SYSTEM_PAGE;
             }
             break;
+        }
 
         case FormatOtherPartition:
+        {
             if (GetNextUnformattedPartition(PartitionList,
-                                            &PartitionList->TempDisk,
-                                            &PartitionList->TempPartition))
+                                            NULL,
+                                            &TempPartition))
             {
-                PartitionList->FormatState = FormatOtherPartition;
-                PartitionList->TempPartition->NeedsCheck = TRUE;
+                FormatState = FormatOtherPartition;
+                TempPartition->NeedsCheck = TRUE;
                 DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
             }
             else
             {
-                PartitionList->FormatState = FormatDone;
+                FormatState = FormatDone;
                 DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
                 return CHECK_FILE_SYSTEM_PAGE;
             }
             break;
+        }
 
         default:
-            DPRINT1("FormatState: Invalid value %ld\n", PartitionList->FormatState);
+        {
+            DPRINT1("FormatState: Invalid value %ld\n", FormatState);
             /* FIXME: show an error dialog */
             return QUIT_PAGE;
+        }
     }
 
-    DiskEntry = PartitionList->TempDisk;
-    PartEntry = PartitionList->TempPartition;
+    PartEntry = TempPartition;
+    DiskEntry = PartEntry->DiskEntry;
 
-    /* adjust disk size */
+    /* Adjust disk size */
     DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
     if (DiskSize >= 10737418240) /* 10 GB */
     {
@@ -2754,7 +2774,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         DiskUnit = MUIGetString(STRING_MB);
     }
 
-    /* adjust partition size */
+    /* Adjust partition size */
     PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
     if (PartSize >= 10737418240) /* 10 GB */
     {
@@ -2767,7 +2787,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         PartUnit = MUIGetString(STRING_MB);
     }
 
-    /* adjust partition type */
+    /* Adjust partition type */
     GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
                                        PartTypeString,
                                        ARRAYSIZE(PartTypeString));
@@ -2784,23 +2804,23 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                             PartTypeString);
 #endif
 
-        CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED),
+        CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1),
                             DiskEntry->DiskNumber,
                             DiskSize,
                             DiskUnit,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
 
         CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
 
-
         PartEntry->AutoCreate = FALSE;
     }
     else if (PartEntry->New != FALSE)
     {
-        switch (PartitionList->FormatState)
+        switch (FormatState)
         {
             case FormatSystemPartition:
                 CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NONFORMATTEDSYSTEMPART));
@@ -2845,32 +2865,30 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                                 PartUnit);
         }
 
-        CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS),
+        CONSOLE_PrintTextXY(6, 12, MUIGetString(STRING_HDINFOPARTEXISTS_1),
                             DiskEntry->DiskNumber,
                             DiskSize,
                             DiskUnit,
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            &DiskEntry->DriverName);
+                            &DiskEntry->DriverName,
+                            DiskEntry->NoMbr ? "GPT" : "MBR");
     }
 
     MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
 
     if (FileSystemList == NULL)
     {
+        /* Create the file system list, and by default select the "FAT" file system */
         FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
         if (FileSystemList == NULL)
         {
             /* FIXME: show an error dialog */
             return QUIT_PAGE;
         }
-
-        /* FIXME: Add file systems to list */
     }
 
-    DrawFileSystemList(FileSystemList);
-
     if (RepairUpdateFlag)
     {
         return CHECK_FILE_SYSTEM_PAGE;
@@ -2881,13 +2899,21 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
     {
         if (UnattendFormatPartition)
         {
-            PartEntry->FileSystem = GetFileSystemByName(FileSystemList, L"FAT");
+            /*
+             * We use whatever currently selected file system we have
+             * (by default, this is "FAT", as per the initialization
+             * performed above). Note that it may be interesting to specify
+             * which file system to use in unattended installations, in the
+             * txtsetup.sif file.
+             */
             return FORMAT_PARTITION_PAGE;
         }
 
         return CHECK_FILE_SYSTEM_PAGE;
     }
 
+    DrawFileSystemList(FileSystemList);
+
     while (TRUE)
     {
         CONSOLE_ConInKey(Ir);
@@ -2903,7 +2929,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))  /* ESC */
         {
-            PartitionList->FormatState = Start;
+            FormatState = Start;
             return SELECT_PARTITION_PAGE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
@@ -2918,19 +2944,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
         {
-            if (!FileSystemList->Selected->FormatFunc)
-            {
-                  return SELECT_FILE_SYSTEM_PAGE;
-            }
+            if (!FileSystemList->Selected->FileSystem)
+                return SELECT_FILE_SYSTEM_PAGE;
             else
-            {
-                PartEntry->FileSystem = FileSystemList->Selected;
                 return FORMAT_PARTITION_PAGE;
-            }
         }
     }
 
-    PartitionList->FormatState = PreviousFormatState;
+    FormatState = PreviousFormatState;
 
     return SELECT_FILE_SYSTEM_PAGE;
 }
@@ -2951,13 +2972,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
  * RETURNS
  *   Number of the next page.
  */
-static ULONG
+static PAGE_NUMBER
 FormatPartitionPage(PINPUT_RECORD Ir)
 {
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PFILE_SYSTEM_ITEM SelectedFileSystem;
     NTSTATUS Status;
 
 #ifndef NDEBUG
@@ -2970,16 +2992,16 @@ FormatPartitionPage(PINPUT_RECORD Ir)
 
     MUIDisplayPage(FORMAT_PARTITION_PAGE);
 
-    if (PartitionList == NULL ||
-        PartitionList->TempDisk == NULL ||
-        PartitionList->TempPartition == NULL)
+    if (PartitionList == NULL || TempPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->TempDisk;
-    PartEntry = PartitionList->TempPartition;
+    PartEntry = TempPartition;
+    DiskEntry = PartEntry->DiskEntry;
+
+    SelectedFileSystem = FileSystemList->Selected;
 
     while (TRUE)
     {
@@ -3000,72 +3022,7 @@ FormatPartitionPage(PINPUT_RECORD Ir)
         {
             CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-            if (wcscmp(PartEntry->FileSystem->FileSystemName, L"FAT") == 0)
-            {
-                if (PartEntry->SectorCount.QuadPart < 8192)
-                {
-                    /* FAT12 CHS partition (disk is smaller than 4.1MB) */
-                    PartEntry->PartitionType = PARTITION_FAT_12;
-                }
-                else if (PartEntry->StartSector.QuadPart < 1450560)
-                {
-                    /* Partition starts below the 8.4GB boundary ==> CHS partition */
-
-                    if (PartEntry->SectorCount.QuadPart < 65536)
-                    {
-                        /* FAT16 CHS partition (partition size < 32MB) */
-                        PartEntry->PartitionType = PARTITION_FAT_16;
-                    }
-                    else if (PartEntry->SectorCount.QuadPart < 1048576)
-                    {
-                        /* FAT16 CHS partition (partition size < 512MB) */
-                        PartEntry->PartitionType = PARTITION_HUGE;
-                    }
-                    else
-                    {
-                        /* FAT32 CHS partition (partition size >= 512MB) */
-                        PartEntry->PartitionType = PARTITION_FAT32;
-                    }
-                }
-                else
-                {
-                    /* Partition starts above the 8.4GB boundary ==> LBA partition */
-
-                    if (PartEntry->SectorCount.QuadPart < 1048576)
-                    {
-                        /* FAT16 LBA partition (partition size < 512MB) */
-                        PartEntry->PartitionType = PARTITION_XINT13;
-                    }
-                    else
-                    {
-                        /* FAT32 LBA partition (partition size >= 512MB) */
-                        PartEntry->PartitionType = PARTITION_FAT32_XINT13;
-                    }
-                }
-
-                DiskEntry->Dirty = TRUE;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
-            }
-#if 0
-            else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"EXT2") == 0)
-            {
-                PartEntry->PartitionType = PARTITION_EXT2;
-
-                DiskEntry->Dirty = TRUE;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
-            }
-            else if (wcscmp(PartEntry->FileSystem->FileSystemName, L"NTFS") == 0)
-            {
-                PartEntry->PartitionType = PARTITION_IFS;
-
-                DiskEntry->Dirty = TRUE;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
-                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
-            }
-#endif
-            else if (!PartEntry->FileSystem->FormatFunc)
+            if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem))
             {
                 /* FIXME: show an error dialog */
                 return QUIT_PAGE;
@@ -3098,7 +3055,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             }
 #endif
 
-            if (WritePartitionsToDisk(PartitionList) == FALSE)
+            /* Commit the partition changes to the disk */
+            if (!WritePartitionsToDisk(PartitionList))
             {
                 DPRINT("WritePartitionsToDisk() failed\n");
                 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
@@ -3106,18 +3064,18 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             }
 
             /* Set PartitionRootPath */
-            swprintf(PathBuffer,
-                     L"\\Device\\Harddisk%lu\\Partition%lu",
-                     DiskEntry->DiskNumber,
-                     PartEntry->PartitionNumber);
-            RtlInitUnicodeString(&PartitionRootPath,
-                                 PathBuffer);
+            StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                    L"\\Device\\Harddisk%lu\\Partition%lu",
+                    DiskEntry->DiskNumber,
+                    PartEntry->PartitionNumber);
+            RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
             DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
 
-            if (PartEntry->FileSystem->FormatFunc)
+            /* Format the partition */
+            if (SelectedFileSystem->FileSystem)
             {
                 Status = FormatPartition(&PartitionRootPath,
-                                         PartEntry->FileSystem);
+                                         SelectedFileSystem);
                 if (!NT_SUCCESS(Status))
                 {
                     DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
@@ -3125,6 +3083,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
                     return QUIT_PAGE;
                 }
 
+                PartEntry->FormatState = Formatted;
+                // PartEntry->FileSystem  = FileSystem;
                 PartEntry->New = FALSE;
             }
 
@@ -3154,10 +3114,10 @@ FormatPartitionPage(PINPUT_RECORD Ir)
  * RETURNS
  *   Number of the next page.
  */
-static ULONG
+static PAGE_NUMBER
 CheckFileSystemPage(PINPUT_RECORD Ir)
 {
-    PFILE_SYSTEM_ITEM CurrentFileSystem;
+    PFILE_SYSTEM CurrentFileSystem;
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
     CHAR Buffer[MAX_PATH];
@@ -3177,10 +3137,10 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     }
 
     /* Set PartitionRootPath */
-    swprintf(PathBuffer,
-             L"\\Device\\Harddisk%lu\\Partition%lu",
-             DiskEntry->DiskNumber,
-             PartEntry->PartitionNumber);
+    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"\\Device\\Harddisk%lu\\Partition%lu",
+            DiskEntry->DiskNumber,
+            PartEntry->PartitionNumber);
     RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
     DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
 
@@ -3188,7 +3148,7 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-    CurrentFileSystem = GetFileSystem(FileSystemList, PartEntry);
+    CurrentFileSystem = PartEntry->FileSystem;
     DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
             PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a"));
 
@@ -3254,9 +3214,8 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 }
 
 
-static
-VOID
-BuildInstallPaths(PWCHAR InstallDir,
+static VOID
+BuildInstallPaths(PWSTR InstallDir,
                   PDISKENTRY DiskEntry,
                   PPARTENTRY PartEntry)
 {
@@ -3268,35 +3227,30 @@ BuildInstallPaths(PWCHAR InstallDir,
 
     /* Create 'DestinationRootPath' string */
     RtlFreeUnicodeString(&DestinationRootPath);
-    swprintf(PathBuffer,
-             L"\\Device\\Harddisk%lu\\Partition%lu",
-             DiskEntry->DiskNumber,
-             PartEntry->PartitionNumber);
+    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"\\Device\\Harddisk%lu\\Partition%lu\\",
+            DiskEntry->DiskNumber,
+            PartEntry->PartitionNumber);
     RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
     DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
 
     /* Create 'DestinationPath' string */
     RtlFreeUnicodeString(&DestinationPath);
-    wcscpy(PathBuffer, DestinationRootPath.Buffer);
-
-    if (InstallDir[0] != L'\\')
-        wcscat(PathBuffer, L"\\");
-
-    wcscat(PathBuffer, InstallDir);
+    CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                 DestinationRootPath.Buffer, InstallDir);
     RtlCreateUnicodeString(&DestinationPath, PathBuffer);
 
     /* Create 'DestinationArcPath' */
     RtlFreeUnicodeString(&DestinationArcPath);
-    swprintf(PathBuffer,
-             L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
-             DiskEntry->BiosDiskNumber,
-             PartEntry->PartitionNumber);
-
-    if (InstallDir[0] != L'\\')
-        wcscat(PathBuffer, L"\\");
-
-    wcscat(PathBuffer, InstallDir);
+    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
+            DiskEntry->BiosDiskNumber,
+            PartEntry->PartitionNumber);
+    ConcatPaths(PathBuffer, ARRAYSIZE(PathBuffer), 1, InstallDir);
     RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
+
+    /* Initialize DestinationDriveLetter */
+    DestinationDriveLetter = (WCHAR)PartEntry->DriveLetter;
 }
 
 
@@ -3498,18 +3452,23 @@ AddSectionToCopyQueueCab(HINF InfFile,
     PWCHAR DirKeyValue;
     PWCHAR TargetFileName;
 
+    /*
+     * This code enumerates the list of files in reactos.dff / reactos.inf
+     * that need to be extracted from reactos.cab and be installed in their
+     * respective directories.
+     */
+
     /* Search for the SectionName section */
     if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
     {
-        char Buffer[128];
+        CHAR Buffer[128];
         sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
         PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
         return FALSE;
     }
 
     /*
-     * Enumerate the files in the section
-     * and add them to the file queue.
+     * Enumerate the files in the section and add them to the file queue.
      */
     do
     {
@@ -3572,24 +3531,27 @@ AddSectionToCopyQueue(HINF InfFile,
     PWCHAR FileKeyValue;
     PWCHAR DirKeyValue;
     PWCHAR TargetFileName;
-    ULONG Length;
-    WCHAR CompleteOrigDirName[512];
+    WCHAR CompleteOrigDirName[512]; // FIXME: MAX_PATH is not enough?
 
     if (SourceCabinet)
         return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
 
+    /*
+     * This code enumerates the list of files in txtsetup.sif
+     * that need to be installed in their respective directories.
+     */
+
     /* Search for the SectionName section */
     if (!SetupFindFirstLineW(InfFile, SectionName, NULL, &FilesContext))
     {
-        char Buffer[128];
+        CHAR Buffer[128];
         sprintf(Buffer, MUIGetString(STRING_TXTSETUPFAILED), SectionName);
         PopupError(Buffer, MUIGetString(STRING_REBOOTCOMPUTER), Ir, POPUP_WAIT_ENTER);
         return FALSE;
     }
 
     /*
-     * Enumerate the files in the section
-     * and add them to the file queue.
+     * Enumerate the files in the section and add them to the file queue.
      */
     do
     {
@@ -3632,29 +3594,35 @@ AddSectionToCopyQueue(HINF InfFile,
             break;
         }
 
-        if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
+        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
         {
             /* Installation path */
-            wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
+            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
+
+            StringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                           SourceRootDir.Buffer);
+
+            DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
         }
         else if (DirKeyValue[0] == L'\\')
         {
             /* Absolute path */
-            wcscpy(CompleteOrigDirName, DirKeyValue);
+            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
+
+            StringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                           DirKeyValue);
+
+            DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName);
         }
         else // if (DirKeyValue[0] != L'\\')
         {
             /* Path relative to the installation path */
-            wcscpy(CompleteOrigDirName, SourceRootDir.Buffer);
-            wcscat(CompleteOrigDirName, L"\\");
-            wcscat(CompleteOrigDirName, DirKeyValue);
-        }
+            DPRINT("RelativePath: '%S'\n", DirKeyValue);
 
-        /* Remove trailing backslash */
-        Length = wcslen(CompleteOrigDirName);
-        if ((Length > 0) && (CompleteOrigDirName[Length - 1] == L'\\'))
-        {
-            CompleteOrigDirName[Length - 1] = 0;
+            CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 2,
+                         SourceRootDir.Buffer, DirKeyValue);
+
+            DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName);
         }
 
         if (!SetupQueueCopy(SetupFileQueue,
@@ -3679,12 +3647,11 @@ PrepareCopyPageInfFile(HINF InfFile,
                        PWCHAR SourceCabinet,
                        PINPUT_RECORD Ir)
 {
-    WCHAR PathBuffer[MAX_PATH];
+    NTSTATUS Status;
     INFCONTEXT DirContext;
     PWCHAR AdditionalSectionName = NULL;
     PWCHAR DirKeyValue;
-    ULONG Length;
-    NTSTATUS Status;
+    WCHAR PathBuffer[MAX_PATH];
 
     /* Add common files */
     if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &DestinationPath, Ir))
@@ -3707,28 +3674,22 @@ PrepareCopyPageInfFile(HINF InfFile,
 
     /*
      * FIXME:
-     * - Install directories like '\reactos\test' are not handled yet.
-     * - Copying files to DestinationRootPath should be done from within
-     *   the SystemPartitionFiles section.
-     *   At the moment we check whether we specify paths like '\foo' or '\\' for that.
-     *   For installing to DestinationPath specify just '\' .
+     * Copying files to DestinationRootPath should be done from within
+     * the SystemPartitionFiles section.
+     * At the moment we check whether we specify paths like '\foo' or '\\' for that.
+     * For installing to DestinationPath specify just '\' .
      */
 
     /* Get destination path */
-    wcscpy(PathBuffer, DestinationPath.Buffer);
+    StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), DestinationPath.Buffer);
 
-    /* Remove trailing backslash */
-    Length = wcslen(PathBuffer);
-    if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
-    {
-        PathBuffer[Length - 1] = 0;
-    }
+    DPRINT("FullPath(1): '%S'\n", PathBuffer);
 
     /* Create the install directory */
     Status = SetupCreateDirectory(PathBuffer);
     if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
     {
-        DPRINT1("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
+        DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
         MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
         return FALSE;
     }
@@ -3757,31 +3718,25 @@ PrepareCopyPageInfFile(HINF InfFile,
             break;
         }
 
-        if ((DirKeyValue[0] == 0) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == 0))
+        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
         {
             /* Installation path */
             DPRINT("InstallationPath: '%S'\n", DirKeyValue);
 
-            wcscpy(PathBuffer, DestinationPath.Buffer);
+            StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
+                           DestinationPath.Buffer);
 
-            DPRINT("FullPath: '%S'\n", PathBuffer);
+            DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
         }
         else if (DirKeyValue[0] == L'\\')
         {
             /* Absolute path */
-            DPRINT("Absolute Path: '%S'\n", DirKeyValue);
+            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
 
-            wcscpy(PathBuffer, DestinationRootPath.Buffer);
-            wcscat(PathBuffer, DirKeyValue);
+            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                         DestinationRootPath.Buffer, DirKeyValue);
 
-            /* Remove trailing backslash */
-            Length = wcslen(PathBuffer);
-            if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
-            {
-                PathBuffer[Length - 1] = 0;
-            }
-
-            DPRINT("FullPath: '%S'\n", PathBuffer);
+            DPRINT("AbsolutePath(2): '%S'\n", PathBuffer);
 
             Status = SetupCreateDirectory(PathBuffer);
             if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
@@ -3796,18 +3751,10 @@ PrepareCopyPageInfFile(HINF InfFile,
             /* Path relative to the installation path */
             DPRINT("RelativePath: '%S'\n", DirKeyValue);
 
-            wcscpy(PathBuffer, DestinationPath.Buffer);
-            wcscat(PathBuffer, L"\\");
-            wcscat(PathBuffer, DirKeyValue);
+            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                         DestinationPath.Buffer, DirKeyValue);
 
-            /* Remove trailing backslash */
-            Length = wcslen(PathBuffer);
-            if ((Length > 0) && (PathBuffer[Length - 1] == L'\\'))
-            {
-                PathBuffer[Length - 1] = 0;
-            }
-
-            DPRINT("FullPath: '%S'\n", PathBuffer);
+            DPRINT("RelativePath(2): '%S'\n", PathBuffer);
 
             Status = SetupCreateDirectory(PathBuffer);
             if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
@@ -3879,9 +3826,8 @@ PrepareCopyPage(PINPUT_RECORD Ir)
         if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
             break;
 
-        wcscpy(PathBuffer, SourcePath.Buffer);
-        wcscat(PathBuffer, L"\\");
-        wcscat(PathBuffer, KeyValue);
+        CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                     SourcePath.Buffer, KeyValue);
 
         CabinetInitialize();
         CabinetSetEventHandlers(NULL, NULL, NULL);
@@ -4015,8 +3961,7 @@ FileCopyCallback(PVOID Context,
  * RETURNS
  *   Number of the next page.
  */
-static
-PAGE_NUMBER
+static PAGE_NUMBER
 FileCopyPage(PINPUT_RECORD Ir)
 {
     COPYCONTEXT CopyContext;
@@ -4124,15 +4069,19 @@ RegistryPage(PINPUT_RECORD Ir)
 
     if (RepairUpdateFlag)
     {
+        // FIXME!
+        DPRINT1("FIXME: Updating / repairing the registry is NOT implemented yet!\n");
         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);
@@ -4213,7 +4162,6 @@ RegistryPage(PINPUT_RECORD Ir)
     }
 
     /* Set GeoID */
-
     if (!SetGeoID(MUIGetGeoID()))
     {
         MUIDisplayError(ERROR_UPDATE_GEOID, Ir, POPUP_WAIT_ENTER);
@@ -4283,10 +4231,10 @@ BootLoaderPage(PINPUT_RECORD Ir)
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
     RtlFreeUnicodeString(&SystemRootPath);
-    swprintf(PathBuffer,
-             L"\\Device\\Harddisk%lu\\Partition%lu",
-             PartitionList->SystemDisk->DiskNumber,
-             PartitionList->SystemPartition->PartitionNumber);
+    StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"\\Device\\Harddisk%lu\\Partition%lu\\",
+            PartitionList->SystemPartition->DiskEntry->DiskNumber,
+            PartitionList->SystemPartition->PartitionNumber);
     RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
     DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath);
 
@@ -4447,7 +4395,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
 
     MUIDisplayPage(BOOT_LOADER_FLOPPY_PAGE);
 
-//  SetStatusText("   Please wait...");
+//  CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
     while (TRUE)
     {
@@ -4463,7 +4411,7 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D)    /* ENTER */
         {
-            if (DoesFileExist(L"\\Device\\Floppy0", L"\\") == FALSE)
+            if (DoesPathExist(NULL, L"\\Device\\Floppy0\\") == FALSE)
             {
                 MUIDisplayError(ERROR_NO_FLOPPY, Ir, POPUP_WAIT_ENTER);
                 return BOOT_LOADER_FLOPPY_PAGE;
@@ -4500,15 +4448,12 @@ BootLoaderFloppyPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
 {
-    UCHAR PartitionType;
     NTSTATUS Status;
 
-    PartitionType = PartitionList->SystemPartition->PartitionType;
-
     Status = InstallVBRToPartition(&SystemRootPath,
                                    &SourceRootPath,
                                    &DestinationArcPath,
-                                   PartitionType);
+                                   PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
@@ -4528,7 +4473,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
  *
  * SIDEEFFECTS
  *  Calls InstallVBRToPartition()
- *  CallsInstallMbrBootCodeToDisk()
+ *  Calls InstallMbrBootCodeToDisk()
  *
  * RETURNS
  *   Number of the next page.
@@ -4536,19 +4481,16 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
 {
-    UCHAR PartitionType;
     NTSTATUS Status;
     WCHAR DestinationDevicePathBuffer[MAX_PATH];
     WCHAR SourceMbrPathBuffer[MAX_PATH];
     WCHAR DstPath[MAX_PATH];
 
     /* Step 1: Write the VBR */
-    PartitionType = PartitionList->SystemPartition->PartitionType;
-
     Status = InstallVBRToPartition(&SystemRootPath,
                                    &SourceRootPath,
                                    &DestinationArcPath,
-                                   PartitionType);
+                                   PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
@@ -4556,18 +4498,16 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     }
 
     /* Step 2: Write the MBR */
-    swprintf(DestinationDevicePathBuffer,
-             L"\\Device\\Harddisk%d\\Partition0",
-             PartitionList->SystemDisk->DiskNumber);
+    StringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
+            L"\\Device\\Harddisk%d\\Partition0",
+            PartitionList->SystemPartition->DiskEntry->DiskNumber);
 
-    wcscpy(SourceMbrPathBuffer, SourceRootPath.Buffer);
-    wcscat(SourceMbrPathBuffer, L"\\loader\\dosmbr.bin");
+    CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, SourceRootPath.Buffer, L"\\loader\\dosmbr.bin");
 
     if (IsThereAValidBootSector(DestinationDevicePathBuffer))
     {
         /* Save current MBR */
-        wcscpy(DstPath, SystemRootPath.Buffer);
-        wcscat(DstPath, L"\\mbr.old");
+        CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath.Buffer, L"mbr.old");
 
         DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
         Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, sizeof(PARTITION_SECTOR));
@@ -4594,6 +4534,201 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
 }
 
 
+/**
+ * @name ProgressTimeOutStringHandler
+ *
+ * Handles the generation (displaying) of the timeout
+ * countdown to the screen dynamically.
+ *
+ * @param   Bar
+ *     A pointer to a progress bar.
+ *
+ * @param   AlwaysUpdate
+ *     Constantly update the progress bar (boolean type).
+ *
+ * @param   Buffer
+ *     A pointer to a string buffer.
+ *
+ * @param   cchBufferSize
+ *     The buffer's size in number of characters.
+ *
+ * @return
+ *     TRUE or FALSE on function termination.
+ *
+ */
+static
+BOOLEAN NTAPI
+ProgressTimeOutStringHandler(
+    IN PPROGRESSBAR Bar,
+    IN BOOLEAN AlwaysUpdate,
+    OUT PSTR Buffer,
+    IN SIZE_T cchBufferSize)
+{
+    ULONG OldProgress = Bar->Progress;
+
+    if (Bar->StepCount == 0)
+    {
+        Bar->Progress = 0;
+    }
+    else
+    {
+        Bar->Progress = Bar->StepCount - Bar->CurrentStep;
+    }
+
+    /* Build the progress string if it has changed */
+    if (Bar->ProgressFormatText &&
+        (AlwaysUpdate || (Bar->Progress != OldProgress)))
+    {
+        RtlStringCchPrintfA(Buffer, cchBufferSize,
+                            Bar->ProgressFormatText, Bar->Progress / max(1, Bar->Width) + 1);
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/**
+ * @name ProgressCountdown
+ *
+ * Displays and draws a red-coloured progress bar with a countdown.
+ * When the timeout is reached, the flush page is displayed for reboot.
+ *
+ * @param   Ir
+ *     A pointer to an input keyboard record.
+ *
+ * @param   TimeOut
+ *     Initial countdown value in seconds.
+ *
+ * @return
+ *     Nothing.
+ *
+ */
+static VOID
+ProgressCountdown(
+    IN PINPUT_RECORD Ir,
+    IN LONG TimeOut)
+{
+    NTSTATUS Status;
+    ULONG StartTime, BarWidth, TimerDiv;
+    LONG TimeElapsed;
+    LONG TimerValue, OldTimerValue;
+    LARGE_INTEGER Timeout;
+    PPROGRESSBAR ProgressBar;
+    BOOLEAN RefreshProgress = TRUE;
+
+    /* Bail out if the timeout is already zero */
+    if (TimeOut <= 0)
+        return;
+
+    /* Create the timeout progress bar and set it up */
+    ProgressBar = CreateProgressBarEx(13,
+                                      26,
+                                      xScreen - 13,
+                                      yScreen - 20,
+                                      10,
+                                      24,
+                                      TRUE,
+                                      FOREGROUND_RED | BACKGROUND_BLUE,
+                                      0,
+                                      NULL,
+                                      MUIGetString(STRING_REBOOTPROGRESSBAR),
+                                      ProgressTimeOutStringHandler);
+
+    BarWidth = max(1, ProgressBar->Width);
+    TimerValue = TimeOut * BarWidth;
+    ProgressSetStepCount(ProgressBar, TimerValue);
+
+    StartTime = NtGetTickCount();
+    CONSOLE_Flush();
+
+    TimerDiv = 1000 / BarWidth;
+    TimerDiv = max(1, TimerDiv);
+    OldTimerValue = TimerValue;
+    while (TRUE)
+    {
+        /* Decrease the timer */
+
+        /*
+         * Compute how much time the previous operations took.
+         * This allows us in particular to take account for any time
+         * elapsed if something slowed down.
+         */
+        TimeElapsed = NtGetTickCount() - StartTime;
+        if (TimeElapsed >= TimerDiv)
+        {
+            /* Increase StartTime by steps of 1 / ProgressBar->Width seconds */
+            TimeElapsed /= TimerDiv;
+            StartTime += (TimerDiv * TimeElapsed);
+
+            if (TimeElapsed <= TimerValue)
+                TimerValue -= TimeElapsed;
+            else
+                TimerValue = 0;
+
+            RefreshProgress = TRUE;
+        }
+
+        if (RefreshProgress)
+        {
+            ProgressSetStep(ProgressBar, OldTimerValue - TimerValue);
+            RefreshProgress = FALSE;
+        }
+
+        /* Stop when the timer reaches zero */
+        if (TimerValue <= 0)
+            break;
+
+        /* Check for user key presses */
+
+        /*
+         * If the timer is used, use a passive wait of maximum 1 second
+         * while monitoring for incoming console input events, so that
+         * we are still able to display the timing count.
+         */
+
+        /* Wait a maximum of 1 second for input events */
+        TimeElapsed = NtGetTickCount() - StartTime;
+        if (TimeElapsed < TimerDiv)
+        {
+            /* Convert the time to NT Format */
+            Timeout.QuadPart = (TimerDiv - TimeElapsed) * -10000LL;
+            Status = NtWaitForSingleObject(StdInput, FALSE, &Timeout);
+        }
+        else
+        {
+            Status = STATUS_TIMEOUT;
+        }
+
+        /* Check whether the input event has been signaled, or a timeout happened */
+        if (Status == STATUS_TIMEOUT)
+        {
+            continue;
+        }
+        if (Status != STATUS_WAIT_0)
+        {
+            /* An error happened, bail out */
+            DPRINT1("NtWaitForSingleObject() failed, Status 0x%08lx\n", Status);
+            break;
+        }
+
+        /* Check for an ENTER key press */
+        while (CONSOLE_ConInKeyPeek(Ir))
+        {
+            if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
+            {
+                /* Found it, stop waiting */
+                goto Exit;
+            }
+        }
+    }
+
+Exit:
+    /* Destroy the progress bar and quit */
+    DestroyProgressBar(ProgressBar);
+}
+
+
 /*
  * Displays the QuitPage.
  *
@@ -4611,48 +4746,51 @@ QuitPage(PINPUT_RECORD Ir)
 {
     MUIDisplayPage(QUIT_PAGE);
 
-    /* Destroy partition list */
+    /* Destroy the partition list */
     if (PartitionList != NULL)
     {
         DestroyPartitionList(PartitionList);
         PartitionList = NULL;
     }
+    TempPartition = NULL;
+    FormatState = Start;
 
-    /* Destroy filesystem list */
+    /* Destroy the filesystem list */
     if (FileSystemList != NULL)
     {
         DestroyFileSystemList(FileSystemList);
         FileSystemList = NULL;
     }
 
-    /* Destroy computer settings list */
+    /* Destroy the computer settings list */
     if (ComputerList != NULL)
     {
         DestroyGenericList(ComputerList, TRUE);
         ComputerList = NULL;
     }
 
-    /* Destroy display settings list */
+    /* Destroy the display settings list */
     if (DisplayList != NULL)
     {
         DestroyGenericList(DisplayList, TRUE);
         DisplayList = NULL;
     }
 
-    /* Destroy keyboard settings list */
+    /* Destroy the keyboard settings list */
     if (KeyboardList != NULL)
     {
         DestroyGenericList(KeyboardList, TRUE);
         KeyboardList = NULL;
     }
 
-    /* Destroy keyboard layout list */
+    /* Destroy the keyboard layout list */
     if (LayoutList != NULL)
     {
         DestroyGenericList(LayoutList, TRUE);
         LayoutList = NULL;
     }
 
+    /* Destroy the languages list */
     if (LanguageList != NULL)
     {
         DestroyGenericList(LanguageList, FALSE);
@@ -4661,15 +4799,9 @@ QuitPage(PINPUT_RECORD Ir)
 
     CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
 
-    while (TRUE)
-    {
-        CONSOLE_ConInKey(Ir);
-
-        if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
-        {
-            return FLUSH_PAGE;
-        }
-    }
+    /* Wait for maximum 15 seconds or an ENTER key before quitting */
+    ProgressCountdown(Ir, 15);
+    return FLUSH_PAGE;
 }
 
 
@@ -4691,19 +4823,11 @@ SuccessPage(PINPUT_RECORD Ir)
     MUIDisplayPage(SUCCESS_PAGE);
 
     if (IsUnattendedSetup)
-    {
         return FLUSH_PAGE;
-    }
-
-    while (TRUE)
-    {
-        CONSOLE_ConInKey(Ir);
 
-        if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */
-        {
-            return FLUSH_PAGE;
-        }
-    }
+    /* Wait for maximum 15 seconds or an ENTER key before quitting */
+    ProgressCountdown(Ir, 15);
+    return FLUSH_PAGE;
 }
 
 
@@ -4731,17 +4855,24 @@ PnpEventThread(IN LPVOID lpParameter);
 /*
  * The start routine and page management
  */
-VOID
+NTSTATUS
 RunUSetup(VOID)
 {
+    NTSTATUS Status;
     INPUT_RECORD Ir;
     PAGE_NUMBER Page;
-    LARGE_INTEGER Time;
-    NTSTATUS Status;
     BOOLEAN Old;
 
-    NtQuerySystemTime(&Time);
+    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(),
                                  NULL,
                                  TRUE,
@@ -4761,9 +4892,8 @@ RunUSetup(VOID)
         PrintString(MUIGetString(STRING_CONSOLEFAIL2));
         PrintString(MUIGetString(STRING_CONSOLEFAIL3));
 
-        /* Raise a hard error (crash the system/BSOD) */
-        NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
-                         0,0,0,0,0);
+        /* We failed to initialize the video, just quit the installer */
+        return STATUS_APP_INIT_FAILURE;
     }
 
     /* Initialize global unicode strings */
@@ -4779,37 +4909,36 @@ RunUSetup(VOID)
     /* Hide the cursor */
     CONSOLE_SetCursorType(TRUE, FALSE);
 
-    Page = START_PAGE;
+    /* Global Initialization page */
+    CONSOLE_ClearScreen();
+    CONSOLE_Flush();
+    Page = SetupStartPage(&Ir);
+
     while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
     {
         CONSOLE_ClearScreen();
         CONSOLE_Flush();
 
-        //CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
-        //CONSOLE_Flush();
+        // CONSOLE_SetUnderlinedTextXY(4, 3, " ReactOS " KERNEL_VERSION_STR " Setup ");
+        // CONSOLE_Flush();
 
         switch (Page)
         {
-            /* Start page */
-            case START_PAGE:
-                Page = SetupStartPage(&Ir);
-                break;
-
             /* Language page */
             case LANGUAGE_PAGE:
                 Page = LanguagePage(&Ir);
                 break;
 
+            /* Welcome page */
+            case WELCOME_PAGE:
+                Page = WelcomePage(&Ir);
+                break;
+
             /* License page */
             case LICENSE_PAGE:
                 Page = LicensePage(&Ir);
                 break;
 
-            /* Intro page */
-            case INTRO_PAGE:
-                Page = IntroPage(&Ir);
-                break;
-
             /* Install pages */
             case INSTALL_INTRO_PAGE:
                 Page = InstallIntroPage(&Ir);
@@ -4819,9 +4948,7 @@ RunUSetup(VOID)
             case SCSI_CONTROLLER_PAGE:
                 Page = ScsiControllerPage(&Ir);
                 break;
-#endif
 
-#if 0
             case OEM_DRIVER_PAGE:
                 Page = OemDriverPage(&Ir);
                 break;
@@ -4876,11 +5003,11 @@ RunUSetup(VOID)
                 break;
 
             case FORMAT_PARTITION_PAGE:
-                Page = (PAGE_NUMBER) FormatPartitionPage(&Ir);
+                Page = FormatPartitionPage(&Ir);
                 break;
 
             case CHECK_FILE_SYSTEM_PAGE:
-                Page = (PAGE_NUMBER) CheckFileSystemPage(&Ir);
+                Page = CheckFileSystemPage(&Ir);
                 break;
 
             case INSTALL_DIRECTORY_PAGE:
@@ -4943,26 +5070,50 @@ RunUSetup(VOID)
 
     FreeConsole();
 
-    /* Avoid bugcheck */
-    Time.QuadPart += 50000000;
-    NtDelayExecution(FALSE, &Time);
-
     /* Reboot */
     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
     NtShutdownSystem(ShutdownReboot);
     RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old);
-    NtTerminateProcess(NtCurrentProcess(), 0);
+
+    return STATUS_SUCCESS;
 }
 
 
 VOID NTAPI
 NtProcessStartup(PPEB Peb)
 {
+    NTSTATUS Status;
+    LARGE_INTEGER Time;
+
     RtlNormalizeProcessParams(Peb->ProcessParameters);
 
     ProcessHeap = Peb->ProcessHeap;
-    InfSetHeap(ProcessHeap);
-    RunUSetup();
+
+    NtQuerySystemTime(&Time);
+
+    Status = RunUSetup();
+
+    if (NT_SUCCESS(Status))
+    {
+        /*
+         * Avoid a bugcheck if RunUSetup() finishes too quickly by implementing
+         * a protective waiting.
+         * This wait is needed because, since we are started as SMSS.EXE,
+         * the NT kernel explicitly waits 5 seconds for the initial process
+         * SMSS.EXE to initialize (as a protective measure), and otherwise
+         * bugchecks with the code SESSION5_INITIALIZATION_FAILED.
+         */
+        Time.QuadPart += 50000000;
+        NtDelayExecution(FALSE, &Time);
+    }
+    else
+    {
+        /* The installer failed to start: raise a hard error (crash the system/BSOD) */
+        Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
+                                  0, 0, NULL, 0, NULL);
+    }
+
+    NtTerminateProcess(NtCurrentProcess(), Status);
 }
 
 /* EOF */