[SETUPLIB][USETUP] Remove CurrentDisk/Partition from the partlist lib code, and move...
[reactos.git] / base / setup / usetup / usetup.c
index f16d651..4367361 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;
 
 /*****************************************************/
@@ -633,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);
@@ -643,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);
 
@@ -798,7 +810,7 @@ RepairIntroPage(PINPUT_RECORD Ir)
 {
     MUIDisplayPage(REPAIR_INTRO_PAGE);
 
-    while(TRUE)
+    while (TRUE)
     {
         CONSOLE_ConInKey(Ir);
 
@@ -858,6 +870,7 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
             return QUIT_PAGE;
         }
 
+        /* Reset the formatter machine state */
         TempPartition = NULL;
         FormatState = Start;
     }
@@ -1461,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;
     }
@@ -1482,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);
@@ -1538,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));
             }
@@ -1556,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));
                 }
@@ -1599,40 +1631,60 @@ 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)
+            if (CurrentPartition->IsPartitioned == FALSE)
             {
-                if (PartitionList->CurrentPartition->LogicalPartition)
+                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);
@@ -1644,9 +1696,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);
@@ -1658,9 +1712,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);
@@ -1672,36 +1728,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;
             }
@@ -1715,7 +1782,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
@@ -1915,8 +1982,8 @@ ShowPartitionSizeInputBox(SHORT Left,
 static PAGE_NUMBER
 CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
 {
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry;
     BOOLEAN Quit;
     BOOLEAN Cancel;
     WCHAR InputBuffer[50];
@@ -1926,16 +1993,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));
 
@@ -1969,7 +2034,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
     {
@@ -1981,19 +2048,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) */
@@ -2050,6 +2119,7 @@ CreatePrimaryPartitionPage(PINPUT_RECORD Ir)
             DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
             CreatePrimaryPartition(PartitionList,
+                                   CurrentPartition,
                                    SectorCount,
                                    FALSE);
 
@@ -2074,8 +2144,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];
@@ -2085,16 +2155,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));
 
@@ -2128,7 +2196,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
     {
@@ -2140,19 +2210,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) */
@@ -2209,6 +2281,7 @@ CreateExtendedPartitionPage(PINPUT_RECORD Ir)
             DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
             CreateExtendedPartition(PartitionList,
+                                    CurrentPartition,
                                     SectorCount);
 
             return SELECT_PARTITION_PAGE;
@@ -2232,8 +2305,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];
@@ -2243,16 +2316,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));
 
@@ -2286,7 +2357,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
     {
@@ -2298,19 +2371,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) */
@@ -2367,6 +2442,7 @@ CreateLogicalPartitionPage(PINPUT_RECORD Ir)
             DPRINT("Partition size: %I64u bytes\n", PartSize);
 
             CreateLogicalPartition(PartitionList,
+                                   CurrentPartition,
                                    SectorCount,
                                    FALSE);
 
@@ -2432,26 +2508,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));
@@ -2525,7 +2600,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
     {
@@ -2537,7 +2614,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)
@@ -2558,8 +2637,9 @@ DeletePartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
         {
-            DeleteCurrentPartition(PartitionList);
-
+            DeletePartition(PartitionList,
+                            CurrentPartition,
+                            &CurrentPartition);
             return SELECT_PARTITION_PAGE;
         }
     }
@@ -2568,6 +2648,16 @@ DeletePartitionPage(PINPUT_RECORD Ir)
 }
 
 
+static VOID
+ResetFileSystemList(VOID)
+{
+    if (!FileSystemList)
+        return;
+
+    DestroyFileSystemList(FileSystemList);
+    FileSystemList = NULL;
+}
+
 /*
  * Displays the SelectFileSystemPage.
  *
@@ -2580,7 +2670,7 @@ DeletePartitionPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Sets PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType (via UpdatePartitionType)
+ *  Calls UpdatePartitionType()
  *  Calls CheckActiveSystemPartition()
  *
  * RETURNS
@@ -2589,58 +2679,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");
             }
@@ -2649,7 +2821,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 
         case FormatSystemPartition:
         {
-            TempPartition = PartitionList->CurrentPartition;
+            TempPartition = InstallPartition;
             TempPartition->NeedsCheck = TRUE;
 
             FormatState = FormatInstallPartition;
@@ -2658,6 +2830,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         }
 
         case FormatInstallPartition:
+        case FormatOtherPartition:
         {
             if (GetNextUnformattedPartition(PartitionList,
                                             NULL,
@@ -2665,34 +2838,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:
@@ -2704,7 +2873,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;
@@ -2759,7 +2930,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));
 
@@ -2820,41 +2993,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);
@@ -2867,14 +3051,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) &&
@@ -2890,9 +3084,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;
+            }
         }
     }
 
@@ -2911,7 +3123,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
  *  QuitPage
  *
  * SIDEEFFECTS
- *  Sets PartitionList->CurrentPartition->FormatState
+ *  Sets InstallPartition->FormatState
  *  Sets USetupData.DestinationRootPath
  *
  * RETURNS
@@ -2921,8 +3133,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];
@@ -2945,22 +3157,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;
         }
@@ -2971,6 +3188,10 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem))
             {
                 /* FIXME: show an error dialog */
+
+                /* Reset the filesystem list */
+                ResetFileSystemList();
+
                 return QUIT_PAGE;
             }
 
@@ -3002,10 +3223,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;
             }
 
@@ -3018,53 +3246,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);
 
-                PartEntry->FormatState = Formatted;
-                // PartEntry->FileSystem  = FileSystem;
-                PartEntry->New = FALSE;
+                /* Reset the filesystem list */
+                ResetFileSystemList();
+
+                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);
@@ -3097,7 +3337,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];
@@ -3113,38 +3352,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),
@@ -3164,7 +3411,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
             }
             else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
             {
-                PartEntry->NeedsCheck = FALSE;
                 return CHECK_FILE_SYSTEM_PAGE;
             }
         }
@@ -3188,19 +3434,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 = PartEntry->DriveLetter;
+
+    return STATUS_SUCCESS;
 }
 
 
@@ -3263,30 +3515,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
@@ -3304,9 +3546,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
@@ -3406,9 +3654,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
@@ -3851,6 +4105,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\\",
@@ -3969,6 +4225,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 */
         {
@@ -4113,7 +4387,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem->FileSystemName);
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
@@ -4150,7 +4424,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem->FileSystemName);
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
@@ -4398,15 +4672,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));
 
@@ -4459,10 +4730,6 @@ FlushPage(PINPUT_RECORD Ir)
 }
 
 
-DWORD WINAPI
-PnpEventThread(IN LPVOID lpParameter);
-
-
 /*
  * The start routine and page management
  */
@@ -4481,19 +4748,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())
     {
@@ -4509,12 +4770,12 @@ RunUSetup(VOID)
     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)
@@ -4666,12 +4927,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);