[USETUP]
[reactos.git] / reactos / base / setup / usetup / partlist.c
index 4962df2..606280f 100644 (file)
@@ -31,7 +31,7 @@
 #define NDEBUG
 #include <debug.h>
 
-#define DUMP_PARTITION_TABLE
+//#define DUMP_PARTITION_TABLE
 
 /* FUNCTIONS ****************************************************************/
 
@@ -47,7 +47,7 @@ DumpPartitionTable(
     for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
     {
         PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
-        DbgPrint("%lu: %12I64u  %12I64u  %10lu  %2lu  %2x  %c  %c\n",
+        DPRINT1("\n%lu: %12I64u  %12I64u  %10lu  %2lu  %2x  %c  %c\n",
                 i,
                 PartitionInfo->StartingOffset.QuadPart,
                 PartitionInfo->PartitionLength.QuadPart,
@@ -166,46 +166,37 @@ 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;
             }
+
+            Entry2 = Entry2->Flink;
         }
 
         Entry1 = Entry1->Flink;
     }
-#endif
 }
 
 
@@ -542,6 +533,8 @@ AddPartitionToDisk(
         return;
     }
 
+    PartEntry->DiskEntry = DiskEntry;
+
     PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
     PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
 
@@ -638,7 +631,7 @@ ScanForUnpartitionedDiskSpace(
     PPARTENTRY NewPartEntry;
     PLIST_ENTRY Entry;
 
-    DPRINT1("ScanForUnpartitionedDiskSpace()\n");
+    DPRINT("ScanForUnpartitionedDiskSpace()\n");
 
     if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
     {
@@ -654,12 +647,13 @@ ScanForUnpartitionedDiskSpace(
         NewPartEntry->DiskEntry = DiskEntry;
 
         NewPartEntry->IsPartitioned = FALSE;
-        NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorsPerTrack;
+        NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
         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;
+
+        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;
 
@@ -670,7 +664,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;
 
@@ -702,9 +696,10 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
                 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
                 NewPartEntry->SectorCount.QuadPart = Align(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;
 
@@ -741,9 +736,10 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
             NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
             NewPartEntry->SectorCount.QuadPart = Align(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;
 
@@ -770,8 +766,8 @@ 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);
@@ -786,7 +782,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 +795,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);
@@ -819,9 +815,10 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
                     NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
                     NewPartEntry->SectorCount.QuadPart = Align(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;
 
@@ -859,9 +856,10 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
                 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
                 NewPartEntry->SectorCount.QuadPart = Align(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;
 
@@ -872,7 +870,7 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         }
     }
 
-    DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
+    DPRINT("ScanForUnpartitionedDiskSpace() done\n");
 }
 
 
@@ -1132,8 +1130,8 @@ AddDiskToList(
 
     DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
 
-    DPRINT1("SectorCount %I64u\n", DiskEntry->SectorCount);
-    DPRINT1("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
+    DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount);
+    DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
 
     DiskEntry->DiskNumber = DiskNumber;
     DiskEntry->Port = ScsiAddress.PortNumber;
@@ -1144,12 +1142,9 @@ 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);
@@ -1168,6 +1163,36 @@ AddDiskToList(
                                    0,
                                    DiskEntry->LayoutBuffer,
                                    LayoutBufferSize);
+    DPRINT("Status: 0x%08lx\n", Status);
+    DPRINT("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
+
+    /* If we need more than 4 partition entries, reallocte the buffer and
+       retrieve the disk layout again */
+    if (!NT_SUCCESS(Status) && DiskEntry->LayoutBuffer->PartitionCount > 4)
+    {
+        LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+                           ((DiskEntry->LayoutBuffer->PartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+        DiskEntry->LayoutBuffer = RtlReAllocateHeap(ProcessHeap,
+                                                    HEAP_ZERO_MEMORY,
+                                                    DiskEntry->LayoutBuffer,
+                                                    LayoutBufferSize);
+        if (DiskEntry->LayoutBuffer == NULL)
+        {
+            return;
+        }
+
+        Status = NtDeviceIoControlFile(FileHandle,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &Iosb,
+                                       IOCTL_DISK_GET_DRIVE_LAYOUT,
+                                       NULL,
+                                       0,
+                                       DiskEntry->LayoutBuffer,
+                                       LayoutBufferSize);
+    }
+
     if (NT_SUCCESS(Status))
     {
 #ifdef DUMP_PARTITION_TABLE
@@ -1180,11 +1205,11 @@ AddDiskToList(
         {
             if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
             {
-                DPRINT1("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
+                DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
             }
-            else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % 1048756 == 0)
+            else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
             {
-                DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+                DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
             }
             else
             {
@@ -1193,7 +1218,7 @@ AddDiskToList(
         }
         else
         {
-            DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+            DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
         }
 
 
@@ -1267,6 +1292,13 @@ CreatePartitionList(
     List->CurrentDisk = NULL;
     List->CurrentPartition = NULL;
 
+    List->BootDisk = NULL;
+    List->BootPartition = NULL;
+
+    List->TempDisk = NULL;
+    List->TempPartition = NULL;
+    List->FormatState = Start;
+
     InitializeListHead(&List->DiskListHead);
     InitializeListHead(&List->BiosDiskListHead);
 
@@ -1556,6 +1588,7 @@ PrintPartitionData(
                     MUIGetString(STRING_HDDINFOUNK5),
                     (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
                     (PartEntry->DriveLetter == 0) ? '-' : ':',
+                    PartEntry->BootIndicator ? '*' : ' ',
                     PartEntry->LogicalPartition ? "  " : "",
                     PartEntry->PartitionType,
                     PartEntry->LogicalPartition ? "" : "  ",
@@ -1565,9 +1598,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 ? "" : "  ",
@@ -2243,7 +2277,7 @@ UpdateDiskLayout(
     ULONG Index = 0;
     ULONG PartitionNumber = 1;
 
-DPRINT1("UpdateDiskLayout()\n");
+    DPRINT1("UpdateDiskLayout()\n");
 
     ListEntry = DiskEntry->PrimaryPartListHead.Flink;
     while (ListEntry != &DiskEntry->PrimaryPartListHead)
@@ -2256,7 +2290,8 @@ DPRINT1("UpdateDiskLayout()\n");
 
             if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
             {
-DPRINT1("Updating partition entry %lu\n", Index);
+                DPRINT1("Updating partition entry %lu\n", Index);
+
                 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
                 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
                 PartitionInfo->HiddenSectors = 0;
@@ -2288,7 +2323,8 @@ DPRINT1("Updating partition entry %lu\n", Index);
 
         if (!IsEmptyLayoutEntry(PartitionInfo))
         {
-DPRINT1("Wiping partition entry %lu\n", Index);
+            DPRINT1("Wiping partition entry %lu\n", Index);
+
             PartitionInfo->StartingOffset.QuadPart = 0;
             PartitionInfo->PartitionLength.QuadPart = 0;
             PartitionInfo->HiddenSectors = 0;
@@ -2371,27 +2407,28 @@ 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)
     {
-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->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,
@@ -2412,13 +2449,13 @@ DPRINT1("Add new partition entry\n");
                                              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->BootIndicator = FALSE;
 
         PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
         PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
@@ -2454,8 +2491,8 @@ 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);
@@ -2490,17 +2527,18 @@ 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)
     {
-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->AutoCreate = FALSE;
         PartEntry->New = FALSE;
-        PartEntry->BootIndicator = FALSE; /* FIXME */
+        PartEntry->BootIndicator = FALSE;
 
         if (PartEntry->StartSector.QuadPart < 1450560)
         {
@@ -2515,13 +2553,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,
@@ -2543,7 +2581,7 @@ DPRINT1("Add new partition entry\n");
 
         NewPartEntry->New = FALSE;
         NewPartEntry->FormatState = Formatted;
-        NewPartEntry->BootIndicator = FALSE; /* FIXME */
+        NewPartEntry->BootIndicator = FALSE;
 
         if (NewPartEntry->StartSector.QuadPart < 1450560)
         {
@@ -2561,9 +2599,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);
@@ -2583,9 +2621,9 @@ CreateLogicalPartition(
     PPARTLIST List,
     ULONGLONG SectorCount)
 {
-//    PDISKENTRY DiskEntry;
+    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-//    PPARTENTRY NewPartEntry;
+    PPARTENTRY NewPartEntry;
 
     DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
 
@@ -2597,10 +2635,71 @@ CreateLogicalPartition(
         return;
     }
 
-//    DiskEntry = List->CurrentDisk;
+    DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
     DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
+    if (Align(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->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 = Align(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->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;
+
+    UpdatePartitionNumbers(DiskEntry);
+
+    AssignDriveLetters(List);
 }
 
 
@@ -2726,14 +2825,14 @@ CheckActiveBootPartition(
     /* Check for empty disk list */
     if (IsListEmpty (&List->DiskListHead))
     {
-        List->ActiveBootDisk = NULL;
-        List->ActiveBootPartition = NULL;
+        List->BootDisk = NULL;
+        List->BootPartition = NULL;
         return;
     }
 
 #if 0
-    if (List->ActiveBootDisk != NULL &&
-        List->ActiveBootPartition != NULL)
+    if (List->BootDisk != NULL &&
+        List->BootPartition != NULL)
     {
         /* We already have an active boot partition */
         return;
@@ -2746,8 +2845,8 @@ CheckActiveBootPartition(
     /* Check for empty partition list */
     if (IsListEmpty (&DiskEntry->PrimaryPartListHead))
     {
-        List->ActiveBootDisk = NULL;
-        List->ActiveBootPartition = NULL;
+        List->BootDisk = NULL;
+        List->BootPartition = NULL;
         return;
     }
 
@@ -2765,15 +2864,15 @@ CheckActiveBootPartition(
         DiskEntry->Dirty = TRUE;
 
         /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
-        List->ActiveBootDisk = DiskEntry;
-        List->ActiveBootPartition = PartEntry;
+        List->BootDisk = DiskEntry;
+        List->BootPartition = PartEntry;
 
         return;
     }
 
     /* Disk is not new, scan all partitions to find a bootable one */
-    List->ActiveBootDisk = NULL;
-    List->ActiveBootPartition = NULL;
+    List->BootDisk = NULL;
+    List->BootPartition = NULL;
 
     ListEntry = DiskEntry->PrimaryPartListHead.Flink;
     while (ListEntry != &DiskEntry->PrimaryPartListHead)
@@ -2789,8 +2888,8 @@ CheckActiveBootPartition(
                 PartEntry->BootIndicator)
             {
                 /* Yes, we found it */
-                List->ActiveBootDisk = DiskEntry;
-                List->ActiveBootPartition = PartEntry;
+                List->BootDisk = DiskEntry;
+                List->BootPartition = PartEntry;
 
                 DPRINT("Found bootable partition disk %d, drive letter %c\n",
                        DiskEntry->DiskNumber, PartEntry->DriveLetter);
@@ -2804,65 +2903,9 @@ CheckActiveBootPartition(
 }
 
 
-BOOLEAN
-CheckForLinuxFdiskPartitions(
-    PPARTLIST List)
-{
-#if 0
-    PDISKENTRY DiskEntry;
-    PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
-    ULONG PartitionCount;
-    ULONG i;
-
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
-    {
-        DiskEntry = CONTAINING_RECORD(Entry1,
-                                      DISKENTRY,
-                                      ListEntry);
-
-        Entry2 = DiskEntry->PartListHead.Flink;
-        while (Entry2 != &DiskEntry->PartListHead)
-        {
-            PartEntry = CONTAINING_RECORD(Entry2,
-                                          PARTENTRY,
-                                          ListEntry);
-
-            if (PartEntry->Unpartitioned == FALSE)
-            {
-                PartitionCount = 0;
-
-                for (i = 0; i < 4; i++)
-                {
-                    if (!IsContainerPartition(PartEntry->PartInfo[i].PartitionType) &&
-                        PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
-                    {
-                        PartitionCount++;
-                    }
-                }
-
-                if (PartitionCount > 1)
-                {
-                    return TRUE;
-                }
-            }
-
-            Entry2 = Entry2->Flink;
-        }
-
-        Entry1 = Entry1->Flink;
-    }
-#endif
-
-    return FALSE;
-}
-
-
 static
 NTSTATUS
-WritePartitons(
+WritePartitions(
     IN PPARTLIST List,
     IN PDISKENTRY DiskEntry)
 {
@@ -2944,7 +2987,8 @@ WritePartitionsToDisk(
 
         if (DiskEntry->Dirty == TRUE)
         {
-            WritePartitons(List, DiskEntry);
+            WritePartitions(List, DiskEntry);
+            DiskEntry->Dirty = FALSE;
         }
 
         Entry = Entry->Flink;
@@ -3003,41 +3047,6 @@ SetMountedDeviceValues(
 }
 
 
-static
-BOOLEAN
-IsLastPrimaryPartiton(
-    IN PPARTENTRY PartEntry)
-{
-    return (PartEntry->ListEntry.Flink == &PartEntry->DiskEntry->PrimaryPartListHead);
-}
-
-
-static
-BOOLEAN
-IsPreviousPartitionExtended(
-    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(
@@ -3079,10 +3088,6 @@ PrimaryPartitionCreationChecks(
     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;
 }
 
@@ -3109,10 +3114,6 @@ ExtendedPartitionCreationChecks(
     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;
 }
 
@@ -3134,4 +3135,114 @@ LogicalPartitionCreationChecks(
     return ERROR_SUCCESS;
 }
 
+
+BOOL
+GetNextUnformattedPartition(
+    IN PPARTLIST List,
+    OUT PDISKENTRY *pDiskEntry,
+    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)
+            {
+                 *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)
+            {
+                 *pDiskEntry = DiskEntry;
+                 *pPartEntry = PartEntry;
+                 return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry1 = Entry1->Flink;
+    }
+
+    *pDiskEntry = NULL;
+    *pPartEntry = NULL;
+
+    return FALSE;
+}
+
+
+BOOL
+GetNextUncheckedPartition(
+    IN PPARTLIST List,
+    OUT PDISKENTRY *pDiskEntry,
+    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)
+            {
+                 *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)
+            {
+                 *pDiskEntry = DiskEntry;
+                 *pPartEntry = PartEntry;
+                 return TRUE;
+            }
+
+            Entry2 = Entry2->Flink;
+        }
+
+        Entry1 = Entry1->Flink;
+    }
+
+    *pDiskEntry = NULL;
+    *pPartEntry = NULL;
+
+    return FALSE;
+}
+
 /* EOF */