[SETUPLIB][USETUP] Remove CurrentDisk/Partition from the partlist lib code, and move...
[reactos.git] / base / setup / lib / utils / partlist.c
index e0f16aa..90dfe7c 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"
@@ -341,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')
                     {
@@ -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')
                     {
@@ -752,18 +755,19 @@ CreateInsertBlankRegion(
 
     NewPartEntry->DiskEntry = DiskEntry;
 
-    NewPartEntry->IsPartitioned = FALSE;
-    NewPartEntry->FormatState = Unformatted;
-    NewPartEntry->FileSystem  = NULL;
-
     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 table into the list */
+    /* Insert the new entry into the list */
     InsertTailList(ListHead, &NewPartEntry->ListEntry);
 
     return NewPartEntry;
@@ -788,17 +792,8 @@ InitializePartitionEntry(
     {
         DPRINT1("Convert existing partition entry\n");
 
-        /* Convert current entry to 'new (unformatted)' */
-        PartEntry->IsPartitioned = TRUE;
-        PartEntry->New = TRUE;
-        PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-        PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
-        PartEntry->AutoCreate = AutoCreate;
-        PartEntry->BootIndicator = FALSE;
-        PartEntry->LogicalPartition = FALSE;
-
         NewPartEntry = PartEntry;
+        NewPartEntry->AutoCreate = AutoCreate;
     }
     else
     {
@@ -811,28 +806,32 @@ InitializePartitionEntry(
         if (NewPartEntry == NULL)
             return NULL;
 
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry,
-                       &NewPartEntry->ListEntry);
-
         NewPartEntry->DiskEntry = DiskEntry;
 
-        NewPartEntry->IsPartitioned = TRUE;
-        NewPartEntry->New = TRUE;
-        NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
-        NewPartEntry->FormatState = Unformatted;
-        NewPartEntry->FileSystem  = NULL;
-        NewPartEntry->BootIndicator = FALSE;
-        NewPartEntry->LogicalPartition = FALSE;
-
         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);
@@ -852,10 +851,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;
@@ -889,10 +888,16 @@ AddPartitionToDisk(
     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;
@@ -900,68 +905,83 @@ AddPartitionToDisk(
     else if (IsRecognizedPartition(PartEntry->PartitionType))
     {
         ASSERT(PartitionInfo->RecognizedPartition);
+        ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
-        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;
-    }
-
-    /* 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;
     }
 
     InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
@@ -1193,6 +1213,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)
@@ -1221,6 +1247,12 @@ SetDiskSignature(
         {
             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;
@@ -1239,13 +1271,19 @@ UpdateDiskSignatures(
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
 
-    /* Print partition lines */
+    /* 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)
         {
@@ -1369,6 +1407,8 @@ AddDiskToList(
         return;
     }
 
+    DiskEntry->PartList = List;
+
 //    DiskEntry->Checksum = Checksum;
 //    DiskEntry->Signature = Signature;
     DiskEntry->BiosFound = FALSE;
@@ -1377,11 +1417,30 @@ 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);
@@ -1478,6 +1537,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));
@@ -1603,9 +1672,6 @@ CreatePartitionList(VOID)
     if (List == NULL)
         return NULL;
 
-    List->CurrentDisk = NULL;
-    List->CurrentPartition = NULL;
-
     List->SystemPartition = NULL;
     List->OriginalSystemPartition = NULL;
 
@@ -1660,30 +1726,6 @@ CreatePartitionList(VOID)
 
     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;
 }
 
@@ -1861,6 +1903,12 @@ 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... */
     for (Entry = DiskEntry->PrimaryPartListHead.Flink;
          Entry != &DiskEntry->PrimaryPartListHead;
@@ -1912,6 +1960,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;
@@ -1927,7 +1981,7 @@ GetDiskOrPartition(
 //
 // NOTE: Was introduced broken in r6258 by Casper
 //
-BOOLEAN
+PPARTENTRY
 SelectPartition(
     IN PPARTLIST List,
     IN ULONG DiskNumber,
@@ -1938,59 +1992,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;
                 }
             }
         }
@@ -1998,49 +2048,49 @@ GetNextPartition(
         {
             /* Primary or extended partition */
 
-            if (List->CurrentPartition->IsPartitioned &&
-                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 */
-    for (DiskListEntry = List->CurrentDisk->ListEntry.Flink;
+    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);
+            DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+            continue;
+        }
 
-            List->CurrentDisk = DiskEntry;
-            List->CurrentPartition = PartEntry;
-            return List->CurrentPartition;
+        PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
+        if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
+        {
+            CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+            return CurrentPart;
         }
     }
 
@@ -2049,90 +2099,92 @@ 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 &&
-                    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 */
-    for (DiskListEntry = List->CurrentDisk->ListEntry.Blink;
+    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 &&
-                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;
             }
         }
     }
@@ -2182,6 +2234,12 @@ GetPrimaryPartitionCount(
     PPARTENTRY PartEntry;
     ULONG Count = 0;
 
+    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)
@@ -2203,6 +2261,12 @@ GetLogicalPartitionCount(
     PPARTENTRY PartEntry;
     ULONG Count = 0;
 
+    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)
@@ -2282,6 +2346,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)
     {
@@ -2299,14 +2369,16 @@ UpdateDiskLayout(
 
         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 partitions */
+            /* Reset the current partition number only for newly-created (unmounted) partitions */
             if (PartEntry->New)
                 PartEntry->PartitionNumber = 0;
 
-            PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+            PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0);
 
             if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
             {
@@ -2341,17 +2413,19 @@ UpdateDiskLayout(
 
         if (PartEntry->IsPartitioned)
         {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
             PartEntry->PartitionIndex = Index;
 
-            DPRINT1("Updating logical partition entry %lu\n", Index);
-
-            /* Reset the current partition number only for newly-created partitions */
+            /* 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;
@@ -2440,12 +2514,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
@@ -2456,8 +2536,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;
@@ -2466,12 +2549,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
@@ -2482,8 +2571,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;
@@ -2492,39 +2584,36 @@ GetNextUnpartitionedEntry(
 BOOLEAN
 CreatePrimaryPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
 
     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;
-
     /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(DiskEntry, PartEntry, SectorCount, AutoCreate);
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
     if (PartEntry == NULL)
         return FALSE;
 
-    UpdateDiskLayout(DiskEntry);
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2563,34 +2652,31 @@ AddLogicalDiskSpace(
 BOOLEAN
 CreateExtendedPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
 
     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;
-
     /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(DiskEntry, PartEntry, SectorCount, FALSE);
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, FALSE);
     if (PartEntry == NULL)
         return FALSE;
 
@@ -2609,11 +2695,11 @@ CreateExtendedPartition(
     PartEntry->New = FALSE;
     PartEntry->FormatState = Formatted;
 
-    DiskEntry->ExtendedPartition = PartEntry;
+    PartEntry->DiskEntry->ExtendedPartition = PartEntry;
 
-    AddLogicalDiskSpace(DiskEntry);
+    AddLogicalDiskSpace(PartEntry->DiskEntry);
 
-    UpdateDiskLayout(DiskEntry);
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2623,41 +2709,38 @@ CreateExtendedPartition(
 BOOLEAN
 CreateLogicalPartition(
     IN PPARTLIST List,
+    IN PPARTENTRY SelectedEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
 
     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;
-
     /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(DiskEntry, PartEntry, SectorCount, AutoCreate);
+    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
     if (PartEntry == NULL)
         return FALSE;
 
     PartEntry->LogicalPartition = TRUE;
 
-    UpdateDiskLayout(DiskEntry);
+    UpdateDiskLayout(PartEntry->DiskEntry);
 
     AssignDriveLetters(List);
 
@@ -2677,19 +2760,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",
@@ -2769,33 +2853,39 @@ 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);
+
+        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)
@@ -2821,49 +2911,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;
 
@@ -2871,54 +2961,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;
 }
 
-VOID
-CheckActiveSystemPartition(
-    IN PPARTLIST List)
+/*
+ * 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)
 {
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
     PLIST_ENTRY ListEntry;
-
-    PFILE_SYSTEM FileSystem;
+    PPARTENTRY PartEntry;
+    PPARTENTRY ActivePartition = NULL;
 
     /* Check for empty disk list */
-    if (IsListEmpty(&List->DiskListHead))
+    // ASSERT(DiskEntry);
+    if (!DiskEntry)
+        return NULL;
+
+    /* Check for empty partition list */
+    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+        return NULL;
+
+    if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
     {
-        List->SystemPartition = NULL;
-        List->OriginalSystemPartition = NULL;
-        return;
+        DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+        return NULL;
     }
 
-    /* Choose the currently selected disk */
-    DiskEntry = List->CurrentDisk;
+    /* 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);
 
-    /* Check for empty partition list */
-    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+        // 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;
+    }
+
+    // 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;
+    }
+
+    return TRUE;
+}
+
+VOID
+CheckActiveSystemPartition(
+    IN PPARTLIST List,
+    IN BOOLEAN ForceSelect,
+    IN PDISKENTRY AlternateDisk OPTIONAL,
+    IN PPARTENTRY AlternatePart OPTIONAL)
+{
+    PLIST_ENTRY ListEntry;
+    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
+    PPARTENTRY ActivePartition;
+    PPARTENTRY CandidatePartition = NULL;
+
+    /* Check for empty disk list */
+    if (IsListEmpty(&List->DiskListHead))
     {
+        /* No system partition! */
         List->SystemPartition = NULL;
         List->OriginalSystemPartition = NULL;
-        return;
+        goto NoSystemPartition;
     }
 
     if (List->SystemPartition != NULL)
@@ -2931,17 +3167,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
@@ -2950,11 +3353,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",
@@ -2969,8 +3373,6 @@ 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.
@@ -2980,12 +3382,12 @@ CheckActiveSystemPartition(
          ListEntry = ListEntry->Flink)
     {
         /* Retrieve the partition */
-        PartEntry = CONTAINING_RECORD(ListEntry,
-                                      PARTENTRY,
-                                      ListEntry);
+        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;
         }
@@ -2996,8 +3398,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,
@@ -3007,85 +3410,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 */
-    for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
-         ListEntry != &DiskEntry->PrimaryPartListHead;
-         ListEntry = ListEntry->Flink)
-    {
-        /* Retrieve the partition */
-        PartEntry = CONTAINING_RECORD(ListEntry,
-                                      PARTENTRY,
-                                      ListEntry);
-
-        /* 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,
@@ -3104,13 +3451,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,
@@ -3125,10 +3476,8 @@ SetSystemPartition:
     List->SystemPartition->DiskEntry->Dirty = TRUE;
 }
 
-static
 NTSTATUS
 WritePartitions(
-    IN PPARTLIST List,
     IN PDISKENTRY DiskEntry)
 {
     NTSTATUS Status;
@@ -3145,6 +3494,10 @@ WritePartitions(
 
     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);
@@ -3227,6 +3580,7 @@ WritePartitions(
 
         if (PartEntry->IsPartitioned)
         {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
             PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
         }
@@ -3241,6 +3595,7 @@ WritePartitions(
 
         if (PartEntry->IsPartitioned)
         {
+            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
             PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
         }
@@ -3256,7 +3611,8 @@ WritePartitions(
     // DiskEntry->NoMbr was TRUE (instead of NewDisk).
     //
 
-    // DiskEntry->Dirty = FALSE;
+    /* The layout has been successfully updated, the disk is not dirty anymore */
+    DiskEntry->Dirty = FALSE;
 
     return Status;
 }
@@ -3265,6 +3621,7 @@ BOOLEAN
 WritePartitionsToDisk(
     IN PPARTLIST List)
 {
+    NTSTATUS Status;
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
 
@@ -3277,10 +3634,20 @@ WritePartitionsToDisk(
     {
         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->Dirty != FALSE)
         {
-            WritePartitions(List, DiskEntry);
-            DiskEntry->Dirty = FALSE;
+            Status = WritePartitions(DiskEntry);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
+                        DiskEntry->DiskNumber, Status);
+            }
         }
     }
 
@@ -3369,13 +3736,21 @@ SetMountedDeviceValues(
                                       DISKENTRY,
                                       ListEntry);
 
+        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)
                 {
@@ -3395,8 +3770,10 @@ SetMountedDeviceValues(
              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)
                 {
@@ -3432,13 +3809,15 @@ SetPartitionType(
 
 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)
@@ -3453,13 +3832,15 @@ 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)
@@ -3478,13 +3859,15 @@ 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)
@@ -3511,6 +3894,12 @@ GetNextUnformattedPartition(
                                       DISKENTRY,
                                       ListEntry);
 
+        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)
@@ -3564,12 +3953,18 @@ GetNextUncheckedPartition(
                                       DISKENTRY,
                                       ListEntry);
 
+        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;
@@ -3583,7 +3978,7 @@ GetNextUncheckedPartition(
              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;