[SETUPLIB][USETUP] Improve disk HW numbering, removable disk support, and "super...
[reactos.git] / base / setup / usetup / usetup.c
index d951a65..82716f6 100644 (file)
@@ -22,7 +22,7 @@
  * FILE:            base/setup/usetup/usetup.c
  * PURPOSE:         Text-mode setup
  * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
- *                  Hervé Poussineau (hpoussin@reactos.org)
+ *                  Hervé Poussineau (hpoussin@reactos.org)
  */
 
 #include <usetup.h>
@@ -31,6 +31,7 @@
 #include "bootsup.h"
 #include "chkdsk.h"
 #include "cmdcons.h"
+#include "devinst.h"
 #include "format.h"
 
 #define NDEBUG
@@ -44,6 +45,10 @@ BOOLEAN IsUnattendedSetup = FALSE;
 
 static USETUP_DATA USetupData;
 
+/* Partition where to perform the installation */
+static PPARTENTRY InstallPartition = NULL;
+// static PPARTENTRY SystemPartition = NULL;    // The system partition we will actually use (can be different from PartitionList->SystemPartition in case we install on removable disk)
+
 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
 static WCHAR DestinationDriveLetter;
 
@@ -56,11 +61,17 @@ static WCHAR DefaultKBLayout[20];   // Copy of string inside KeyboardList
 
 static BOOLEAN RepairUpdateFlag = FALSE;
 
-static HANDLE hPnpThread = NULL;
-
+/* Global partition list on the system */
 static PPARTLIST PartitionList = NULL;
-static PPARTENTRY TempPartition = NULL;
+
+/* Currently selected partition entry in the list */
+static PPARTENTRY CurrentPartition = NULL;
+
+/* List of supported file systems for the partition to be formatted */
 static PFILE_SYSTEM_LIST FileSystemList = NULL;
+
+/* Machine state for the formatter */
+static PPARTENTRY TempPartition = NULL;
 static FORMATMACHINESTATE FormatState = Start;
 
 /*****************************************************/
@@ -69,19 +80,6 @@ static PNTOS_INSTALLATION CurrentInstallation = NULL;
 static PGENERIC_LIST NtOsInstallsList = NULL;
 
 
-// HACK: Temporary compatibility code.
-#if 1
-    static CABINET_CONTEXT CabinetContext;
-    #define CabinetInitialize() (CabinetInitialize(&CabinetContext))
-    #define CabinetSetEventHandlers(a,b,c) (CabinetSetEventHandlers(&CabinetContext,(a),(b),(c)))
-    #define CabinetSetCabinetName(a) (CabinetSetCabinetName(&CabinetContext,(a)))
-    #define CabinetOpen() (CabinetOpen(&CabinetContext))
-    #define CabinetGetCabinetName() (CabinetGetCabinetName(&CabinetContext))
-    #define CabinetGetCabinetReservedArea(a) (CabinetGetCabinetReservedArea(&CabinetContext,(a)))
-    #define CabinetCleanup() (CabinetCleanup(&CabinetContext))
-#endif
-
-
 /* FUNCTIONS ****************************************************************/
 
 static VOID
@@ -452,7 +450,7 @@ GetNTOSInstallationName(
     {
         /* We have retrieved a partition that is mounted */
         return RtlStringCchPrintfA(Buffer, cchBufferSize,
-                                   "%c:%S  \"%S\"",
+                                   "%C:%S  \"%S\"",
                                    PartEntry->DriveLetter,
                                    NtOsInstall->PathComponent,
                                    NtOsInstall->InstallationName);
@@ -646,7 +644,7 @@ SetupStartPage(PINPUT_RECORD Ir)
     PGENERIC_LIST_ENTRY ListEntry;
     PCWSTR LocaleId;
 
-    CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
+    MUIDisplayPage(SETUP_INIT_PAGE);
 
     /* Initialize Setup, phase 1 */
     Error = InitializeSetup(&USetupData, 1);
@@ -656,12 +654,13 @@ SetupStartPage(PINPUT_RECORD Ir)
         return QUIT_PAGE;
     }
 
-    /* Start the PnP thread */
-    if (hPnpThread != NULL)
-    {
-        NtResumeThread(hPnpThread, NULL);
-        hPnpThread = NULL;
-    }
+    /* Initialize the user-mode PnP manager */
+    if (!EnableUserModePnpManager())
+        DPRINT1("The user-mode PnP manager could not initialize, expect unavailable devices!\n");
+
+    /* Wait for any immediate pending installations to finish */
+    if (WaitNoPendingInstallEvents(NULL) != STATUS_WAIT_0)
+        DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
 
     CheckUnattendedSetup(&USetupData);
 
@@ -811,7 +810,7 @@ RepairIntroPage(PINPUT_RECORD Ir)
 {
     MUIDisplayPage(REPAIR_INTRO_PAGE);
 
-    while(TRUE)
+    while (TRUE)
     {
         CONSOLE_ConInKey(Ir);
 
@@ -871,6 +870,7 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
             return QUIT_PAGE;
         }
 
+        /* Reset the formatter machine state */
         TempPartition = NULL;
         FormatState = Start;
     }
@@ -1474,20 +1474,25 @@ SelectPartitionPage(PINPUT_RECORD Ir)
             return QUIT_PAGE;
         }
 
+        /* Reset the formatter machine state */
         TempPartition = NULL;
         FormatState = Start;
     }
 
     if (RepairUpdateFlag)
     {
+        ASSERT(CurrentInstallation);
+
         /* Determine the selected installation disk & partition */
-        if (!SelectPartition(PartitionList,
-                             CurrentInstallation->DiskNumber,
-                             CurrentInstallation->PartitionNumber))
+        InstallPartition = SelectPartition(PartitionList,
+                                           CurrentInstallation->DiskNumber,
+                                           CurrentInstallation->PartitionNumber);
+        if (!InstallPartition)
         {
             DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE, assert!\n");
             ASSERT(FALSE);
         }
+        ASSERT(!IsContainerPartition(InstallPartition->PartitionType));
 
         return SELECT_FILE_SYSTEM_PAGE;
     }
@@ -1495,50 +1500,62 @@ SelectPartitionPage(PINPUT_RECORD Ir)
     MUIDisplayPage(SELECT_PARTITION_PAGE);
 
     InitPartitionListUi(&ListUi, PartitionList,
-                        2,
-                        23,
+                        CurrentPartition,
+                        2, 23,
                         xScreen - 3,
                         yScreen - 3);
     DrawPartitionList(&ListUi);
 
     if (IsUnattendedSetup)
     {
-        if (!SelectPartition(PartitionList,
-                             USetupData.DestinationDiskNumber,
-                             USetupData.DestinationPartitionNumber))
+        /* Determine the selected installation disk & partition */
+        InstallPartition = SelectPartition(PartitionList,
+                                           USetupData.DestinationDiskNumber,
+                                           USetupData.DestinationPartitionNumber);
+        if (!InstallPartition)
         {
+            CurrentPartition = ListUi.CurrentPartition;
+
             if (USetupData.AutoPartition)
             {
-                if (PartitionList->CurrentPartition->LogicalPartition)
+                ASSERT(CurrentPartition != NULL);
+                ASSERT(!IsContainerPartition(CurrentPartition->PartitionType));
+
+                if (CurrentPartition->LogicalPartition)
                 {
                     CreateLogicalPartition(PartitionList,
-                                           PartitionList->CurrentPartition->SectorCount.QuadPart,
+                                           CurrentPartition,
+                                           CurrentPartition->SectorCount.QuadPart,
                                            TRUE);
                 }
                 else
                 {
                     CreatePrimaryPartition(PartitionList,
-                                           PartitionList->CurrentPartition->SectorCount.QuadPart,
+                                           CurrentPartition,
+                                           CurrentPartition->SectorCount.QuadPart,
                                            TRUE);
                 }
 
 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
-                if (!IsDiskSizeValid(PartitionList->CurrentPartition))
+                if (!IsDiskSizeValid(CurrentPartition))
                 {
                     MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
                                     USetupData.RequiredPartitionDiskSpace);
                     return SELECT_PARTITION_PAGE; /* let the user select another partition */
                 }
 
+                InstallPartition = CurrentPartition;
                 return SELECT_FILE_SYSTEM_PAGE;
             }
         }
         else
         {
-            DrawPartitionList(&ListUi);
+            ASSERT(!IsContainerPartition(InstallPartition->PartitionType));
+
+            DrawPartitionList(&ListUi); // FIXME: Doesn't make much sense...
 
 // FIXME?? Aren't we going to enter an infinite loop, if this test fails??
-            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
+            if (!IsDiskSizeValid(InstallPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
                                 USetupData.RequiredPartitionDiskSpace);
@@ -1551,14 +1568,16 @@ SelectPartitionPage(PINPUT_RECORD Ir)
 
     while (TRUE)
     {
+        CurrentPartition = ListUi.CurrentPartition;
+
         /* Update status text */
-        if (PartitionList->CurrentPartition == NULL)
+        if (CurrentPartition == NULL)
         {
             CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
         }
-        else if (PartitionList->CurrentPartition->LogicalPartition)
+        else if (CurrentPartition->LogicalPartition)
         {
-            if (PartitionList->CurrentPartition->IsPartitioned)
+            if (CurrentPartition->IsPartitioned)
             {
                 CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
             }
@@ -1569,9 +1588,9 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else
         {
-            if (PartitionList->CurrentPartition->IsPartitioned)
+            if (CurrentPartition->IsPartitioned)
             {
-                if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
+                if (IsContainerPartition(CurrentPartition->PartitionType))
                 {
                     CONSOLE_SetStatusText(MUIGetString(STRING_DELETEPARTITION));
                 }
@@ -1612,40 +1631,77 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN)  /* ENTER */
         {
-            if (IsContainerPartition(PartitionList->CurrentPartition->PartitionType))
+            ASSERT(CurrentPartition != NULL);
+
+            if (IsContainerPartition(CurrentPartition->PartitionType))
                 continue; // return SELECT_PARTITION_PAGE;
 
-            if (PartitionList->CurrentPartition == NULL ||
-                PartitionList->CurrentPartition->IsPartitioned == FALSE)
+            /*
+             * Check whether the user wants to install ReactOS on a disk that
+             * is not recognized by the computer's firmware and if so, display
+             * a warning since such disks may not be bootable.
+             */
+            if (CurrentPartition->DiskEntry->MediaType == FixedMedia &&
+                !CurrentPartition->DiskEntry->BiosFound)
             {
-                if (PartitionList->CurrentPartition->LogicalPartition)
+                PopupError("The disk you have selected for installing ReactOS\n"
+                           "is not visible by the firmware of your computer,\n"
+                           "and so may not be bootable.\n"
+                           "Press ENTER to continue nonetheless.",
+                           MUIGetString(STRING_CONTINUE),
+                           Ir, POPUP_WAIT_ENTER);
+                // return SELECT_PARTITION_PAGE;
+            }
+
+            if (CurrentPartition->IsPartitioned == FALSE)
+            {
+                if (CurrentPartition->LogicalPartition)
                 {
+                    Error = LogicalPartitionCreationChecks(CurrentPartition);
+                    if (Error != NOT_AN_ERROR)
+                    {
+                        MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
+                        return SELECT_PARTITION_PAGE;
+                    }
+
                     CreateLogicalPartition(PartitionList,
+                                           CurrentPartition,
                                            0ULL,
                                            TRUE);
                 }
                 else
                 {
+                    Error = PrimaryPartitionCreationChecks(CurrentPartition);
+                    if (Error != NOT_AN_ERROR)
+                    {
+                        MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
+                        return SELECT_PARTITION_PAGE;
+                    }
+
                     CreatePrimaryPartition(PartitionList,
+                                           CurrentPartition,
                                            0ULL,
                                            TRUE);
                 }
             }
 
-            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
+            if (!IsDiskSizeValid(CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, POPUP_WAIT_ANY_KEY,
                                 USetupData.RequiredPartitionDiskSpace);
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
 
+            InstallPartition = CurrentPartition;
             return SELECT_FILE_SYSTEM_PAGE;
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'P')  /* P */
         {
-            if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
+            ASSERT(CurrentPartition != NULL);
+
+            if (CurrentPartition->LogicalPartition == FALSE)
             {
-                Error = PrimaryPartitionCreationChecks(PartitionList);
+                Error = PrimaryPartitionCreationChecks(CurrentPartition);
                 if (Error != NOT_AN_ERROR)
                 {
                     MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
@@ -1657,9 +1713,11 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'E')  /* E */
         {
-            if (PartitionList->CurrentPartition->LogicalPartition == FALSE)
+            ASSERT(CurrentPartition != NULL);
+
+            if (CurrentPartition->LogicalPartition == FALSE)
             {
-                Error = ExtendedPartitionCreationChecks(PartitionList);
+                Error = ExtendedPartitionCreationChecks(CurrentPartition);
                 if (Error != NOT_AN_ERROR)
                 {
                     MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
@@ -1671,9 +1729,11 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'L')  /* L */
         {
-            if (PartitionList->CurrentPartition->LogicalPartition)
+            ASSERT(CurrentPartition != NULL);
+
+            if (CurrentPartition->LogicalPartition)
             {
-                Error = LogicalPartitionCreationChecks(PartitionList);
+                Error = LogicalPartitionCreationChecks(CurrentPartition);
                 if (Error != NOT_AN_ERROR)
                 {
                     MUIDisplayError(Error, Ir, POPUP_WAIT_ANY_KEY);
@@ -1685,36 +1745,47 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D')  /* D */
         {
+            UNICODE_STRING CurrentPartitionU;
             WCHAR PathBuffer[MAX_PATH];
-            UNICODE_STRING CurrentPartition;
 
-            if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
+            ASSERT(CurrentPartition != NULL);
+
+            if (CurrentPartition->IsPartitioned == FALSE)
             {
                 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
                 return SELECT_PARTITION_PAGE;
             }
 
-            RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
-                    L"\\Device\\Harddisk%lu\\Partition%lu\\",
-                    PartitionList->CurrentDisk->DiskNumber,
-                    PartitionList->CurrentPartition->PartitionNumber);
-            RtlInitUnicodeString(&CurrentPartition, PathBuffer);
-
-            /*
-             * Check whether the user attempts to delete the partition on which
-             * the installation source is present. If so, fail with an error.
-             */
-            // &USetupData.SourceRootPath
-            if (RtlPrefixUnicodeString(&CurrentPartition, &USetupData.SourcePath, TRUE))
+// TODO: Do something similar before trying to format the partition?
+            if (!CurrentPartition->New &&
+                !IsContainerPartition(CurrentPartition->PartitionType) &&
+                CurrentPartition->FormatState != Unformatted)
             {
-                PopupError("You cannot delete the partition containing the installation source!",
-                           MUIGetString(STRING_CONTINUE),
-                           Ir, POPUP_WAIT_ENTER);
-                return SELECT_PARTITION_PAGE;
+                ASSERT(CurrentPartition->PartitionNumber != 0);
+
+                RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                        L"\\Device\\Harddisk%lu\\Partition%lu\\",
+                        CurrentPartition->DiskEntry->DiskNumber,
+                        CurrentPartition->PartitionNumber);
+                RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
+
+                /*
+                 * Check whether the user attempts to delete the partition on which
+                 * the installation source is present. If so, fail with an error.
+                 */
+                // &USetupData.SourceRootPath
+                if (RtlPrefixUnicodeString(&CurrentPartitionU, &USetupData.SourcePath, TRUE))
+                {
+                    PopupError("You cannot delete the partition containing the installation source!",
+                               MUIGetString(STRING_CONTINUE),
+                               Ir, POPUP_WAIT_ENTER);
+                    return SELECT_PARTITION_PAGE;
+                }
             }
 
-            if (PartitionList->CurrentPartition->BootIndicator ||
-                PartitionList->CurrentPartition == PartitionList->SystemPartition)
+// FIXME TODO: PartitionList->SystemPartition is not yet initialized!!!!
+            if (CurrentPartition == PartitionList->SystemPartition ||
+                CurrentPartition->BootIndicator)
             {
                 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
             }
@@ -1728,7 +1799,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
 
 
 #define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
-/* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
+/* Restriction for MaxSize */
 #define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
 
 static VOID
@@ -1928,8 +1999,8 @@ ShowPartitionSizeInputBox(SHORT Left,
 static PAGE_NUMBER
 CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     BOOLEAN Quit;
     BOOLEAN Cancel;
     WCHAR InputBuffer[50];
@@ -1939,16 +2010,14 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
     ULONGLONG SectorCount;
     PCHAR Unit;
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || CurrentPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->CurrentDisk;
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
+    DiskEntry = CurrentPartition->DiskEntry;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
@@ -1982,7 +2051,9 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
     else
     {
@@ -1994,19 +2065,21 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
 
 #if 0
     CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
-                        PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
+                        CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
 #endif
 
     CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
 
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
     while (TRUE)
     {
         MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB;  /* in MBytes (rounded) */
@@ -2063,6 +2136,7 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
             DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
             CreatePrimaryPartition(PartitionList,
+                                   CurrentPartition,
                                    SectorCount,
                                    FALSE);
 
@@ -2087,8 +2161,8 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 CreateExtendedPartitionPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     BOOLEAN Quit;
     BOOLEAN Cancel;
     WCHAR InputBuffer[50];
@@ -2098,16 +2172,14 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
     ULONGLONG SectorCount;
     PCHAR Unit;
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || CurrentPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->CurrentDisk;
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
+    DiskEntry = CurrentPartition->DiskEntry;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
@@ -2141,7 +2213,9 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
     else
     {
@@ -2153,19 +2227,21 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
 
 #if 0
     CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
-                        PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
+                        CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
 #endif
 
     CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
 
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
     while (TRUE)
     {
         MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB;  /* in MBytes (rounded) */
@@ -2222,6 +2298,7 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
             DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
             CreateExtendedPartition(PartitionList,
+                                    CurrentPartition,
                                     SectorCount);
 
             return SELECT_PARTITION_PAGE;
@@ -2245,8 +2322,8 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 CreateLogicalPartitionPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     BOOLEAN Quit;
     BOOLEAN Cancel;
     WCHAR InputBuffer[50];
@@ -2256,16 +2333,14 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
     ULONGLONG SectorCount;
     PCHAR Unit;
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || CurrentPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->CurrentDisk;
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
+    DiskEntry = CurrentPartition->DiskEntry;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
@@ -2299,7 +2374,9 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
     else
     {
@@ -2311,19 +2388,21 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
 
     CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_HDDSIZE));
 
 #if 0
     CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
-                        PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
+                        CurrentPartition->SectorCount * DiskEntry->BytesPerSector / MB);
 #endif
 
     CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
 
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
     while (TRUE)
     {
         MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / MB;  /* in MBytes (rounded) */
@@ -2380,6 +2459,7 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
             DPRINT("Partition size: %I64u bytes\n", PartSize);
 
             CreateLogicalPartition(PartitionList,
+                                   CurrentPartition,
                                    SectorCount,
                                    FALSE);
 
@@ -2445,26 +2525,25 @@ ConfirmDeleteSystemPartitionPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 DeletePartitionPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     ULONGLONG DiskSize;
     ULONGLONG PartSize;
     PCHAR Unit;
     CHAR PartTypeString[32];
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || CurrentPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->CurrentDisk;
-    PartEntry = PartitionList->CurrentPartition;
+    PartEntry = CurrentPartition;
+    DiskEntry = CurrentPartition->DiskEntry;
 
     MUIDisplayPage(DELETE_PARTITION_PAGE);
 
+    /* Adjust partition type */
     GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
                                        PartTypeString,
                                        ARRAYSIZE(PartTypeString));
@@ -2493,7 +2572,7 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     {
         CONSOLE_PrintTextXY(6, 10,
                             MUIGetString(STRING_HDDINFOUNK2),
-                            (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                            (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
                             (PartEntry->DriveLetter == 0) ? '-' : ':',
                             PartEntry->PartitionType,
                             PartSize,
@@ -2503,7 +2582,7 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     {
         CONSOLE_PrintTextXY(6, 10,
                             "   %c%c  %s    %I64u %s",
-                            (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                            (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
                             (PartEntry->DriveLetter == 0) ? '-' : ':',
                             PartTypeString,
                             PartSize,
@@ -2538,7 +2617,9 @@ DeletePartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
     else
     {
@@ -2550,7 +2631,9 @@ DeletePartitionPage(PINPUT_RECORD Ir)
                             DiskEntry->Port,
                             DiskEntry->Bus,
                             DiskEntry->Id,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
 
     while (TRUE)
@@ -2571,8 +2654,9 @@ DeletePartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
         {
-            DeleteCurrentPartition(PartitionList);
-
+            DeletePartition(PartitionList,
+                            CurrentPartition,
+                            &CurrentPartition);
             return SELECT_PARTITION_PAGE;
         }
     }
@@ -2581,6 +2665,16 @@ DeletePartitionPage(PINPUT_RECORD Ir)
 }
 
 
+static VOID
+ResetFileSystemList(VOID)
+{
+    if (!FileSystemList)
+        return;
+
+    DestroyFileSystemList(FileSystemList);
+    FileSystemList = NULL;
+}
+
 /*
  * Displays the SelectFileSystemPage.
  *
@@ -2593,7 +2687,7 @@ DeletePartitionPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
+ *  Calls UpdatePartitionType()
  *  Calls CheckActiveSystemPartition()
  *
  * RETURNS
@@ -2602,58 +2696,140 @@ DeletePartitionPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 SelectFileSystemPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     ULONGLONG DiskSize;
     ULONGLONG PartSize;
     PCHAR DiskUnit;
     PCHAR PartUnit;
     CHAR PartTypeString[32];
     FORMATMACHINESTATE PreviousFormatState;
+    PCWSTR DefaultFs;
 
     DPRINT("SelectFileSystemPage()\n");
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || InstallPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    /* Find or set the active system partition */
-    CheckActiveSystemPartition(PartitionList);
-    if (PartitionList->SystemPartition == NULL)
+    /* Find or set the active system partition when starting formatting */
+    if (FormatState == Start)
     {
-        /* 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;
+        /* Find or set the active system partition */
+        CheckActiveSystemPartition(PartitionList,
+                                   FALSE,
+                                   InstallPartition->DiskEntry,
+                                   InstallPartition);
+        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;
+        }
+
+        /*
+         * If the system partition can be created in some
+         * non-partitioned space, create it now.
+         */
+        if (!PartitionList->SystemPartition->IsPartitioned)
+        {
+            // if (IsUnattendedSetup)
+            {
+                CreatePrimaryPartition(PartitionList,
+                                       PartitionList->SystemPartition,
+                                       0LL, // PartitionList->SystemPartition->SectorCount.QuadPart,
+                                       TRUE);
+                ASSERT(PartitionList->SystemPartition->IsPartitioned);
+            }
+            // else
+            {
+            }
+        }
+
+        /* Commit all partition changes to all the disks */
+        if (!WritePartitionsToDisk(PartitionList))
+        {
+            DPRINT("WritePartitionsToDisk() failed\n");
+            MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
+            return QUIT_PAGE;
+        }
+
+        /*
+         * In all cases, whether or not we are going to perform a formatting,
+         * we must perform a filesystem check of both the system and the
+         * installation partitions.
+         */
+        InstallPartition->NeedsCheck = TRUE;
+        if (PartitionList->SystemPartition != InstallPartition)
+            PartitionList->SystemPartition->NeedsCheck = TRUE;
+
+        /*
+         * In case we just repair an existing installation, or make
+         * an unattended setup without formatting, just go to the
+         * filesystem check step.
+         */
+        if (RepairUpdateFlag)
+            return CHECK_FILE_SYSTEM_PAGE;
+
+        if (IsUnattendedSetup && !USetupData.FormatPartition)
+            return CHECK_FILE_SYSTEM_PAGE;
     }
 
+    // ASSERT(PartitionList->SystemPartition->IsPartitioned);
+
+    /* Reset the filesystem list for each partition that is to be formatted */
+    ResetFileSystemList();
+
     PreviousFormatState = FormatState;
     switch (FormatState)
     {
         case Start:
         {
-            if (PartitionList->CurrentPartition != PartitionList->SystemPartition)
+            /*
+             * We start by formatting the system partition in case it is new
+             * (it didn't exist before) and is not the same as the installation
+             * partition. Otherwise we just require a filesystem check on it,
+             * and start by formatting the installation partition instead.
+             */
+
+            ASSERT(PartitionList->SystemPartition->IsPartitioned);
+
+            if ((PartitionList->SystemPartition != InstallPartition) &&
+                (PartitionList->SystemPartition->FormatState == Unformatted))
             {
                 TempPartition = PartitionList->SystemPartition;
                 TempPartition->NeedsCheck = TRUE;
 
+                // TODO: Should we let the user using a custom file-system,
+                // or should we always use FAT(32) for it?
+                // For "compatibility", FAT(32) would be best indeed.
+
                 FormatState = FormatSystemPartition;
                 DPRINT1("FormatState: Start --> FormatSystemPartition\n");
             }
             else
             {
-                TempPartition = PartitionList->CurrentPartition;
+                TempPartition = InstallPartition;
                 TempPartition->NeedsCheck = TRUE;
 
+                if (PartitionList->SystemPartition != InstallPartition)
+                {
+                    /* The system partition is separate, so it had better be formatted! */
+                    ASSERT((PartitionList->SystemPartition->FormatState == Preformatted) ||
+                           (PartitionList->SystemPartition->FormatState == Formatted));
+
+                    /* Require a filesystem check on the system partition too */
+                    PartitionList->SystemPartition->NeedsCheck = TRUE;
+                }
+
                 FormatState = FormatInstallPartition;
                 DPRINT1("FormatState: Start --> FormatInstallPartition\n");
             }
@@ -2662,7 +2838,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 
         case FormatSystemPartition:
         {
-            TempPartition = PartitionList->CurrentPartition;
+            TempPartition = InstallPartition;
             TempPartition->NeedsCheck = TRUE;
 
             FormatState = FormatInstallPartition;
@@ -2671,6 +2847,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         }
 
         case FormatInstallPartition:
+        case FormatOtherPartition:
         {
             if (GetNextUnformattedPartition(PartitionList,
                                             NULL,
@@ -2678,34 +2855,30 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
             {
                 FormatState = FormatOtherPartition;
                 TempPartition->NeedsCheck = TRUE;
-                DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
+
+                if (FormatState == FormatInstallPartition)
+                    DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
+                else
+                    DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
             }
             else
             {
                 FormatState = FormatDone;
-                DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
+
+                if (FormatState == FormatInstallPartition)
+                    DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
+                else
+                    DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
+
                 return CHECK_FILE_SYSTEM_PAGE;
             }
             break;
         }
 
-        case FormatOtherPartition:
+        case FormatDone:
         {
-            if (GetNextUnformattedPartition(PartitionList,
-                                            NULL,
-                                            &TempPartition))
-            {
-                FormatState = FormatOtherPartition;
-                TempPartition->NeedsCheck = TRUE;
-                DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
-            }
-            else
-            {
-                FormatState = FormatDone;
-                DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
-                return CHECK_FILE_SYSTEM_PAGE;
-            }
-            break;
+            DPRINT1("FormatState: FormatDone\n");
+            return CHECK_FILE_SYSTEM_PAGE;
         }
 
         default:
@@ -2717,7 +2890,9 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
     }
 
     PartEntry = TempPartition;
-    DiskEntry = PartEntry->DiskEntry;
+    DiskEntry = TempPartition->DiskEntry;
+
+    ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
     /* Adjust disk size */
     DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
@@ -2772,7 +2947,9 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
 
         CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
 
@@ -2808,7 +2985,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         {
             CONSOLE_PrintTextXY(8, 10,
                                 MUIGetString(STRING_HDDINFOUNK4),
-                                (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                                (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
                                 (PartEntry->DriveLetter == 0) ? '-' : ':',
                                 PartEntry->PartitionType,
                                 PartSize,
@@ -2818,7 +2995,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         {
             CONSOLE_PrintTextXY(8, 10,
                                 "%c%c  %s    %I64u %s",
-                                (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                                (PartEntry->DriveLetter == 0) ? '-' : (CHAR)PartEntry->DriveLetter,
                                 (PartEntry->DriveLetter == 0) ? '-' : ':',
                                 PartTypeString,
                                 PartSize,
@@ -2833,41 +3010,52 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                             DiskEntry->Bus,
                             DiskEntry->Id,
                             &DiskEntry->DriverName,
-                            DiskEntry->NoMbr ? "GPT" : "MBR");
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
     }
 
-    if (FileSystemList == NULL)
+    ASSERT(FileSystemList == NULL);
+
+    if (IsUnattendedSetup)
     {
-        /* Create the file system list, and by default select the "FAT" file system */
-        FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, L"FAT");
-        if (FileSystemList == NULL)
+        ASSERT(USetupData.FormatPartition);
+
+        switch (USetupData.FsType)
         {
-            /* FIXME: show an error dialog */
-            return QUIT_PAGE;
+            /* 1 is for BtrFS */
+            case 1:
+                DefaultFs = L"BTRFS";
+                break;
+
+            /* If we don't understand input, default to FAT */
+            default:
+                DefaultFs = L"FAT";
+                break;
         }
     }
+    else
+    {
+        /* By default select the "FAT" file system */
+        DefaultFs = L"FAT";
+    }
 
-    if (RepairUpdateFlag)
+    /* Create the file system list */
+    // TODO: Display only the FSes compatible with the selected partition!
+    FileSystemList = CreateFileSystemList(6, 26,
+                                          PartEntry->New ||
+                                          PartEntry->FormatState == Unformatted,
+                                          DefaultFs);
+    if (FileSystemList == NULL)
     {
-        return CHECK_FILE_SYSTEM_PAGE;
-        //return SELECT_PARTITION_PAGE;
+        /* FIXME: show an error dialog */
+        return QUIT_PAGE;
     }
 
     if (IsUnattendedSetup)
     {
-        if (USetupData.FormatPartition)
-        {
-            /*
-             * 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;
+        ASSERT(USetupData.FormatPartition);
+        return FORMAT_PARTITION_PAGE;
     }
 
     DrawFileSystemList(FileSystemList);
@@ -2880,14 +3068,24 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))  /* F3 */
         {
             if (ConfirmQuit(Ir))
+            {
+                /* Reset the filesystem list */
+                ResetFileSystemList();
                 return QUIT_PAGE;
+            }
 
             break;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE))  /* ESC */
         {
+            /* Reset the formatter machine state */
+            TempPartition = NULL;
             FormatState = Start;
+
+            /* Reset the filesystem list */
+            ResetFileSystemList();
+
             return SELECT_PARTITION_PAGE;
         }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
@@ -2903,9 +3101,27 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
         {
             if (!FileSystemList->Selected->FileSystem)
+            {
+                ASSERT(!TempPartition->New && TempPartition->FormatState != Unformatted);
+
+                /*
+                 * Skip formatting this partition. We will also ignore
+                 * filesystem checks on it, unless it is either the system
+                 * or the installation partition.
+                 */
+                if (TempPartition != PartitionList->SystemPartition &&
+                    TempPartition != InstallPartition)
+                {
+                    PartEntry->NeedsCheck = FALSE;
+                }
+
                 return SELECT_FILE_SYSTEM_PAGE;
+            }
             else
+            {
+                /* Format this partition */
                 return FORMAT_PARTITION_PAGE;
+            }
         }
     }
 
@@ -2924,7 +3140,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Sets PartitionList->CurrentPartition->FormatState
+ *  Sets InstallPartition->FormatState
  *  Sets USetupData.DestinationRootPath
  *
  * RETURNS
@@ -2934,8 +3150,8 @@ static PAGE_NUMBER
 FormatPartitionPage(PINPUT_RECORD Ir)
 {
     NTSTATUS Status;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     PFILE_SYSTEM_ITEM SelectedFileSystem;
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
@@ -2958,22 +3174,27 @@ FormatPartitionPage(PINPUT_RECORD Ir)
     }
 
     PartEntry = TempPartition;
-    DiskEntry = PartEntry->DiskEntry;
+    DiskEntry = TempPartition->DiskEntry;
+
+    ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
     SelectedFileSystem = FileSystemList->Selected;
+    ASSERT(SelectedFileSystem && SelectedFileSystem->FileSystem);
 
     while (TRUE)
     {
         if (!IsUnattendedSetup)
-        {
             CONSOLE_ConInKey(Ir);
-        }
 
         if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
             (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))  /* F3 */
         {
             if (ConfirmQuit(Ir))
+            {
+                /* Reset the filesystem list */
+                ResetFileSystemList();
                 return QUIT_PAGE;
+            }
 
             break;
         }
@@ -2984,6 +3205,10 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem))
             {
                 /* FIXME: show an error dialog */
+
+                /* Reset the filesystem list */
+                ResetFileSystemList();
+
                 return QUIT_PAGE;
             }
 
@@ -3015,10 +3240,17 @@ FormatPartitionPage(PINPUT_RECORD Ir)
 #endif
 
             /* Commit the partition changes to the disk */
-            if (!WritePartitionsToDisk(PartitionList))
+            Status = WritePartitions(DiskEntry);
+            if (!NT_SUCCESS(Status))
             {
-                DPRINT("WritePartitionsToDisk() failed\n");
+                DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
+                        DiskEntry->DiskNumber, Status);
+
                 MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
+
+                /* Reset the filesystem list */
+                ResetFileSystemList();
+
                 return QUIT_PAGE;
             }
 
@@ -3031,53 +3263,65 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
 
             /* Format the partition */
-            if (SelectedFileSystem->FileSystem)
+            Status = FormatPartition(&PartitionRootPath,
+                                     SelectedFileSystem->FileSystem,
+                                     SelectedFileSystem->QuickFormat);
+            if (Status == STATUS_NOT_SUPPORTED)
             {
-                Status = FormatPartition(&PartitionRootPath,
-                                         SelectedFileSystem);
-                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);
+
+                PopupError(Buffer,
+                           MUIGetString(STRING_QUITCONTINUE),
+                           NULL, POPUP_WAIT_NONE);
+
+                while (TRUE)
                 {
-                    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);
+                    CONSOLE_ConInKey(Ir);
 
-                        if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
-                            Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)  /* F3 */
+                    if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
+                        Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)  /* F3 */
+                    {
+                        if (ConfirmQuit(Ir))
                         {
-                            if (ConfirmQuit(Ir))
-                                return QUIT_PAGE;
-                            else
-                                return SELECT_FILE_SYSTEM_PAGE;
+                            /* Reset the filesystem list */
+                            ResetFileSystemList();
+                            return QUIT_PAGE;
                         }
-                        else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
+                        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);
-                    return QUIT_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);
+
+                /* Reset the filesystem list */
+                ResetFileSystemList();
 
-                PartEntry->FormatState = Formatted;
-                // PartEntry->FileSystem  = FileSystem;
-                PartEntry->New = FALSE;
+                return QUIT_PAGE;
             }
 
+//
+// TODO: Here, call a partlist.c function that update the actual FS name
+// and the label fields of the volume.
+//
+            PartEntry->FormatState = Formatted;
+            // PartEntry->FileSystem  = FileSystem;
+            PartEntry->New = FALSE;
+
 #ifndef NDEBUG
             CONSOLE_SetStatusText("   Done.  Press any key ...");
             CONSOLE_ConInKey(Ir);
@@ -3110,7 +3354,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     NTSTATUS Status;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PFILE_SYSTEM CurrentFileSystem;
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
     CHAR Buffer[MAX_PATH];
@@ -3126,38 +3369,46 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
         return INSTALL_DIRECTORY_PAGE;
     }
 
-    /* Set PartitionRootPath */
-    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
-            L"\\Device\\Harddisk%lu\\Partition%lu",
-            DiskEntry->DiskNumber,
-            PartEntry->PartitionNumber);
-    RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
-    DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
+    ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
     CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-    CurrentFileSystem = PartEntry->FileSystem;
-    DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
-            PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a"));
+    DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
+            PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
 
     /* HACK: Do not try to check a partition with an unknown filesystem */
-    if (CurrentFileSystem == NULL)
+    if (!*PartEntry->FileSystem)
     {
         PartEntry->NeedsCheck = FALSE;
         return CHECK_FILE_SYSTEM_PAGE;
     }
 
-    Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
+    /* Set PartitionRootPath */
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"\\Device\\Harddisk%lu\\Partition%lu",
+            DiskEntry->DiskNumber,
+            PartEntry->PartitionNumber);
+    RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
+    DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
+
+    /* Check the partition */
+    Status = ChkdskPartition(&PartitionRootPath, PartEntry->FileSystem);
     if (Status == STATUS_NOT_SUPPORTED)
     {
+        /*
+         * Partition checking is not supported with the current filesystem,
+         * so disable FS checks on it.
+         */
+        PartEntry->NeedsCheck = FALSE;
+
         sprintf(Buffer,
                 "Setup is currently unable to check a partition formatted in %S.\n"
                 "\n"
                 "  \x07  Press ENTER to continue Setup.\n"
                 "  \x07  Press F3 to quit Setup.",
-                CurrentFileSystem->FileSystemName);
+                PartEntry->FileSystem);
 
         PopupError(Buffer,
                    MUIGetString(STRING_QUITCONTINUE),
@@ -3177,7 +3428,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
             }
             else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
             {
-                PartEntry->NeedsCheck = FALSE;
                 return CHECK_FILE_SYSTEM_PAGE;
             }
         }
@@ -3201,19 +3451,25 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 }
 
 
-static VOID
-BuildInstallPaths(PWSTR InstallDir,
-                  PDISKENTRY DiskEntry,
-                  PPARTENTRY PartEntry)
+static NTSTATUS
+BuildInstallPaths(
+    IN PCWSTR InstallDir,
+    IN PPARTENTRY PartEntry)
 {
     NTSTATUS Status;
 
-    Status = InitDestinationPaths(&USetupData, InstallDir, DiskEntry, PartEntry);
-    // TODO: Check Status
-    UNREFERENCED_PARAMETER(Status);
+    Status = InitDestinationPaths(&USetupData, InstallDir, PartEntry);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("InitDestinationPaths() failed with status 0x%08lx\n", Status);
+        return Status;
+    }
 
     /* Initialize DestinationDriveLetter */
-    DestinationDriveLetter = (WCHAR)PartEntry->DriveLetter;
+    DestinationDriveLetter = PartEntry->DriveLetter;
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -3276,30 +3532,20 @@ IsValidPath(
 static PAGE_NUMBER
 InstallDirectoryPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
-    WCHAR InstallDir[MAX_PATH];
-    WCHAR c;
+    NTSTATUS Status;
     ULONG Length, Pos;
+    WCHAR c;
+    WCHAR InstallDir[MAX_PATH];
 
     /* We do not need the filesystem list anymore */
-    if (FileSystemList != NULL)
-    {
-        DestroyFileSystemList(FileSystemList);
-        FileSystemList = NULL;
-    }
+    ResetFileSystemList();
 
-    if (PartitionList == NULL ||
-        PartitionList->CurrentDisk == NULL ||
-        PartitionList->CurrentPartition == NULL)
+    if (PartitionList == NULL || InstallPartition == NULL)
     {
         /* FIXME: show an error dialog */
         return QUIT_PAGE;
     }
 
-    DiskEntry = PartitionList->CurrentDisk;
-    PartEntry = PartitionList->CurrentPartition;
-
     // if (IsUnattendedSetup)
     if (RepairUpdateFlag)
         wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
@@ -3317,9 +3563,15 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
      */
     if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
     {
-        BuildInstallPaths(InstallDir,
-                          DiskEntry,
-                          PartEntry);
+        Status = BuildInstallPaths(InstallDir, InstallPartition);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status);
+            PopupError("Failed to build the installation paths for the ReactOS installation directory!",
+                       MUIGetString(STRING_CONTINUE),
+                       Ir, POPUP_WAIT_ENTER);
+            return QUIT_PAGE;
+        }
 
         /*
          * Check whether the user attempts to install ReactOS within the
@@ -3419,9 +3671,15 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
                 return INSTALL_DIRECTORY_PAGE;
             }
 
-            BuildInstallPaths(InstallDir,
-                              DiskEntry,
-                              PartEntry);
+            Status = BuildInstallPaths(InstallDir, InstallPartition);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status);
+                PopupError("Failed to build the installation paths for the ReactOS installation directory!",
+                           MUIGetString(STRING_CONTINUE),
+                           Ir, POPUP_WAIT_ENTER);
+                return QUIT_PAGE;
+            }
 
             /*
              * Check whether the user attempts to install ReactOS within the
@@ -3481,433 +3739,28 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
 }
 
 
-static BOOLEAN
-AddSectionToCopyQueueCab(HINF InfFile,
-                         PCWSTR SectionName,
-                         PCWSTR SourceCabinet,
-                         PCUNICODE_STRING DestinationPath,
-                         PINPUT_RECORD Ir)
-{
-    INFCONTEXT FilesContext;
-    INFCONTEXT DirContext;
-    PCWSTR FileKeyName;
-    PCWSTR FileKeyValue;
-    PCWSTR DirKeyValue;
-    PCWSTR TargetFileName;
-    WCHAR FileDstPath[MAX_PATH];
-
-    /*
-     * 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 (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
-    {
-        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
-        return FALSE;
-    }
-
-    /*
-     * Enumerate the files in the section and add them to the file queue.
-     */
-    do
-    {
-        /* Get source file name and target directory id */
-        if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            break;
-        }
-
-        /* Get optional target file name */
-        if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
-            TargetFileName = NULL;
-
-        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
-
-        /* Lookup target directory */
-        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SetupFindFirstLine() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(FileKeyValue);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        INF_FreeData(FileKeyValue);
-
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-#if 1 // HACK moved! (r66604)
-        {
-        ULONG Length = wcslen(DirKeyValue);
-        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
-            Length--;
-        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
-        }
-
-        /* Build the full target path */
-        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
-                          USetupData.DestinationRootPath.Buffer);
-        if (DirKeyValue[0] == UNICODE_NULL)
-        {
-            /* Installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            // if (DirKeyValue[1] != UNICODE_NULL)
-                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
-                        USetupData.InstallPath.Buffer, DirKeyValue);
-        }
-#endif
-
-        if (!SpFileQueueCopy((HSPFILEQ)USetupData.SetupFileQueue,
-                             USetupData.SourceRootPath.Buffer,
-                             USetupData.SourceRootDir.Buffer,
-                             FileKeyName,
-                             NULL,
-                             SourceCabinet,
-                             NULL,
-                             FileDstPath,
-                             TargetFileName,
-                             0 /* FIXME */))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SpFileQueueCopy() failed\n");
-        }
-
-        INF_FreeData(FileKeyName);
-        INF_FreeData(TargetFileName);
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
-
-    return TRUE;
-}
-
-
-static BOOLEAN
-AddSectionToCopyQueue(HINF InfFile,
-                      PCWSTR SectionName,
-                      PCWSTR SourceCabinet,
-                      PCUNICODE_STRING DestinationPath,
-                      PINPUT_RECORD Ir)
-{
-    INFCONTEXT FilesContext;
-    INFCONTEXT DirContext;
-    PCWSTR FileKeyName;
-    PCWSTR FileKeyValue;
-    PCWSTR DirKeyValue;
-    PCWSTR TargetFileName;
-    WCHAR CompleteOrigDirName[512]; // FIXME: MAX_PATH is not enough?
-    WCHAR FileDstPath[MAX_PATH];
-
-    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 (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
-    {
-        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
-        return FALSE;
-    }
-
-    /*
-     * Enumerate the files in the section and add them to the file queue.
-     */
-    do
-    {
-        /* Get source file name */
-        if (!INF_GetDataField(&FilesContext, 0, &FileKeyName))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            break;
-        }
-
-        /* Get target directory id */
-        if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            break;
-        }
-
-        /* Get optional target file name */
-        if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
-            TargetFileName = NULL;
-        else if (!*TargetFileName)
-            TargetFileName = NULL;
-
-        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
-
-        /* Lookup target directory */
-        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SetupFindFirstLine() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(FileKeyValue);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        INF_FreeData(FileKeyValue);
-
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
-        {
-            /* Installation path */
-            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                              USetupData.SourceRootDir.Buffer);
-
-            DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                              DirKeyValue);
-
-            DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-            DPRINT("RelativePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 2,
-                         USetupData.SourceRootDir.Buffer, DirKeyValue);
-
-            DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName);
-        }
-
-#if 1 // HACK moved! (r66604)
-        {
-        ULONG Length = wcslen(DirKeyValue);
-        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
-            Length--;
-        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
-        }
-
-        /* Build the full target path */
-        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
-                          USetupData.DestinationRootPath.Buffer);
-        if (DirKeyValue[0] == UNICODE_NULL)
-        {
-            /* Installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            // if (DirKeyValue[1] != UNICODE_NULL)
-                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
-                        USetupData.InstallPath.Buffer, DirKeyValue);
-        }
-#endif
-
-        if (!SpFileQueueCopy((HSPFILEQ)USetupData.SetupFileQueue,
-                             USetupData.SourceRootPath.Buffer,
-                             CompleteOrigDirName,
-                             FileKeyName,
-                             NULL,
-                             SourceCabinet,
-                             NULL,
-                             FileDstPath,
-                             TargetFileName,
-                             0 /* FIXME */))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SpFileQueueCopy() failed\n");
-        }
-
-        INF_FreeData(FileKeyName);
-        INF_FreeData(TargetFileName);
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
-
-    return TRUE;
-}
-
-
-static BOOLEAN
-PrepareCopyPageInfFile(HINF InfFile,
-                       PCWSTR SourceCabinet,
-                       PINPUT_RECORD Ir)
+// PSETUP_ERROR_ROUTINE
+static VOID
+__cdecl
+USetupErrorRoutine(
+    IN PUSETUP_DATA pSetupData,
+    ...)
 {
-    NTSTATUS Status;
-    INFCONTEXT DirContext;
-    PWCHAR AdditionalSectionName = NULL;
-    PCWSTR DirKeyValue;
-    WCHAR PathBuffer[MAX_PATH];
-
-    /* Add common files */
-    if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &USetupData.DestinationPath, Ir))
-        return FALSE;
-
-    /* Add specific files depending of computer type */
-    if (SourceCabinet == NULL)
-    {
-        if (!ProcessComputerFiles(InfFile, USetupData.ComputerList, &AdditionalSectionName))
-            return FALSE;
-
-        if (AdditionalSectionName)
-        {
-            if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &USetupData.DestinationPath, Ir))
-                return FALSE;
-        }
-    }
-
-    /* Create directories */
-
-    /*
-     * FIXME:
-     * Copying files to USetupData.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 USetupData.DestinationPath specify just '\' .
-     */
-
-    /* Get destination path */
-    RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), USetupData.DestinationPath.Buffer);
+    INPUT_RECORD Ir;
+    va_list arg_ptr;
 
-    DPRINT("FullPath(1): '%S'\n", PathBuffer);
+    va_start(arg_ptr, pSetupData);
 
-    /* Create the install directory */
-    Status = SetupCreateDirectory(PathBuffer);
-    if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+    if (pSetupData->LastErrorNumber >= ERROR_SUCCESS &&
+        pSetupData->LastErrorNumber <  ERROR_LAST_ERROR_CODE)
     {
-        DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
-        MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
-        return FALSE;
+        // Note: the "POPUP_WAIT_ENTER" actually depends on the LastErrorNumber...
+        MUIDisplayErrorV(pSetupData->LastErrorNumber, &Ir, POPUP_WAIT_ENTER, arg_ptr);
     }
 
-    /* Search for the 'Directories' section */
-    if (!SpInfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
-    {
-        if (SourceCabinet)
-            MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
-        else
-            MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
-
-        return FALSE;
-    }
-
-    /* Enumerate the directory values and create the subdirectories */
-    do
-    {
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            DPRINT1("break\n");
-            break;
-        }
-
-        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
-        {
-            /* Installation path */
-            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
-                              USetupData.DestinationPath.Buffer);
-
-            DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         USetupData.DestinationRootPath.Buffer, DirKeyValue);
-
-            DPRINT("AbsolutePath(2): '%S'\n", PathBuffer);
-
-            Status = SetupCreateDirectory(PathBuffer);
-            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
-            {
-                INF_FreeData(DirKeyValue);
-                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
-                MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
-                return FALSE;
-            }
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-            DPRINT("RelativePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         USetupData.DestinationPath.Buffer, DirKeyValue);
-
-            DPRINT("RelativePath(2): '%S'\n", PathBuffer);
-
-            Status = SetupCreateDirectory(PathBuffer);
-            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
-            {
-                INF_FreeData(DirKeyValue);
-                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
-                MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
-                return FALSE;
-            }
-        }
-
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&DirContext, &DirContext));
-
-    return TRUE;
+    va_end(arg_ptr);
 }
 
-
 /*
  * Displays the PrepareCopyPage.
  *
@@ -3916,8 +3769,7 @@ PrepareCopyPageInfFile(HINF InfFile,
  *  QuitPage
  *
  * SIDEEFFECTS
- * Inits SetupFileQueue
- * Calls PrepareCopyPageInfFile
+ * Calls PrepareFileCopy
  *
  * RETURNS
  *   Number of the next page.
@@ -3925,92 +3777,18 @@ PrepareCopyPageInfFile(HINF InfFile,
 static PAGE_NUMBER
 PrepareCopyPage(PINPUT_RECORD Ir)
 {
-    HINF InfHandle;
-    WCHAR PathBuffer[MAX_PATH];
-    INFCONTEXT CabinetsContext;
-    ULONG InfFileSize;
-    PCWSTR KeyValue;
-    UINT ErrorLine;
-    PVOID InfFileData;
+    // ERROR_NUMBER ErrorNumber;
+    BOOLEAN Success;
 
     MUIDisplayPage(PREPARE_COPY_PAGE);
 
-    /* Create the file queue */
-    USetupData.SetupFileQueue = SpFileQueueOpen();
-    if (USetupData.SetupFileQueue == NULL)
+    /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
+    if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
     {
-        MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
+        // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
 
-    if (!PrepareCopyPageInfFile(USetupData.SetupInf, NULL, Ir))
-    {
-        /* FIXME: show an error dialog */
-        return QUIT_PAGE;
-    }
-
-    /* Search for the 'Cabinets' section */
-    if (!SpInfFindFirstLine(USetupData.SetupInf, L"Cabinets", NULL, &CabinetsContext))
-    {
-        return FILE_COPY_PAGE;
-    }
-
-    /*
-     * Enumerate the directory values in the 'Cabinets'
-     * section and parse their inf files.
-     */
-    do
-    {
-        if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
-            break;
-
-        CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                     USetupData.SourcePath.Buffer, KeyValue);
-
-        CabinetInitialize();
-        CabinetSetEventHandlers(NULL, NULL, NULL);
-        CabinetSetCabinetName(PathBuffer);
-
-        if (CabinetOpen() == CAB_STATUS_SUCCESS)
-        {
-            DPRINT("Cabinet %S\n", CabinetGetCabinetName());
-
-            InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
-            if (InfFileData == NULL)
-            {
-                MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
-                return QUIT_PAGE;
-            }
-        }
-        else
-        {
-            DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
-            MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
-            return QUIT_PAGE;
-        }
-
-        InfHandle = INF_OpenBufferedFileA((PSTR)InfFileData,
-                                          InfFileSize,
-                                          NULL,
-                                          INF_STYLE_WIN4,
-                                          USetupData.LanguageId,
-                                          &ErrorLine);
-
-        if (InfHandle == INVALID_HANDLE_VALUE)
-        {
-            MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
-            return QUIT_PAGE;
-        }
-
-        CabinetCleanup();
-
-        if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
-        {
-            /* FIXME: show an error dialog */
-            return QUIT_PAGE;
-        }
-    } while (SpInfFindNextLine(&CabinetsContext, &CabinetsContext));
-
     return FILE_COPY_PAGE;
 }
 
@@ -4165,8 +3943,7 @@ FileCopyCallback(PVOID Context,
  *  RegistryPage(At once)
  *
  * SIDEEFFECTS
- *  Calls SetupCommitFileQueueW
- *  Calls SpFileQueueClose
+ *  Calls DoFileCopy
  *
  * RETURNS
  *   Number of the next page.
@@ -4228,13 +4005,9 @@ FileCopyPage(PINPUT_RECORD Ir)
                                                   "Free Memory");
 
     /* Do the file copying */
-    SpFileQueueCommit(NULL,
-                      USetupData.SetupFileQueue,
-                      FileCopyCallback,
-                      &CopyContext);
+    DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
 
-    /* If we get here, we're done, so cleanup the queue and progress bar */
-    SpFileQueueClose(USetupData.SetupFileQueue);
+    /* If we get here, we're done, so cleanup the progress bar */
     DestroyProgressBar(CopyContext.ProgressBar);
     DestroyProgressBar(CopyContext.MemoryBars[0]);
     DestroyProgressBar(CopyContext.MemoryBars[1]);
@@ -4349,6 +4122,8 @@ BootLoaderPage(PINPUT_RECORD Ir)
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
+    ASSERT(PartitionList->SystemPartition->IsPartitioned && PartitionList->SystemPartition->PartitionNumber != 0);
+
     RtlFreeUnicodeString(&USetupData.SystemRootPath);
     RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
@@ -4384,10 +4159,10 @@ BootLoaderPage(PINPUT_RECORD Ir)
         DPRINT("Found OS/2 boot manager partition\n");
         InstallOnFloppy = TRUE;
     }
-    else if (PartitionType == PARTITION_EXT2)
+    else if (PartitionType == PARTITION_LINUX)
     {
-        /* Linux EXT2 partition */
-        DPRINT("Found Linux EXT2 partition\n");
+        /* Linux partition */
+        DPRINT("Found Linux native partition (ext2/ext3/ReiserFS/BTRFS/etc)\n");
         InstallOnFloppy = FALSE;
     }
     else if (PartitionType == PARTITION_IFS)
@@ -4467,6 +4242,24 @@ BootLoaderPage(PINPUT_RECORD Ir)
 
             CONSOLE_InvertTextXY(8, Line, 60, 1);
         }
+        else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+                 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_HOME))  /* HOME */
+        {
+            CONSOLE_NormalTextXY(8, Line, 60, 1);
+
+            Line = 12;
+
+            CONSOLE_InvertTextXY(8, Line, 60, 1);
+        }
+        else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
+                 (Ir->Event.KeyEvent.wVirtualKeyCode == VK_END))  /* END */
+        {
+            CONSOLE_NormalTextXY(8, Line, 60, 1);
+
+            Line = 15;
+            
+            CONSOLE_InvertTextXY(8, Line, 60, 1);
+        }
         else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
                  (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3))  /* F3 */
         {
@@ -4603,13 +4396,15 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
 {
     NTSTATUS Status;
 
+    // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
     Status = InstallVBRToPartition(&USetupData.SystemRootPath,
                                    &USetupData.SourceRootPath,
                                    &USetupData.DestinationArcPath,
                                    PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
-        MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
+        MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
@@ -4638,28 +4433,33 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     WCHAR DestinationDevicePathBuffer[MAX_PATH];
 
     /* Step 1: Write the VBR */
+    // FIXME! We must not use the partition type, but instead use the partition FileSystem!!
     Status = InstallVBRToPartition(&USetupData.SystemRootPath,
                                    &USetupData.SourceRootPath,
                                    &USetupData.DestinationArcPath,
                                    PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
-        MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER);
+        MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
-    /* Step 2: Write the MBR */
-    RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
-            L"\\Device\\Harddisk%d\\Partition0",
-            PartitionList->SystemPartition->DiskEntry->DiskNumber);
-    Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
-                                      &USetupData.SourceRootPath,
-                                      DestinationDevicePathBuffer);
-    if (!NT_SUCCESS(Status))
+    /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
+    if (!IsSuperFloppy(PartitionList->SystemPartition->DiskEntry))
     {
-        DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
-        MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
+        RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
+                L"\\Device\\Harddisk%d\\Partition0",
+                PartitionList->SystemPartition->DiskEntry->DiskNumber);
+        Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
+                                          &USetupData.SourceRootPath,
+                                          DestinationDevicePathBuffer);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("InstallMbrBootCodeToDisk() failed (Status %lx)\n", Status);
+            MUIDisplayError(ERROR_INSTALL_BOOTCODE, Ir, POPUP_WAIT_ENTER, L"MBR");
+            return QUIT_PAGE;
+        }
     }
 
     return SUCCESS_PAGE;
@@ -4892,15 +4692,12 @@ QuitPage(PINPUT_RECORD Ir)
         PartitionList = NULL;
     }
 
+    /* Reset the formatter machine state */
     TempPartition = NULL;
     FormatState = Start;
 
     /* Destroy the filesystem list */
-    if (FileSystemList != NULL)
-    {
-        DestroyFileSystemList(FileSystemList);
-        FileSystemList = NULL;
-    }
+    ResetFileSystemList();
 
     CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));
 
@@ -4953,10 +4750,6 @@ FlushPage(PINPUT_RECORD Ir)
 }
 
 
-DWORD WINAPI
-PnpEventThread(IN LPVOID lpParameter);
-
-
 /*
  * The start routine and page management
  */
@@ -4975,19 +4768,13 @@ RunUSetup(VOID)
     if (!NT_SUCCESS(Status))
         DPRINT1("NtInitializeRegistry() failed (Status 0x%08lx)\n", Status);
 
-    /* Create the PnP thread in suspended state */
-    Status = RtlCreateUserThread(NtCurrentProcess(),
-                                 NULL,
-                                 TRUE,
-                                 0,
-                                 0,
-                                 0,
-                                 PnpEventThread,
-                                 &USetupData.SetupInf,
-                                 &hPnpThread,
-                                 NULL);
+    /* Initialize the user-mode PnP manager */
+    Status = InitializeUserModePnpManager(&USetupData.SetupInf);
     if (!NT_SUCCESS(Status))
-        hPnpThread = NULL;
+    {
+        // PrintString(??);
+        DPRINT1("The user-mode PnP manager could not initialize (Status 0x%08lx), expect unavailable devices!\n", Status);
+    }
 
     if (!CONSOLE_Init())
     {
@@ -5001,13 +4788,14 @@ RunUSetup(VOID)
 
     /* Initialize Setup, phase 0 */
     InitializeSetup(&USetupData, 0);
+    USetupData.ErrorRoutine = USetupErrorRoutine;
 
-    /* Hide the cursor */
+    /* Hide the cursor and clear the screen and keyboard buffer */
     CONSOLE_SetCursorType(TRUE, FALSE);
-
-    /* Global Initialization page */
     CONSOLE_ClearScreen();
     CONSOLE_Flush();
+
+    /* Global Initialization page */
     Page = SetupStartPage(&Ir);
 
     while (Page != REBOOT_PAGE && Page != RECOVERY_PAGE)
@@ -5159,12 +4947,17 @@ RunUSetup(VOID)
                 Page = QuitPage(&Ir);
                 break;
 
-            case RECOVERY_PAGE:
+            /* Virtual pages */
+            case SETUP_INIT_PAGE:
             case REBOOT_PAGE:
+            case RECOVERY_PAGE:
                 break;
         }
     }
 
+    /* Terminate the user-mode PnP manager */
+    TerminateUserModePnpManager();
+
     /* Setup has finished */
     FinishSetup(&USetupData);