[SETUPLIB][USETUP] Improve disk HW numbering, removable disk support, and "super...
[reactos.git] / base / setup / lib / utils / partlist.c
index 89178ae..1930748 100644 (file)
@@ -2,7 +2,8 @@
  * PROJECT:     ReactOS Setup Library
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Partition list functions
- * COPYRIGHT:   Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * COPYRIGHT:   Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Copyright 2018-2019 Hermes Belusca-Maito
  */
 
 #include "precomp.h"
@@ -324,13 +325,15 @@ AssignDriveLetters(
     Letter = L'C';
 
     /* Assign drive letters to primary partitions */
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    for (Entry1 = List->DiskListHead.Flink;
+         Entry1 != &List->DiskListHead;
+         Entry1 = Entry1->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
-        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
-        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+             Entry2 != &DiskEntry->PrimaryPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
@@ -339,9 +342,10 @@ AssignDriveLetters(
             if (PartEntry->IsPartitioned &&
                 !IsContainerPartition(PartEntry->PartitionType))
             {
+                ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
                 if (IsRecognizedPartition(PartEntry->PartitionType) ||
-                    (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
-                     PartEntry->SectorCount.QuadPart != 0LL))
+                    PartEntry->SectorCount.QuadPart != 0LL)
                 {
                     if (Letter <= L'Z')
                     {
@@ -350,21 +354,19 @@ AssignDriveLetters(
                     }
                 }
             }
-
-            Entry2 = Entry2->Flink;
         }
-
-        Entry1 = Entry1->Flink;
     }
 
     /* Assign drive letters to logical drives */
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    for (Entry1 = List->DiskListHead.Flink;
+         Entry1 != &List->DiskListHead;
+         Entry1 = Entry1->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
-        Entry2 = DiskEntry->LogicalPartListHead.Flink;
-        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+             Entry2 != &DiskEntry->LogicalPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
@@ -372,9 +374,10 @@ AssignDriveLetters(
 
             if (PartEntry->IsPartitioned)
             {
+                ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
                 if (IsRecognizedPartition(PartEntry->PartitionType) ||
-                    (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
-                     PartEntry->SectorCount.QuadPart != 0LL))
+                    PartEntry->SectorCount.QuadPart != 0LL)
                 {
                     if (Letter <= L'Z')
                     {
@@ -383,11 +386,7 @@ AssignDriveLetters(
                     }
                 }
             }
-
-            Entry2 = Entry2->Flink;
         }
-
-        Entry1 = Entry1->Flink;
     }
 }
 
@@ -405,7 +404,8 @@ DiskIdentifierQueryRoutine(
     UNICODE_STRING NameU;
 
     if (ValueType == REG_SZ &&
-        ValueLength == 20 * sizeof(WCHAR))
+        ValueLength == 20 * sizeof(WCHAR) &&
+        ((PWCHAR)ValueData)[8] == L'-')
     {
         NameU.Buffer = (PWCHAR)ValueData;
         NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
@@ -518,6 +518,7 @@ EnumerateBiosDiskEntries(
     RTL_QUERY_REGISTRY_TABLE QueryTable[3];
     WCHAR Name[120];
     ULONG AdapterCount;
+    ULONG ControllerCount;
     ULONG DiskCount;
     NTSTATUS Status;
     PCM_INT13_DRIVE_PARAMETER Int13Drives;
@@ -541,8 +542,7 @@ EnumerateBiosDiskEntries(
         return;
     }
 
-    AdapterCount = 0;
-    while (TRUE)
+    for (AdapterCount = 0; ; ++AdapterCount)
     {
         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
                             L"%s\\%lu",
@@ -567,11 +567,11 @@ EnumerateBiosDiskEntries(
                                         NULL);
         if (NT_SUCCESS(Status))
         {
-            while (TRUE)
+            for (ControllerCount = 0; ; ++ControllerCount)
             {
                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                    L"%s\\%lu\\DiskController\\0",
-                                    ROOT_NAME, AdapterCount);
+                                    L"%s\\%lu\\DiskController\\%lu",
+                                    ROOT_NAME, AdapterCount, ControllerCount);
                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                 Name,
                                                 &QueryTable[2],
@@ -584,8 +584,8 @@ EnumerateBiosDiskEntries(
                 }
 
                 RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                    L"%s\\%lu\\DiskController\\0\\DiskPeripheral",
-                                    ROOT_NAME, AdapterCount);
+                                    L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral",
+                                    ROOT_NAME, AdapterCount, ControllerCount);
                 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                 Name,
                                                 &QueryTable[2],
@@ -598,18 +598,18 @@ EnumerateBiosDiskEntries(
                     QueryTable[1].Name = L"Configuration Data";
                     QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
 
-                    DiskCount = 0;
-                    while (TRUE)
+                    for (DiskCount = 0; ; ++DiskCount)
                     {
                         BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
                         if (BiosDiskEntry == NULL)
                         {
-                            break;
+                            RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+                            return;
                         }
 
                         RtlStringCchPrintfW(Name, ARRAYSIZE(Name),
-                                            L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu",
-                                            ROOT_NAME, AdapterCount, DiskCount);
+                                            L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu",
+                                            ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
                         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
                                                         Name,
                                                         QueryTable,
@@ -618,11 +618,14 @@ EnumerateBiosDiskEntries(
                         if (!NT_SUCCESS(Status))
                         {
                             RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
-                            break;
+                            RtlFreeHeap(ProcessHeap, 0, Int13Drives);
+                            return;
                         }
 
+                        BiosDiskEntry->AdapterNumber = 0; // And NOT "AdapterCount" as it needs to be hardcoded for BIOS!
+                        BiosDiskEntry->ControllerNumber = ControllerCount;
                         BiosDiskEntry->DiskNumber = DiskCount;
-                        BiosDiskEntry->Recognized = FALSE;
+                        BiosDiskEntry->DiskEntry = NULL;
 
                         if (DiskCount < Int13Drives[0].NumberDrives)
                         {
@@ -630,11 +633,14 @@ EnumerateBiosDiskEntries(
                         }
                         else
                         {
-                            DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
+                            DPRINT1("Didn't find Int13 drive data for disk %u\n", DiskCount);
                         }
 
                         InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
 
+                        DPRINT("--->\n");
+                        DPRINT("AdapterNumber:     %lu\n", BiosDiskEntry->AdapterNumber);
+                        DPRINT("ControllerNumber:  %lu\n", BiosDiskEntry->ControllerNumber);
                         DPRINT("DiskNumber:        %lu\n", BiosDiskEntry->DiskNumber);
                         DPRINT("Signature:         %08lx\n", BiosDiskEntry->Signature);
                         DPRINT("Checksum:          %08lx\n", BiosDiskEntry->Checksum);
@@ -646,17 +652,11 @@ EnumerateBiosDiskEntries(
                         DPRINT("SectorsPerTrack:   %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
                         DPRINT("MaxHeads:          %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
                         DPRINT("NumberDrives:      %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
-
-                        DiskCount++;
+                        DPRINT("<---\n");
                     }
                 }
-
-                RtlFreeHeap(ProcessHeap, 0, Int13Drives);
-                return;
             }
         }
-
-        AdapterCount++;
     }
 
     RtlFreeHeap(ProcessHeap, 0, Int13Drives);
@@ -664,6 +664,258 @@ EnumerateBiosDiskEntries(
 #undef ROOT_NAME
 }
 
+
+/*
+ * Detects whether a disk reports as a "super-floppy", i.e. an unpartitioned
+ * disk with a valid VBR, following the criteria used by IoReadPartitionTable()
+ * and IoWritePartitionTable():
+ * only one single partition starting at the beginning of the disk; the reported
+ * defaults are: partition number being zero and its type being FAT16 non-bootable.
+ * Note also that accessing \Device\HarddiskN\Partition0 or Partition1 returns
+ * the same data.
+ */
+// static
+BOOLEAN
+IsSuperFloppy(
+    IN PDISKENTRY DiskEntry)
+{
+    PPARTITION_INFORMATION PartitionInfo;
+    ULONGLONG PartitionLengthEstimate;
+
+    /* No layout buffer: we cannot say anything yet */
+    if (DiskEntry->LayoutBuffer == NULL)
+        return FALSE;
+
+    /* We must have only one partition */
+    if (DiskEntry->LayoutBuffer->PartitionCount != 1)
+        return FALSE;
+
+    /* Get the single partition entry */
+    PartitionInfo = DiskEntry->LayoutBuffer->PartitionEntry;
+
+    /* The single partition must start at the beginning of the disk */
+    if (!(PartitionInfo->StartingOffset.QuadPart == 0 &&
+          PartitionInfo->HiddenSectors == 0))
+    {
+        return FALSE;
+    }
+
+    /* The disk signature is usually set to one; warn in case it's not */
+    if (DiskEntry->LayoutBuffer->Signature != 1)
+    {
+        DPRINT1("Super-Floppy disk %lu signature %08x != 1!\n",
+                DiskEntry->DiskNumber, DiskEntry->LayoutBuffer->Signature);
+    }
+
+    /*
+     * The partition number must be zero or one, be recognized,
+     * have FAT16 type and report as non-bootable.
+     */
+    if ((PartitionInfo->PartitionNumber != 0 &&
+         PartitionInfo->PartitionNumber != 1) ||
+        PartitionInfo->RecognizedPartition != TRUE ||
+        PartitionInfo->PartitionType != PARTITION_FAT_16 ||
+        PartitionInfo->BootIndicator != FALSE)
+    {
+        DPRINT1("Super-Floppy disk %lu does not return default settings!\n"
+                "    PartitionNumber = %lu, expected 0\n"
+                "    RecognizedPartition = %s, expected TRUE\n"
+                "    PartitionType = 0x%02x, expected 0x04 (PARTITION_FAT_16)\n"
+                "    BootIndicator = %s, expected FALSE\n",
+                DiskEntry->DiskNumber,
+                PartitionInfo->PartitionNumber,
+                PartitionInfo->RecognizedPartition ? "TRUE" : "FALSE",
+                PartitionInfo->PartitionType,
+                PartitionInfo->BootIndicator ? "TRUE" : "FALSE");
+    }
+
+    /* The partition lengths should agree */
+    PartitionLengthEstimate = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+    if (PartitionInfo->PartitionLength.QuadPart != PartitionLengthEstimate)
+    {
+        DPRINT1("PartitionLength = %I64u is different from PartitionLengthEstimate = %I64u\n",
+                PartitionInfo->PartitionLength.QuadPart, PartitionLengthEstimate);
+    }
+
+    return TRUE;
+}
+
+
+/*
+ * Inserts the disk region represented by PartEntry into either the primary
+ * or the logical partition list of the given disk.
+ * The lists are kept sorted by increasing order of start sectors.
+ * Of course no disk region should overlap at all with one another.
+ */
+static
+VOID
+InsertDiskRegion(
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry,
+    IN BOOLEAN LogicalPartition)
+{
+    PLIST_ENTRY List;
+    PLIST_ENTRY Entry;
+    PPARTENTRY PartEntry2;
+
+    /* Use the correct partition list */
+    if (LogicalPartition)
+        List = &DiskEntry->LogicalPartListHead;
+    else
+        List = &DiskEntry->PrimaryPartListHead;
+
+    /* Find the first disk region before which we need to insert the new one */
+    for (Entry = List->Flink; Entry != List; Entry = Entry->Flink)
+    {
+        PartEntry2 = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+        /* Ignore any unused empty region */
+        if ((PartEntry2->PartitionType == PARTITION_ENTRY_UNUSED &&
+             PartEntry2->StartSector.QuadPart == 0) || PartEntry2->SectorCount.QuadPart == 0)
+        {
+            continue;
+        }
+
+        /* If the current region ends before the one to be inserted, try again */
+        if (PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1 < PartEntry->StartSector.QuadPart)
+            continue;
+
+        /*
+         * One of the disk region boundaries crosses the desired region
+         * (it starts after the desired region, or ends before the end
+         * of the desired region): this is an impossible situation because
+         * disk regions (partitions) cannot overlap!
+         * Throw an error and bail out.
+         */
+        if (max(PartEntry->StartSector.QuadPart, PartEntry2->StartSector.QuadPart)
+            <=
+            min( PartEntry->StartSector.QuadPart +  PartEntry->SectorCount.QuadPart - 1,
+                PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1))
+        {
+            DPRINT1("Disk region overlap problem, stopping there!\n"
+                    "Partition to be inserted:\n"
+                    "    StartSector = %I64u ; EndSector = %I64u\n"
+                    "Existing disk region:\n"
+                    "    StartSector = %I64u ; EndSector = %I64u\n",
+                     PartEntry->StartSector.QuadPart,
+                     PartEntry->StartSector.QuadPart +  PartEntry->SectorCount.QuadPart - 1,
+                    PartEntry2->StartSector.QuadPart,
+                    PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1);
+            return;
+        }
+
+        /* We have found the first region before which the new one has to be inserted */
+        break;
+    }
+
+    /* Insert the disk region */
+    InsertTailList(Entry, &PartEntry->ListEntry);
+}
+
+static
+PPARTENTRY
+CreateInsertBlankRegion(
+    IN PDISKENTRY DiskEntry,
+    IN OUT PLIST_ENTRY ListHead,
+    IN ULONGLONG StartSector,
+    IN ULONGLONG SectorCount,
+    IN BOOLEAN LogicalSpace)
+{
+    PPARTENTRY NewPartEntry;
+
+    NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                   HEAP_ZERO_MEMORY,
+                                   sizeof(PARTENTRY));
+    if (NewPartEntry == NULL)
+        return NULL;
+
+    NewPartEntry->DiskEntry = DiskEntry;
+
+    NewPartEntry->StartSector.QuadPart = StartSector;
+    NewPartEntry->SectorCount.QuadPart = SectorCount;
+
+    NewPartEntry->IsPartitioned = FALSE;
+    NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
+    NewPartEntry->FormatState = Unformatted;
+    NewPartEntry->FileSystem[0] = L'\0';
+
+    DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
+    DPRINT1("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+    DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+    /* Insert the new entry into the list */
+    InsertTailList(ListHead, &NewPartEntry->ListEntry);
+
+    return NewPartEntry;
+}
+
+static
+// BOOLEAN
+PPARTENTRY
+InitializePartitionEntry(
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry,
+    IN ULONGLONG SectorCount,
+    IN BOOLEAN AutoCreate)
+{
+    PPARTENTRY NewPartEntry;
+
+    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+    if ((AutoCreate != FALSE) ||
+        (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+                   PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
+    {
+        DPRINT1("Convert existing partition entry\n");
+
+        NewPartEntry = PartEntry;
+        NewPartEntry->AutoCreate = AutoCreate;
+    }
+    else
+    {
+        DPRINT1("Add new partition entry\n");
+
+        /* Insert and initialize a new partition entry */
+        NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                       HEAP_ZERO_MEMORY,
+                                       sizeof(PARTENTRY));
+        if (NewPartEntry == NULL)
+            return NULL;
+
+        NewPartEntry->DiskEntry = DiskEntry;
+
+        NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+                                             NewPartEntry->StartSector.QuadPart;
+
+        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+
+        /* Insert the new entry into the list */
+        InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry);
+    }
+
+    /* Create entry as 'New (Unformatted)' */
+    NewPartEntry->New = TRUE;
+    NewPartEntry->IsPartitioned = TRUE;
+
+    NewPartEntry->PartitionType = FileSystemToPartitionType(L"RAW", &NewPartEntry->StartSector, &NewPartEntry->SectorCount);
+    ASSERT(NewPartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+    NewPartEntry->FormatState = Unformatted;
+    NewPartEntry->FileSystem[0] = L'\0';
+    // NewPartEntry->AutoCreate = AutoCreate;
+    NewPartEntry->BootIndicator = FALSE;
+    NewPartEntry->LogicalPartition = FALSE;
+
+    DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
+    DPRINT1("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
+    DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+
+    return NewPartEntry;
+}
+
+
 static
 VOID
 AddPartitionToDisk(
@@ -675,10 +927,10 @@ AddPartitionToDisk(
     NTSTATUS Status;
     PPARTITION_INFORMATION PartitionInfo;
     PPARTENTRY PartEntry;
-    HANDLE FileHandle;
+    HANDLE PartitionHandle;
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK IoStatusBlock;
-    WCHAR Buffer[MAX_PATH];
+    WCHAR PathBuffer[MAX_PATH];
     UNICODE_STRING Name;
     UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
     PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)LabelBuffer;
@@ -708,87 +960,107 @@ AddPartitionToDisk(
 
     PartEntry->LogicalPartition = LogicalPartition;
     PartEntry->IsPartitioned = TRUE;
+    PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
     PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
     PartEntry->PartitionIndex = PartitionIndex;
 
+    /* Specify the partition as initially unformatted */
+    PartEntry->FormatState = Unformatted;
+    PartEntry->FileSystem[0] = L'\0';
+
+    /* Initialize the partition volume label */
+    RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+
     if (IsContainerPartition(PartEntry->PartitionType))
     {
         PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
 
         if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
             DiskEntry->ExtendedPartition = PartEntry;
     }
     else if (IsRecognizedPartition(PartEntry->PartitionType))
     {
-        PartEntry->FileSystem = GetFileSystem(PartEntry);
-        if (PartEntry->FileSystem)
-            PartEntry->FormatState = Preformatted;
-        else
-            PartEntry->FormatState = Unformatted;
-        // PartEntry->FormatState = UnknownFormat;
-    }
-    else
-    {
-        /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
-        PartEntry->FormatState = UnknownFormat;
-    }
+        ASSERT(PartitionInfo->RecognizedPartition);
+        ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
-    /* Initialize the partition volume label */
-    RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+        /* Open the volume, ignore any errors */
+        RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                            L"\\Device\\Harddisk%lu\\Partition%lu",
+                            DiskEntry->DiskNumber,
+                            PartEntry->PartitionNumber);
+        RtlInitUnicodeString(&Name, PathBuffer);
 
-    /* Open the volume, ignore any errors */
-    RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
-                        L"\\Device\\Harddisk%lu\\Partition%lu",
-                        DiskEntry->DiskNumber, PartEntry->PartitionNumber);
-    RtlInitUnicodeString(&Name, Buffer);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &Name,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
 
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &Name,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
+        PartitionHandle = NULL;
+        Status = NtOpenFile(&PartitionHandle,
+                            FILE_READ_DATA | SYNCHRONIZE,
+                            &ObjectAttributes,
+                            &IoStatusBlock,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE,
+                            FILE_SYNCHRONOUS_IO_NONALERT);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
+        }
 
-    Status = NtOpenFile(&FileHandle,
-                        FILE_READ_DATA | SYNCHRONIZE,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
-    if (NT_SUCCESS(Status))
-    {
-        /* Retrieve the partition volume label */
-        Status = NtQueryVolumeInformationFile(FileHandle,
-                                              &IoStatusBlock,
-                                              &LabelBuffer,
-                                              sizeof(LabelBuffer),
-                                              FileFsVolumeInformation);
-        /* Close the handle */
-        NtClose(FileHandle);
-
-        /* Check for success */
-        if (NT_SUCCESS(Status))
+        if (/* NT_SUCCESS(Status) && */ PartitionHandle)
+        {
+            /* We don't have a FS, try to guess one */
+            Status = InferFileSystemByHandle(PartitionHandle,
+                                             PartEntry->PartitionType,
+                                             PartEntry->FileSystem,
+                                             sizeof(PartEntry->FileSystem));
+            if (!NT_SUCCESS(Status))
+                DPRINT1("InferFileSystemByHandle() failed, Status 0x%08lx\n", Status);
+        }
+        if (*PartEntry->FileSystem)
         {
-            /* Copy the (possibly truncated) volume label and NULL-terminate it */
-            RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
-                              LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
+            if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
+                PartEntry->FormatState = Unformatted;
+            else
+                PartEntry->FormatState = Preformatted;
         }
         else
         {
-            DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
+            PartEntry->FormatState = UnknownFormat;
+        }
+
+        /* Retrieve the partition volume label */
+        if (PartitionHandle)
+        {
+            Status = NtQueryVolumeInformationFile(PartitionHandle,
+                                                  &IoStatusBlock,
+                                                  &LabelBuffer,
+                                                  sizeof(LabelBuffer),
+                                                  FileFsVolumeInformation);
+            if (NT_SUCCESS(Status))
+            {
+                /* Copy the (possibly truncated) volume label and NULL-terminate it */
+                RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
+                                  LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
+            }
+            else
+            {
+                DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
+            }
         }
+
+        /* Close the partition */
+        if (PartitionHandle)
+            NtClose(PartitionHandle);
     }
     else
     {
-        DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
+        /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
+        PartEntry->FormatState = UnknownFormat;
     }
 
-    if (LogicalPartition)
-        InsertTailList(&DiskEntry->LogicalPartListHead,
-                       &PartEntry->ListEntry);
-    else
-        InsertTailList(&DiskEntry->PrimaryPartListHead,
-                       &PartEntry->ListEntry);
+    InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
 }
 
 static
@@ -796,6 +1068,8 @@ VOID
 ScanForUnpartitionedDiskSpace(
     IN PDISKENTRY DiskEntry)
 {
+    ULONGLONG StartSector;
+    ULONGLONG SectorCount;
     ULONGLONG LastStartSector;
     ULONGLONG LastSectorCount;
     ULONGLONG LastUnusedSectorCount;
@@ -810,31 +1084,20 @@ ScanForUnpartitionedDiskSpace(
         DPRINT1("No primary partition!\n");
 
         /* Create a partition entry that represents the empty disk */
-        NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof(PARTENTRY));
-        if (NewPartEntry == NULL)
-            return;
-
-        NewPartEntry->DiskEntry = DiskEntry;
 
-        NewPartEntry->IsPartitioned = FALSE;
         if (DiskEntry->SectorAlignment < 2048)
-            NewPartEntry->StartSector.QuadPart = 2048ULL;
+            StartSector = 2048ULL;
         else
-            NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
-        NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
-                                             NewPartEntry->StartSector.QuadPart;
-
-        DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-        NewPartEntry->FormatState = Unformatted;
-        NewPartEntry->FileSystem  = NULL;
-
-        InsertTailList(&DiskEntry->PrimaryPartListHead,
-                       &NewPartEntry->ListEntry);
+            StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
+        SectorCount = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - StartSector;
+
+        NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                               &DiskEntry->PrimaryPartListHead,
+                                               StartSector,
+                                               SectorCount,
+                                               FALSE);
+        if (NewPartEntry == NULL)
+            DPRINT1("Failed to create a new empty region for full disk space!\n");
 
         return;
     }
@@ -843,12 +1106,13 @@ ScanForUnpartitionedDiskSpace(
     if (DiskEntry->SectorAlignment < 2048)
         LastStartSector = 2048ULL;
     else
-        LastStartSector = DiskEntry->SectorAlignment;
+        LastStartSector = (ULONGLONG)DiskEntry->SectorAlignment;
     LastSectorCount = 0ULL;
     LastUnusedSectorCount = 0ULL;
 
-    Entry = DiskEntry->PrimaryPartListHead.Flink;
-    while (Entry != &DiskEntry->PrimaryPartListHead)
+    for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+         Entry != &DiskEntry->PrimaryPartListHead;
+         Entry = Entry->Flink)
     {
         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
 
@@ -863,36 +1127,25 @@ ScanForUnpartitionedDiskSpace(
             {
                 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
 
-                NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                               HEAP_ZERO_MEMORY,
-                                               sizeof(PARTENTRY));
-                if (NewPartEntry == NULL)
-                    return;
-
-                NewPartEntry->DiskEntry = DiskEntry;
-
-                NewPartEntry->IsPartitioned = FALSE;
-                NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
-                                                     NewPartEntry->StartSector.QuadPart;
-
-                DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-                DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-                DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-                NewPartEntry->FormatState = Unformatted;
-                NewPartEntry->FileSystem  = NULL;
+                StartSector = LastStartSector + LastSectorCount;
+                SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
 
                 /* Insert the table into the list */
-                InsertTailList(&PartEntry->ListEntry,
-                               &NewPartEntry->ListEntry);
+                NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                                       &PartEntry->ListEntry,
+                                                       StartSector,
+                                                       SectorCount,
+                                                       FALSE);
+                if (NewPartEntry == NULL)
+                {
+                    DPRINT1("Failed to create a new empty region for disk space!\n");
+                    return;
+                }
             }
 
             LastStartSector = PartEntry->StartSector.QuadPart;
             LastSectorCount = PartEntry->SectorCount.QuadPart;
         }
-
-        Entry = Entry->Flink;
     }
 
     /* Check for trailing unpartitioned disk space */
@@ -904,29 +1157,20 @@ ScanForUnpartitionedDiskSpace(
         {
             DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
 
-            NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                           HEAP_ZERO_MEMORY,
-                                           sizeof(PARTENTRY));
-            if (NewPartEntry == NULL)
-                return;
-
-            NewPartEntry->DiskEntry = DiskEntry;
-
-            NewPartEntry->IsPartitioned = FALSE;
-            NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-            NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
-                                                 NewPartEntry->StartSector.QuadPart;
-
-            DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-            DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-            DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-            NewPartEntry->FormatState = Unformatted;
-            NewPartEntry->FileSystem  = NULL;
+            StartSector = LastStartSector + LastSectorCount;
+            SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
 
             /* Append the table to the list */
-            InsertTailList(&DiskEntry->PrimaryPartListHead,
-                           &NewPartEntry->ListEntry);
+            NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                                   &DiskEntry->PrimaryPartListHead,
+                                                   StartSector,
+                                                   SectorCount,
+                                                   FALSE);
+            if (NewPartEntry == NULL)
+            {
+                DPRINT1("Failed to create a new empty region for trailing disk space!\n");
+                return;
+            }
         }
     }
 
@@ -937,29 +1181,22 @@ ScanForUnpartitionedDiskSpace(
             DPRINT1("No logical partition!\n");
 
             /* Create a partition entry that represents the empty extended partition */
-            NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                           HEAP_ZERO_MEMORY,
-                                           sizeof(PARTENTRY));
+
+            StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+            SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
+
+            NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                                   &DiskEntry->LogicalPartListHead,
+                                                   StartSector,
+                                                   SectorCount,
+                                                   TRUE);
             if (NewPartEntry == NULL)
+            {
+                DPRINT1("Failed to create a new empty region for full extended partition space!\n");
                 return;
-
-            NewPartEntry->DiskEntry = DiskEntry;
+            }
             NewPartEntry->LogicalPartition = TRUE;
 
-            NewPartEntry->IsPartitioned = FALSE;
-            NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
-            NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
-
-            DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-            DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-            DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-            NewPartEntry->FormatState = Unformatted;
-            NewPartEntry->FileSystem  = NULL;
-
-            InsertTailList(&DiskEntry->LogicalPartListHead,
-                           &NewPartEntry->ListEntry);
-
             return;
         }
 
@@ -968,8 +1205,9 @@ ScanForUnpartitionedDiskSpace(
         LastSectorCount = 0ULL;
         LastUnusedSectorCount = 0ULL;
 
-        Entry = DiskEntry->LogicalPartListHead.Flink;
-        while (Entry != &DiskEntry->LogicalPartListHead)
+        for (Entry = DiskEntry->LogicalPartListHead.Flink;
+             Entry != &DiskEntry->LogicalPartListHead;
+             Entry = Entry->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
 
@@ -984,72 +1222,54 @@ ScanForUnpartitionedDiskSpace(
                 {
                     DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
 
-                    NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                                   HEAP_ZERO_MEMORY,
-                                                   sizeof(PARTENTRY));
+                    StartSector = LastStartSector + LastSectorCount;
+                    SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
+
+                    /* Insert the table into the list */
+                    NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                                           &PartEntry->ListEntry,
+                                                           StartSector,
+                                                           SectorCount,
+                                                           TRUE);
                     if (NewPartEntry == NULL)
+                    {
+                        DPRINT1("Failed to create a new empty region for extended partition space!\n");
                         return;
-
-                    NewPartEntry->DiskEntry = DiskEntry;
+                    }
                     NewPartEntry->LogicalPartition = TRUE;
-
-                    NewPartEntry->IsPartitioned = FALSE;
-                    NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                    NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
-                                                         NewPartEntry->StartSector.QuadPart;
-
-                    DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-                    DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-                    DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-                    NewPartEntry->FormatState = Unformatted;
-                    NewPartEntry->FileSystem  = NULL;
-
-                    /* Insert the table into the list */
-                    InsertTailList(&PartEntry->ListEntry,
-                                   &NewPartEntry->ListEntry);
-                }
+                }
 
                 LastStartSector = PartEntry->StartSector.QuadPart;
                 LastSectorCount = PartEntry->SectorCount.QuadPart;
             }
-
-            Entry = Entry->Flink;
         }
 
         /* Check for trailing unpartitioned disk space */
         if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
         {
-            LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
+            LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart +
+                                              DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
+                                              DiskEntry->SectorAlignment);
 
             if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
             {
                 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
 
-                NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                               HEAP_ZERO_MEMORY,
-                                               sizeof(PARTENTRY));
+                StartSector = LastStartSector + LastSectorCount;
+                SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
+
+                /* Append the table to the list */
+                NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                                       &DiskEntry->LogicalPartListHead,
+                                                       StartSector,
+                                                       SectorCount,
+                                                       TRUE);
                 if (NewPartEntry == NULL)
+                {
+                    DPRINT1("Failed to create a new empty region for extended partition space!\n");
                     return;
-
-                NewPartEntry->DiskEntry = DiskEntry;
+                }
                 NewPartEntry->LogicalPartition = TRUE;
-
-                NewPartEntry->IsPartitioned = FALSE;
-                NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
-                                                     NewPartEntry->StartSector.QuadPart;
-
-                DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-                DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-                DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-                NewPartEntry->FormatState = Unformatted;
-                NewPartEntry->FileSystem  = NULL;
-
-                /* Append the table to the list */
-                InsertTailList(&DiskEntry->LogicalPartListHead,
-                               &NewPartEntry->ListEntry);
             }
         }
     }
@@ -1069,6 +1289,12 @@ SetDiskSignature(
     PDISKENTRY DiskEntry2;
     PUCHAR Buffer;
 
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return;
+    }
+
     Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
 
     while (TRUE)
@@ -1091,16 +1317,21 @@ SetDiskSignature(
          *   Check also signatures from disks, which are
          *   not visible (bootable) by the bios.
          */
-        Entry2 = List->DiskListHead.Flink;
-        while (Entry2 != &List->DiskListHead)
+        for (Entry2 = List->DiskListHead.Flink;
+             Entry2 != &List->DiskListHead;
+             Entry2 = Entry2->Flink)
         {
             DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
 
+            if (DiskEntry2->DiskStyle == PARTITION_STYLE_GPT)
+            {
+                DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+                continue;
+            }
+
             if (DiskEntry != DiskEntry2 &&
                 DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
                 break;
-
-            Entry2 = Entry2->Flink;
         }
 
         if (Entry2 == &List->DiskListHead)
@@ -1116,20 +1347,86 @@ UpdateDiskSignatures(
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
 
-    /* Print partition lines */
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    /* Update each disk */
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+        {
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
+
         if (DiskEntry->LayoutBuffer &&
             DiskEntry->LayoutBuffer->Signature == 0)
         {
             SetDiskSignature(List, DiskEntry);
             DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
         }
+    }
+}
 
-        Entry = Entry->Flink;
+static
+VOID
+UpdateHwDiskNumbers(
+    IN PPARTLIST List)
+{
+    PLIST_ENTRY ListEntry;
+    PBIOSDISKENTRY BiosDiskEntry;
+    PDISKENTRY DiskEntry;
+    ULONG HwAdapterNumber = 0;
+    ULONG HwControllerNumber = 0;
+    ULONG RemovableDiskCount = 0;
+
+    /*
+     * Enumerate the disks recognized by the BIOS and recompute the disk
+     * numbers on the system when *ALL* removable disks are not connected.
+     * The entries are inserted in increasing order of AdapterNumber,
+     * ControllerNumber and DiskNumber.
+     */
+    for (ListEntry = List->BiosDiskListHead.Flink;
+         ListEntry != &List->BiosDiskListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
+        DiskEntry = BiosDiskEntry->DiskEntry;
+
+        /*
+         * If the adapter or controller numbers change, update them and reset
+         * the number of removable disks on this adapter/controller.
+         */
+        if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
+            HwControllerNumber != BiosDiskEntry->ControllerNumber)
+        {
+            HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+            HwControllerNumber = BiosDiskEntry->ControllerNumber;
+            RemovableDiskCount = 0;
+        }
+
+        /* Adjust the actual hardware disk number */
+        if (DiskEntry)
+        {
+            ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
+
+            if (DiskEntry->MediaType == RemovableMedia)
+            {
+                /* Increase the number of removable disks and set the disk number to zero */
+                ++RemovableDiskCount;
+                DiskEntry->HwFixedDiskNumber = 0;
+            }
+            else // if (DiskEntry->MediaType == FixedMedia)
+            {
+                /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
+                DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
+            }
+        }
+        else
+        {
+            DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
+        }
     }
 }
 
@@ -1234,7 +1531,9 @@ AddDiskToList(
     Checksum = ~Checksum + 1;
 
     RtlStringCchPrintfW(Identifier, ARRAYSIZE(Identifier),
-                        L"%08x-%08x-A", Checksum, Signature);
+                        L"%08x-%08x-%c",
+                        Checksum, Signature,
+                        (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
     DPRINT("Identifier: %S\n", Identifier);
 
     DiskEntry = RtlAllocateHeap(ProcessHeap,
@@ -1247,6 +1546,39 @@ AddDiskToList(
         return;
     }
 
+    DiskEntry->PartList = List;
+
+#if 0
+    {
+        FILE_FS_DEVICE_INFORMATION FileFsDevice;
+
+        /* Query the device for its type */
+        Status = NtQueryVolumeInformationFile(FileHandle,
+                                              &Iosb,
+                                              &FileFsDevice,
+                                              sizeof(FileFsDevice),
+                                              FileFsDeviceInformation);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
+        }
+        else
+        {
+            DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
+        }
+    }
+    // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
+#endif
+    DiskEntry->MediaType = DiskGeometry.MediaType;
+    if (DiskEntry->MediaType == RemovableMedia)
+    {
+        DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
+    }
+    else // if (DiskEntry->MediaType == FixedMedia)
+    {
+        DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
+    }
+
 //    DiskEntry->Checksum = Checksum;
 //    DiskEntry->Signature = Signature;
     DiskEntry->BiosFound = FALSE;
@@ -1255,18 +1587,38 @@ AddDiskToList(
      * Check if this disk has a valid MBR: verify its signature,
      * and whether its two first bytes are a valid instruction
      * (related to this, see IsThereAValidBootSector() in partlist.c).
+     *
+     * See also ntoskrnl/fstub/fstubex.c!FstubDetectPartitionStyle().
      */
-    if (Mbr->Magic != 0xaa55 || (*(PUSHORT)Mbr->BootCode) == 0x0000)
-        DiskEntry->NoMbr = TRUE;
+
+    // DiskEntry->NoMbr = (Mbr->Magic != PARTITION_MAGIC || (*(PUSHORT)Mbr->BootCode) == 0x0000);
+
+    /* If we have not the 0xAA55 then it's raw partition */
+    if (Mbr->Magic != PARTITION_MAGIC)
+    {
+        DiskEntry->DiskStyle = PARTITION_STYLE_RAW;
+    }
+    /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
+    else if (Mbr->Partition[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
+             Mbr->Partition[1].PartitionType == 0 &&
+             Mbr->Partition[2].PartitionType == 0 &&
+             Mbr->Partition[3].PartitionType == 0)
+    {
+        DiskEntry->DiskStyle = PARTITION_STYLE_GPT;
+    }
+    /* Otherwise, partition table is in MBR */
     else
-        DiskEntry->NoMbr = FALSE;
+    {
+        DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
+    }
 
     /* Free the MBR sector buffer */
     RtlFreeHeap(ProcessHeap, 0, Mbr);
 
 
-    ListEntry = List->BiosDiskListHead.Flink;
-    while (ListEntry != &List->BiosDiskListHead)
+    for (ListEntry = List->BiosDiskListHead.Flink;
+         ListEntry != &List->BiosDiskListHead;
+         ListEntry = ListEntry->Flink)
     {
         BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
         /* FIXME:
@@ -1277,35 +1629,42 @@ AddDiskToList(
          */
         if (BiosDiskEntry->Signature == Signature &&
             BiosDiskEntry->Checksum == Checksum &&
-            !BiosDiskEntry->Recognized)
+            BiosDiskEntry->DiskEntry == NULL)
         {
             if (!DiskEntry->BiosFound)
             {
-                DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
+                DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
+                DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
+                DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
+
+                if (DiskEntry->MediaType == RemovableMedia)
+                {
+                    /* Set the removable disk number to zero */
+                    DiskEntry->HwFixedDiskNumber = 0;
+                }
+                else // if (DiskEntry->MediaType == FixedMedia)
+                {
+                    /* The fixed disk number will later be adjusted using the number of removable disks */
+                    DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
+                }
+
                 DiskEntry->BiosFound = TRUE;
-                BiosDiskEntry->Recognized = TRUE;
+                BiosDiskEntry->DiskEntry = DiskEntry;
+                break;
             }
             else
             {
                 // FIXME: What to do?
+                DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
             }
         }
-        ListEntry = ListEntry->Flink;
     }
 
     if (!DiskEntry->BiosFound)
     {
-#if 0
-        RtlFreeHeap(ProcessHeap, 0, DiskEntry);
-        return;
-#else
-        DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
-#endif
+        DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
     }
 
-    InitializeListHead(&DiskEntry->PrimaryPartListHead);
-    InitializeListHead(&DiskEntry->LogicalPartListHead);
-
     DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
     DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
     DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
@@ -1349,6 +1708,9 @@ AddDiskToList(
      * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
      */
 
+    InitializeListHead(&DiskEntry->PrimaryPartListHead);
+    InitializeListHead(&DiskEntry->LogicalPartListHead);
+
     InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
 
 
@@ -1356,6 +1718,16 @@ AddDiskToList(
      * We now retrieve the disk partition layout
      */
 
+    /*
+     * Stop there now if the disk is GPT-partitioned,
+     * since we currently do not support such disks.
+     */
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return;
+    }
+
     /* Allocate a layout buffer with 4 partition entries first */
     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
                        ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
@@ -1411,6 +1783,9 @@ AddDiskToList(
     DumpPartitionTable(DiskEntry);
 #endif
 
+    if (IsSuperFloppy(DiskEntry))
+        DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
+
     if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
         DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != PARTITION_ENTRY_UNUSED)
@@ -1433,22 +1808,25 @@ AddDiskToList(
         DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
     }
 
-
     if (DiskEntry->LayoutBuffer->PartitionCount == 0)
     {
         DiskEntry->NewDisk = TRUE;
         DiskEntry->LayoutBuffer->PartitionCount = 4;
 
         for (i = 0; i < 4; i++)
+        {
             DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+        }
     }
     else
     {
+        /* Enumerate and add the first four primary partitions */
         for (i = 0; i < 4; i++)
         {
             AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
         }
 
+        /* Enumerate and add the remaining partitions as logical ones */
         for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
         {
             AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
@@ -1478,9 +1856,6 @@ CreatePartitionList(VOID)
     if (List == NULL)
         return NULL;
 
-    List->CurrentDisk = NULL;
-    List->CurrentPartition = NULL;
-
     List->SystemPartition = NULL;
     List->OriginalSystemPartition = NULL;
 
@@ -1532,33 +1907,9 @@ CreatePartitionList(VOID)
     }
 
     UpdateDiskSignatures(List);
-
+    UpdateHwDiskNumbers(List);
     AssignDriveLetters(List);
 
-    /* Search for first usable disk and partition */
-    if (IsListEmpty(&List->DiskListHead))
-    {
-        List->CurrentDisk = NULL;
-        List->CurrentPartition = NULL;
-    }
-    else
-    {
-        List->CurrentDisk = CONTAINING_RECORD(List->DiskListHead.Flink,
-                                              DISKENTRY,
-                                              ListEntry);
-
-        if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
-        {
-            List->CurrentPartition = NULL;
-        }
-        else
-        {
-            List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
-                                                       PARTENTRY,
-                                                       ListEntry);
-        }
-    }
-
     return List;
 }
 
@@ -1622,19 +1973,19 @@ DestroyPartitionList(
 PDISKENTRY
 GetDiskByBiosNumber(
     IN PPARTLIST List,
-    IN ULONG BiosDiskNumber)
+    IN ULONG HwDiskNumber)
 {
     PDISKENTRY DiskEntry;
     PLIST_ENTRY Entry;
 
     /* Loop over the disks and find the correct one */
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
-        Entry = Entry->Flink;
 
-        if (DiskEntry->BiosDiskNumber == BiosDiskNumber)
+        if (DiskEntry->HwDiskNumber == HwDiskNumber)
         {
             /* Disk found */
             return DiskEntry;
@@ -1654,11 +2005,11 @@ GetDiskByNumber(
     PLIST_ENTRY Entry;
 
     /* Loop over the disks and find the correct one */
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
-        Entry = Entry->Flink;
 
         if (DiskEntry->DiskNumber == DiskNumber)
         {
@@ -1682,11 +2033,11 @@ GetDiskBySCSI(
     PLIST_ENTRY Entry;
 
     /* Loop over the disks and find the correct one */
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
-        Entry = Entry->Flink;
 
         if (DiskEntry->Port == Port &&
             DiskEntry->Bus  == Bus  &&
@@ -1710,11 +2061,11 @@ GetDiskBySignature(
     PLIST_ENTRY Entry;
 
     /* Loop over the disks and find the correct one */
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
-        Entry = Entry->Flink;
 
         if (DiskEntry->LayoutBuffer->Signature == Signature)
         {
@@ -1736,12 +2087,18 @@ GetPartition(
     PPARTENTRY PartEntry;
     PLIST_ENTRY Entry;
 
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return NULL;
+    }
+
     /* Disk found, loop over the primary partitions first... */
-    Entry = DiskEntry->PrimaryPartListHead.Flink;
-    while (Entry != &DiskEntry->PrimaryPartListHead)
+    for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+         Entry != &DiskEntry->PrimaryPartListHead;
+         Entry = Entry->Flink)
     {
         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-        Entry = Entry->Flink;
 
         if (PartEntry->PartitionNumber == PartitionNumber)
         {
@@ -1751,11 +2108,11 @@ GetPartition(
     }
 
     /* ... then over the logical partitions if needed */
-    Entry = DiskEntry->LogicalPartListHead.Flink;
-    while (Entry != &DiskEntry->LogicalPartListHead)
+    for (Entry = DiskEntry->LogicalPartListHead.Flink;
+         Entry != &DiskEntry->LogicalPartListHead;
+         Entry = Entry->Flink)
     {
         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-        Entry = Entry->Flink;
 
         if (PartEntry->PartitionNumber == PartitionNumber)
         {
@@ -1787,6 +2144,12 @@ GetDiskOrPartition(
     /* If we have a partition (PartitionNumber != 0), find it */
     if (PartitionNumber != 0)
     {
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+        {
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            return FALSE;
+        }
+
         PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
         if (!PartEntry)
             return FALSE;
@@ -1802,7 +2165,7 @@ GetDiskOrPartition(
 //
 // NOTE: Was introduced broken in r6258 by Casper
 //
-BOOLEAN
+PPARTENTRY
 SelectPartition(
     IN PPARTLIST List,
     IN ULONG DiskNumber,
@@ -1813,59 +2176,55 @@ SelectPartition(
 
     DiskEntry = GetDiskByNumber(List, DiskNumber);
     if (!DiskEntry)
-        return FALSE;
+        return NULL;
 
     PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
     if (!PartEntry)
-        return FALSE;
+        return NULL;
 
     ASSERT(PartEntry->DiskEntry == DiskEntry);
     ASSERT(DiskEntry->DiskNumber == DiskNumber);
     ASSERT(PartEntry->PartitionNumber == PartitionNumber);
 
-    List->CurrentDisk = DiskEntry;
-    List->CurrentPartition = PartEntry;
-    return TRUE;
+    return PartEntry;
 }
 
 PPARTENTRY
 GetNextPartition(
-    IN PPARTLIST List)
+    IN PPARTLIST List,
+    IN PPARTENTRY CurrentPart OPTIONAL)
 {
     PLIST_ENTRY DiskListEntry;
     PLIST_ENTRY PartListEntry;
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
+    PDISKENTRY CurrentDisk;
 
     /* Fail if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
         return NULL;
 
-    /* Check for next usable entry on current disk */
-    if (List->CurrentPartition != NULL)
+    /* Check for the next usable entry on the current partition's disk */
+    if (CurrentPart != NULL)
     {
-        if (List->CurrentPartition->LogicalPartition)
+        CurrentDisk = CurrentPart->DiskEntry;
+
+        if (CurrentPart->LogicalPartition)
         {
             /* Logical partition */
 
-            PartListEntry = List->CurrentPartition->ListEntry.Flink;
-            if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+            PartListEntry = CurrentPart->ListEntry.Flink;
+            if (PartListEntry != &CurrentDisk->LogicalPartListHead)
             {
                 /* Next logical partition */
-                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-                List->CurrentPartition = PartEntry;
-                return List->CurrentPartition;
+                CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                return CurrentPart;
             }
             else
             {
-                PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
-                if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+                PartListEntry = CurrentDisk->ExtendedPartition->ListEntry.Flink;
+                if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
                 {
-                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-                    List->CurrentPartition = PartEntry;
-                    return List->CurrentPartition;
+                    CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                    return CurrentPart;
                 }
             }
         }
@@ -1873,51 +2232,50 @@ GetNextPartition(
         {
             /* Primary or extended partition */
 
-            if ((List->CurrentPartition->IsPartitioned != FALSE) &&
-                IsContainerPartition(List->CurrentPartition->PartitionType))
+            if (CurrentPart->IsPartitioned &&
+                IsContainerPartition(CurrentPart->PartitionType))
             {
                 /* First logical partition */
-                PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
-                if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+                PartListEntry = CurrentDisk->LogicalPartListHead.Flink;
+                if (PartListEntry != &CurrentDisk->LogicalPartListHead)
                 {
-                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-                    List->CurrentPartition = PartEntry;
-                    return List->CurrentPartition;
+                    CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                    return CurrentPart;
                 }
             }
             else
             {
                 /* Next primary partition */
-                PartListEntry = List->CurrentPartition->ListEntry.Flink;
-                if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+                PartListEntry = CurrentPart->ListEntry.Flink;
+                if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
                 {
-                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-                    List->CurrentPartition = PartEntry;
-                    return List->CurrentPartition;
+                    CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                    return CurrentPart;
                 }
             }
         }
     }
 
     /* Search for the first partition entry on the next disk */
-    DiskListEntry = List->CurrentDisk->ListEntry.Flink;
-    while (DiskListEntry != &List->DiskListHead)
+    for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Flink
+                                      : List->DiskListHead.Flink);
+         DiskListEntry != &List->DiskListHead;
+         DiskListEntry = DiskListEntry->Flink)
     {
-        DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+        CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
 
-        PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
-        if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+        if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
         {
-            PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-            List->CurrentDisk = DiskEntry;
-            List->CurrentPartition = PartEntry;
-            return List->CurrentPartition;
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
         }
 
-        DiskListEntry = DiskListEntry->Flink;
+        PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
+        if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
+        {
+            CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+            return CurrentPart;
+        }
     }
 
     return NULL;
@@ -1925,93 +2283,94 @@ GetNextPartition(
 
 PPARTENTRY
 GetPrevPartition(
-    IN PPARTLIST List)
+    IN PPARTLIST List,
+    IN PPARTENTRY CurrentPart OPTIONAL)
 {
     PLIST_ENTRY DiskListEntry;
     PLIST_ENTRY PartListEntry;
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
+    PDISKENTRY CurrentDisk;
 
     /* Fail if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
         return NULL;
 
-    /* Check for previous usable entry on current disk */
-    if (List->CurrentPartition != NULL)
+    /* Check for the previous usable entry on the current partition's disk */
+    if (CurrentPart != NULL)
     {
-        if (List->CurrentPartition->LogicalPartition)
+        CurrentDisk = CurrentPart->DiskEntry;
+
+        if (CurrentPart->LogicalPartition)
         {
             /* Logical partition */
-            PartListEntry = List->CurrentPartition->ListEntry.Blink;
-            if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+
+            PartListEntry = CurrentPart->ListEntry.Blink;
+            if (PartListEntry != &CurrentDisk->LogicalPartListHead)
             {
                 /* Previous logical partition */
-                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
             }
             else
             {
                 /* Extended partition */
-                PartEntry = List->CurrentDisk->ExtendedPartition;
+                CurrentPart = CurrentDisk->ExtendedPartition;
             }
-
-            List->CurrentPartition = PartEntry;
-            return List->CurrentPartition;
+            return CurrentPart;
         }
         else
         {
             /* Primary or extended partition */
 
-            PartListEntry = List->CurrentPartition->ListEntry.Blink;
-            if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+            PartListEntry = CurrentPart->ListEntry.Blink;
+            if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
             {
-                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-                if ((PartEntry->IsPartitioned != FALSE) &&
-                    IsContainerPartition(PartEntry->PartitionType))
+                if (CurrentPart->IsPartitioned &&
+                    IsContainerPartition(CurrentPart->PartitionType))
                 {
-                    PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
-                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                    PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
+                    CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
                 }
 
-                List->CurrentPartition = PartEntry;
-                return List->CurrentPartition;
+                return CurrentPart;
             }
         }
     }
 
     /* Search for the last partition entry on the previous disk */
-    DiskListEntry = List->CurrentDisk->ListEntry.Blink;
-    while (DiskListEntry != &List->DiskListHead)
+    for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Blink
+                                      : List->DiskListHead.Blink);
+         DiskListEntry != &List->DiskListHead;
+         DiskListEntry = DiskListEntry->Blink)
     {
-        DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+        CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
 
-        PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
-        if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+        if (CurrentDisk->DiskStyle == PARTITION_STYLE_GPT)
         {
-            PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
 
-            if ((PartEntry->IsPartitioned != FALSE) &&
-                IsContainerPartition(PartEntry->PartitionType))
+        PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
+        if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
+        {
+            CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+            if (CurrentPart->IsPartitioned &&
+                IsContainerPartition(CurrentPart->PartitionType))
             {
-                PartListEntry = DiskEntry->LogicalPartListHead.Blink;
-                if (PartListEntry != &DiskEntry->LogicalPartListHead)
+                PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
+                if (PartListEntry != &CurrentDisk->LogicalPartListHead)
                 {
-                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
-
-                    List->CurrentDisk = DiskEntry;
-                    List->CurrentPartition = PartEntry;
-                    return List->CurrentPartition;
+                    CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                    return CurrentPart;
                 }
             }
             else
             {
-                List->CurrentDisk = DiskEntry;
-                List->CurrentPartition = PartEntry;
-                return List->CurrentPartition;
+                return CurrentPart;
             }
         }
-
-        DiskListEntry = DiskListEntry->Blink;
     }
 
     return NULL;
@@ -2042,7 +2401,6 @@ IsSamePrimaryLayoutEntry(
 {
     if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
         PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
-//        PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
 //        PartitionInfo->PartitionType == PartEntry->PartitionType
     {
         return TRUE;
@@ -2060,14 +2418,19 @@ GetPrimaryPartitionCount(
     PPARTENTRY PartEntry;
     ULONG Count = 0;
 
-    Entry = DiskEntry->PrimaryPartListHead.Flink;
-    while (Entry != &DiskEntry->PrimaryPartListHead)
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return 0;
+    }
+
+    for (Entry = DiskEntry->PrimaryPartListHead.Flink;
+         Entry != &DiskEntry->PrimaryPartListHead;
+         Entry = Entry->Flink)
     {
         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
         if (PartEntry->IsPartitioned)
             Count++;
-
-        Entry = Entry->Flink;
     }
 
     return Count;
@@ -2082,14 +2445,19 @@ GetLogicalPartitionCount(
     PPARTENTRY PartEntry;
     ULONG Count = 0;
 
-    ListEntry = DiskEntry->LogicalPartListHead.Flink;
-    while (ListEntry != &DiskEntry->LogicalPartListHead)
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return 0;
+    }
+
+    for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+         ListEntry != &DiskEntry->LogicalPartListHead;
+         ListEntry = ListEntry->Flink)
     {
         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
         if (PartEntry->IsPartitioned)
             Count++;
-
-        ListEntry = ListEntry->Flink;
     }
 
     return Count;
@@ -2113,7 +2481,7 @@ ReAllocateLayoutBuffer(
     if (DiskEntry->LayoutBuffer)
         CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
 
-    DPRINT1("CurrentPartitionCount: %lu    NewPartitionCount: %lu\n",
+    DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
             CurrentPartitionCount, NewPartitionCount);
 
     if (CurrentPartitionCount == NewPartitionCount)
@@ -2131,15 +2499,18 @@ ReAllocateLayoutBuffer(
         return FALSE;
     }
 
+    NewLayoutBuffer->PartitionCount = NewPartitionCount;
+
     /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
     if (NewPartitionCount > CurrentPartitionCount)
     {
         for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
+        {
             NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+        }
     }
 
     DiskEntry->LayoutBuffer = NewLayoutBuffer;
-    DiskEntry->LayoutBuffer->PartitionCount = NewPartitionCount;
 
     return TRUE;
 }
@@ -2159,6 +2530,12 @@ UpdateDiskLayout(
 
     DPRINT1("UpdateDiskLayout()\n");
 
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return;
+    }
+
     /* Resize the layout buffer if necessary */
     if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
     {
@@ -2168,14 +2545,24 @@ UpdateDiskLayout(
 
     /* Update the primary partition table */
     Index = 0;
-    ListEntry = DiskEntry->PrimaryPartListHead.Flink;
-    while (ListEntry != &DiskEntry->PrimaryPartListHead)
+    for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+         ListEntry != &DiskEntry->PrimaryPartListHead;
+         ListEntry = ListEntry->Flink)
     {
         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
 
-        if (PartEntry->IsPartitioned != FALSE)
+        if (PartEntry->IsPartitioned)
         {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+            PartEntry->PartitionIndex = Index;
+
+            /* Reset the current partition number only for newly-created (unmounted) partitions */
+            if (PartEntry->New)
+                PartEntry->PartitionNumber = 0;
+
+            PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0);
 
             if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
             {
@@ -2184,52 +2571,54 @@ UpdateDiskLayout(
                 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
                 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
                 PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
-                PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+                PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
                 PartitionInfo->PartitionType = PartEntry->PartitionType;
                 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
-                PartitionInfo->RecognizedPartition = FALSE;
+                PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
                 PartitionInfo->RewritePartition = TRUE;
             }
 
-            PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
-            PartEntry->PartitionIndex = Index;
-
             if (!IsContainerPartition(PartEntry->PartitionType))
                 PartitionNumber++;
 
             Index++;
         }
-
-        ListEntry = ListEntry->Flink;
     }
 
     ASSERT(Index <= 4);
 
     /* Update the logical partition table */
     Index = 4;
-    ListEntry = DiskEntry->LogicalPartListHead.Flink;
-    while (ListEntry != &DiskEntry->LogicalPartListHead)
+    for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+         ListEntry != &DiskEntry->LogicalPartListHead;
+         ListEntry = ListEntry->Flink)
     {
         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
 
         if (PartEntry->IsPartitioned)
         {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+            PartEntry->PartitionIndex = Index;
+
+            /* Reset the current partition number only for newly-created (unmounted) partitions */
+            if (PartEntry->New)
+                PartEntry->PartitionNumber = 0;
+
+            PartEntry->OnDiskPartitionNumber = PartitionNumber;
 
             DPRINT1("Updating logical partition entry %lu\n", Index);
 
             PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
             PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
             PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
-            PartitionInfo->PartitionNumber = PartitionNumber;
+            PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
             PartitionInfo->PartitionType = PartEntry->PartitionType;
             PartitionInfo->BootIndicator = FALSE;
-            PartitionInfo->RecognizedPartition = FALSE;
+            PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
             PartitionInfo->RewritePartition = TRUE;
 
-            PartEntry->PartitionNumber = PartitionNumber;
-            PartEntry->PartitionIndex = Index;
-
             /* Fill the link entry of the previous partition entry */
             if (LinkInfo != NULL)
             {
@@ -2250,8 +2639,6 @@ UpdateDiskLayout(
             PartitionNumber++;
             Index += 4;
         }
-
-        ListEntry = ListEntry->Flink;
     }
 
     /* Wipe unused primary partition entries */
@@ -2301,6 +2688,8 @@ UpdateDiskLayout(
         }
     }
 
+    DiskEntry->Dirty = TRUE;
+
 #ifdef DUMP_PARTITION_TABLE
     DumpPartitionTable(DiskEntry);
 #endif
@@ -2309,12 +2698,18 @@ UpdateDiskLayout(
 static
 PPARTENTRY
 GetPrevUnpartitionedEntry(
-    IN PDISKENTRY DiskEntry,
     IN PPARTENTRY PartEntry)
 {
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
     PPARTENTRY PrevPartEntry;
     PLIST_ENTRY ListHead;
 
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return NULL;
+    }
+
     if (PartEntry->LogicalPartition)
         ListHead = &DiskEntry->LogicalPartListHead;
     else
@@ -2325,8 +2720,11 @@ GetPrevUnpartitionedEntry(
         PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
                                           PARTENTRY,
                                           ListEntry);
-        if (PrevPartEntry->IsPartitioned == FALSE)
+        if (!PrevPartEntry->IsPartitioned)
+        {
+            ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
             return PrevPartEntry;
+        }
     }
 
     return NULL;
@@ -2335,12 +2733,18 @@ GetPrevUnpartitionedEntry(
 static
 PPARTENTRY
 GetNextUnpartitionedEntry(
-    IN PDISKENTRY DiskEntry,
     IN PPARTENTRY PartEntry)
 {
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
     PPARTENTRY NextPartEntry;
     PLIST_ENTRY ListHead;
 
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return NULL;
+    }
+
     if (PartEntry->LogicalPartition)
         ListHead = &DiskEntry->LogicalPartListHead;
     else
@@ -2351,8 +2755,11 @@ GetNextUnpartitionedEntry(
         NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
                                           PARTENTRY,
                                           ListEntry);
-        if (NextPartEntry->IsPartitioned == FALSE)
+        if (!NextPartEntry->IsPartitioned)
+        {
+            ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
             return NextPartEntry;
+        }
     }
 
     return NULL;
@@ -2361,93 +2768,36 @@ GetNextUnpartitionedEntry(
 BOOLEAN
 CreatePrimaryPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PPARTENTRY NewPartEntry;
 
     DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
 
     if (List == NULL ||
-        List->CurrentDisk == NULL ||
-        List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned)
+        SelectedEntry == NULL ||
+        SelectedEntry->DiskEntry == NULL ||
+        SelectedEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = PrimaryPartitionCreationChecks(List);
+    Error = PrimaryPartitionCreationChecks(SelectedEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("PrimaryPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
-
-    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
-
-    if ((AutoCreate != FALSE) ||
-        (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
-    {
-        DPRINT1("Convert existing partition entry\n");
-
-        /* Convert current entry to 'new (unformatted)' */
-        PartEntry->IsPartitioned = TRUE;
-        PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-        PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
-        PartEntry->AutoCreate = AutoCreate;
-        PartEntry->New = TRUE;
-        PartEntry->BootIndicator = FALSE;
-
-        DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
-    }
-    else
-    {
-        DPRINT1("Add new partition entry\n");
-
-        /* Insert and initialize a new partition entry */
-        NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof(PARTENTRY));
-        if (NewPartEntry == NULL)
-            return FALSE;
-
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry,
-                       &NewPartEntry->ListEntry);
-
-        NewPartEntry->DiskEntry = DiskEntry;
-
-        NewPartEntry->IsPartitioned = TRUE;
-        NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
-                                             NewPartEntry->StartSector.QuadPart;
-        NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-
-        DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-        NewPartEntry->New = TRUE;
-        NewPartEntry->FormatState = Unformatted;
-        NewPartEntry->FileSystem  = NULL;
-        NewPartEntry->BootIndicator = FALSE;
-
-        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
-        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
-    }
-
-    UpdateDiskLayout(DiskEntry);
+    /* Convert the current entry, or insert and initialize a new partition entry */
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
+    if (PartEntry == NULL)
+        return FALSE;
 
-    DiskEntry->Dirty = TRUE;
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2459,149 +2809,81 @@ VOID
 AddLogicalDiskSpace(
     IN PDISKENTRY DiskEntry)
 {
+    ULONGLONG StartSector;
+    ULONGLONG SectorCount;
     PPARTENTRY NewPartEntry;
 
     DPRINT1("AddLogicalDiskSpace()\n");
 
     /* Create a partition entry that represents the empty space in the container partition */
-    NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                   HEAP_ZERO_MEMORY,
-                                   sizeof(PARTENTRY));
+
+    StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
+    SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
+
+    NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                           &DiskEntry->LogicalPartListHead,
+                                           StartSector,
+                                           SectorCount,
+                                           TRUE);
     if (NewPartEntry == NULL)
+    {
+        DPRINT1("Failed to create a new empty region for extended partition space!\n");
         return;
-
-    NewPartEntry->DiskEntry = DiskEntry;
+    }
     NewPartEntry->LogicalPartition = TRUE;
-
-    NewPartEntry->IsPartitioned = FALSE;
-    NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
-    NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
-
-    DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-    DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-    DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-    NewPartEntry->FormatState = Unformatted;
-    NewPartEntry->FileSystem  = NULL;
-
-    InsertTailList(&DiskEntry->LogicalPartListHead,
-                   &NewPartEntry->ListEntry);
 }
 
 BOOLEAN
 CreateExtendedPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PPARTENTRY NewPartEntry;
 
     DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
 
     if (List == NULL ||
-        List->CurrentDisk == NULL ||
-        List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned)
+        SelectedEntry == NULL ||
+        SelectedEntry->DiskEntry == NULL ||
+        SelectedEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = ExtendedPartitionCreationChecks(List);
+    Error = ExtendedPartitionCreationChecks(SelectedEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("ExtendedPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
-
-    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+    /* Convert the current entry, or insert and initialize a new partition entry */
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, FALSE);
+    if (PartEntry == NULL)
+        return FALSE;
 
-    if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
+    if (PartEntry->StartSector.QuadPart < 1450560)
     {
-        DPRINT1("Convert existing partition entry\n");
-
-        /* Convert current entry to 'new (unformatted)' */
-        PartEntry->IsPartitioned = TRUE;
-        PartEntry->FormatState = Formatted;     // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
-        PartEntry->FileSystem  = NULL;
-        PartEntry->AutoCreate = FALSE;
-        PartEntry->New = FALSE;
-        PartEntry->BootIndicator = FALSE;
-
-        if (PartEntry->StartSector.QuadPart < 1450560)
-        {
-            /* Partition starts below the 8.4GB boundary ==> CHS partition */
-            PartEntry->PartitionType = PARTITION_EXTENDED;
-        }
-        else
-        {
-            /* Partition starts above the 8.4GB boundary ==> LBA partition */
-            PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
-        }
-
-        DiskEntry->ExtendedPartition = PartEntry;
-
-        DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
+        /* Partition starts below the 8.4GB boundary ==> CHS partition */
+        PartEntry->PartitionType = PARTITION_EXTENDED;
     }
     else
     {
-        DPRINT1("Add new partition entry\n");
-
-        /* Insert and initialize a new partition entry */
-        NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof(PARTENTRY));
-        if (NewPartEntry == NULL)
-            return FALSE;
-
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry,
-                       &NewPartEntry->ListEntry);
-
-        NewPartEntry->DiskEntry = DiskEntry;
-
-        NewPartEntry->IsPartitioned = TRUE;
-        NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
-                                             NewPartEntry->StartSector.QuadPart;
-
-        NewPartEntry->New = FALSE;
-        NewPartEntry->FormatState = Formatted;     // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
-        NewPartEntry->FileSystem  = NULL;
-        NewPartEntry->BootIndicator = FALSE;
-
-        if (NewPartEntry->StartSector.QuadPart < 1450560)
-        {
-            /* Partition starts below the 8.4GB boundary ==> CHS partition */
-            NewPartEntry->PartitionType = PARTITION_EXTENDED;
-        }
-        else
-        {
-            /* Partition starts above the 8.4GB boundary ==> LBA partition */
-            NewPartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
-        }
-
-        DiskEntry->ExtendedPartition = NewPartEntry;
-
-        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
-        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
-
-        DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+        /* Partition starts above the 8.4GB boundary ==> LBA partition */
+        PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
     }
 
-    AddLogicalDiskSpace(DiskEntry);
+    // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
+    PartEntry->New = FALSE;
+    PartEntry->FormatState = Formatted;
 
-    UpdateDiskLayout(DiskEntry);
+    PartEntry->DiskEntry->ExtendedPartition = PartEntry;
 
-    DiskEntry->Dirty = TRUE;
+    AddLogicalDiskSpace(PartEntry->DiskEntry);
+
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2611,95 +2893,38 @@ CreateExtendedPartition(
 BOOLEAN
 CreateLogicalPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PPARTENTRY NewPartEntry;
 
     DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
 
     if (List == NULL ||
-        List->CurrentDisk == NULL ||
-        List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned)
+        SelectedEntry == NULL ||
+        SelectedEntry->DiskEntry == NULL ||
+        SelectedEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = LogicalPartitionCreationChecks(List);
+    Error = LogicalPartitionCreationChecks(SelectedEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("LogicalPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
-
-    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
-
-    if ((AutoCreate != FALSE) ||
-        (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
-    {
-        DPRINT1("Convert existing partition entry\n");
-
-        /* Convert current entry to 'new (unformatted)' */
-        PartEntry->IsPartitioned = TRUE;
-        PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-        PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
-        PartEntry->AutoCreate = FALSE;
-        PartEntry->New = TRUE;
-        PartEntry->BootIndicator = FALSE;
-        PartEntry->LogicalPartition = TRUE;
-
-        DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
-    }
-    else
-    {
-        DPRINT1("Add new partition entry\n");
-
-        /* Insert and initialize a new partition entry */
-        NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof(PARTENTRY));
-        if (NewPartEntry == NULL)
-            return FALSE;
-
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry,
-                       &NewPartEntry->ListEntry);
-
-        NewPartEntry->DiskEntry = DiskEntry;
-
-        NewPartEntry->IsPartitioned = TRUE;
-        NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
-                                             NewPartEntry->StartSector.QuadPart;
-        NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-
-        DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
-        DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-        DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
-
-        NewPartEntry->New = TRUE;
-        NewPartEntry->FormatState = Unformatted;
-        NewPartEntry->FileSystem  = NULL;
-        NewPartEntry->BootIndicator = FALSE;
-        NewPartEntry->LogicalPartition = TRUE;
+    /* Convert the current entry, or insert and initialize a new partition entry */
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
+    if (PartEntry == NULL)
+        return FALSE;
 
-        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
-        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
-    }
+    PartEntry->LogicalPartition = TRUE;
 
-    UpdateDiskLayout(DiskEntry);
-
-    DiskEntry->Dirty = TRUE;
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2719,19 +2944,20 @@ DismountVolume(
     HANDLE PartitionHandle;
     WCHAR Buffer[MAX_PATH];
 
-    /* Check whether the partition is valid and may have been mounted in the system */
+    /* Check whether the partition is valid and was mounted by the system */
     if (!PartEntry->IsPartitioned ||
-        PartEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
-        IsContainerPartition(PartEntry->PartitionType)     ||
-        !IsRecognizedPartition(PartEntry->PartitionType)   ||
+        IsContainerPartition(PartEntry->PartitionType)   ||
+        !IsRecognizedPartition(PartEntry->PartitionType) ||
         PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ ||
-        PartEntry->FileSystem == NULL ||
+        !*PartEntry->FileSystem ||
         PartEntry->PartitionNumber == 0)
     {
         /* The partition is not mounted, so just return success */
         return STATUS_SUCCESS;
     }
 
+    ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
     /* Open the volume */
     RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
                         L"\\Device\\Harddisk%lu\\Partition%lu",
@@ -2811,33 +3037,40 @@ DismountVolume(
     return Status;
 }
 
-VOID
-DeleteCurrentPartition(
-    IN PPARTLIST List)
+BOOLEAN
+DeletePartition(
+    IN PPARTLIST List,
+    IN PPARTENTRY PartEntry,
+    OUT PPARTENTRY* FreeRegion OPTIONAL)
 {
     PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
     PPARTENTRY PrevPartEntry;
     PPARTENTRY NextPartEntry;
     PPARTENTRY LogicalPartEntry;
     PLIST_ENTRY Entry;
 
     if (List == NULL ||
-        List->CurrentDisk == NULL ||
-        List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned == FALSE)
+        PartEntry == NULL ||
+        PartEntry->DiskEntry == NULL ||
+        PartEntry->IsPartitioned == FALSE)
     {
-        return;
+        return FALSE;
     }
 
-    /* Clear the system disk and partition pointers if the system partition is being deleted */
-    if (List->SystemPartition == List->CurrentPartition)
+    ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+    /* Clear the system partition pointers if it is being deleted */
+    if (List->SystemPartition == PartEntry)
     {
+        ASSERT(List->SystemPartition);
+        ASSERT(List->SystemPartition->DiskEntry->MediaType != RemovableMedia);
+
+        if (List->SystemPartition == List->OriginalSystemPartition)
+            List->OriginalSystemPartition = NULL;
         List->SystemPartition = NULL;
     }
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
+    DiskEntry = PartEntry->DiskEntry;
 
     /* Check which type of partition (primary/logical or extended) is being deleted */
     if (DiskEntry->ExtendedPartition == PartEntry)
@@ -2863,49 +3096,49 @@ DeleteCurrentPartition(
         DismountVolume(PartEntry);
     }
 
-    /* Adjust unpartitioned disk space entries */
+    /* Adjust the unpartitioned disk space entries */
 
     /* Get pointer to previous and next unpartitioned entries */
-    PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry, PartEntry);
-    NextPartEntry = GetNextUnpartitionedEntry(DiskEntry, PartEntry);
+    PrevPartEntry = GetPrevUnpartitionedEntry(PartEntry);
+    NextPartEntry = GetNextUnpartitionedEntry(PartEntry);
 
     if (PrevPartEntry != NULL && NextPartEntry != NULL)
     {
-        /* Merge previous, current and next unpartitioned entry */
+        /* Merge the previous, current and next unpartitioned entries */
 
-        /* Adjust the previous entries length */
+        /* Adjust the previous entry length */
         PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
 
-        /* Remove the current entry */
+        /* Remove the current and next entries */
         RemoveEntryList(&PartEntry->ListEntry);
         RtlFreeHeap(ProcessHeap, 0, PartEntry);
-
-        /* Remove the next entry */
         RemoveEntryList(&NextPartEntry->ListEntry);
         RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
 
-        /* Update current partition */
-        List->CurrentPartition = PrevPartEntry;
+        /* Optionally return the freed region */
+        if (FreeRegion)
+            *FreeRegion = PrevPartEntry;
     }
     else if (PrevPartEntry != NULL && NextPartEntry == NULL)
     {
-        /* Merge current and previous unpartitioned entry */
+        /* Merge the current and the previous unpartitioned entries */
 
-        /* Adjust the previous entries length */
+        /* Adjust the previous entry length */
         PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
 
         /* Remove the current entry */
         RemoveEntryList(&PartEntry->ListEntry);
         RtlFreeHeap(ProcessHeap, 0, PartEntry);
 
-        /* Update current partition */
-        List->CurrentPartition = PrevPartEntry;
+        /* Optionally return the freed region */
+        if (FreeRegion)
+            *FreeRegion = PrevPartEntry;
     }
     else if (PrevPartEntry == NULL && NextPartEntry != NULL)
     {
-        /* Merge current and next unpartitioned entry */
+        /* Merge the current and the next unpartitioned entries */
 
-        /* Adjust the next entries offset and length */
+        /* Adjust the next entry offset and length */
         NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
         NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
 
@@ -2913,53 +3146,200 @@ DeleteCurrentPartition(
         RemoveEntryList(&PartEntry->ListEntry);
         RtlFreeHeap(ProcessHeap, 0, PartEntry);
 
-        /* Update current partition */
-        List->CurrentPartition = NextPartEntry;
+        /* Optionally return the freed region */
+        if (FreeRegion)
+            *FreeRegion = NextPartEntry;
     }
     else
     {
-        /* Nothing to merge but change current entry */
+        /* Nothing to merge but change the current entry */
         PartEntry->IsPartitioned = FALSE;
         PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
         PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
+        PartEntry->FileSystem[0] = L'\0';
         PartEntry->DriveLetter = 0;
+        PartEntry->OnDiskPartitionNumber = 0;
+        PartEntry->PartitionNumber = 0;
+        // PartEntry->PartitionIndex = 0;
+
+        /* Optionally return the freed region */
+        if (FreeRegion)
+            *FreeRegion = PartEntry;
+    }
+
+    UpdateDiskLayout(DiskEntry);
+
+    AssignDriveLetters(List);
+
+    return TRUE;
+}
+
+/*
+ * Retrieve the actual "active" partition of the given disk.
+ * On MBR disks, partition with the Active/Boot flag set;
+ * on GPT disks, partition with the correct GUID.
+ */
+static
+PPARTENTRY
+GetActiveDiskPartition(
+    IN PDISKENTRY DiskEntry)
+{
+    PLIST_ENTRY ListEntry;
+    PPARTENTRY PartEntry;
+    PPARTENTRY ActivePartition = NULL;
+
+    /* Check for empty disk list */
+    // ASSERT(DiskEntry);
+    if (!DiskEntry)
+        return NULL;
+
+    /* Check for empty partition list */
+    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+        return NULL;
+
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return NULL;
     }
 
-    UpdateDiskLayout(DiskEntry);
+    /* Scan all (primary) partitions to find the active disk partition */
+    for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+         ListEntry != &DiskEntry->PrimaryPartListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        /* Retrieve the partition */
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+        // TODO: Support for GPT disks!
+
+        /* Check if the partition is partitioned, used and active */
+        if (PartEntry->IsPartitioned &&
+            // !IsContainerPartition(PartEntry->PartitionType) &&
+            PartEntry->BootIndicator)
+        {
+            /* Yes, we found it */
+            ASSERT(DiskEntry == PartEntry->DiskEntry);
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+            ActivePartition = PartEntry;
+
+            DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
+                    PartEntry->PartitionNumber, DiskEntry->DiskNumber,
+                    (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
+            break;
+        }
+    }
+
+    /* Check if the disk is new and if so, use its first partition as the active system partition */
+    if (DiskEntry->NewDisk && ActivePartition != NULL)
+    {
+        // FIXME: What to do??
+        DPRINT1("NewDisk TRUE but already existing active partition?\n");
+    }
+
+    /* Return the active partition found (or none) */
+    return ActivePartition;
+}
+
+static
+BOOLEAN
+IsSupportedActivePartition(
+    IN PPARTENTRY PartEntry)
+{
+    /* Check the type and the filesystem of this partition */
+
+    /*
+     * We do not support extended partition containers (on MBR disks) marked
+     * as active, and containing code inside their extended boot records.
+     */
+    if (IsContainerPartition(PartEntry->PartitionType))
+    {
+        DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
+                PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
+        return FALSE;
+    }
+
+    /*
+     * ADDITIONAL CHECKS / BIG HACK:
+     *
+     * Retrieve its file system and check whether we have
+     * write support for it. If that is the case we are fine
+     * and we can use it directly. However if we don't have
+     * write support we will need to change the active system
+     * partition.
+     *
+     * NOTE that this is completely useless on architectures
+     * where a real system partition is required, as on these
+     * architectures the partition uses the FAT FS, for which
+     * we do have write support.
+     * NOTE also that for those architectures looking for a
+     * partition boot indicator is insufficient.
+     */
+    if ((PartEntry->FormatState == Unformatted ) ||
+        (PartEntry->FormatState == Preformatted) ||
+        (PartEntry->FormatState == Formatted   ))
+    {
+        ASSERT(*PartEntry->FileSystem);
+
+        /* NOTE: Please keep in sync with the RegisteredFileSystems list! */
+        if (wcsicmp(PartEntry->FileSystem, L"FAT")   == 0 ||
+            wcsicmp(PartEntry->FileSystem, L"FAT32") == 0 ||
+         // wcsicmp(PartEntry->FileSystem, L"NTFS")  == 0 ||
+            wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0 ||
+            wcsicmp(PartEntry->FileSystem, L"RAW")   == 0)
+        {
+            return TRUE;
+        }
+        else
+        {
+            // WARNING: We cannot write on this FS yet!
+            DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
+                    PartEntry->FileSystem);
+            return FALSE;
+        }
+    }
+    else // if (PartEntry->FormatState == UnknownFormat)
+    {
+        ASSERT(!*PartEntry->FileSystem);
+
+        DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
+                PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
+        return FALSE;
+    }
 
-    DiskEntry->Dirty = TRUE;
+    // HACK: WARNING: We cannot write on this FS yet!
+    // See fsutil.c:InferFileSystem()
+    if (PartEntry->PartitionType == PARTITION_IFS)
+    {
+        DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
+                PartEntry->FileSystem);
+        return FALSE;
+    }
 
-    AssignDriveLetters(List);
+    return TRUE;
 }
 
 VOID
 CheckActiveSystemPartition(
-    IN PPARTLIST List)
+    IN PPARTLIST List,
+    IN BOOLEAN ForceSelect,
+    IN PDISKENTRY AlternateDisk OPTIONAL,
+    IN PPARTENTRY AlternatePart OPTIONAL)
 {
+    PLIST_ENTRY ListEntry;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PLIST_ENTRY ListEntry;
-
-    PFILE_SYSTEM FileSystem;
+    PPARTENTRY ActivePartition;
+    PPARTENTRY CandidatePartition = NULL;
 
     /* Check for empty disk list */
     if (IsListEmpty(&List->DiskListHead))
     {
+        /* No system partition! */
         List->SystemPartition = NULL;
         List->OriginalSystemPartition = NULL;
-        return;
-    }
-
-    /* Choose the currently selected disk */
-    DiskEntry = List->CurrentDisk;
-
-    /* Check for empty partition list */
-    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
-    {
-        List->SystemPartition = NULL;
-        List->OriginalSystemPartition = NULL;
-        return;
+        goto NoSystemPartition;
     }
 
     if (List->SystemPartition != NULL)
@@ -2972,17 +3352,184 @@ CheckActiveSystemPartition(
         return;
     }
 
-    DPRINT1("We are here (1)!\n");
-
+    /* Start fresh */
     List->SystemPartition = NULL;
     List->OriginalSystemPartition = NULL;
 
+    /* Adjust the optional alternate disk if needed */
+    if (!AlternateDisk && AlternatePart)
+        AlternateDisk = AlternatePart->DiskEntry;
+
+    /* Ensure that the alternate partition is on the alternate disk */
+    if (AlternatePart)
+        ASSERT(AlternateDisk && (AlternatePart->DiskEntry == AlternateDisk));
+
+    /* Ensure that the alternate disk is in the list */
+    if (AlternateDisk)
+        ASSERT(AlternateDisk->PartList == List);
+
+//
+// Pass == 1 : Check the first (system) disk.
+//
+
+    /*
+     * First, check whether the first disk (the one that will be booted
+     * by default by the hardware) contains an active partition. If so
+     * this should be our system partition.
+     */
+    DiskEntry = CONTAINING_RECORD(List->DiskListHead.Flink,
+                                  DISKENTRY, ListEntry);
+
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("First (system) disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        goto UseAlternateDisk;
+    }
+
+    ActivePartition = GetActiveDiskPartition(DiskEntry);
+    if (ActivePartition)
+    {
+        /* Save the actual system partition */
+        List->OriginalSystemPartition = ActivePartition;
+
+        /* If we get a candidate active partition in the first disk, validate it */
+        if (IsSupportedActivePartition(ActivePartition))
+        {
+            CandidatePartition = ActivePartition;
+            goto SystemPartitionFound;
+        }
+    }
+
+    /* If this first disk is not the optional alternate disk, perform the minimal checks */
+    if (DiskEntry != AlternateDisk)
+    {
+        /*
+         * No active partition has been recognized. Enumerate all the (primary)
+         * partitions in the first disk, excluding the possible current active
+         * partition, to find a new candidate.
+         */
+        for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+             ListEntry != &DiskEntry->PrimaryPartListHead;
+             ListEntry = ListEntry->Flink)
+        {
+            /* Retrieve the partition */
+            PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+            /* Skip the current active partition */
+            if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+                continue;
+
+            /* Check if the partition is partitioned and used */
+            if (PartEntry->IsPartitioned &&
+                !IsContainerPartition(PartEntry->PartitionType))
+            {
+                ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+                /* If we get a candidate active partition in the first disk, validate it */
+                if (IsSupportedActivePartition(PartEntry))
+                {
+                    CandidatePartition = PartEntry;
+                    goto FindAndUseAlternativeSystemPartition;
+                }
+            }
+
+#if 0
+            /* Check if the partition is partitioned and used */
+            if (!PartEntry->IsPartitioned)
+            {
+                ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+                // TODO: Check for minimal size!!
+                CandidatePartition = PartEntry;
+                goto FindAndUseAlternativeSystemPartition;
+            }
+#endif
+        }
+
+        /*
+         * Still nothing, look whether there is some free space that we can use
+         * for the new system partition. We must be sure that the total number
+         * of partition is less than the maximum allowed, and that the minimal
+         * size is fine.
+         */
+//
+// TODO: Fix the handling of system partition being created in unpartitioned space!!
+// --> When to partition it? etc...
+//
+        if (GetPrimaryPartitionCount(DiskEntry) < 4)
+        {
+            for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+                 ListEntry != &DiskEntry->PrimaryPartListHead;
+                 ListEntry = ListEntry->Flink)
+            {
+                /* Retrieve the partition */
+                PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+                /* Skip the current active partition */
+                if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+                    continue;
+
+                /* Check for unpartitioned space */
+                if (!PartEntry->IsPartitioned)
+                {
+                    ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+                    // TODO: Check for minimal size!!
+                    CandidatePartition = PartEntry;
+                    goto FindAndUseAlternativeSystemPartition;
+                }
+            }
+        }
+    }
+
+
+//
+// Pass == 2 : No active partition found: Check the alternate disk if specified.
+//
+
+UseAlternateDisk:
+    if (!AlternateDisk || (!ForceSelect && (DiskEntry != AlternateDisk)))
+        goto NoSystemPartition;
+
+    if (AlternateDisk->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("Alternate disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        goto NoSystemPartition;
+    }
+
+    if (DiskEntry != AlternateDisk)
+    {
+        /* Choose the alternate disk */
+        DiskEntry = AlternateDisk;
+
+        ActivePartition = GetActiveDiskPartition(DiskEntry);
+        if (ActivePartition)
+        {
+            /* If we get a candidate active partition, validate it */
+            if (IsSupportedActivePartition(ActivePartition))
+            {
+                CandidatePartition = ActivePartition;
+                goto FindAndUseAlternativeSystemPartition;
+            }
+        }
+    }
+
+    /* We now may have an unsupported active partition, or none */
+
+/***
+ *** TODO: Improve the selection:
+ *** - If we want a really separate system partition from the partition where
+ ***   we install, do something similar to what's done below in the code.
+ *** - Otherwise if we allow for the system partition to be also the partition
+ ***   where we install, just directly fall down to using AlternatePart.
+ ***/
+
     /* Retrieve the first partition of the disk */
     PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
-                                  PARTENTRY,
-                                  ListEntry);
+                                  PARTENTRY, ListEntry);
     ASSERT(DiskEntry == PartEntry->DiskEntry);
-    List->SystemPartition = PartEntry;
+
+    CandidatePartition = PartEntry;
 
     //
     // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
@@ -2991,11 +3538,12 @@ CheckActiveSystemPartition(
     /* Check if the disk is new and if so, use its first partition as the active system partition */
     if (DiskEntry->NewDisk)
     {
-        if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
+        // !IsContainerPartition(PartEntry->PartitionType);
+        if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
         {
-            ASSERT(DiskEntry == PartEntry->DiskEntry);
-            List->SystemPartition = PartEntry;
+            ASSERT(DiskEntry == CandidatePartition->DiskEntry);
 
+            List->SystemPartition = CandidatePartition;
             List->OriginalSystemPartition = List->SystemPartition;
 
             DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
@@ -3010,28 +3558,24 @@ CheckActiveSystemPartition(
         DPRINT1("NewDisk TRUE but first partition is used?\n");
     }
 
-    DPRINT1("We are here (2)!\n");
-
     /*
      * The disk is not new, check if any partition is initialized;
      * if not, the first one becomes the system partition.
      */
-    ListEntry = DiskEntry->PrimaryPartListHead.Flink;
-    while (ListEntry != &DiskEntry->PrimaryPartListHead)
+    for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+         ListEntry != &DiskEntry->PrimaryPartListHead;
+         ListEntry = ListEntry->Flink)
     {
-        /* Retrieve the partition and go to the next one */
-        PartEntry = CONTAINING_RECORD(ListEntry,
-                                      PARTENTRY,
-                                      ListEntry);
+        /* Retrieve the partition */
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
 
         /* Check if the partition is partitioned and is used */
-        if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
+        // !IsContainerPartition(PartEntry->PartitionType);
+        if (/* PartEntry->IsPartitioned && */
+            PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
         {
             break;
         }
-
-        /* Go to the next one */
-        ListEntry = ListEntry->Flink;
     }
     if (ListEntry == &DiskEntry->PrimaryPartListHead)
     {
@@ -3039,8 +3583,9 @@ CheckActiveSystemPartition(
          * OK we haven't encountered any used and active partition,
          * so use the first one as the system partition.
          */
-        ASSERT(DiskEntry == List->SystemPartition->DiskEntry);
-        List->OriginalSystemPartition = List->SystemPartition; // First PartEntry
+        ASSERT(DiskEntry == CandidatePartition->DiskEntry);
+        List->SystemPartition = CandidatePartition; // The first PartEntry
+        List->OriginalSystemPartition = List->SystemPartition;
 
         DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
                 List->SystemPartition->PartitionNumber,
@@ -3050,85 +3595,29 @@ CheckActiveSystemPartition(
         goto SetSystemPartition;
     }
 
-    List->SystemPartition = NULL;
-    List->OriginalSystemPartition = NULL;
-
-    DPRINT1("We are here (3)!\n");
-
-    /* The disk is not new, scan all partitions to find the (active) system partition */
-    ListEntry = DiskEntry->PrimaryPartListHead.Flink;
-    while (ListEntry != &DiskEntry->PrimaryPartListHead)
-    {
-        /* Retrieve the partition and go to the next one */
-        PartEntry = CONTAINING_RECORD(ListEntry,
-                                      PARTENTRY,
-                                      ListEntry);
-        ListEntry = ListEntry->Flink;
-
-        /* Check if the partition is partitioned and used */
-        if (PartEntry->IsPartitioned &&
-            PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
-        {
-            /* Check if the partition is active */
-            if (PartEntry->BootIndicator)
-            {
-                /* Yes, we found it */
-                ASSERT(DiskEntry == PartEntry->DiskEntry);
-                List->SystemPartition = PartEntry;
-
-                DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
-                        PartEntry->PartitionNumber,
-                        DiskEntry->DiskNumber,
-                        (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
-                break;
-            }
-        }
-    }
-
-    /* Check if we have found the system partition */
-    if (List->SystemPartition == NULL)
-    {
-        /* Nothing, use the alternative system partition */
-        DPRINT1("No system partition found, use the alternative partition!\n");
-        goto UseAlternativeSystemPartition;
-    }
-
-    /* Save it */
-    List->OriginalSystemPartition = List->SystemPartition;
-
     /*
-     * ADDITIONAL CHECKS / BIG HACK:
-     *
-     * Retrieve its file system and check whether we have
-     * write support for it. If that is the case we are fine
-     * and we can use it directly. However if we don't have
-     * write support we will need to change the active system
-     * partition.
-     *
-     * NOTE that this is completely useless on architectures
-     * where a real system partition is required, as on these
-     * architectures the partition uses the FAT FS, for which
-     * we do have write support.
-     * NOTE also that for those architectures looking for a
-     * partition boot indicator is insufficient.
+     * The disk is not new, we did not find any actual active partition,
+     * or the one we found was not supported, or any possible other canditate
+     * is not supported. We then use the alternate partition if specified.
      */
-    FileSystem = GetFileSystem(List->OriginalSystemPartition);
-    if (FileSystem == NULL)
+    if (AlternatePart)
     {
-        DPRINT1("System partition %lu in disk %lu with no FS?!\n",
-                List->OriginalSystemPartition->PartitionNumber,
-                List->OriginalSystemPartition->DiskEntry->DiskNumber);
-        goto FindAndUseAlternativeSystemPartition;
+        DPRINT1("No system partition found, use the alternative partition!\n");
+        CandidatePartition = AlternatePart;
+        goto UseAlternativeSystemPartition;
     }
-    // HACK: WARNING: We cannot write on this FS yet!
-    // See fsutil.c:GetFileSystem()
-    if (List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
+    else
     {
-        DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
-                FileSystem->FileSystemName);
-        goto FindAndUseAlternativeSystemPartition;
+NoSystemPartition:
+        DPRINT1("No valid or supported system partition has been found on this system!\n");
+        return;
     }
 
+
+SystemPartitionFound:
+    ASSERT(CandidatePartition);
+    List->SystemPartition = CandidatePartition;
+
     DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %C\n",
             List->SystemPartition->PartitionNumber,
             List->SystemPartition->DiskEntry->DiskNumber,
@@ -3147,13 +3636,17 @@ FindAndUseAlternativeSystemPartition:
      */
 
     /* Unset the old system partition */
-    List->SystemPartition->BootIndicator = FALSE;
-    List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = FALSE;
-    List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
-    List->SystemPartition->DiskEntry->Dirty = TRUE;
+    if (List->OriginalSystemPartition)
+    {
+        List->OriginalSystemPartition->BootIndicator = FALSE;
+        List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].BootIndicator = FALSE;
+        List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].RewritePartition = TRUE;
+        List->OriginalSystemPartition->DiskEntry->Dirty = TRUE;
+    }
 
 UseAlternativeSystemPartition:
-    List->SystemPartition = List->CurrentPartition;
+    ASSERT(CandidatePartition);
+    List->SystemPartition = CandidatePartition;
 
     DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
             List->SystemPartition->PartitionNumber,
@@ -3168,22 +3661,28 @@ SetSystemPartition:
     List->SystemPartition->DiskEntry->Dirty = TRUE;
 }
 
-static
 NTSTATUS
 WritePartitions(
-    IN PPARTLIST List,
     IN PDISKENTRY DiskEntry)
 {
-    WCHAR DstPath[MAX_PATH];
+    NTSTATUS Status;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    IO_STATUS_BLOCK Iosb;
     UNICODE_STRING Name;
+    HANDLE FileHandle;
+    IO_STATUS_BLOCK Iosb;
     ULONG BufferSize;
-    HANDLE FileHandle = NULL;
-    NTSTATUS Status;
+    PPARTITION_INFORMATION PartitionInfo;
+    ULONG PartitionCount;
+    PLIST_ENTRY ListEntry;
+    PPARTENTRY PartEntry;
+    WCHAR DstPath[MAX_PATH];
 
     DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
 
+    /* If the disk is not dirty, there is nothing to do */
+    if (!DiskEntry->Dirty)
+        return STATUS_SUCCESS;
+
     RtlStringCchPrintfW(DstPath, ARRAYSIZE(DstPath),
                         L"\\Device\\Harddisk%lu\\Partition0",
                         DiskEntry->DiskNumber);
@@ -3217,8 +3716,12 @@ WritePartitions(
     // For this we must ask the user which format to use.
     //
 
+    /* Save the original partition count to be restored later (see comment below) */
+    PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
+
+    /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
     BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
-                 ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
+                 ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
     Status = NtDeviceIoControlFile(FileHandle,
                                    NULL,
                                    NULL,
@@ -3227,26 +3730,75 @@ WritePartitions(
                                    IOCTL_DISK_SET_DRIVE_LAYOUT,
                                    DiskEntry->LayoutBuffer,
                                    BufferSize,
-                                   NULL,
-                                   0);
+                                   DiskEntry->LayoutBuffer,
+                                   BufferSize);
+    NtClose(FileHandle);
+
+    /*
+     * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
+     * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
+     * where such a table is expected to enumerate up to 4 partitions:
+     * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
+     * Due to this we need to restore the original PartitionCount number.
+     */
+    DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
+
+    /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
+        return Status;
+    }
+
+#ifdef DUMP_PARTITION_TABLE
+    DumpPartitionTable(DiskEntry);
+#endif
+
+    /* Update the partition numbers */
+
+    /* Update the primary partition table */
+    for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+         ListEntry != &DiskEntry->PrimaryPartListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+        if (PartEntry->IsPartitioned)
+        {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+            PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
+            PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+        }
     }
 
-    if (FileHandle != NULL)
-        NtClose(FileHandle);
+    /* Update the logical partition table */
+    for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
+         ListEntry != &DiskEntry->LogicalPartListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+        if (PartEntry->IsPartitioned)
+        {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+            PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
+            PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+        }
+    }
 
     //
     // NOTE: Originally (see r40437), we used to install here also a new MBR
     // for this disk (by calling InstallMbrBootCodeToDisk), only if:
-    // DiskEntry->NewDisk == TRUE and DiskEntry->BiosDiskNumber == 0.
+    // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 0.
     // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
     // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
     // was called too, the installation test was modified by checking whether
     // DiskEntry->NoMbr was TRUE (instead of NewDisk).
     //
 
+    /* The layout has been successfully updated, the disk is not dirty anymore */
+    DiskEntry->Dirty = FALSE;
+
     return Status;
 }
 
@@ -3254,24 +3806,34 @@ BOOLEAN
 WritePartitionsToDisk(
     IN PPARTLIST List)
 {
+    NTSTATUS Status;
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
 
     if (List == NULL)
         return TRUE;
 
-    Entry = List->DiskListHead.Flink;
-    while (Entry != &List->DiskListHead)
+    for (Entry = List->DiskListHead.Flink;
+         Entry != &List->DiskListHead;
+         Entry = Entry->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
-        if (DiskEntry->Dirty != FALSE)
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
         {
-            WritePartitions(List, DiskEntry);
-            DiskEntry->Dirty = FALSE;
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
         }
 
-        Entry = Entry->Flink;
+        if (DiskEntry->Dirty != FALSE)
+        {
+            Status = WritePartitions(DiskEntry);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
+                        DiskEntry->DiskNumber, Status);
+            }
+        }
     }
 
     return TRUE;
@@ -3351,19 +3913,29 @@ SetMountedDeviceValues(
     if (List == NULL)
         return FALSE;
 
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    for (Entry1 = List->DiskListHead.Flink;
+         Entry1 != &List->DiskListHead;
+         Entry1 = Entry1->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry1,
                                       DISKENTRY,
                                       ListEntry);
 
-        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
-        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+        {
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
+
+        for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+             Entry2 != &DiskEntry->PrimaryPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-            if (PartEntry->IsPartitioned)
+            if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
             {
+                ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
                 /* Assign a "\DosDevices\#:" mount point to this partition */
                 if (PartEntry->DriveLetter)
                 {
@@ -3376,16 +3948,17 @@ SetMountedDeviceValues(
                     }
                 }
             }
-
-            Entry2 = Entry2->Flink;
         }
 
-        Entry2 = DiskEntry->LogicalPartListHead.Flink;
-        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+             Entry2 != &DiskEntry->LogicalPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-            if (PartEntry->IsPartitioned)
+            if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
             {
+                ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
                 /* Assign a "\DosDevices\#:" mount point to this partition */
                 if (PartEntry->DriveLetter)
                 {
@@ -3398,11 +3971,7 @@ SetMountedDeviceValues(
                     }
                 }
             }
-
-            Entry2 = Entry2->Flink;
         }
-
-        Entry1 = Entry1->Flink;
     }
 
     return TRUE;
@@ -3419,23 +3988,30 @@ SetPartitionType(
 
     DiskEntry->Dirty = TRUE;
     DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
+    DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RecognizedPartition = IsRecognizedPartition(PartitionType);
     DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
 }
 
 ERROR_NUMBER
 PrimaryPartitionCreationChecks(
-    IN PPARTLIST List)
+    IN PPARTENTRY PartEntry)
 {
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return ERROR_WARN_PARTITION;
+    }
 
     /* Fail if the partition is already in use */
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     /* Fail if there are already 4 primary partitions in the list */
     if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
@@ -3445,18 +4021,24 @@ PrimaryPartitionCreationChecks(
 
 ERROR_NUMBER
 ExtendedPartitionCreationChecks(
-    IN PPARTLIST List)
+    IN PPARTENTRY PartEntry)
 {
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
 
-    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return ERROR_WARN_PARTITION;
+    }
 
     /* Fail if the partition is already in use */
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     /* Fail if there are already 4 primary partitions in the list */
     if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
@@ -3470,18 +4052,24 @@ ExtendedPartitionCreationChecks(
 
 ERROR_NUMBER
 LogicalPartitionCreationChecks(
-    IN PPARTLIST List)
+    IN PPARTENTRY PartEntry)
 {
-//    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
 
-//    DiskEntry = List->CurrentDisk;
-    PartEntry = List->CurrentPartition;
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+    {
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return ERROR_WARN_PARTITION;
+    }
 
     /* Fail if the partition is already in use */
     if (PartEntry->IsPartitioned)
         return ERROR_NEW_PARTITION;
 
+    /* Only one primary partition is allowed on super-floppy */
+    if (IsSuperFloppy(DiskEntry))
+        return ERROR_PARTITION_TABLE_FULL;
+
     return ERROR_SUCCESS;
 }
 
@@ -3495,15 +4083,23 @@ GetNextUnformattedPartition(
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
 
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    for (Entry1 = List->DiskListHead.Flink;
+         Entry1 != &List->DiskListHead;
+         Entry1 = Entry1->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry1,
                                       DISKENTRY,
                                       ListEntry);
 
-        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
-        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+        {
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
+
+        for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+             Entry2 != &DiskEntry->PrimaryPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
             if (PartEntry->IsPartitioned && PartEntry->New)
@@ -3513,12 +4109,11 @@ GetNextUnformattedPartition(
                 *pPartEntry = PartEntry;
                 return TRUE;
             }
-
-            Entry2 = Entry2->Flink;
         }
 
-        Entry2 = DiskEntry->LogicalPartListHead.Flink;
-        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+             Entry2 != &DiskEntry->LogicalPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
             if (PartEntry->IsPartitioned && PartEntry->New)
@@ -3528,11 +4123,7 @@ GetNextUnformattedPartition(
                 *pPartEntry = PartEntry;
                 return TRUE;
             }
-
-            Entry2 = Entry2->Flink;
         }
-
-        Entry1 = Entry1->Flink;
     }
 
     if (pDiskEntry) *pDiskEntry = NULL;
@@ -3551,44 +4142,47 @@ GetNextUncheckedPartition(
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
 
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    for (Entry1 = List->DiskListHead.Flink;
+         Entry1 != &List->DiskListHead;
+         Entry1 = Entry1->Flink)
     {
         DiskEntry = CONTAINING_RECORD(Entry1,
                                       DISKENTRY,
                                       ListEntry);
 
-        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
-        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+        {
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
+
+        for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+             Entry2 != &DiskEntry->PrimaryPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-            if (PartEntry->NeedsCheck == TRUE)
+            if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
             {
                 ASSERT(DiskEntry == PartEntry->DiskEntry);
                 if (pDiskEntry) *pDiskEntry = DiskEntry;
                 *pPartEntry = PartEntry;
                 return TRUE;
             }
-
-            Entry2 = Entry2->Flink;
         }
 
-        Entry2 = DiskEntry->LogicalPartListHead.Flink;
-        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
+             Entry2 != &DiskEntry->LogicalPartListHead;
+             Entry2 = Entry2->Flink)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-            if (PartEntry->NeedsCheck == TRUE)
+            if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
             {
                 ASSERT(DiskEntry == PartEntry->DiskEntry);
                 if (pDiskEntry) *pDiskEntry = DiskEntry;
                 *pPartEntry = PartEntry;
                 return TRUE;
             }
-
-            Entry2 = Entry2->Flink;
         }
-
-        Entry1 = Entry1->Flink;
     }
 
     if (pDiskEntry) *pDiskEntry = NULL;