[USETUP] Similarly to what was done for GenLists, factor out the UI code from the...
[reactos.git] / base / setup / usetup / partlist.c
index 0e28213..31c657f 100644 (file)
@@ -18,7 +18,7 @@
  */
 /* COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS text-mode setup
- * FILE:            subsys/system/usetup/partlist.c
+ * FILE:            base/setup/usetup/partlist.c
  * PURPOSE:         Partition list functions
  * PROGRAMMER:      Eric Kohl
  *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
 #define NDEBUG
 #include <debug.h>
 
-#define DUMP_PARTITION_TABLE
+//#define DUMP_PARTITION_TABLE
+
+/* HELPERS FOR PARTITION TYPES **********************************************/
+
+typedef struct _PARTITION_TYPE
+{
+    UCHAR Type;
+    PCHAR Description;
+} PARTITION_TYPE, *PPARTITION_TYPE;
+
+/*
+ * This partition type list was ripped off the kernelDisk.c module from:
+ *
+ * Visopsys Operating System
+ * Copyright (C) 1998-2015 J. Andrew McLaughlin
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
+ * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
+ * for a complete list.
+ */
+
+/* This is a table for keeping known partition type codes and descriptions */
+static PARTITION_TYPE PartitionTypes[] =
+{
+    { 0x00, "(Empty)" },
+    { 0x01, "FAT12" },
+    { 0x02, "XENIX root" },
+    { 0x03, "XENIX /usr" },
+    { 0x04, "FAT16 (small)" },
+    { 0x05, "Extended" },
+    { 0x06, "FAT16" },
+    { 0x07, "NTFS/HPFS/exFAT" },
+    { 0x08, "OS/2 or AIX boot" },
+    { 0x09, "AIX data" },
+    { 0x0A, "OS/2 Boot Manager" },
+    { 0x0B, "FAT32" },
+    { 0x0C, "FAT32 (LBA)" },
+    { 0x0E, "FAT16 (LBA)" },
+    { 0x0F, "Extended (LBA)" },
+    { 0x11, "Hidden FAT12" },
+    { 0x12, "FAT diagnostic" },
+    { 0x14, "Hidden FAT16 (small)" },
+    { 0x16, "Hidden FAT16" },
+    { 0x17, "Hidden HPFS or NTFS" },
+    { 0x1B, "Hidden FAT32" },
+    { 0x1C, "Hidden FAT32 (LBA)" },
+    { 0x1E, "Hidden FAT16 (LBA)" },
+    { 0x35, "JFS" },
+    { 0x39, "Plan 9" },
+    { 0x3C, "PartitionMagic" },
+    { 0x3D, "Hidden Netware" },
+    { 0x41, "PowerPC PReP" },
+    { 0x42, "Win2K dynamic extended" },
+    { 0x43, "Old Linux" },
+    { 0x44, "GoBack" },
+    { 0x4D, "QNX4.x" },
+    { 0x4D, "QNX4.x 2nd" },
+    { 0x4D, "QNX4.x 3rd" },
+    { 0x50, "Ontrack R/O" },
+    { 0x51, "Ontrack R/W or Novell" },
+    { 0x52, "CP/M" },
+    { 0x63, "GNU HURD or UNIX SysV" },
+    { 0x64, "Netware 2" },
+    { 0x65, "Netware 3/4" },
+    { 0x66, "Netware SMS" },
+    { 0x67, "Novell" },
+    { 0x68, "Novell" },
+    { 0x69, "Netware 5+" },
+    { 0x7E, "Veritas VxVM public" },
+    { 0x7F, "Veritas VxVM private" },
+    { 0x80, "Minix" },
+    { 0x81, "Linux or Minix" },
+    { 0x82, "Linux swap or Solaris" },
+    { 0x83, "Linux" },
+    { 0x84, "Hibernation" },
+    { 0x85, "Linux extended" },
+    { 0x86, "HPFS or NTFS mirrored" },
+    { 0x87, "HPFS or NTFS mirrored" },
+    { 0x8E, "Linux LVM" },
+    { 0x93, "Hidden Linux" },
+    { 0x96, "CDFS/ISO-9660" },
+    { 0x9F, "BSD/OS" },
+    { 0xA0, "Laptop hibernation" },
+    { 0xA1, "Laptop hibernation" },
+    { 0xA5, "BSD, NetBSD, FreeBSD" },
+    { 0xA6, "OpenBSD" },
+    { 0xA7, "NeXTSTEP" },
+    { 0xA8, "OS-X UFS" },
+    { 0xA9, "NetBSD" },
+    { 0xAB, "OS-X boot" },
+    { 0xAF, "OS-X HFS" },
+    { 0xB6, "NT corrupt mirror" },
+    { 0xB7, "BSDI" },
+    { 0xB8, "BSDI swap" },
+    { 0xBE, "Solaris 8 boot" },
+    { 0xBF, "Solaris x86" },
+    { 0xC0, "NTFT" },
+    { 0xC1, "DR-DOS FAT12" },
+    { 0xC2, "Hidden Linux" },
+    { 0xC3, "Hidden Linux swap" },
+    { 0xC4, "DR-DOS FAT16 (small)" },
+    { 0xC5, "DR-DOS Extended" },
+    { 0xC6, "DR-DOS FAT16" },
+    { 0xC7, "HPFS mirrored" },
+    { 0xCB, "DR-DOS FAT32" },
+    { 0xCC, "DR-DOS FAT32 (LBA)" },
+    { 0xCE, "DR-DOS FAT16 (LBA)" },
+    { 0xD0, "MDOS" },
+    { 0xD1, "MDOS FAT12" },
+    { 0xD4, "MDOS FAT16 (small)" },
+    { 0xD5, "MDOS Extended" },
+    { 0xD6, "MDOS FAT16" },
+    { 0xD8, "CP/M-86" },
+    { 0xDF, "BootIt EMBRM(FAT16/32)" },
+    { 0xEB, "BeOS BFS" },
+    { 0xEE, "EFI GPT protective" },
+    { 0xEF, "EFI filesystem" },
+    { 0xF0, "Linux/PA-RISC boot" },
+    { 0xF2, "DOS 3.3+ second" },
+    { 0xFA, "Bochs" },
+    { 0xFB, "VmWare" },
+    { 0xFC, "VmWare swap" },
+    { 0xFD, "Linux RAID" },
+    { 0xFE, "NT hidden" },
+};
+
+VOID
+GetPartTypeStringFromPartitionType(
+    IN UCHAR partitionType,
+    OUT PCHAR strPartType,
+    IN ULONG cchPartType)
+{
+    /* Determine partition type */
+
+    if (IsContainerPartition(partitionType))
+    {
+        RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_EXTENDED_PARTITION));
+    }
+    else if (partitionType == PARTITION_ENTRY_UNUSED)
+    {
+        RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_FORMATUNUSED));
+    }
+    else
+    {
+        UINT i;
+
+        /* Do the table lookup */
+        for (i = 0; i < ARRAYSIZE(PartitionTypes); i++)
+        {
+            if (partitionType == PartitionTypes[i].Type)
+            {
+                RtlStringCchCopyA(strPartType, cchPartType, PartitionTypes[i].Description);
+                return;
+            }
+        }
+
+        /* We are here because the partition type is unknown */
+        RtlStringCchCopyA(strPartType, cchPartType, MUIGetString(STRING_FORMATUNKNOWN));
+    }
+}
 
 /* FUNCTIONS ****************************************************************/
 
@@ -44,25 +218,31 @@ DumpPartitionTable(
     PPARTITION_INFORMATION PartitionInfo;
     ULONG i;
 
+    DbgPrint("\n");
+    DbgPrint("Index  Start         Length        Hidden      Nr  Type  Boot  RW\n");
+    DbgPrint("-----  ------------  ------------  ----------  --  ----  ----  --\n");
+
     for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
     {
         PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
-        DbgPrint("%lu: %12I64u  %12I64u  %10lu  %2lu  %2x  %c  %c\n",
-                i,
-                PartitionInfo->StartingOffset.QuadPart,
-                PartitionInfo->PartitionLength.QuadPart,
-                PartitionInfo->HiddenSectors,
-                PartitionInfo->PartitionNumber,
-                PartitionInfo->PartitionType,
-                PartitionInfo->BootIndicator ? '*': ' ',
-                PartitionInfo->RewritePartition ? 'Y': 'N');
-    }
+        DbgPrint("  %3lu  %12I64u  %12I64u  %10lu  %2lu    %2x     %c   %c\n",
+                 i,
+                 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
+                 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
+                 PartitionInfo->HiddenSectors,
+                 PartitionInfo->PartitionNumber,
+                 PartitionInfo->PartitionType,
+                 PartitionInfo->BootIndicator ? '*': ' ',
+                 PartitionInfo->RewritePartition ? 'Y': 'N');
+    }
+
+    DbgPrint("\n");
 }
 #endif
 
 
 ULONGLONG
-Align(
+AlignDown(
     IN ULONGLONG Value,
     IN ULONG Alignment)
 {
@@ -73,6 +253,21 @@ Align(
     return Temp * Alignment;
 }
 
+ULONGLONG
+AlignUp(
+    IN ULONGLONG Value,
+    IN ULONG Alignment)
+{
+    ULONGLONG Temp, Result;
+
+    Temp = Value / Alignment;
+
+    Result = Temp * Alignment;
+    if (Value % Alignment)
+        Result += Alignment;
+
+    return Result;
+}
 
 ULONGLONG
 RoundingDivide(
@@ -86,7 +281,7 @@ RoundingDivide(
 static
 VOID
 GetDriverName(
-    PDISKENTRY DiskEntry)
+    IN PDISKENTRY DiskEntry)
 {
     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
     WCHAR KeyName[32];
@@ -96,7 +291,7 @@ GetDriverName(
                          NULL);
 
     swprintf(KeyName,
-             L"\\Scsi\\Scsi Port %lu",
+             L"\\Scsi\\Scsi Port %hu",
              DiskEntry->Port);
 
     RtlZeroMemory(&QueryTable,
@@ -121,7 +316,7 @@ GetDriverName(
 static
 VOID
 AssignDriveLetters(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
@@ -166,96 +361,41 @@ AssignDriveLetters(
     }
 
     /* Assign drive letters to logical drives */
-#if 0
     Entry1 = List->DiskListHead.Flink;
     while (Entry1 != &List->DiskListHead)
     {
         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
-        Entry2 = DiskEntry->PartListHead.Flink;
-        if (Entry2 != &DiskEntry->PartListHead)
+        Entry2 = DiskEntry->LogicalPartListHead.Flink;
+        while (Entry2 != &DiskEntry->LogicalPartListHead)
         {
-            Entry2 = Entry2->Flink;
-            while (Entry2 != &DiskEntry->PartListHead)
-            {
-                PartEntry = CONTAINING_RECORD(Entry2,
-                                              PARTENTRY,
-                                              ListEntry);
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-                PartEntry->DriveLetter = 0;
+            PartEntry->DriveLetter = 0;
 
-                if (PartEntry->Unpartitioned == FALSE &&
-                    !IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
+            if (PartEntry->IsPartitioned)
+            {
+                if (IsRecognizedPartition(PartEntry->PartitionType) ||
+                    (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+                     PartEntry->SectorCount.QuadPart != 0LL))
                 {
-                    if (IsRecognizedPartition(PartEntry->PartInfo[0].PartitionType) ||
-                        (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
-                         PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
+                    if (Letter <= 'Z')
                     {
-                        if (Letter <= 'Z')
-                        {
-                            PartEntry->DriveLetter = Letter;
-                            Letter++;
-                        }
+                        PartEntry->DriveLetter = Letter;
+                        Letter++;
                     }
                 }
-
-                Entry2 = Entry2->Flink;
-            }
-        }
-
-        Entry1 = Entry1->Flink;
-    }
-#endif
-}
-
-
-static
-VOID
-UpdatePartitionNumbers(
-    PDISKENTRY DiskEntry)
-{
-    PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry;
-//    ULONG PartitionNumber = 1;
-    ULONG PartitionIndex = 0;
-
-    Entry = DiskEntry->PrimaryPartListHead.Flink;
-    while (Entry != &DiskEntry->PrimaryPartListHead)
-    {
-        PartEntry = CONTAINING_RECORD(Entry,
-                                      PARTENTRY,
-                                      ListEntry);
-
-        if (PartEntry->IsPartitioned == FALSE)
-        {
-//            PartEntry->PartitionNumber = 0;
-            PartEntry->PartitionIndex = (ULONG)-1;
-        }
-        else
-        {
-            if (IsContainerPartition(PartEntry->PartitionType))
-            {
-//                PartEntry->PartitionNumber = 0;
-            }
-            else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
-                     PartEntry->SectorCount.QuadPart == 0ULL)
-            {
-//                PartEntry->PartitionNumber = 0;
-            }
-            else
-            {
-//                PartEntry->PartitionNumber = PartitionNumber++;
             }
 
-            PartEntry->PartitionIndex = PartitionIndex++;
+            Entry2 = Entry2->Flink;
         }
 
-        Entry = Entry->Flink;
+        Entry1 = Entry1->Flink;
     }
 }
 
 
-NTSTATUS
+static NTSTATUS
 NTAPI
 DiskIdentifierQueryRoutine(
     PWSTR ValueName,
@@ -285,7 +425,7 @@ DiskIdentifierQueryRoutine(
 }
 
 
-NTSTATUS
+static NTSTATUS
 NTAPI
 DiskConfigurationDataQueryRoutine(
     PWSTR ValueName,
@@ -329,7 +469,7 @@ DiskConfigurationDataQueryRoutine(
 }
 
 
-NTSTATUS
+static NTSTATUS
 NTAPI
 SystemConfigurationDataQueryRoutine(
     PWSTR ValueName,
@@ -344,7 +484,7 @@ SystemConfigurationDataQueryRoutine(
     ULONG i;
 
     if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
-        ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR))
+        ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
         return STATUS_UNSUCCESSFUL;
 
     FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
@@ -362,7 +502,8 @@ SystemConfigurationDataQueryRoutine(
             FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
             continue;
 
-        *Int13Drives = (CM_INT13_DRIVE_PARAMETER*) RtlAllocateHeap(ProcessHeap, 0, FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
+        *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(ProcessHeap, 0,
+                       FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
         if (*Int13Drives == NULL)
             return STATUS_NO_MEMORY;
 
@@ -380,7 +521,7 @@ SystemConfigurationDataQueryRoutine(
 
 static VOID
 EnumerateBiosDiskEntries(
-    PPARTLIST PartList)
+    IN PPARTLIST PartList)
 {
     RTL_QUERY_REGISTRY_TABLE QueryTable[3];
     WCHAR Name[120];
@@ -458,7 +599,7 @@ EnumerateBiosDiskEntries(
                     DiskCount = 0;
                     while (1)
                     {
-                        BiosDiskEntry = (BIOSDISKENTRY*) RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
+                        BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
                         if (BiosDiskEntry == NULL)
                         {
                             break;
@@ -521,17 +662,17 @@ EnumerateBiosDiskEntries(
 static
 VOID
 AddPartitionToDisk(
-    ULONG DiskNumber,
-    PDISKENTRY DiskEntry,
-    ULONG PartitionIndex,
-    BOOLEAN LogicalPartition)
+    IN ULONG DiskNumber,
+    IN PDISKENTRY DiskEntry,
+    IN ULONG PartitionIndex,
+    IN BOOLEAN LogicalPartition)
 {
     PPARTITION_INFORMATION PartitionInfo;
     PPARTENTRY PartEntry;
 
     PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
-    if (PartitionInfo->PartitionType == 0 ||
-        (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType)))
+    if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED ||
+        ((LogicalPartition != FALSE) && IsContainerPartition(PartitionInfo->PartitionType)))
         return;
 
     PartEntry = RtlAllocateHeap(ProcessHeap,
@@ -542,6 +683,8 @@ AddPartitionToDisk(
         return;
     }
 
+    PartEntry->DiskEntry = DiskEntry;
+
     PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
     PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
 
@@ -557,10 +700,28 @@ AddPartitionToDisk(
     if (IsContainerPartition(PartEntry->PartitionType))
     {
         PartEntry->FormatState = Unformatted;
+        PartEntry->FileSystem  = NULL;
 
         if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
             DiskEntry->ExtendedPartition = PartEntry;
     }
+#if 0
+    else if (IsRecognizedPartition(PartEntry->PartitionType))
+    {
+        // FIXME FIXME! We should completely rework how we get this 'FileSystemList' available...
+        PartEntry->FileSystem = GetFileSystem(FileSystemList, PartEntry);
+        if (!PartEntry->FileSystem)
+            PartEntry->FormatState = Preformatted;
+        else
+            PartEntry->FormatState = Unformatted;
+        // PartEntry->FormatState = UnknownFormat;
+    }
+    else
+    {
+        /* Unknown partition, so unknown partition format (may or may not be actually formatted) */
+        PartEntry->FormatState = UnknownFormat;
+    }
+#endif
     else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
              (PartEntry->PartitionType == PARTITION_FAT_16) ||
              (PartEntry->PartitionType == PARTITION_HUGE) ||
@@ -629,7 +790,7 @@ AddPartitionToDisk(
 static
 VOID
 ScanForUnpartitionedDiskSpace(
-    PDISKENTRY DiskEntry)
+    IN PDISKENTRY DiskEntry)
 {
     ULONGLONG LastStartSector;
     ULONGLONG LastSectorCount;
@@ -638,13 +799,13 @@ ScanForUnpartitionedDiskSpace(
     PPARTENTRY NewPartEntry;
     PLIST_ENTRY Entry;
 
-    DPRINT1("ScanForUnpartitionedDiskSpace()\n");
+    DPRINT("ScanForUnpartitionedDiskSpace()\n");
 
     if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
     {
         DPRINT1("No primary partition!\n");
 
-        /* Create a partition table that represents the empty disk */
+        /* Create a partition entry that represents the empty disk */
         NewPartEntry = RtlAllocateHeap(ProcessHeap,
                                        HEAP_ZERO_MEMORY,
                                        sizeof(PARTENTRY));
@@ -654,14 +815,16 @@ ScanForUnpartitionedDiskSpace(
         NewPartEntry->DiskEntry = DiskEntry;
 
         NewPartEntry->IsPartitioned = FALSE;
-        NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorsPerTrack;
-        NewPartEntry->SectorCount.QuadPart = Align(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
-                                             DiskEntry->SectorsPerTrack;
-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->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);
@@ -670,7 +833,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
     }
 
     /* Start partition at head 1, cylinder 0 */
-    LastStartSector = DiskEntry->SectorsPerTrack;
+    LastStartSector = DiskEntry->SectorAlignment;
     LastSectorCount = 0ULL;
     LastUnusedSectorCount = 0ULL;
 
@@ -700,13 +863,15 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
                 NewPartEntry->IsPartitioned = FALSE;
                 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+                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);
+
+                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;
 
                 /* Insert the table into the list */
                 InsertTailList(&PartEntry->ListEntry,
@@ -723,7 +888,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
     /* Check for trailing unpartitioned disk space */
     if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
     {
-        LastUnusedSectorCount = Align(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
+        LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
 
         if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
         {
@@ -739,13 +904,15 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
             NewPartEntry->IsPartitioned = FALSE;
             NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-            NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+            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);
+
+            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->PrimaryPartListHead,
@@ -759,7 +926,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         {
             DPRINT1("No logical partition!\n");
 
-            /* Create a partition table entry that represents the empty extended partition */
+            /* Create a partition entry that represents the empty extended partition */
             NewPartEntry = RtlAllocateHeap(ProcessHeap,
                                            HEAP_ZERO_MEMORY,
                                            sizeof(PARTENTRY));
@@ -770,14 +937,15 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
             NewPartEntry->LogicalPartition = TRUE;
 
             NewPartEntry->IsPartitioned = FALSE;
-            NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
-            NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack;
+            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);
@@ -786,7 +954,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         }
 
         /* Start partition at head 1, cylinder 0 */
-        LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+        LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
         LastSectorCount = 0ULL;
         LastUnusedSectorCount = 0ULL;
 
@@ -799,9 +967,9 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
                 PartEntry->SectorCount.QuadPart != 0ULL)
             {
                 LastUnusedSectorCount =
-                    PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack - (LastStartSector + LastSectorCount);
+                    PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
 
-                if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack) > (LastStartSector + LastSectorCount) &&
+                if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
                     LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
                 {
                     DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
@@ -817,13 +985,15 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
                     NewPartEntry->IsPartitioned = FALSE;
                     NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                    NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+                    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);
+
+                    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,
@@ -840,7 +1010,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         /* Check for trailing unpartitioned disk space */
         if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
         {
-            LastUnusedSectorCount = Align(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)
             {
@@ -857,13 +1027,15 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
                 NewPartEntry->IsPartitioned = FALSE;
                 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
-                NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
+                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);
+
+                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,
@@ -872,7 +1044,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         }
     }
 
-    DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
+    DPRINT("ScanForUnpartitionedDiskSpace() done\n");
 }
 
 
@@ -931,12 +1103,12 @@ SetDiskSignature(
 static
 VOID
 UpdateDiskSignatures(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
 
-    /* Print partition lines*/
+    /* Print partition lines */
     Entry = List->DiskListHead.Flink;
     while (Entry != &List->DiskListHead)
     {
@@ -957,9 +1129,9 @@ UpdateDiskSignatures(
 static
 VOID
 AddDiskToList(
-    HANDLE FileHandle,
-    ULONG DiskNumber,
-    PPARTLIST List)
+    IN HANDLE FileHandle,
+    IN ULONG DiskNumber,
+    IN PPARTLIST List)
 {
     DISK_GEOMETRY DiskGeometry;
     SCSI_ADDRESS ScsiAddress;
@@ -976,6 +1148,7 @@ AddDiskToList(
     PLIST_ENTRY ListEntry;
     PBIOSDISKENTRY BiosDiskEntry;
     ULONG LayoutBufferSize;
+    PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
 
     Status = NtDeviceIoControlFile(FileHandle,
                                    NULL,
@@ -988,9 +1161,7 @@ AddDiskToList(
                                    &DiskGeometry,
                                    sizeof(DISK_GEOMETRY));
     if (!NT_SUCCESS(Status))
-    {
         return;
-    }
 
     if (DiskGeometry.MediaType != FixedMedia &&
         DiskGeometry.MediaType != RemovableMedia)
@@ -1009,17 +1180,18 @@ AddDiskToList(
                                    &ScsiAddress,
                                    sizeof(SCSI_ADDRESS));
     if (!NT_SUCCESS(Status))
-    {
         return;
-    }
+
+    /*
+     * Check whether the disk is initialized, by looking at its MBR.
+     * NOTE that this must be generalized to GPT disks as well!
+     */
 
     Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
                                              0,
                                              DiskGeometry.BytesPerSector);
     if (Mbr == NULL)
-    {
         return;
-    }
 
     FileOffset.QuadPart = 0;
     Status = NtReadFile(FileHandle,
@@ -1033,9 +1205,7 @@ AddDiskToList(
                         NULL);
     if (!NT_SUCCESS(Status))
     {
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    Mbr);
+        RtlFreeHeap(ProcessHeap, 0, Mbr);
         DPRINT1("NtReadFile failed, status=%x\n", Status);
         return;
     }
@@ -1066,23 +1236,23 @@ AddDiskToList(
     DiskEntry->BiosFound = FALSE;
 
     /* Check if this disk has a valid MBR */
+    // FIXME: Check for the MBR signature as well, etc...
     if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
         DiskEntry->NoMbr = TRUE;
     else
         DiskEntry->NoMbr = FALSE;
 
-    /* Free Mbr sector buffer */
-    RtlFreeHeap(ProcessHeap,
-                0,
-                Mbr);
+    /* Free the MBR sector buffer */
+    RtlFreeHeap(ProcessHeap, 0, Mbr);
+
 
     ListEntry = List->BiosDiskListHead.Flink;
-    while(ListEntry != &List->BiosDiskListHead)
+    while (ListEntry != &List->BiosDiskListHead)
     {
         BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
         /* FIXME:
          *   Compare the size from bios and the reported size from driver.
-         *   If we have more than one disk with a zero or with the same signatur
+         *   If we have more than one disk with a zero or with the same signature
          *   we must create new signatures and reboot. After the reboot,
          *   it is possible to identify the disks.
          */
@@ -1122,18 +1292,20 @@ AddDiskToList(
     DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
 
     DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
-    DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
-    DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
-    DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
+    DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
+    DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
+    DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
 
     DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
                                       (ULONGLONG)DiskGeometry.TracksPerCylinder *
                                       (ULONGLONG)DiskGeometry.SectorsPerTrack;
 
     DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
+    DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
+                                   DiskGeometry.SectorsPerTrack;
 
-    DPRINT1("SectorCount %I64u\n", DiskEntry->SectorCount);
-    DPRINT1("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
+    DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
+    DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
 
     DiskEntry->DiskNumber = DiskNumber;
     DiskEntry->Port = ScsiAddress.PortNumber;
@@ -1144,84 +1316,101 @@ AddDiskToList(
 
     InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
 
-    /*
-     * Allocate a buffer for 26 logical drives (2 entries each == 52) 
-     * plus the main partiton table (4 entries). Total 56 entries.
-     */
+    /* Allocate a layout buffer with 4 partition entries first */
     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
-                       ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+                       ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
     DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
                                               HEAP_ZERO_MEMORY,
                                               LayoutBufferSize);
     if (DiskEntry->LayoutBuffer == NULL)
     {
+        DPRINT1("Failed to allocate the disk layout buffer!\n");
         return;
     }
 
-    Status = NtDeviceIoControlFile(FileHandle,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &Iosb,
-                                   IOCTL_DISK_GET_DRIVE_LAYOUT,
-                                   NULL,
-                                   0,
-                                   DiskEntry->LayoutBuffer,
-                                   LayoutBufferSize);
-    if (NT_SUCCESS(Status))
+    for (;;)
     {
+        DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
+        Status = NtDeviceIoControlFile(FileHandle,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &Iosb,
+                                       IOCTL_DISK_GET_DRIVE_LAYOUT,
+                                       NULL,
+                                       0,
+                                       DiskEntry->LayoutBuffer,
+                                       LayoutBufferSize);
+        if (NT_SUCCESS(Status))
+            break;
+
+        if (Status != STATUS_BUFFER_TOO_SMALL)
+        {
+            DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
+            return;
+        }
+
+        LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
+        NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
+                                            HEAP_ZERO_MEMORY,
+                                            DiskEntry->LayoutBuffer,
+                                            LayoutBufferSize);
+        if (NewLayoutBuffer == NULL)
+        {
+            DPRINT1("Failed to reallocate the disk layout buffer!\n");
+            return;
+        }
+
+        DiskEntry->LayoutBuffer = NewLayoutBuffer;
+    }
+
+    DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
+
 #ifdef DUMP_PARTITION_TABLE
-        DumpPartitionTable(DiskEntry);
+    DumpPartitionTable(DiskEntry);
 #endif
 
-        if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
-            DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
-            DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
+    if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
+        DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
+        DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != PARTITION_ENTRY_UNUSED)
+    {
+        if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
         {
-            if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
-            {
-                DPRINT1("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
-            }
-            else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % 1048756 == 0)
-            {
-                DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
-            }
-            else
-            {
-                DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
-            }
+            DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
+        }
+        else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
+        {
+            DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
         }
         else
         {
-            DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+            DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
         }
+    }
+    else
+    {
+        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;
+    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
+        for (i = 0; i < 4; i++)
+            DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+    }
+    else
+    {
+        for (i = 0; i < 4; i++)
         {
-            for (i = 0; i < 4; i++)
-            {
-                AddPartitionToDisk(DiskNumber,
-                                   DiskEntry,
-                                   i,
-                                   FALSE);
-            }
+            AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
+        }
 
-            for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
-            {
-                AddPartitionToDisk(DiskNumber,
-                                   DiskEntry,
-                                   i,
-                                   TRUE);
-            }
+        for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
+        {
+            AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
         }
     }
 
@@ -1230,11 +1419,7 @@ AddDiskToList(
 
 
 PPARTLIST
-CreatePartitionList(
-    SHORT Left,
-    SHORT Top,
-    SHORT Right,
-    SHORT Bottom)
+CreatePartitionList(VOID)
 {
     PPARTLIST List;
     OBJECT_ATTRIBUTES ObjectAttributes;
@@ -1253,20 +1438,15 @@ CreatePartitionList(
     if (List == NULL)
         return NULL;
 
-    List->Left = Left;
-    List->Top = Top;
-    List->Right = Right;
-    List->Bottom = Bottom;
-
-    List->Line = 0;
-    List->Offset = 0;
-
-    List->TopDisk = (ULONG)-1;
-    List->TopPartition = (ULONG)-1;
-
     List->CurrentDisk = NULL;
     List->CurrentPartition = NULL;
 
+    List->SystemPartition = NULL;
+    List->OriginalSystemPartition = NULL;
+
+    List->TempPartition = NULL;
+    List->FormatState = Start;
+
     InitializeListHead(&List->DiskListHead);
     InitializeListHead(&List->BiosDiskListHead);
 
@@ -1274,10 +1454,11 @@ CreatePartitionList(
 
     Status = NtQuerySystemInformation(SystemDeviceInformation,
                                       &Sdi,
-                                      sizeof(SYSTEM_DEVICE_INFORMATION),
+                                      sizeof(Sdi),
                                       &ReturnSize);
     if (!NT_SUCCESS(Status))
     {
+        DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status);
         RtlFreeHeap(ProcessHeap, 0, List);
         return NULL;
     }
@@ -1304,9 +1485,7 @@ CreatePartitionList(
                             FILE_SYNCHRONOUS_IO_NONALERT);
         if (NT_SUCCESS(Status))
         {
-            AddDiskToList(FileHandle,
-                          DiskNumber,
-                          List);
+            AddDiskToList(FileHandle, DiskNumber, List);
 
             NtClose(FileHandle);
         }
@@ -1316,9 +1495,6 @@ CreatePartitionList(
 
     AssignDriveLetters(List);
 
-    List->TopDisk = 0;
-    List->TopPartition = 0;
-
     /* Search for first usable disk and partition */
     if (IsListEmpty(&List->DiskListHead))
     {
@@ -1333,7 +1509,7 @@ CreatePartitionList(
 
         if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
         {
-            List->CurrentPartition = 0;
+            List->CurrentPartition = NULL;
         }
         else
         {
@@ -1349,7 +1525,7 @@ CreatePartitionList(
 
 VOID
 DestroyPartitionList(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PDISKENTRY DiskEntry;
     PBIOSDISKENTRY BiosDiskEntry;
@@ -1392,8 +1568,8 @@ DestroyPartitionList(
         RtlFreeHeap(ProcessHeap, 0, DiskEntry);
     }
 
-    /* release the bios disk info */
-    while(!IsListEmpty(&List->BiosDiskListHead))
+    /* Release the bios disk info */
+    while (!IsListEmpty(&List->BiosDiskListHead))
     {
         Entry = RemoveHeadList(&List->BiosDiskListHead);
         BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
@@ -1406,23 +1582,47 @@ DestroyPartitionList(
 }
 
 
+VOID
+InitPartitionListUi(
+    IN OUT PPARTLIST_UI ListUi,
+    IN PPARTLIST List,
+    IN SHORT Left,
+    IN SHORT Top,
+    IN SHORT Right,
+    IN SHORT Bottom)
+{
+    ListUi->List = List;
+    // ListUi->FirstShown = NULL;
+    // ListUi->LastShown = NULL;
+
+    ListUi->Left = Left;
+    ListUi->Top = Top;
+    ListUi->Right = Right;
+    ListUi->Bottom = Bottom;
+
+    ListUi->Line = 0;
+    ListUi->Offset = 0;
+
+    // ListUi->Redraw = TRUE;
+}
+
 static
 VOID
 PrintEmptyLine(
-    PPARTLIST List)
+    IN PPARTLIST_UI ListUi)
 {
     COORD coPos;
-    DWORD Written;
+    ULONG Written;
     USHORT Width;
     USHORT Height;
 
-    Width = List->Right - List->Left - 1;
-    Height = List->Bottom - List->Top - 2;
+    Width = ListUi->Right - ListUi->Left - 1;
+    Height = ListUi->Bottom - ListUi->Top - 2;
 
-    coPos.X = List->Left + 1;
-    coPos.Y = List->Top + 1 + List->Line;
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top + 1 + ListUi->Line;
 
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         FillConsoleOutputAttribute(StdOutput,
                                    FOREGROUND_WHITE | BACKGROUND_BLUE,
@@ -1437,32 +1637,34 @@ PrintEmptyLine(
                                     &Written);
     }
 
-    List->Line++;
+    ListUi->Line++;
 }
 
 
 static
 VOID
 PrintPartitionData(
-    PPARTLIST List,
-    PDISKENTRY DiskEntry,
-    PPARTENTRY PartEntry)
+    IN PPARTLIST_UI ListUi,
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry)
 {
+    PPARTLIST List = ListUi->List;
     CHAR LineBuffer[128];
     COORD coPos;
-    DWORD Written;
+    ULONG Written;
     USHORT Width;
     USHORT Height;
     LARGE_INTEGER PartSize;
     PCHAR Unit;
     UCHAR Attribute;
-    PCHAR PartType;
+    CHAR PartTypeString[32];
+    PCHAR PartType = PartTypeString;
 
-    Width = List->Right - List->Left - 1;
-    Height = List->Bottom - List->Top - 2;
+    Width = ListUi->Right - ListUi->Left - 1;
+    Height = ListUi->Bottom - ListUi->Top - 2;
 
-    coPos.X = List->Left + 1;
-    coPos.Y = List->Top + 1 + List->Line;
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top + 1 + ListUi->Line;
 
     if (PartEntry->IsPartitioned == FALSE)
     {
@@ -1496,38 +1698,17 @@ PrintPartitionData(
     else
     {
         /* Determine partition type */
-        PartType = NULL;
-        if (PartEntry->New == TRUE)
+        PartTypeString[0] = '\0';
+        if (PartEntry->New != FALSE)
         {
             PartType = MUIGetString(STRING_UNFORMATTED);
         }
-        else if (PartEntry->IsPartitioned == TRUE)
+        else if (PartEntry->IsPartitioned != FALSE)
         {
-            if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
-                (PartEntry->PartitionType == PARTITION_FAT_16) ||
-                (PartEntry->PartitionType == PARTITION_HUGE) ||
-                (PartEntry->PartitionType == PARTITION_XINT13))
-            {
-                PartType = "FAT";
-            }
-            else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
-                     (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
-            {
-                PartType = "FAT32";
-            }
-            else if (PartEntry->PartitionType == PARTITION_EXT2)
-            {
-                PartType = "EXT2";
-            }
-            else if (PartEntry->PartitionType == PARTITION_IFS)
-            {
-                PartType = "NTFS"; /* FIXME: Not quite correct! */
-            }
-            else if ((PartEntry->PartitionType == PARTITION_EXTENDED) ||
-                     (PartEntry->PartitionType == PARTITION_XINT13_EXTENDED))
-            {
-                PartType = MUIGetString(STRING_EXTENDED_PARTITION);
-            }
+           GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
+                                              PartTypeString,
+                                              ARRAYSIZE(PartTypeString));
+           PartType = PartTypeString;
         }
 
         PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
@@ -1550,12 +1731,13 @@ PrintPartitionData(
             Unit = MUIGetString(STRING_KB);
         }
 
-        if (PartType == NULL)
+        if (strcmp(PartType, MUIGetString(STRING_FORMATUNKNOWN)) == 0)
         {
             sprintf(LineBuffer,
                     MUIGetString(STRING_HDDINFOUNK5),
                     (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
                     (PartEntry->DriveLetter == 0) ? '-' : ':',
+                    PartEntry->BootIndicator ? '*' : ' ',
                     PartEntry->LogicalPartition ? "  " : "",
                     PartEntry->PartitionType,
                     PartEntry->LogicalPartition ? "" : "  ",
@@ -1565,9 +1747,10 @@ PrintPartitionData(
         else
         {
             sprintf(LineBuffer,
-                    "%c%c  %s%-24s%s      %6lu %s",
+                    "%c%c %c %s%-24s%s     %6lu %s",
                     (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
                     (PartEntry->DriveLetter == 0) ? '-' : ':',
+                    PartEntry->BootIndicator ? '*' : ' ',
                     PartEntry->LogicalPartition ? "  " : "",
                     PartType,
                     PartEntry->LogicalPartition ? "" : "  ",
@@ -1581,7 +1764,7 @@ PrintPartitionData(
                  FOREGROUND_BLUE | BACKGROUND_WHITE :
                  FOREGROUND_WHITE | BACKGROUND_BLUE;
 
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         FillConsoleOutputCharacterA(StdOutput,
                                     ' ',
@@ -1591,7 +1774,7 @@ PrintPartitionData(
     }
     coPos.X += 4;
     Width -= 8;
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         FillConsoleOutputAttribute(StdOutput,
                                    Attribute,
@@ -1601,7 +1784,7 @@ PrintPartitionData(
     }
     coPos.X++;
     Width -= 2;
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         WriteConsoleOutputCharacterA(StdOutput,
                                      LineBuffer,
@@ -1610,31 +1793,32 @@ PrintPartitionData(
                                      &Written);
     }
 
-    List->Line++;
+    ListUi->Line++;
 }
 
 
 static
 VOID
 PrintDiskData(
-    PPARTLIST List,
-    PDISKENTRY DiskEntry)
+    IN PPARTLIST_UI ListUi,
+    IN PDISKENTRY DiskEntry)
 {
+    // PPARTLIST List = ListUi->List;
     PPARTENTRY PrimaryPartEntry, LogicalPartEntry;
     PLIST_ENTRY PrimaryEntry, LogicalEntry;
     CHAR LineBuffer[128];
     COORD coPos;
-    DWORD Written;
+    ULONG Written;
     USHORT Width;
     USHORT Height;
     ULARGE_INTEGER DiskSize;
     PCHAR Unit;
 
-    Width = List->Right - List->Left - 1;
-    Height = List->Bottom - List->Top - 2;
+    Width = ListUi->Right - ListUi->Left - 1;
+    Height = ListUi->Bottom - ListUi->Top - 2;
 
-    coPos.X = List->Left + 1;
-    coPos.Y = List->Top + 1 + List->Line;
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top + 1 + ListUi->Line;
 
     DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
     if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
@@ -1674,7 +1858,7 @@ PrintDiskData(
                 DiskEntry->Id);
     }
 
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         FillConsoleOutputAttribute(StdOutput,
                                    FOREGROUND_WHITE | BACKGROUND_BLUE,
@@ -1690,7 +1874,7 @@ PrintDiskData(
     }
 
     coPos.X++;
-    if (List->Line >= 0 && List->Line <= Height)
+    if (ListUi->Line >= 0 && ListUi->Line <= Height)
     {
         WriteConsoleOutputCharacterA(StdOutput,
                                      LineBuffer,
@@ -1699,18 +1883,18 @@ PrintDiskData(
                                      &Written);
     }
 
-    List->Line++;
+    ListUi->Line++;
 
     /* Print separator line */
-    PrintEmptyLine(List);
+    PrintEmptyLine(ListUi);
 
-    /* Print partition lines*/
+    /* Print partition lines */
     PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink;
     while (PrimaryEntry != &DiskEntry->PrimaryPartListHead)
     {
         PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
 
-        PrintPartitionData(List,
+        PrintPartitionData(ListUi,
                            DiskEntry,
                            PrimaryPartEntry);
 
@@ -1721,7 +1905,7 @@ PrintDiskData(
             {
                 LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
 
-                PrintPartitionData(List,
+                PrintPartitionData(ListUi,
                                    DiskEntry,
                                    LogicalPartEntry);
 
@@ -1733,25 +1917,26 @@ PrintDiskData(
     }
 
     /* Print separator line */
-    PrintEmptyLine(List);
+    PrintEmptyLine(ListUi);
 }
 
 
 VOID
 DrawPartitionList(
-    PPARTLIST List)
+    IN PPARTLIST_UI ListUi)
 {
+    PPARTLIST List = ListUi->List;
     PLIST_ENTRY Entry, Entry2;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry = NULL;
     COORD coPos;
-    DWORD Written;
+    ULONG Written;
     SHORT i;
     SHORT CurrentDiskLine;
     SHORT CurrentPartLine;
     SHORT LastLine;
-    BOOL CurrentPartLineFound = FALSE;
-    BOOL CurrentDiskLineFound = FALSE;
+    BOOLEAN CurrentPartLineFound = FALSE;
+    BOOLEAN CurrentDiskLineFound = FALSE;
 
     /* Calculate the line of the current disk and partition */
     CurrentDiskLine = 0;
@@ -1787,6 +1972,27 @@ DrawPartitionList(
             LastLine++;
         }
 
+        if (CurrentPartLineFound == FALSE)
+        {
+            Entry2 = DiskEntry->LogicalPartListHead.Flink;
+            while (Entry2 != &DiskEntry->LogicalPartListHead)
+            {
+                PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+                if (PartEntry == List->CurrentPartition)
+                {
+                    CurrentPartLineFound = TRUE;
+                }
+
+                Entry2 = Entry2->Flink;
+                if (CurrentPartLineFound == FALSE)
+                {
+                    CurrentPartLine++;
+                }
+
+                LastLine++;
+            }
+        }
+
         if (DiskEntry == List->CurrentDisk)
         {
             CurrentDiskLineFound = TRUE;
@@ -1810,37 +2016,37 @@ DrawPartitionList(
     }
 
     /* If it possible, make the disk name visible */
-    if (CurrentPartLine < List->Offset)
+    if (CurrentPartLine < ListUi->Offset)
     {
-        List->Offset = CurrentPartLine;
+        ListUi->Offset = CurrentPartLine;
     }
-    else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
+    else if (CurrentPartLine - ListUi->Offset > ListUi->Bottom - ListUi->Top - 2)
     {
-        List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
+        ListUi->Offset = CurrentPartLine - (ListUi->Bottom - ListUi->Top - 2);
     }
 
-    if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
+    if (CurrentDiskLine < ListUi->Offset && CurrentPartLine - CurrentDiskLine < ListUi->Bottom - ListUi->Top - 2)
     {
-        List->Offset = CurrentDiskLine;
+        ListUi->Offset = CurrentDiskLine;
     }
 
-    /* draw upper left corner */
-    coPos.X = List->Left;
-    coPos.Y = List->Top;
+    /* Draw upper left corner */
+    coPos.X = ListUi->Left;
+    coPos.Y = ListUi->Top;
     FillConsoleOutputCharacterA(StdOutput,
                                 0xDA, // '+',
                                 1,
                                 coPos,
                                 &Written);
 
-    /* draw upper edge */
-    coPos.X = List->Left + 1;
-    coPos.Y = List->Top;
-    if (List->Offset == 0)
+    /* Draw upper edge */
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top;
+    if (ListUi->Offset == 0)
     {
         FillConsoleOutputCharacterA(StdOutput,
                                     0xC4, // '-',
-                                    List->Right - List->Left - 1,
+                                    ListUi->Right - ListUi->Left - 1,
                                     coPos,
                                     &Written);
     }
@@ -1848,16 +2054,16 @@ DrawPartitionList(
     {
         FillConsoleOutputCharacterA(StdOutput,
                                     0xC4, // '-',
-                                    List->Right - List->Left - 5,
+                                    ListUi->Right - ListUi->Left - 5,
                                     coPos,
                                     &Written);
-        coPos.X = List->Right - 5;
+        coPos.X = ListUi->Right - 5;
         WriteConsoleOutputCharacterA(StdOutput,
                                      "(\x18)", // "(up)"
                                      3,
                                      coPos,
                                      &Written);
-        coPos.X = List->Right - 2;
+        coPos.X = ListUi->Right - 2;
         FillConsoleOutputCharacterA(StdOutput,
                                     0xC4, // '-',
                                     2,
@@ -1865,19 +2071,19 @@ DrawPartitionList(
                                     &Written);
     }
 
-    /* draw upper right corner */
-    coPos.X = List->Right;
-    coPos.Y = List->Top;
+    /* Draw upper right corner */
+    coPos.X = ListUi->Right;
+    coPos.Y = ListUi->Top;
     FillConsoleOutputCharacterA(StdOutput,
                                 0xBF, // '+',
                                 1,
                                 coPos,
                                 &Written);
 
-    /* draw left and right edge */
-    for (i = List->Top + 1; i < List->Bottom; i++)
+    /* Draw left and right edge */
+    for (i = ListUi->Top + 1; i < ListUi->Bottom; i++)
     {
-        coPos.X = List->Left;
+        coPos.X = ListUi->Left;
         coPos.Y = i;
         FillConsoleOutputCharacterA(StdOutput,
                                     0xB3, // '|',
@@ -1885,7 +2091,7 @@ DrawPartitionList(
                                     coPos,
                                     &Written);
 
-        coPos.X = List->Right;
+        coPos.X = ListUi->Right;
         FillConsoleOutputCharacterA(StdOutput,
                                     0xB3, //'|',
                                     1,
@@ -1893,23 +2099,23 @@ DrawPartitionList(
                                     &Written);
     }
 
-    /* draw lower left corner */
-    coPos.X = List->Left;
-    coPos.Y = List->Bottom;
+    /* Draw lower left corner */
+    coPos.X = ListUi->Left;
+    coPos.Y = ListUi->Bottom;
     FillConsoleOutputCharacterA(StdOutput,
                                 0xC0, // '+',
                                 1,
                                 coPos,
                                 &Written);
 
-    /* draw lower edge */
-    coPos.X = List->Left + 1;
-    coPos.Y = List->Bottom;
-    if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
+    /* Draw lower edge */
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Bottom;
+    if (LastLine - ListUi->Offset <= ListUi->Bottom - ListUi->Top - 2)
     {
         FillConsoleOutputCharacterA(StdOutput,
                                     0xC4, // '-',
-                                    List->Right - List->Left - 1,
+                                    ListUi->Right - ListUi->Left - 1,
                                     coPos,
                                     &Written);
     }
@@ -1917,16 +2123,16 @@ DrawPartitionList(
     {
         FillConsoleOutputCharacterA(StdOutput,
                                     0xC4, // '-',
-                                    List->Right - List->Left - 5,
+                                    ListUi->Right - ListUi->Left - 5,
                                     coPos,
                                     &Written);
-        coPos.X = List->Right - 5;
+        coPos.X = ListUi->Right - 5;
         WriteConsoleOutputCharacterA(StdOutput,
                                      "(\x19)", // "(down)"
                                      3,
                                      coPos,
                                      &Written);
-       coPos.X = List->Right - 2;
+       coPos.X = ListUi->Right - 2;
        FillConsoleOutputCharacterA(StdOutput,
                                    0xC4, // '-',
                                    2,
@@ -1934,9 +2140,9 @@ DrawPartitionList(
                                    &Written);
     }
 
-    /* draw lower right corner */
-    coPos.X = List->Right;
-    coPos.Y = List->Bottom;
+    /* Draw lower right corner */
+    coPos.X = ListUi->Right;
+    coPos.Y = ListUi->Bottom;
     FillConsoleOutputCharacterA(StdOutput,
                                 0xD9, // '+',
                                 1,
@@ -1944,7 +2150,7 @@ DrawPartitionList(
                                 &Written);
 
     /* print list entries */
-    List->Line = - List->Offset;
+    ListUi->Line = - ListUi->Offset;
 
     Entry = List->DiskListHead.Flink;
     while (Entry != &List->DiskListHead)
@@ -1952,24 +2158,22 @@ DrawPartitionList(
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
         /* Print disk entry */
-        PrintDiskData(List,
-                      DiskEntry);
+        PrintDiskData(ListUi, DiskEntry);
 
         Entry = Entry->Flink;
     }
 }
 
 
-DWORD
+ULONG
 SelectPartition(
-    PPARTLIST List,
-    ULONG DiskNumber,
-    ULONG PartitionNumber)
+    IN PPARTLIST List,
+    IN ULONG DiskNumber,
+    IN ULONG PartitionNumber)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
+    PLIST_ENTRY Entry1, Entry2;
 
     /* Check for empty disks */
     if (IsListEmpty(&List->DiskListHead))
@@ -1990,10 +2194,9 @@ SelectPartition(
 
                 if (PartEntry->PartitionNumber == PartitionNumber)
                 {
-                     List->CurrentDisk = DiskEntry;
-                     List->CurrentPartition = PartEntry;
-                     DrawPartitionList(List);
-                     return TRUE;
+                    List->CurrentDisk = DiskEntry;
+                    List->CurrentPartition = PartEntry;
+                    return TRUE;
                 }
 
                 Entry2 = Entry2->Flink;
@@ -2009,9 +2212,9 @@ SelectPartition(
 }
 
 
-BOOL
-ScrollDownPartitionList(
-    PPARTLIST List)
+PPARTENTRY
+GetNextPartition(
+    IN PPARTLIST List)
 {
     PLIST_ENTRY DiskListEntry;
     PLIST_ENTRY PartListEntry;
@@ -2020,7 +2223,7 @@ ScrollDownPartitionList(
 
     /* Fail, if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
-        return FALSE;
+        return NULL;
 
     /* Check for next usable entry on current disk */
     if (List->CurrentPartition != NULL)
@@ -2036,7 +2239,7 @@ ScrollDownPartitionList(
                 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
                 List->CurrentPartition = PartEntry;
-                return TRUE;
+                return List->CurrentPartition;
             }
             else
             {
@@ -2046,7 +2249,7 @@ ScrollDownPartitionList(
                     PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
                     List->CurrentPartition = PartEntry;
-                    return TRUE;
+                    return List->CurrentPartition;
                 }
             }
         }
@@ -2054,7 +2257,8 @@ ScrollDownPartitionList(
         {
             /* Primary or extended partition */
 
-            if (IsContainerPartition(List->CurrentPartition->PartitionType))
+            if ((List->CurrentPartition->IsPartitioned != FALSE) &&
+                IsContainerPartition(List->CurrentPartition->PartitionType))
             {
                 /* First logical partition */
                 PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
@@ -2063,7 +2267,7 @@ ScrollDownPartitionList(
                     PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
                     List->CurrentPartition = PartEntry;
-                    return TRUE;
+                    return List->CurrentPartition;
                 }
             }
             else
@@ -2075,7 +2279,7 @@ ScrollDownPartitionList(
                     PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
                     List->CurrentPartition = PartEntry;
-                    return TRUE;
+                    return List->CurrentPartition;
                 }
             }
         }
@@ -2094,20 +2298,19 @@ ScrollDownPartitionList(
 
             List->CurrentDisk = DiskEntry;
             List->CurrentPartition = PartEntry;
-            return TRUE;
+            return List->CurrentPartition;
         }
 
         DiskListEntry = DiskListEntry->Flink;
     }
 
-    return FALSE;
+    return NULL;
 }
 
-
-BOOL
-ScrollUpPartitionList(
-    PPARTLIST List)
-{
+PPARTENTRY
+GetPrevPartition(
+    IN PPARTLIST List)
+{
     PLIST_ENTRY DiskListEntry;
     PLIST_ENTRY PartListEntry;
     PDISKENTRY DiskEntry;
@@ -2115,7 +2318,7 @@ ScrollUpPartitionList(
 
     /* Fail, if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
-        return FALSE;
+        return NULL;
 
     /* Check for previous usable entry on current disk */
     if (List->CurrentPartition != NULL)
@@ -2131,12 +2334,12 @@ ScrollUpPartitionList(
             }
             else
             {
-                /* Extended partition*/
+                /* Extended partition */
                 PartEntry = List->CurrentDisk->ExtendedPartition;
             }
 
             List->CurrentPartition = PartEntry;
-            return TRUE;
+            return List->CurrentPartition;
         }
         else
         {
@@ -2147,16 +2350,16 @@ ScrollUpPartitionList(
             {
                 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-                if (IsContainerPartition(PartEntry->PartitionType))
+                if ((PartEntry->IsPartitioned != FALSE) &&
+                    IsContainerPartition(PartEntry->PartitionType))
                 {
                     PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
                     PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
                 }
 
                 List->CurrentPartition = PartEntry;
-                return TRUE;
+                return List->CurrentPartition;
             }
-
         }
     }
 
@@ -2171,7 +2374,8 @@ ScrollUpPartitionList(
         {
             PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-            if (IsContainerPartition(PartEntry->PartitionType))
+            if ((PartEntry->IsPartitioned != FALSE) &&
+                IsContainerPartition(PartEntry->PartitionType))
             {
                 PartListEntry = DiskEntry->LogicalPartListHead.Blink;
                 if (PartListEntry != &DiskEntry->LogicalPartListHead)
@@ -2180,32 +2384,49 @@ ScrollUpPartitionList(
 
                     List->CurrentDisk = DiskEntry;
                     List->CurrentPartition = PartEntry;
-                    return TRUE;
+                    return List->CurrentPartition;
                 }
             }
             else
             {
                 List->CurrentDisk = DiskEntry;
                 List->CurrentPartition = PartEntry;
-                return TRUE;
+                return List->CurrentPartition;
             }
         }
 
         DiskListEntry = DiskListEntry->Blink;
     }
 
-    return FALSE;
+    return NULL;
+}
+
+
+
+VOID
+ScrollDownPartitionList(
+    IN PPARTLIST_UI ListUi)
+{
+    if (GetNextPartition(ListUi->List))
+        DrawPartitionList(ListUi);
+}
+
+VOID
+ScrollUpPartitionList(
+    IN PPARTLIST_UI ListUi)
+{
+    if (GetPrevPartition(ListUi->List))
+        DrawPartitionList(ListUi);
 }
 
 
 static
 BOOLEAN
 IsEmptyLayoutEntry(
-    PPARTITION_INFORMATION PartitionInfo)
+    IN PPARTITION_INFORMATION PartitionInfo)
 {
     if (PartitionInfo->StartingOffset.QuadPart == 0 &&
         PartitionInfo->PartitionLength.QuadPart == 0)
-//        PartitionInfo->PartitionType == 0)
         return TRUE;
 
     return FALSE;
@@ -2229,74 +2450,257 @@ IsSamePrimaryLayoutEntry(
 }
 
 
+static
+ULONG
+GetPrimaryPartitionCount(
+    IN PDISKENTRY DiskEntry)
+{
+    PLIST_ENTRY Entry;
+    PPARTENTRY PartEntry;
+    ULONG Count = 0;
+
+    Entry = DiskEntry->PrimaryPartListHead.Flink;
+    while (Entry != &DiskEntry->PrimaryPartListHead)
+    {
+        PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+        if (PartEntry->IsPartitioned == TRUE)
+            Count++;
+
+        Entry = Entry->Flink;
+    }
+
+    return Count;
+}
+
+
+static
+ULONG
+GetLogicalPartitionCount(
+    IN PDISKENTRY DiskEntry)
+{
+    PLIST_ENTRY ListEntry;
+    PPARTENTRY PartEntry;
+    ULONG Count = 0;
+
+    ListEntry = DiskEntry->LogicalPartListHead.Flink;
+    while (ListEntry != &DiskEntry->LogicalPartListHead)
+    {
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+        if (PartEntry->IsPartitioned)
+            Count++;
+
+        ListEntry = ListEntry->Flink;
+    }
+
+    return Count;
+}
+
+
+static
+BOOLEAN
+ReAllocateLayoutBuffer(
+    IN PDISKENTRY DiskEntry)
+{
+    PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
+    ULONG NewPartitionCount;
+    ULONG CurrentPartitionCount = 0;
+    ULONG LayoutBufferSize;
+    ULONG i;
+
+    DPRINT1("ReAllocateLayoutBuffer()\n");
+
+    NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
+
+    if (DiskEntry->LayoutBuffer)
+        CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
+
+    DPRINT1("CurrentPartitionCount: %lu    NewPartitionCount: %lu\n",
+            CurrentPartitionCount, NewPartitionCount);
+
+    if (CurrentPartitionCount == NewPartitionCount)
+        return TRUE;
+
+    LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+                       ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+    NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
+                                        HEAP_ZERO_MEMORY,
+                                        DiskEntry->LayoutBuffer,
+                                        LayoutBufferSize);
+    if (NewLayoutBuffer == NULL)
+    {
+        DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
+        return FALSE;
+    }
+
+    /* 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;
+}
+
+
 static
 VOID
 UpdateDiskLayout(
     IN PDISKENTRY DiskEntry)
 {
     PPARTITION_INFORMATION PartitionInfo;
+    PPARTITION_INFORMATION LinkInfo = NULL;
     PLIST_ENTRY ListEntry;
     PPARTENTRY PartEntry;
-    ULONG Index = 0;
+    LARGE_INTEGER HiddenSectors64;
+    ULONG Index;
     ULONG PartitionNumber = 1;
 
-DPRINT1("UpdateDiskLayout()\n");
+    DPRINT1("UpdateDiskLayout()\n");
 
+    /* Resize the layout buffer if necessary */
+    if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
+    {
+        DPRINT("ReAllocateLayoutBuffer() failed.\n");
+        return;
+    }
+
+    /* Update the primary partition table */
+    Index = 0;
     ListEntry = DiskEntry->PrimaryPartListHead.Flink;
     while (ListEntry != &DiskEntry->PrimaryPartListHead)
     {
         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
 
-        if (PartEntry->IsPartitioned == TRUE)
+        if (PartEntry->IsPartitioned != FALSE)
         {
             PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
 
             if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
             {
-DPRINT1("Updating partition entry %lu\n", Index);
+                DPRINT1("Updating primary partition entry %lu\n", Index);
+
                 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
                 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
-                PartitionInfo->HiddenSectors = 0;
+                PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
                 PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
                 PartitionInfo->PartitionType = PartEntry->PartitionType;
                 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
                 PartitionInfo->RecognizedPartition = FALSE;
                 PartitionInfo->RewritePartition = TRUE;
+            }
 
-                PartEntry->PartitionNumber = PartitionNumber;
-                PartEntry->PartitionIndex = Index;
+            PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
+            PartEntry->PartitionIndex = Index;
 
+            if (!IsContainerPartition(PartEntry->PartitionType))
                 PartitionNumber++;
-            }
-            else if (!IsEmptyLayoutEntry(PartitionInfo))
+
+            Index++;
+        }
+
+        ListEntry = ListEntry->Flink;
+    }
+
+    /* Update the logical partition table */
+    Index = 4;
+    ListEntry = DiskEntry->LogicalPartListHead.Flink;
+    while (ListEntry != &DiskEntry->LogicalPartListHead)
+    {
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+        if (PartEntry->IsPartitioned)
+        {
+            PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+
+            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->PartitionType = PartEntry->PartitionType;
+            PartitionInfo->BootIndicator = FALSE;
+            PartitionInfo->RecognizedPartition = FALSE;
+            PartitionInfo->RewritePartition = TRUE;
+
+            PartEntry->PartitionNumber = PartitionNumber;
+            PartEntry->PartitionIndex = Index;
+
+            /* Fill the link entry of the previous partition entry */
+            if (LinkInfo != NULL)
             {
-                PartitionNumber++;
+                LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
+                LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
+                HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
+                LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
+                LinkInfo->PartitionNumber = 0;
+                LinkInfo->PartitionType = PARTITION_EXTENDED;
+                LinkInfo->BootIndicator = FALSE;
+                LinkInfo->RecognizedPartition = FALSE;
+                LinkInfo->RewritePartition = TRUE;
             }
 
-            Index++;
+            /* Save a pointer to the link entry of the current partition entry */
+            LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
+
+            PartitionNumber++;
+            Index += 4;
         }
 
         ListEntry = ListEntry->Flink;
     }
 
-    for (;Index < 4; Index++)
+    /* Wipe unused primary partition entries */
+    for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
     {
+        DPRINT1("Primary partition entry %lu\n", Index);
+
         PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
 
         if (!IsEmptyLayoutEntry(PartitionInfo))
         {
-DPRINT1("Wiping partition entry %lu\n", Index);
+            DPRINT1("Wiping primary partition entry %lu\n", Index);
+
             PartitionInfo->StartingOffset.QuadPart = 0;
             PartitionInfo->PartitionLength.QuadPart = 0;
             PartitionInfo->HiddenSectors = 0;
             PartitionInfo->PartitionNumber = 0;
-            PartitionInfo->PartitionType = 0;
+            PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
             PartitionInfo->BootIndicator = FALSE;
             PartitionInfo->RecognizedPartition = FALSE;
             PartitionInfo->RewritePartition = TRUE;
         }
     }
 
+    /* Wipe unused logical partition entries */
+    for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
+    {
+        if (Index % 4 >= 2)
+        {
+            DPRINT1("Logical partition entry %lu\n", Index);
+
+            PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
+
+            if (!IsEmptyLayoutEntry(PartitionInfo))
+            {
+                DPRINT1("Wiping partition entry %lu\n", Index);
+
+                PartitionInfo->StartingOffset.QuadPart = 0;
+                PartitionInfo->PartitionLength.QuadPart = 0;
+                PartitionInfo->HiddenSectors = 0;
+                PartitionInfo->PartitionNumber = 0;
+                PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
+                PartitionInfo->BootIndicator = FALSE;
+                PartitionInfo->RecognizedPartition = FALSE;
+                PartitionInfo->RewritePartition = TRUE;
+            }
+        }
+    }
+
 #ifdef DUMP_PARTITION_TABLE
     DumpPartitionTable(DiskEntry);
 #endif
@@ -2306,12 +2710,18 @@ DPRINT1("Wiping partition entry %lu\n", Index);
 static
 PPARTENTRY
 GetPrevUnpartitionedEntry(
-    PDISKENTRY DiskEntry,
-    PPARTENTRY PartEntry)
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry)
 {
     PPARTENTRY PrevPartEntry;
+    PLIST_ENTRY ListHead;
 
-    if (PartEntry->ListEntry.Blink != &DiskEntry->PrimaryPartListHead)
+    if (PartEntry->LogicalPartition)
+        ListHead = &DiskEntry->LogicalPartListHead;
+    else
+        ListHead = &DiskEntry->PrimaryPartListHead;
+
+    if (PartEntry->ListEntry.Blink != ListHead)
     {
         PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
                                           PARTENTRY,
@@ -2327,12 +2737,18 @@ GetPrevUnpartitionedEntry(
 static
 PPARTENTRY
 GetNextUnpartitionedEntry(
-    PDISKENTRY DiskEntry,
-    PPARTENTRY PartEntry)
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry)
 {
     PPARTENTRY NextPartEntry;
+    PLIST_ENTRY ListHead;
 
-    if (PartEntry->ListEntry.Flink != &DiskEntry->PrimaryPartListHead)
+    if (PartEntry->LogicalPartition)
+        ListHead = &DiskEntry->LogicalPartListHead;
+    else
+        ListHead = &DiskEntry->PrimaryPartListHead;
+
+    if (PartEntry->ListEntry.Flink != ListHead)
     {
         NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
                                           PARTENTRY,
@@ -2347,9 +2763,9 @@ GetNextUnpartitionedEntry(
 
 VOID
 CreatePrimaryPartition(
-    PPARTLIST List,
-    ULONGLONG SectorCount,
-    BOOLEAN AutoCreate)
+    IN PPARTLIST List,
+    IN ULONGLONG SectorCount,
+    IN BOOLEAN AutoCreate)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
@@ -2360,7 +2776,7 @@ CreatePrimaryPartition(
     if (List == NULL ||
         List->CurrentDisk == NULL ||
         List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned == TRUE)
+        List->CurrentPartition->IsPartitioned != FALSE)
     {
         return;
     }
@@ -2368,27 +2784,29 @@ CreatePrimaryPartition(
     DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
-DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
 
-    if (AutoCreate == TRUE ||
-        Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == 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");
+        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; /* FIXME */
+        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);
+        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");
+        DPRINT1("Add new partition entry\n");
 
         /* Insert and initialize a new partition entry */
         NewPartEntry = RtlAllocateHeap(ProcessHeap,
@@ -2405,17 +2823,18 @@ DPRINT1("Add new partition entry\n");
 
         NewPartEntry->IsPartitioned = TRUE;
         NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+        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);
+        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->BootIndicator = FALSE; /* FIXME */
+        NewPartEntry->FileSystem  = NULL;
+        NewPartEntry->BootIndicator = FALSE;
 
         PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
         PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
@@ -2425,8 +2844,6 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
     DiskEntry->Dirty = TRUE;
 
-    UpdatePartitionNumbers(DiskEntry);
-
     AssignDriveLetters(List);
 }
 
@@ -2434,13 +2851,13 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 static
 VOID
 AddLogicalDiskSpace(
-    PDISKENTRY DiskEntry)
+    IN PDISKENTRY DiskEntry)
 {
     PPARTENTRY NewPartEntry;
 
     DPRINT1("AddLogicalDiskSpace()\n");
 
-    /* Create a partition table entry that represents the empty space in the container partition */
+    /* Create a partition entry that represents the empty space in the container partition */
     NewPartEntry = RtlAllocateHeap(ProcessHeap,
                                    HEAP_ZERO_MEMORY,
                                    sizeof(PARTENTRY));
@@ -2451,14 +2868,15 @@ AddLogicalDiskSpace(
     NewPartEntry->LogicalPartition = TRUE;
 
     NewPartEntry->IsPartitioned = FALSE;
-    NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
-    NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack;
+    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);
@@ -2467,8 +2885,8 @@ AddLogicalDiskSpace(
 
 VOID
 CreateExtendedPartition(
-    PPARTLIST List,
-    ULONGLONG SectorCount)
+    IN PPARTLIST List,
+    IN ULONGLONG SectorCount)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
@@ -2479,7 +2897,7 @@ CreateExtendedPartition(
     if (List == NULL ||
         List->CurrentDisk == NULL ||
         List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned == TRUE)
+        List->CurrentPartition->IsPartitioned != FALSE)
     {
         return;
     }
@@ -2487,17 +2905,19 @@ CreateExtendedPartition(
     DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
-DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
 
-    if (Align(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
+    if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
     {
-DPRINT1("Convert existing partition entry\n");
+        DPRINT1("Convert existing partition entry\n");
+
         /* Convert current entry to 'new (unformatted)' */
         PartEntry->IsPartitioned = TRUE;
-        PartEntry->FormatState = Formatted;
+        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; /* FIXME */
+        PartEntry->BootIndicator = FALSE;
 
         if (PartEntry->StartSector.QuadPart < 1450560)
         {
@@ -2512,13 +2932,13 @@ DPRINT1("Convert existing partition entry\n");
 
         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);
+        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");
+        DPRINT1("Add new partition entry\n");
 
         /* Insert and initialize a new partition entry */
         NewPartEntry = RtlAllocateHeap(ProcessHeap,
@@ -2535,12 +2955,13 @@ DPRINT1("Add new partition entry\n");
 
         NewPartEntry->IsPartitioned = TRUE;
         NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = Align(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
+        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
                                              NewPartEntry->StartSector.QuadPart;
 
         NewPartEntry->New = FALSE;
-        NewPartEntry->FormatState = Formatted;
-        NewPartEntry->BootIndicator = FALSE; /* FIXME */
+        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)
         {
@@ -2558,9 +2979,9 @@ DPRINT1("Add new partition entry\n");
         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);
+        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);
     }
 
     AddLogicalDiskSpace(DiskEntry);
@@ -2569,41 +2990,102 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 
     DiskEntry->Dirty = TRUE;
 
-    UpdatePartitionNumbers(DiskEntry);
-
     AssignDriveLetters(List);
 }
 
 
 VOID
 CreateLogicalPartition(
-    PPARTLIST List,
-    ULONGLONG SectorCount)
+    IN PPARTLIST List,
+    IN ULONGLONG SectorCount,
+    IN BOOLEAN AutoCreate)
 {
-//    PDISKENTRY DiskEntry;
+    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-//    PPARTENTRY NewPartEntry;
+    PPARTENTRY NewPartEntry;
 
     DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
 
     if (List == NULL ||
         List->CurrentDisk == NULL ||
         List->CurrentPartition == NULL ||
-        List->CurrentPartition->IsPartitioned == TRUE)
+        List->CurrentPartition->IsPartitioned != FALSE)
     {
         return;
     }
 
-//    DiskEntry = List->CurrentDisk;
+    DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
     DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+    if (AutoCreate == TRUE ||
+        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;
+
+        /* 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;
+
+        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+    }
+
+    UpdateDiskLayout(DiskEntry);
+
+    DiskEntry->Dirty = TRUE;
+
+    AssignDriveLetters(List);
 }
 
 
 VOID
 DeleteCurrentPartition(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
@@ -2620,10 +3102,16 @@ DeleteCurrentPartition(
         return;
     }
 
+    /* Clear the system disk and partition pointers if the system partition is being deleted */
+    if (List->SystemPartition == List->CurrentPartition)
+    {
+        List->SystemPartition = NULL;
+    }
+
     DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
-    /* Delete all logical partiton entries if an extended partition will be deleted */
+    /* Delete all logical partition entries if an extended partition will be deleted */
     if (DiskEntry->ExtendedPartition == PartEntry)
     {
         while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
@@ -2640,11 +3128,8 @@ DeleteCurrentPartition(
     /* Adjust unpartitioned disk space entries */
 
     /* Get pointer to previous and next unpartitioned entries */
-    PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry,
-                                              PartEntry);
-
-    NextPartEntry = GetNextUnpartitionedEntry(DiskEntry,
-                                              PartEntry);
+    PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry, PartEntry);
+    NextPartEntry = GetNextUnpartitionedEntry(DiskEntry, PartEntry);
 
     if (PrevPartEntry != NULL && NextPartEntry != NULL)
     {
@@ -2697,7 +3182,9 @@ DeleteCurrentPartition(
     {
         /* Nothing to merge but change current entry */
         PartEntry->IsPartitioned = FALSE;
+        PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
         PartEntry->FormatState = Unformatted;
+        PartEntry->FileSystem  = NULL;
         PartEntry->DriveLetter = 0;
     }
 
@@ -2705,160 +3192,252 @@ DeleteCurrentPartition(
 
     DiskEntry->Dirty = TRUE;
 
-    UpdatePartitionNumbers(DiskEntry);
-
     AssignDriveLetters(List);
 }
 
 
 VOID
-CheckActiveBootPartition(
-    PPARTLIST List)
+CheckActiveSystemPartition(
+    IN PPARTLIST List,
+    IN PFILE_SYSTEM_LIST FileSystemList /* Needed for checking the FS of the candidate system partition */
+    )
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
     PLIST_ENTRY ListEntry;
 
-    /* Check for empty disk list */
-    if (IsListEmpty (&List->DiskListHead))
-    {
-        List->ActiveBootDisk = NULL;
-        List->ActiveBootPartition = NULL;
-        return;
-    }
+    PFILE_SYSTEM_ITEM FileSystem;
 
-#if 0
-    if (List->ActiveBootDisk != NULL &&
-        List->ActiveBootPartition != NULL)
+    /* Check for empty disk list */
+    if (IsListEmpty(&List->DiskListHead))
     {
-        /* We already have an active boot partition */
+        List->SystemPartition = NULL;
+        List->OriginalSystemPartition = NULL;
         return;
     }
-#endif
 
     /* Choose the currently selected disk */
     DiskEntry = List->CurrentDisk;
 
     /* Check for empty partition list */
-    if (IsListEmpty (&DiskEntry->PrimaryPartListHead))
+    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
     {
-        List->ActiveBootDisk = NULL;
-        List->ActiveBootPartition = NULL;
+        List->SystemPartition = NULL;
+        List->OriginalSystemPartition = NULL;
         return;
     }
 
+    if (List->SystemPartition != NULL)
+    {
+        /* We already have an active system partition */
+        DPRINT1("Use the current system partition %lu in disk %lu, drive letter %c\n",
+                List->SystemPartition->PartitionNumber,
+                List->SystemPartition->DiskEntry->DiskNumber,
+                (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+        return;
+    }
+
+    DPRINT1("We are here (1)!\n");
+
+    List->SystemPartition = NULL;
+    List->OriginalSystemPartition = NULL;
+
+    /* Retrieve the first partition of the disk */
     PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
                                   PARTENTRY,
                                   ListEntry);
+    ASSERT(DiskEntry == PartEntry->DiskEntry);
+    List->SystemPartition = PartEntry;
+
+    //
+    // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
+    //
 
-    /* Set active boot partition */
-    if ((DiskEntry->NewDisk == TRUE) ||
-        (PartEntry->BootIndicator == FALSE))
+    /* Check if the disk is new and if so, use its first partition as the active system partition */
+    if (DiskEntry->NewDisk)
     {
-        PartEntry->BootIndicator = TRUE;
-        DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
-        DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
-        DiskEntry->Dirty = TRUE;
+        if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
+        {
+            ASSERT(DiskEntry == PartEntry->DiskEntry);
+            List->SystemPartition = PartEntry;
 
-        /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
-        List->ActiveBootDisk = DiskEntry;
-        List->ActiveBootPartition = PartEntry;
+            List->OriginalSystemPartition = List->SystemPartition;
 
-        return;
+            DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %c\n",
+                    List->SystemPartition->PartitionNumber,
+                    List->SystemPartition->DiskEntry->DiskNumber,
+                    (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+            goto SetSystemPartition;
+        }
+
+        // FIXME: What to do??
+        DPRINT1("NewDisk TRUE but first partition is used?\n");
     }
 
-    /* Disk is not new, scan all partitions to find a bootable one */
-    List->ActiveBootDisk = NULL;
-    List->ActiveBootPartition = NULL;
+    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)
     {
+        /* Retrieve the partition and go to the next one */
         PartEntry = CONTAINING_RECORD(ListEntry,
                                       PARTENTRY,
                                       ListEntry);
 
-        /* Check if it is partitioned */
-        if (PartEntry->IsPartitioned)
+        /* Check if the partition is partitioned and is used */
+        if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
         {
-            if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED &&
-                PartEntry->BootIndicator)
-            {
-                /* Yes, we found it */
-                List->ActiveBootDisk = DiskEntry;
-                List->ActiveBootPartition = PartEntry;
-
-                DPRINT("Found bootable partition disk %d, drive letter %c\n",
-                       DiskEntry->DiskNumber, PartEntry->DriveLetter);
-                break;
-            }
+            break;
         }
 
         /* Go to the next one */
         ListEntry = ListEntry->Flink;
     }
-}
+    if (ListEntry == &DiskEntry->PrimaryPartListHead)
+    {
+        /*
+         * 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
 
+        DPRINT1("Use first active system partition %lu in disk %lu, drive letter %c\n",
+                List->SystemPartition->PartitionNumber,
+                List->SystemPartition->DiskEntry->DiskNumber,
+                (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
 
-BOOLEAN
-CheckForLinuxFdiskPartitions(
-    PPARTLIST List)
-{
-#if 0
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
-    ULONG PartitionCount;
-    ULONG i;
+        goto SetSystemPartition;
+    }
 
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
+    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)
     {
-        DiskEntry = CONTAINING_RECORD(Entry1,
-                                      DISKENTRY,
+        /* Retrieve the partition and go to the next one */
+        PartEntry = CONTAINING_RECORD(ListEntry,
+                                      PARTENTRY,
                                       ListEntry);
+        ListEntry = ListEntry->Flink;
 
-        Entry2 = DiskEntry->PartListHead.Flink;
-        while (Entry2 != &DiskEntry->PartListHead)
+        /* Check if the partition is partitioned and used */
+        if (PartEntry->IsPartitioned &&
+            PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
         {
-            PartEntry = CONTAINING_RECORD(Entry2,
-                                          PARTENTRY,
-                                          ListEntry);
-
-            if (PartEntry->Unpartitioned == FALSE)
+            /* Check if the partition is active */
+            if (PartEntry->BootIndicator)
             {
-                PartitionCount = 0;
-
-                for (i = 0; i < 4; i++)
-                {
-                    if (!IsContainerPartition(PartEntry->PartInfo[i].PartitionType) &&
-                        PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
-                    {
-                        PartitionCount++;
-                    }
-                }
+                /* Yes, we found it */
+                ASSERT(DiskEntry == PartEntry->DiskEntry);
+                List->SystemPartition = PartEntry;
 
-                if (PartitionCount > 1)
-                {
-                    return TRUE;
-                }
+                DPRINT1("Found active system partition %lu in disk %lu, drive letter %c\n",
+                        PartEntry->PartitionNumber,
+                        DiskEntry->DiskNumber,
+                        (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter);
+                break;
             }
-
-            Entry2 = Entry2->Flink;
         }
+    }
 
-        Entry1 = Entry1->Flink;
+    /* 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;
     }
-#endif
 
-    return FALSE;
+    /* 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.
+     */
+    FileSystem = GetFileSystem(FileSystemList, List->OriginalSystemPartition);
+    if (FileSystem == NULL)
+    {
+        DPRINT1("System partition %lu in disk %lu with no FS?!\n",
+                List->OriginalSystemPartition->PartitionNumber,
+                List->OriginalSystemPartition->DiskEntry->DiskNumber);
+        goto FindAndUseAlternativeSystemPartition;
+    }
+    // HACK: WARNING: We cannot write on this FS yet!
+    // See fslist.c:GetFileSystem()
+    if (List->OriginalSystemPartition->PartitionType == PARTITION_EXT2 ||
+        List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
+    {
+        DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
+                FileSystem->FileSystemName);
+        goto FindAndUseAlternativeSystemPartition;
+    }
+
+    DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %c\n",
+            List->SystemPartition->PartitionNumber,
+            List->SystemPartition->DiskEntry->DiskNumber,
+            (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+    return;
+
+FindAndUseAlternativeSystemPartition:
+    /*
+     * We are here because we have not found any (active) candidate
+     * system partition that we know how to support. What we are going
+     * to do is to change the existing system partition and use the
+     * partition on which we install ReactOS as the new system partition,
+     * and then we will need to add in FreeLdr's entry a boot entry to boot
+     * from the original system partition.
+     */
+
+    /* 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;
+
+UseAlternativeSystemPartition:
+    List->SystemPartition = List->CurrentPartition;
+
+    DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %c\n",
+            List->SystemPartition->PartitionNumber,
+            List->SystemPartition->DiskEntry->DiskNumber,
+            (List->SystemPartition->DriveLetter == 0) ? '-' : List->SystemPartition->DriveLetter);
+
+SetSystemPartition:
+    /* Set the new active system partition */
+    List->SystemPartition->BootIndicator = TRUE;
+    List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = TRUE;
+    List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
+    List->SystemPartition->DiskEntry->Dirty = TRUE;
 }
 
 
 static
 NTSTATUS
-WritePartitons(
+WritePartitions(
     IN PPARTLIST List,
     IN PDISKENTRY DiskEntry)
 {
@@ -2919,13 +3498,23 @@ WritePartitons(
     if (FileHandle != NULL)
         NtClose(FileHandle);
 
+    //
+    // 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.
+    // 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).
+    //
+
     return Status;
 }
 
 
 BOOLEAN
 WritePartitionsToDisk(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PLIST_ENTRY Entry;
     PDISKENTRY DiskEntry;
@@ -2938,9 +3527,10 @@ WritePartitionsToDisk(
     {
         DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
-        if (DiskEntry->Dirty == TRUE)
+        if (DiskEntry->Dirty != FALSE)
         {
-            WritePartitons(List, DiskEntry);
+            WritePartitions(List, DiskEntry);
+            DiskEntry->Dirty = FALSE;
         }
 
         Entry = Entry->Flink;
@@ -2950,9 +3540,9 @@ WritePartitionsToDisk(
 }
 
 
-BOOL
+BOOLEAN
 SetMountedDeviceValues(
-    PPARTLIST List)
+    IN PPARTLIST List)
 {
     PLIST_ENTRY Entry1, Entry2;
     PDISKENTRY DiskEntry;
@@ -2960,9 +3550,7 @@ SetMountedDeviceValues(
     LARGE_INTEGER StartingOffset;
 
     if (List == NULL)
-    {
         return FALSE;
-    }
 
     Entry1 = List->DiskListHead.Flink;
     while (Entry1 != &List->DiskListHead)
@@ -2977,6 +3565,29 @@ SetMountedDeviceValues(
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
             if (PartEntry->IsPartitioned)
             {
+                /* Assign a "\DosDevices\#:" mount point to this partition */
+                if (PartEntry->DriveLetter)
+                {
+                    StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+                    if (!SetMountedDeviceValue(PartEntry->DriveLetter,
+                                               DiskEntry->LayoutBuffer->Signature,
+                                               StartingOffset))
+                    {
+                        return FALSE;
+                    }
+                }
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry2 = DiskEntry->LogicalPartListHead.Flink;
+        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            if (PartEntry->IsPartitioned)
+            {
+                /* Assign a "\DosDevices\#:" mount point to this partition */
                 if (PartEntry->DriveLetter)
                 {
                     StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
@@ -2998,65 +3609,20 @@ SetMountedDeviceValues(
     return TRUE;
 }
 
-
-static
-BOOLEAN
-IsLastPrimaryPartiton(
-    IN PPARTENTRY PartEntry)
-{
-    return (PartEntry->ListEntry.Flink == &PartEntry->DiskEntry->PrimaryPartListHead);
-}
-
-
-static
-BOOLEAN
-IsPreviousPartitionExtended(
+VOID
+SetPartitionType(
     IN PPARTENTRY PartEntry,
-    IN PDISKENTRY DiskEntry)
-{
-    PPARTENTRY PrevPartEntry;
-    PLIST_ENTRY Entry;
-
-    Entry = PartEntry->ListEntry.Blink;
-
-    while (Entry != &DiskEntry->PrimaryPartListHead)
-    {
-        PrevPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-
-        if (IsContainerPartition(PrevPartEntry->PartitionType))
-            return TRUE;
-
-        Entry = Entry->Blink;
-    }
-
-    return FALSE;
-
-}
-
-
-static
-ULONG
-GetPrimaryPartitionCount(
-    IN PDISKENTRY DiskEntry)
+    IN UCHAR PartitionType)
 {
-    PLIST_ENTRY Entry;
-    PPARTENTRY PartEntry;
-    UINT nCount = 0;
-
-    Entry = DiskEntry->PrimaryPartListHead.Flink;
-    while (Entry != &DiskEntry->PrimaryPartListHead)
-    {
-        PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-        if (PartEntry->IsPartitioned == TRUE)
-            nCount++;
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
 
-        Entry = Entry->Flink;
-    }
+    PartEntry->PartitionType = PartitionType;
 
-    return nCount;
+    DiskEntry->Dirty = TRUE;
+    DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
+    DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
 }
 
-
 ULONG
 PrimaryPartitionCreationChecks(
     IN PPARTLIST List)
@@ -3068,17 +3634,13 @@ PrimaryPartitionCreationChecks(
     PartEntry = List->CurrentPartition;
 
     /* Fail if partition is already in use */
-    if (PartEntry->IsPartitioned == TRUE)
+    if (PartEntry->IsPartitioned != FALSE)
         return ERROR_NEW_PARTITION;
 
-    /* Fail if there are more than 4 partitions in the list */
-    if (GetPrimaryPartitionCount(DiskEntry) > 4)
+    /* Fail if there are already 4 primary partitions in the list */
+    if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
 
-    /* Fail if this partiton is located behind an extended partition */
-    if (IsPreviousPartitionExtended(PartEntry, DiskEntry))
-        return ERROR_NOT_BEHIND_EXTENDED;
-
     return ERROR_SUCCESS;
 }
 
@@ -3094,21 +3656,17 @@ ExtendedPartitionCreationChecks(
     PartEntry = List->CurrentPartition;
 
     /* Fail if partition is already in use */
-    if (PartEntry->IsPartitioned == TRUE)
+    if (PartEntry->IsPartitioned != FALSE)
         return ERROR_NEW_PARTITION;
 
-    /* Fail if there are more than 4 partitions in the list */
-    if (GetPrimaryPartitionCount(DiskEntry) > 4)
+    /* Fail if there are already 4 primary partitions in the list */
+    if (GetPrimaryPartitionCount(DiskEntry) >= 4)
         return ERROR_PARTITION_TABLE_FULL;
 
     /* Fail if there is another extended partition in the list */
     if (DiskEntry->ExtendedPartition != NULL)
         return ERROR_ONLY_ONE_EXTENDED;
 
-    /* Fail if the partition is not the last list entry */
-    if (!IsLastPrimaryPartiton(PartEntry))
-        return ERROR_EXTENDED_NOT_LAST;
-
     return ERROR_SUCCESS;
 }
 
@@ -3124,10 +3682,123 @@ LogicalPartitionCreationChecks(
     PartEntry = List->CurrentPartition;
 
     /* Fail if partition is already in use */
-    if (PartEntry->IsPartitioned == TRUE)
+    if (PartEntry->IsPartitioned != FALSE)
         return ERROR_NEW_PARTITION;
 
     return ERROR_SUCCESS;
 }
 
+
+BOOLEAN
+GetNextUnformattedPartition(
+    IN PPARTLIST List,
+    OUT PDISKENTRY *pDiskEntry OPTIONAL,
+    OUT PPARTENTRY *pPartEntry)
+{
+    PLIST_ENTRY Entry1, Entry2;
+    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
+
+    Entry1 = List->DiskListHead.Flink;
+    while (Entry1 != &List->DiskListHead)
+    {
+        DiskEntry = CONTAINING_RECORD(Entry1,
+                                      DISKENTRY,
+                                      ListEntry);
+
+        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            if (PartEntry->IsPartitioned && PartEntry->New)
+            {
+                ASSERT(DiskEntry == PartEntry->DiskEntry);
+                if (pDiskEntry) *pDiskEntry = DiskEntry;
+                *pPartEntry = PartEntry;
+                return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry2 = DiskEntry->LogicalPartListHead.Flink;
+        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            if (PartEntry->IsPartitioned && PartEntry->New)
+            {
+                ASSERT(DiskEntry == PartEntry->DiskEntry);
+                if (pDiskEntry) *pDiskEntry = DiskEntry;
+                *pPartEntry = PartEntry;
+                return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry1 = Entry1->Flink;
+    }
+
+    if (pDiskEntry) *pDiskEntry = NULL;
+    *pPartEntry = NULL;
+
+    return FALSE;
+}
+
+BOOLEAN
+GetNextUncheckedPartition(
+    IN PPARTLIST List,
+    OUT PDISKENTRY *pDiskEntry OPTIONAL,
+    OUT PPARTENTRY *pPartEntry)
+{
+    PLIST_ENTRY Entry1, Entry2;
+    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
+
+    Entry1 = List->DiskListHead.Flink;
+    while (Entry1 != &List->DiskListHead)
+    {
+        DiskEntry = CONTAINING_RECORD(Entry1,
+                                      DISKENTRY,
+                                      ListEntry);
+
+        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+        while (Entry2 != &DiskEntry->PrimaryPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            if (PartEntry->NeedsCheck == TRUE)
+            {
+                ASSERT(DiskEntry == PartEntry->DiskEntry);
+                if (pDiskEntry) *pDiskEntry = DiskEntry;
+                *pPartEntry = PartEntry;
+                return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry2 = DiskEntry->LogicalPartListHead.Flink;
+        while (Entry2 != &DiskEntry->LogicalPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            if (PartEntry->NeedsCheck == TRUE)
+            {
+                ASSERT(DiskEntry == PartEntry->DiskEntry);
+                if (pDiskEntry) *pDiskEntry = DiskEntry;
+                *pPartEntry = PartEntry;
+                return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry1 = Entry1->Flink;
+    }
+
+    if (pDiskEntry) *pDiskEntry = NULL;
+    *pPartEntry = NULL;
+
+    return FALSE;
+}
+
 /* EOF */