[USETUP]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 18 May 2014 15:14:24 +0000 (15:14 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 18 May 2014 15:14:24 +0000 (15:14 +0000)
First part of the partition management code rewrite. This part fixes the handling of primary partitions. Extended partitions and logical drives are not handled yet. Safety checks and warnings are still missing! Partitions created by the new code are accepted by gparted and Windows.

svn path=/trunk/; revision=63355

reactos/base/setup/usetup/bootsup.c
reactos/base/setup/usetup/interface/usetup.c
reactos/base/setup/usetup/partlist.c
reactos/base/setup/usetup/partlist.h

index 74d5ad3..183641c 100644 (file)
@@ -1444,7 +1444,6 @@ InstallFat16BootCodeToDisk(
     NTSTATUS Status;
     PFAT_BOOTSECTOR OrigBootSector;
     PFAT_BOOTSECTOR NewBootSector;
-    PARTITION_INFORMATION *PartInfo;
 
     /* Allocate buffer for original bootsector */
     OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
@@ -1543,8 +1542,7 @@ InstallFat16BootCodeToDisk(
            FIELD_OFFSET(FAT_BOOTSECTOR, BootCodeAndData) -
            FIELD_OFFSET(FAT_BOOTSECTOR, OemName));
 
-    PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
-    NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
+    NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
 
     /* Free the original boot sector */
     RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
@@ -1606,7 +1604,6 @@ InstallFat32BootCodeToDisk(
     PFAT32_BOOTSECTOR NewBootSector;
     LARGE_INTEGER FileOffset;
     USHORT BackupBootSector;
-    PARTITION_INFORMATION *PartInfo;
 
     /* Allocate buffer for original bootsector */
     OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE);
@@ -1704,8 +1701,7 @@ InstallFat32BootCodeToDisk(
            FIELD_OFFSET(FAT32_BOOTSECTOR, BootCodeAndData) -
            FIELD_OFFSET(FAT32_BOOTSECTOR, OemName));
 
-    PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber];
-    NewBootSector->HiddenSectors = PartInfo->HiddenSectors;
+    NewBootSector->HiddenSectors = PartitionList->CurrentDisk->SectorsPerTrack;
 
     /* Get the location of the backup boot sector */
     BackupBootSector = OrigBootSector->BackupBootSector;
index 8ba4d85..c0c597e 100644 (file)
@@ -1428,6 +1428,7 @@ LayoutSettingsPage(PINPUT_RECORD Ir)
 }
 
 
+#if 0
 static BOOL
 IsDiskSizeValid(PPARTENTRY PartEntry)
 {
@@ -1456,6 +1457,7 @@ IsDiskSizeValid(PPARTENTRY PartEntry)
         return TRUE;
     }
 }
+#endif
 
 
 static PAGE_NUMBER
@@ -1512,32 +1514,32 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         {
             if (AutoPartition)
             {
-                PPARTENTRY PartEntry = PartitionList->CurrentPartition;
-                ULONG MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;  /* in MBytes (rounded) */
-                if(!IsDiskSizeValid(PartitionList->CurrentPartition))
+#if 0
+                if (!IsDiskSizeValid(PartitionList->CurrentPartition))
                 {
                     MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
                     return SELECT_PARTITION_PAGE; /* let the user select another partition */
                 }
-
+#endif
                 CreateNewPartition(PartitionList,
-                                   MaxSize,
+                                   PartitionList->CurrentPartition->SectorCount.QuadPart,
                                    TRUE);
 
-                DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter[0];
+                DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
                 return SELECT_FILE_SYSTEM_PAGE;
             }
         }
         else
         {
-            if(!IsDiskSizeValid(PartitionList->CurrentPartition))
+#if 0
+            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
-
-            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter[0];
+#endif
+            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
             return SELECT_FILE_SYSTEM_PAGE;
         }
@@ -1547,7 +1549,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
     {
         /* Update status text */
         if (PartitionList->CurrentPartition == NULL ||
-            PartitionList->CurrentPartition->Unpartitioned == TRUE)
+            PartitionList->CurrentPartition->IsPartitioned == FALSE)
         {
             CONSOLE_SetStatusText(MUIGetString(STRING_INSTALLCREATEPARTITION));
         }
@@ -1582,26 +1584,28 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN)  /* ENTER */
         {
-            if(!IsDiskSizeValid(PartitionList->CurrentPartition))
+#if 0
+            if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_DISKSPACE, Ir, POPUP_WAIT_ANY_KEY);
                 return SELECT_PARTITION_PAGE; /* let the user select another partition */
             }
+#endif
             if (PartitionList->CurrentPartition == NULL ||
-                PartitionList->CurrentPartition->Unpartitioned == TRUE)
+                PartitionList->CurrentPartition->IsPartitioned == FALSE)
             {
                 CreateNewPartition(PartitionList,
                                    0ULL,
                                    TRUE);
             }
 
-            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter[0];
+            DestinationDriveLetter = (WCHAR)PartitionList->CurrentPartition->DriveLetter;
 
             return SELECT_FILE_SYSTEM_PAGE;
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'C')  /* C */
         {
-            if (PartitionList->CurrentPartition->Unpartitioned == FALSE)
+            if (PartitionList->CurrentPartition->IsPartitioned == TRUE)
             {
                 MUIDisplayError(ERROR_NEW_PARTITION, Ir, POPUP_WAIT_ANY_KEY);
                 return SELECT_PARTITION_PAGE;
@@ -1611,7 +1615,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         }
         else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D')  /* D */
         {
-            if (PartitionList->CurrentPartition->Unpartitioned == TRUE)
+            if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
             {
                 MUIDisplayError(ERROR_DELETE_SPACE, Ir, POPUP_WAIT_ANY_KEY);
                 return SELECT_PARTITION_PAGE;
@@ -1779,6 +1783,7 @@ CreatePartitionPage(PINPUT_RECORD Ir)
     ULONG MaxSize;
     ULONGLONG PartSize;
     ULONGLONG DiskSize;
+    ULONGLONG SectorCount;
     PCHAR Unit;
 
     if (PartitionList == NULL ||
@@ -1796,17 +1801,17 @@ CreatePartitionPage(PINPUT_RECORD Ir)
 
     CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHOOSENEWPARTITION));
 
+    DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
 #if 0
-    if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    if (DiskSize >= 10737418240) /* 10 GB */
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+        DiskSize = DiskSize / 1073741824;
         Unit = MUIGetString(STRING_GB);
     }
     else
 #endif
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
-
+        DiskSize = DiskSize / 1048576;
         if (DiskSize == 0)
             DiskSize = 1;
 
@@ -1841,7 +1846,7 @@ CreatePartitionPage(PINPUT_RECORD Ir)
 
 #if 0
     CONSOLE_PrintTextXY(8, 10, "Maximum size of the new partition is %I64u MB",
-                        PartitionList->CurrentPartition->UnpartitionedLength / (1024*1024));
+                        PartitionList->CurrentPartition->SectorCount * DiskEntry->BytesPerSector / 1048576);
 #endif
 
     CONSOLE_SetStatusText(MUIGetString(STRING_CREATEPARTITION));
@@ -1849,9 +1854,10 @@ CreatePartitionPage(PINPUT_RECORD Ir)
     PartEntry = PartitionList->CurrentPartition;
     while (TRUE)
     {
-        MaxSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;  /* in MBytes (rounded) */
+        MaxSize = (PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector) / 1048576;  /* in MBytes (rounded) */
 
-        if (MaxSize > PARTITION_MAXSIZE) MaxSize = PARTITION_MAXSIZE;
+        if (MaxSize > PARTITION_MAXSIZE)
+            MaxSize = PARTITION_MAXSIZE;
 
         ShowPartitionSizeInputBox(12, 14, xScreen - 12, 17, /* left, top, right, bottom */
                                   MaxSize, InputBuffer, &Quit, &Cancel);
@@ -1887,23 +1893,22 @@ CreatePartitionPage(PINPUT_RECORD Ir)
             if (PartSize == MaxSize)
             {
                 /* Use all of the unpartitioned disk space */
-                PartSize = PartEntry->UnpartitionedLength;
+                SectorCount = PartEntry->SectorCount.QuadPart;
             }
             else
             {
-                /* Round-up by cylinder size */
-                PartSize = (PartSize * 1024 * 1024 + DiskEntry->CylinderSize - 1) /
-                           DiskEntry->CylinderSize * DiskEntry->CylinderSize;
+                /* Calculate the sector count from the size in MB */
+                SectorCount = PartSize * 1048576 / DiskEntry->BytesPerSector;
 
                 /* But never get larger than the unpartitioned disk space */
-                if (PartSize > PartEntry->UnpartitionedLength)
-                    PartSize = PartEntry->UnpartitionedLength;
+                if (SectorCount > PartEntry->SectorCount.QuadPart)
+                    SectorCount = PartEntry->SectorCount.QuadPart;
             }
 
             DPRINT ("Partition size: %I64u bytes\n", PartSize);
 
             CreateNewPartition(PartitionList,
-                               PartSize,
+                               SectorCount,
                                FALSE);
 
             return SELECT_PARTITION_PAGE;
@@ -1923,7 +1928,6 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     ULONGLONG PartSize;
     PCHAR Unit;
     PCHAR PartType;
-    UCHAR PartNumber;
 
     if (PartitionList == NULL ||
         PartitionList->CurrentDisk == NULL ||
@@ -1935,7 +1939,6 @@ DeletePartitionPage(PINPUT_RECORD Ir)
 
     DiskEntry = PartitionList->CurrentDisk;
     PartEntry = PartitionList->CurrentPartition;
-    PartNumber = PartitionList->CurrentPartitionNumber;
 
     MUIDisplayPage(DELETE_PARTITION_PAGE);
 
@@ -1945,46 +1948,47 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     {
         PartType = MUIGetString(STRING_UNFORMATTED);
     }
-    else if (PartEntry->Unpartitioned == FALSE)
+    else if (PartEntry->IsPartitioned == TRUE)
     {
-        if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
-            (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
-            (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
-            (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
+        if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+            (PartEntry->PartitionType == PARTITION_FAT_16) ||
+            (PartEntry->PartitionType == PARTITION_HUGE) ||
+            (PartEntry->PartitionType == PARTITION_XINT13))
         {
             PartType = "FAT";
         }
-        else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
-                 (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
+        else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
+                 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
         {
             PartType = "FAT32";
         }
-        else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
+        else if (PartEntry->PartitionType == PARTITION_EXT2)
         {
             PartType = "EXT2";
         }
-        else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
+        else if (PartEntry->PartitionType == PARTITION_IFS)
         {
             PartType = "NTFS"; /* FIXME: Not quite correct! */
         }
     }
 
+    PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
 #if 0
-    if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
+    if (PartSize >= 10737418240) /* 10 GB */
     {
-        PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
+        PartSize = PartSize / 1073741824;
         Unit = MUIGetString(STRING_GB);
     }
     else
 #endif
-    if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
+    if (PartSize >= 10485760) /* 10 MB */
     {
-        PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
+        PartSize = PartSize / 1048576;
         Unit = MUIGetString(STRING_MB);
     }
     else
     {
-        PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
+        PartSize = PartSize / 1024;
         Unit = MUIGetString(STRING_KB);
     }
 
@@ -1992,9 +1996,9 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     {
         CONSOLE_PrintTextXY(6, 10,
                             MUIGetString(STRING_HDDINFOUNK2),
-                            (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                            (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
-                            PartEntry->PartInfo[PartNumber].PartitionType,
+                            (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                            (PartEntry->DriveLetter == 0) ? '-' : ':',
+                            PartEntry->PartitionType,
                             PartSize,
                             Unit);
     }
@@ -2002,24 +2006,24 @@ DeletePartitionPage(PINPUT_RECORD Ir)
     {
         CONSOLE_PrintTextXY(6, 10,
                             "   %c%c  %s    %I64u %s",
-                            (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                            (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
+                            (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                            (PartEntry->DriveLetter == 0) ? '-' : ':',
                             PartType,
                             PartSize,
                             Unit);
     }
 
+    DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
 #if 0
-    if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    if (DiskSize >= 10737418240) /* 10 GB */
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+        DiskSize = DiskSize / 1073741824;
         Unit = MUIGetString(STRING_GB);
     }
     else
 #endif
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
-
+        DiskSize = DiskSize / 1048576;
         if (DiskSize == 0)
             DiskSize = 1;
 
@@ -2085,7 +2089,6 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    UCHAR      PartNumber;
     ULONGLONG DiskSize;
     ULONGLONG PartSize;
     PCHAR DiskUnit;
@@ -2102,54 +2105,55 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 
     DiskEntry = PartitionList->CurrentDisk;
     PartEntry = PartitionList->CurrentPartition;
-    PartNumber = PartitionList->CurrentPartitionNumber;
 
     /* adjust disk size */
-    if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    DiskSize = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+    if (DiskSize >= 10737418240) /* 10 GB */
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+        DiskSize = DiskSize / 1073741824;
         DiskUnit = MUIGetString(STRING_GB);
     }
     else
     {
-        DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+        DiskSize = DiskSize / 1048576;
         DiskUnit = MUIGetString(STRING_MB);
     }
 
     /* adjust partition size */
-    if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
+    PartSize = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+    if (PartSize >= 10737418240) /* 10 GB */
     {
-        PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
+        PartSize = PartSize / 1073741824;
         PartUnit = MUIGetString(STRING_GB);
     }
     else
     {
-        PartSize = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
+        PartSize = PartSize / 1048576;
         PartUnit = MUIGetString(STRING_MB);
     }
 
     /* adjust partition type */
-    if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
-        (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
-        (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
-        (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
+    if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+        (PartEntry->PartitionType == PARTITION_FAT_16) ||
+        (PartEntry->PartitionType == PARTITION_HUGE) ||
+        (PartEntry->PartitionType == PARTITION_XINT13))
     {
         PartType = "FAT";
     }
-    else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
-             (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
+    else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
+             (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
     {
         PartType = "FAT32";
     }
-    else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
+    else if (PartEntry->PartitionType == PARTITION_EXT2)
     {
         PartType = "EXT2";
     }
-    else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
+    else if (PartEntry->PartitionType == PARTITION_IFS)
     {
         PartType = "NTFS"; /* FIXME: Not quite correct! */
     }
-    else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_ENTRY_UNUSED)
+    else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED)
     {
         PartType = MUIGetString(STRING_FORMATUNUSED);
     }
@@ -2164,7 +2168,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 
 #if 0
         CONSOLE_PrintTextXY(8, 10, "Partition %lu (%I64u %s) %s of",
-                            PartEntry->PartInfo[PartNumber].PartitionNumber,
+                            PartEntry->PartitionNumber,
                             PartSize,
                             PartUnit,
                             PartType);
@@ -2197,9 +2201,9 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         {
             CONSOLE_PrintTextXY(8, 10,
                                 MUIGetString(STRING_HDDINFOUNK4),
-                                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
-                                PartEntry->PartInfo[PartNumber].PartitionType,
+                                (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                                (PartEntry->DriveLetter == 0) ? '-' : ':',
+                                PartEntry->PartitionType,
                                 PartSize,
                                 PartUnit);
         }
@@ -2207,8 +2211,8 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         {
             CONSOLE_PrintTextXY(8, 10,
                                 "%c%c  %s    %I64u %s",
-                                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                                (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
+                                (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                                (PartEntry->DriveLetter == 0) ? '-' : ':',
                                 PartType,
                                 PartSize,
                                 PartUnit);
@@ -2237,6 +2241,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
 
         /* FIXME: Add file systems to list */
     }
+
     DrawFileSystemList(FileSystemList);
 
     if (RepairUpdateFlag)
@@ -2305,12 +2310,11 @@ static ULONG
 FormatPartitionPage(PINPUT_RECORD Ir)
 {
     WCHAR PathBuffer[MAX_PATH];
+    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    UCHAR PartNum;
     NTSTATUS Status;
 
 #ifndef NDEBUG
-    PDISKENTRY DiskEntry;
     ULONG Line;
     ULONG i;
     PLIST_ENTRY Entry;
@@ -2326,11 +2330,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
         return QUIT_PAGE;
     }
 
-#ifndef NDEBUG
     DiskEntry = PartitionList->CurrentDisk;
-#endif
     PartEntry = PartitionList->CurrentPartition;
-    PartNum = PartitionList->CurrentPartitionNumber;
 
     while (TRUE)
     {
@@ -2355,50 +2356,55 @@ FormatPartitionPage(PINPUT_RECORD Ir)
 
             if (wcscmp(FileSystemList->Selected->FileSystem, L"FAT") == 0)
             {
-                if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (4200LL * 1024LL))
+                if (PartEntry->SectorCount.QuadPart < 8192)
                 {
                     /* FAT12 CHS partition (disk is smaller than 4.1MB) */
-                    PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_12;
+                    PartEntry->PartitionType = PARTITION_FAT_12;
                 }
-                else if (PartEntry->PartInfo[PartNum].StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL))
+                else if (PartEntry->StartSector.QuadPart < 1450560)
                 {
                     /* Partition starts below the 8.4GB boundary ==> CHS partition */
 
-                    if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (32LL * 1024LL * 1024LL))
+                    if (PartEntry->SectorCount.QuadPart < 65536)
                     {
                         /* FAT16 CHS partition (partiton size < 32MB) */
-                        PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT_16;
+                        PartEntry->PartitionType = PARTITION_FAT_16;
                     }
-                    else if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
+                    else if (PartEntry->SectorCount.QuadPart < 1048576)
                     {
                         /* FAT16 CHS partition (partition size < 512MB) */
-                        PartEntry->PartInfo[PartNum].PartitionType = PARTITION_HUGE;
+                        PartEntry->PartitionType = PARTITION_HUGE;
                     }
                     else
                     {
                         /* FAT32 CHS partition (partition size >= 512MB) */
-                        PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32;
+                        PartEntry->PartitionType = PARTITION_FAT32;
                     }
                 }
                 else
                 {
                     /* Partition starts above the 8.4GB boundary ==> LBA partition */
 
-                    if (PartEntry->PartInfo[PartNum].PartitionLength.QuadPart < (512LL * 1024LL * 1024LL))
+                    if (PartEntry->SectorCount.QuadPart < 1048576)
                     {
                         /* FAT16 LBA partition (partition size < 512MB) */
-                        PartEntry->PartInfo[PartNum].PartitionType = PARTITION_XINT13;
+                        PartEntry->PartitionType = PARTITION_XINT13;
                     }
                     else
                     {
                         /* FAT32 LBA partition (partition size >= 512MB) */
-                        PartEntry->PartInfo[PartNum].PartitionType = PARTITION_FAT32_XINT13;
+                        PartEntry->PartitionType = PARTITION_FAT32_XINT13;
                     }
                 }
+
+                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
             }
 #if 0
             else if (wcscmp(FileSystemList->Selected->FileSystem, L"EXT2") == 0)
+            {
                 PartEntry->PartInfo[PartNum].PartitionType = PARTITION_EXT2;
+                DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartEntry->PartitionType;
+            }
 #endif
             else if (!FileSystemList->Selected->FormatFunc)
                 return QUIT_PAGE;
@@ -2414,27 +2420,21 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             DiskEntry = PartitionList->CurrentDisk;
             Entry = DiskEntry->PartListHead.Flink;
 
-            while (Entry != &DiskEntry->PartListHead)
+            while (Entry != &DiskEntry->PrimaryPartListHead)
             {
                 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
 
-                if (PartEntry->Unpartitioned == FALSE)
+                if (PartEntry->IsPartitioned == TRUE)
                 {
-                    for (i = 0; i < 4; i++)
-                    {
-                        CONSOLE_PrintTextXY(6, Line,
-                                            "%2u:  %2u  %c  %12I64u  %12I64u  %2u  %c",
-                                            i,
-                                            PartEntry->PartInfo[i].PartitionNumber,
-                                            PartEntry->PartInfo[i].BootIndicator ? 'A' : '-',
-                                            PartEntry->PartInfo[i].StartingOffset.QuadPart,
-                                            PartEntry->PartInfo[i].PartitionLength.QuadPart,
-                                            PartEntry->PartInfo[i].PartitionType,
-                                            PartEntry->PartInfo[i].RewritePartition ? '*' : ' ');
-
-                        Line++;
-                    }
-
+                    CONSOLE_PrintTextXY(6, Line,
+                                        "%2u:  %2u  %c  %12I64u  %12I64u  %2u  %c",
+                                        i,
+                                        PartEntry->PartitionNumber,
+                                        PartEntry->BootIndicator ? 'A' : '-',
+                                        PartEntry->StartSector.QuadPart,
+                                        PartEntry->SectorCount.QuadPart,
+                                        PartEntry->PartitionType,
+                                        PartEntry->Dirty ? '*' : ' ');
                     Line++;
                 }
 
@@ -2445,6 +2445,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             PartEntry = PartitionList->CurrentPartition;
 #endif
 
+            CheckActiveBootPartition(PartitionList);
+
             if (WritePartitionsToDisk(PartitionList) == FALSE)
             {
                 DPRINT("WritePartitionsToDisk() failed\n");
@@ -2457,7 +2459,7 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             swprintf(PathBuffer,
                      L"\\Device\\Harddisk%lu\\Partition%lu",
                      PartitionList->CurrentDisk->DiskNumber,
-                     PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
+                     PartitionList->CurrentPartition->PartitionNumber);
             RtlCreateUnicodeString(&DestinationRootPath,
                                    PathBuffer);
             DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
@@ -2475,7 +2477,6 @@ FormatPartitionPage(PINPUT_RECORD Ir)
 
                 PartEntry->New = FALSE;
 
-                CheckActiveBootPartition(PartitionList);
             }
 
 #ifndef NDEBUG
@@ -2500,7 +2501,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     WCHAR PathBuffer[MAX_PATH];
     CHAR Buffer[MAX_PATH];
     NTSTATUS Status;
-    UCHAR PartNum = PartitionList->CurrentPartitionNumber;
 
     /* FIXME: code duplicated in FormatPartitionPage */
     /* Set DestinationRootPath */
@@ -2508,7 +2508,7 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     swprintf(PathBuffer,
              L"\\Device\\Harddisk%lu\\Partition%lu",
     PartitionList->CurrentDisk->DiskNumber,
-    PartitionList->CurrentPartition->PartInfo[PartNum].PartitionNumber);
+    PartitionList->CurrentPartition->PartitionNumber);
     RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
     DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
 
@@ -2574,8 +2574,7 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 static PAGE_NUMBER
 InstallDirectoryPage1(PWCHAR InstallDir,
                       PDISKENTRY DiskEntry,
-                      PPARTENTRY PartEntry,
-                      UCHAR PartNum)
+                      PPARTENTRY PartEntry)
 {
     WCHAR PathBuffer[MAX_PATH];
 
@@ -2599,7 +2598,7 @@ InstallDirectoryPage1(PWCHAR InstallDir,
     swprintf(PathBuffer,
              L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
              DiskEntry->BiosDiskNumber,
-             PartEntry->PartInfo[PartNum].PartitionNumber);
+             PartEntry->PartitionNumber);
 
     if (InstallDir[0] != L'\\')
         wcscat(PathBuffer, L"\\");
@@ -2643,8 +2642,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
     {
         return InstallDirectoryPage1(InstallDir,
                                      DiskEntry,
-                                     PartEntry,
-                                     PartitionList->CurrentPartitionNumber);
+                                     PartEntry);
     }
 
     while (TRUE)
@@ -2663,8 +2661,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
         {
             return InstallDirectoryPage1(InstallDir,
                                          DiskEntry,
-                                         PartEntry,
-                                         PartitionList->CurrentPartitionNumber);
+                                         PartEntry);
         }
         else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */
         {
@@ -3382,14 +3379,12 @@ BootLoaderPage(PINPUT_RECORD Ir)
     swprintf(PathBuffer,
              L"\\Device\\Harddisk%lu\\Partition%lu",
              PartitionList->ActiveBootDisk->DiskNumber,
-             PartitionList->ActiveBootPartition->
-                PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionNumber);
+             PartitionList->ActiveBootPartition->PartitionNumber);
     RtlCreateUnicodeString(&SystemRootPath,
                            PathBuffer);
     DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
 
-    PartitionType = PartitionList->ActiveBootPartition->
-        PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
+    PartitionType = PartitionList->ActiveBootPartition->PartitionType;
 
     if (IsUnattendedSetup)
     {
@@ -3573,8 +3568,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
     UCHAR PartitionType;
     NTSTATUS Status;
 
-    PartitionType = PartitionList->ActiveBootPartition->
-                    PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
+    PartitionType = PartitionList->ActiveBootPartition->PartitionType;
 
     Status = InstallVBRToPartition(&SystemRootPath,
                                    &SourceRootPath,
@@ -3598,8 +3592,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     WCHAR SourceMbrPathBuffer[MAX_PATH];
 
     /* Step 1: Write the VBR */
-    PartitionType = PartitionList->ActiveBootPartition->
-        PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
+    PartitionType = PartitionList->ActiveBootPartition->PartitionType;
 
     Status = InstallVBRToPartition(&SystemRootPath,
                                    &SourceRootPath,
index c81ce91..3312e21 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+#define DUMP_PARTITION_TABLE
+
 /* FUNCTIONS ****************************************************************/
 
+#ifdef DUMP_PARTITION_TABLE
+static
+VOID
+DumpPartitionTable(
+    PDISKENTRY DiskEntry)
+{
+    PPARTITION_INFORMATION PartitionInfo;
+    ULONG i;
+
+    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');
+    }
+}
+#endif
+
+
+ULONGLONG
+Align(
+    IN ULONGLONG Value,
+    IN ULONG Alignment)
+{
+    ULONGLONG Temp;
+
+    Temp = Value / Alignment;
+
+    return Temp * Alignment;
+}
+
+
+ULONGLONG
+RoundingDivide(
+   IN ULONGLONG Dividend,
+   IN ULONGLONG Divisor)
+{
+    return (Dividend + Divisor / 2) / Divisor;
+}
+
+
 static
 VOID
 GetDriverName(
@@ -70,15 +120,14 @@ GetDriverName(
 
 static
 VOID
-AssignDriverLetters(
+AssignDriveLetters(
     PPARTLIST List)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
     PLIST_ENTRY Entry1;
-    //PLIST_ENTRY Entry2;
+    PLIST_ENTRY Entry2;
     CHAR Letter;
-    UCHAR i;
 
     Letter = 'C';
 
@@ -88,34 +137,29 @@ AssignDriverLetters(
     {
         DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
-        if (!IsListEmpty(&DiskEntry->PartListHead))
+        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+        while (Entry2 != &DiskEntry->PrimaryPartListHead)
         {
-            PartEntry = CONTAINING_RECORD(DiskEntry->PartListHead.Flink,
-                                          PARTENTRY,
-                                          ListEntry);
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-            for (i = 0; i < 4; i++)
-                PartEntry->DriveLetter[i] = 0;
+            PartEntry->DriveLetter = 0;
 
-            if (PartEntry->Unpartitioned == FALSE)
+            if (PartEntry->IsPartitioned &&
+                !IsContainerPartition(PartEntry->PartitionType))
             {
-                for (i = 0; i < 4; i++)
+                if (IsRecognizedPartition(PartEntry->PartitionType) ||
+                    (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+                     PartEntry->SectorCount.QuadPart != 0LL))
                 {
-                    if (IsContainerPartition(PartEntry->PartInfo[i].PartitionType))
-                        continue;
-
-                    if (IsRecognizedPartition(PartEntry->PartInfo[i].PartitionType) ||
-                        (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
-                         PartEntry->PartInfo[i].PartitionLength.QuadPart != 0LL))
+                    if (Letter <= 'Z')
                     {
-                        if (Letter <= 'Z')
-                        {
-                            PartEntry->DriveLetter[i] = Letter;
-                            Letter++;
-                        }
+                        PartEntry->DriveLetter = Letter;
+                        Letter++;
                     }
                 }
             }
+
+            Entry2 = Entry2->Flink;
         }
 
         Entry1 = Entry1->Flink;
@@ -172,287 +216,41 @@ UpdatePartitionNumbers(
 {
     PPARTENTRY PartEntry;
     PLIST_ENTRY Entry;
-    ULONG PartNumber;
-    ULONG i;
+//    ULONG PartitionNumber = 1;
+    ULONG PartitionIndex = 0;
 
-    PartNumber = 1;
-    Entry = DiskEntry->PartListHead.Flink;
-    while (Entry != &DiskEntry->PartListHead)
+    Entry = DiskEntry->PrimaryPartListHead.Flink;
+    while (Entry != &DiskEntry->PrimaryPartListHead)
     {
         PartEntry = CONTAINING_RECORD(Entry,
                                       PARTENTRY,
                                       ListEntry);
 
-        if (PartEntry->Unpartitioned == TRUE)
+        if (PartEntry->IsPartitioned == FALSE)
         {
-            for (i = 0; i < 4; i++)
-            {
-                PartEntry->PartInfo[i].PartitionNumber = 0;
-            }
+//            PartEntry->PartitionNumber = 0;
+            PartEntry->PartitionIndex = (ULONG)-1;
         }
         else
         {
-            for (i = 0; i < 4; i++)
-            {
-                if (IsContainerPartition(PartEntry->PartInfo[i].PartitionType))
-                {
-                    PartEntry->PartInfo[i].PartitionNumber = 0;
-                }
-                else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
-                         PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
-                {
-                    PartEntry->PartInfo[i].PartitionNumber = 0;
-                }
-                else
-                {
-                    PartEntry->PartInfo[i].PartitionNumber = PartNumber;
-                    PartNumber++;
-                }
-            }
-        }
-
-        Entry = Entry->Flink;
-    }
-}
-
-
-static
-VOID
-AddPartitionToList(
-    ULONG DiskNumber,
-    PDISKENTRY DiskEntry,
-    DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
-{
-    PPARTENTRY PartEntry;
-    ULONG i;
-    ULONG j;
-
-    for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
-    {
-        for (j = 0; j < 4; j++)
-        {
-            if (LayoutBuffer->PartitionEntry[i+j].PartitionType != PARTITION_ENTRY_UNUSED ||
-                LayoutBuffer->PartitionEntry[i+j].PartitionLength.QuadPart != 0ULL)
-            {
-                break;
-            }
-        }
-
-        if (j >= 4)
-        {
-            continue;
-        }
-
-        PartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
-                                                0,
-                                                sizeof(PARTENTRY));
-        if (PartEntry == NULL)
-        {
-            return;
-        }
-
-        RtlZeroMemory(PartEntry,
-                      sizeof(PARTENTRY));
-
-        PartEntry->Unpartitioned = FALSE;
-
-        for (j = 0; j < 4; j++)
-        {
-            RtlCopyMemory(&PartEntry->PartInfo[j],
-                          &LayoutBuffer->PartitionEntry[i+j],
-                          sizeof(PARTITION_INFORMATION));
-        }
-
-        if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
-        {
-            PartEntry->FormatState = Unformatted;
-        }
-        else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
-                 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
-                 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
-                 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
-                 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
-                 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
-        {
-#if 0
-            if (CheckFatFormat())
-            {
-                PartEntry->FormatState = Preformatted;
-            }
-            else
-            {
-                PartEntry->FormatState = Unformatted;
-            }
-#endif
-            PartEntry->FormatState = Preformatted;
-        }
-        else if (PartEntry->PartInfo[0].PartitionType == PARTITION_EXT2)
-        {
-#if 0
-            if (CheckExt2Format())
-            {
-                PartEntry->FormatState = Preformatted;
-            }
-            else
-            {
-                PartEntry->FormatState = Unformatted;
-            }
-#endif
-            PartEntry->FormatState = Preformatted;
-        }
-        else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
-        {
-#if 0
-            if (CheckNtfsFormat())
+            if (IsContainerPartition(PartEntry->PartitionType))
             {
-                PartEntry->FormatState = Preformatted;
+//                PartEntry->PartitionNumber = 0;
             }
-            else if (CheckHpfsFormat())
+            else if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
+                     PartEntry->SectorCount.QuadPart == 0ULL)
             {
-                PartEntry->FormatState = Preformatted;
+//                PartEntry->PartitionNumber = 0;
             }
             else
             {
-                PartEntry->FormatState = Unformatted;
-            }
-#endif
-            PartEntry->FormatState = Preformatted;
-        }
-        else
-        {
-            PartEntry->FormatState = UnknownFormat;
-        }
-
-        InsertTailList(&DiskEntry->PartListHead,
-                       &PartEntry->ListEntry);
-    }
-}
-
-
-static
-VOID
-ScanForUnpartitionedDiskSpace(
-    PDISKENTRY DiskEntry)
-{
-    ULONGLONG LastStartingOffset;
-    ULONGLONG LastPartitionLength;
-    ULONGLONG LastUnusedPartitionLength;
-    PPARTENTRY PartEntry;
-    PPARTENTRY NewPartEntry;
-    PLIST_ENTRY Entry;
-    ULONG i;
-    ULONG j;
-
-    if (IsListEmpty (&DiskEntry->PartListHead))
-    {
-        /* Create a partition table that represents the empty disk */
-        PartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
-                     0,
-                     sizeof(PARTENTRY));
-        if (PartEntry == NULL)
-            return;
-
-        RtlZeroMemory(PartEntry,
-                      sizeof(PARTENTRY));
-
-        PartEntry->Unpartitioned = TRUE;
-        PartEntry->UnpartitionedOffset = 0ULL;
-        PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
-
-        PartEntry->FormatState = Unformatted;
-
-        InsertTailList(&DiskEntry->PartListHead,
-                       &PartEntry->ListEntry);
-    }
-    else
-    {
-        /* Start partition at head 1, cylinder 0 */
-        LastStartingOffset = DiskEntry->TrackSize;
-        LastPartitionLength = 0ULL;
-        LastUnusedPartitionLength = 0ULL;
-
-        i = 0;
-        Entry = DiskEntry->PartListHead.Flink;
-        while (Entry != &DiskEntry->PartListHead)
-        {
-            PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-
-            for (j = 0; j < 4; j++)
-            {
-                if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
-                    (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
-                     PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
-                {
-                    LastUnusedPartitionLength =
-                        PartEntry->PartInfo[j].StartingOffset.QuadPart -
-                        (LastStartingOffset + LastPartitionLength);
-
-                    if (PartEntry->PartInfo[j].StartingOffset.QuadPart > (LastStartingOffset + LastPartitionLength) &&
-                        LastUnusedPartitionLength >= DiskEntry->CylinderSize)
-                    {
-                        DPRINT("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
-
-                        NewPartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
-                                                                   0,
-                                                                   sizeof(PARTENTRY));
-                        if (NewPartEntry == NULL)
-                            return;
-
-                        RtlZeroMemory(NewPartEntry,
-                                      sizeof(PARTENTRY));
-
-                        NewPartEntry->Unpartitioned = TRUE;
-                        NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
-                        NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
-                        if (j == 0)
-                            NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;
-
-                        NewPartEntry->FormatState = Unformatted;
-
-                        /* Insert the table into the list */
-                        InsertTailList(&PartEntry->ListEntry,
-                                       &NewPartEntry->ListEntry);
-                    }
-
-                    LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
-                    LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
-                }
+//                PartEntry->PartitionNumber = PartitionNumber++;
             }
 
-            i += 4;
-            Entry = Entry->Flink;
+            PartEntry->PartitionIndex = PartitionIndex++;
         }
 
-        /* Check for trailing unpartitioned disk space */
-        if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
-        {
-            /* Round-down to cylinder size */
-            LastUnusedPartitionLength =
-                (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength))
-                & ~(DiskEntry->CylinderSize - 1);
-
-            if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
-            {
-                DPRINT("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
-
-                NewPartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
-                                                           0,
-                                                           sizeof(PARTENTRY));
-                if (NewPartEntry == NULL)
-                    return;
-
-                RtlZeroMemory(NewPartEntry,
-                              sizeof(PARTENTRY));
-
-                NewPartEntry->Unpartitioned = TRUE;
-                NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
-                NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
-
-                /* Append the table to the list */
-                InsertTailList(&DiskEntry->PartListHead,
-                               &NewPartEntry->ListEntry);
-            }
-        }
+        Entry = Entry->Flink;
     }
 }
 
@@ -722,119 +520,418 @@ EnumerateBiosDiskEntries(
 
 static
 VOID
-AddDiskToList(
-    HANDLE FileHandle,
+AddPrimaryPartitionToDisk(
     ULONG DiskNumber,
-    PPARTLIST List)
+    PDISKENTRY DiskEntry,
+    ULONG PartitionIndex)
 {
-    DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
-    DISK_GEOMETRY DiskGeometry;
-    SCSI_ADDRESS ScsiAddress;
-    PDISKENTRY DiskEntry;
-    IO_STATUS_BLOCK Iosb;
-    NTSTATUS Status;
-    PPARTITION_SECTOR Mbr;
-    PULONG Buffer;
-    LARGE_INTEGER FileOffset;
-    WCHAR Identifier[20];
-    ULONG Checksum;
-    ULONG Signature;
-    ULONG i;
-    PLIST_ENTRY ListEntry;
-    PBIOSDISKENTRY BiosDiskEntry;
-    ULONG LayoutBufferSize;
+    PPARTITION_INFORMATION PartitionInfo;
+    PPARTENTRY PartEntry;
 
-    Status = NtDeviceIoControlFile(FileHandle,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &Iosb,
-                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
-                                   NULL,
-                                   0,
-                                   &DiskGeometry,
-                                   sizeof(DISK_GEOMETRY));
-    if (!NT_SUCCESS(Status))
-    {
-        return;
-    }
+    PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
 
-    if (DiskGeometry.MediaType != FixedMedia &&
-        DiskGeometry.MediaType != RemovableMedia)
+    PartEntry = RtlAllocateHeap(ProcessHeap,
+                                HEAP_ZERO_MEMORY,
+                                sizeof(PARTENTRY));
+    if (PartEntry == NULL)
     {
         return;
     }
 
-    Status = NtDeviceIoControlFile(FileHandle,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &Iosb,
-                                   IOCTL_SCSI_GET_ADDRESS,
-                                   NULL,
-                                   0,
-                                   &ScsiAddress,
-                                   sizeof(SCSI_ADDRESS));
-    if (!NT_SUCCESS(Status))
-    {
-        return;
-    }
+    PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
+    PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
 
-    Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
-                                             0,
-                                             DiskGeometry.BytesPerSector);
-    if (Mbr == NULL)
-    {
-        return;
-    }
+    PartEntry->BootIndicator = PartitionInfo->BootIndicator;
+    PartEntry->PartitionType = PartitionInfo->PartitionType;
+    PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
 
-    FileOffset.QuadPart = 0;
-    Status = NtReadFile(FileHandle,
-                        NULL,
-                        NULL,
-                        NULL,
-                        &Iosb,
-                        (PVOID)Mbr,
-                        DiskGeometry.BytesPerSector,
-                        &FileOffset,
-                        NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    Mbr);
-        DPRINT1("NtReadFile failed, status=%x\n", Status);
-        return;
-    }
-    Signature = Mbr->Signature;
+    PartEntry->IsPartitioned = TRUE;
+    PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+    PartEntry->PartitionIndex = PartitionIndex;
 
-    /* Calculate the MBR checksum */
-    Checksum = 0;
-    Buffer = (PULONG)Mbr;
-    for (i = 0; i < 128; i++)
+    if (IsContainerPartition(PartEntry->PartitionType))
     {
-        Checksum += Buffer[i];
+        PartEntry->FormatState = Unformatted;
     }
-    Checksum = ~Checksum + 1;
-
+    else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+             (PartEntry->PartitionType == PARTITION_FAT_16) ||
+             (PartEntry->PartitionType == PARTITION_HUGE) ||
+             (PartEntry->PartitionType == PARTITION_XINT13) ||
+             (PartEntry->PartitionType == PARTITION_FAT32) ||
+             (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
+    {
+#if 0
+        if (CheckFatFormat())
+        {
+            PartEntry->FormatState = Preformatted;
+        }
+        else
+        {
+            PartEntry->FormatState = Unformatted;
+        }
+#endif
+        PartEntry->FormatState = Preformatted;
+    }
+    else if (PartEntry->PartitionType == PARTITION_EXT2)
+    {
+#if 0
+        if (CheckExt2Format())
+        {
+            PartEntry->FormatState = Preformatted;
+        }
+        else
+        {
+            PartEntry->FormatState = Unformatted;
+        }
+#endif
+        PartEntry->FormatState = Preformatted;
+    }
+    else if (PartEntry->PartitionType == PARTITION_IFS)
+    {
+#if 0
+        if (CheckNtfsFormat())
+        {
+            PartEntry->FormatState = Preformatted;
+        }
+        else if (CheckHpfsFormat())
+        {
+            PartEntry->FormatState = Preformatted;
+        }
+        else
+        {
+            PartEntry->FormatState = Unformatted;
+        }
+#endif
+        PartEntry->FormatState = Preformatted;
+    }
+    else
+    {
+        PartEntry->FormatState = UnknownFormat;
+    }
+
+    InsertTailList(&DiskEntry->PrimaryPartListHead,
+                   &PartEntry->ListEntry);
+}
+
+
+static
+VOID
+ScanForUnpartitionedDiskSpace(
+    PDISKENTRY DiskEntry)
+{
+    ULONGLONG LastStartSector;
+    ULONGLONG LastSectorCount;
+    ULONGLONG LastUnusedSectorCount;
+    PPARTENTRY PartEntry;
+    PPARTENTRY NewPartEntry;
+    PLIST_ENTRY Entry;
+
+    DPRINT1("ScanForUnpartitionedDiskSpace()\n");
+
+    if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+    {
+        DPRINT1("No primary partition!\n");
+
+        /* Create a partition table that represents the empty disk */
+        NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                       HEAP_ZERO_MEMORY,
+                                       sizeof(PARTENTRY));
+        if (NewPartEntry == NULL)
+            return;
+
+        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->FormatState = Unformatted;
+
+        InsertTailList(&DiskEntry->PrimaryPartListHead,
+                       &NewPartEntry->ListEntry);
+
+        return;
+    }
+
+    /* Start partition at head 1, cylinder 0 */
+    LastStartSector = DiskEntry->SectorsPerTrack;
+    LastSectorCount = 0ULL;
+    LastUnusedSectorCount = 0ULL;
+
+    Entry = DiskEntry->PrimaryPartListHead.Flink;
+    while (Entry != &DiskEntry->PrimaryPartListHead)
+    {
+        PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+        if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
+            PartEntry->SectorCount.QuadPart != 0ULL)
+        {
+            LastUnusedSectorCount =
+                PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
+
+            if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
+                LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+            {
+                DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
+
+                NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                               HEAP_ZERO_MEMORY,
+                                               sizeof(PARTENTRY));
+                if (NewPartEntry == NULL)
+                    return;
+
+                NewPartEntry->DiskEntry = DiskEntry;
+
+                NewPartEntry->IsPartitioned = FALSE;
+                NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
+                NewPartEntry->SectorCount.QuadPart = 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);
+
+                NewPartEntry->FormatState = Unformatted;
+
+                /* Insert the table into the list */
+                InsertTailList(&PartEntry->ListEntry,
+                               &NewPartEntry->ListEntry);
+            }
+
+            LastStartSector = PartEntry->StartSector.QuadPart;
+            LastSectorCount = PartEntry->SectorCount.QuadPart;
+        }
+
+        Entry = Entry->Flink;
+    }
+
+    /* Check for trailing unpartitioned disk space */
+    if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
+    {
+        LastUnusedSectorCount = Align(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
+
+        if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+        {
+            DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
+
+            NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           sizeof(PARTENTRY));
+            if (NewPartEntry == NULL)
+                return;
+
+            NewPartEntry->DiskEntry = DiskEntry;
+
+            NewPartEntry->IsPartitioned = FALSE;
+            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);
+
+            NewPartEntry->FormatState = Unformatted;
+
+            /* Append the table to the list */
+            InsertTailList(&DiskEntry->PrimaryPartListHead,
+                           &NewPartEntry->ListEntry);
+        }
+    }
+
+    DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
+}
+
+
+static
+VOID
+SetDiskSignature(
+    IN PPARTLIST List,
+    IN PDISKENTRY DiskEntry)
+{
+    LARGE_INTEGER SystemTime;
+    TIME_FIELDS TimeFields;
+    PLIST_ENTRY Entry2;
+    PDISKENTRY DiskEntry2;
+    PUCHAR Buffer;
+
+    Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
+
+    while (1)
+    {
+        NtQuerySystemTime(&SystemTime);
+        RtlTimeToTimeFields(&SystemTime, &TimeFields);
+
+        Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
+        Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
+        Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
+        Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
+
+        if (DiskEntry->LayoutBuffer->Signature == 0)
+        {
+            continue;
+        }
+
+        /* check if the signature already exist */
+        /* FIXME:
+         *   Check also signatures from disks, which are
+         *   not visible (bootable) by the bios.
+         */
+        Entry2 = List->DiskListHead.Flink;
+        while (Entry2 != &List->DiskListHead)
+        {
+            DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
+
+            if (DiskEntry != DiskEntry2 &&
+                DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
+                break;
+
+            Entry2 = Entry2->Flink;
+        }
+
+        if (Entry2 == &List->DiskListHead)
+            break;
+    }
+}
+
+
+static
+VOID
+UpdateDiskSignatures(
+    PPARTLIST List)
+{
+    PLIST_ENTRY Entry;
+    PDISKENTRY DiskEntry;
+
+    /* Print partition lines*/
+    Entry = List->DiskListHead.Flink;
+    while (Entry != &List->DiskListHead)
+    {
+        DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
+
+        if (DiskEntry->LayoutBuffer &&
+            DiskEntry->LayoutBuffer->Signature == 0)
+        {
+            SetDiskSignature(List, DiskEntry);
+            DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
+        }
+
+        Entry = Entry->Flink;
+    }
+}
+
+
+static
+VOID
+AddDiskToList(
+    HANDLE FileHandle,
+    ULONG DiskNumber,
+    PPARTLIST List)
+{
+    DISK_GEOMETRY DiskGeometry;
+    SCSI_ADDRESS ScsiAddress;
+    PDISKENTRY DiskEntry;
+    IO_STATUS_BLOCK Iosb;
+    NTSTATUS Status;
+    PPARTITION_SECTOR Mbr;
+    PULONG Buffer;
+    LARGE_INTEGER FileOffset;
+    WCHAR Identifier[20];
+    ULONG Checksum;
+    ULONG Signature;
+    ULONG i;
+    PLIST_ENTRY ListEntry;
+    PBIOSDISKENTRY BiosDiskEntry;
+    ULONG LayoutBufferSize;
+
+    Status = NtDeviceIoControlFile(FileHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &Iosb,
+                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                   NULL,
+                                   0,
+                                   &DiskGeometry,
+                                   sizeof(DISK_GEOMETRY));
+    if (!NT_SUCCESS(Status))
+    {
+        return;
+    }
+
+    if (DiskGeometry.MediaType != FixedMedia &&
+        DiskGeometry.MediaType != RemovableMedia)
+    {
+        return;
+    }
+
+    Status = NtDeviceIoControlFile(FileHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &Iosb,
+                                   IOCTL_SCSI_GET_ADDRESS,
+                                   NULL,
+                                   0,
+                                   &ScsiAddress,
+                                   sizeof(SCSI_ADDRESS));
+    if (!NT_SUCCESS(Status))
+    {
+        return;
+    }
+
+    Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
+                                             0,
+                                             DiskGeometry.BytesPerSector);
+    if (Mbr == NULL)
+    {
+        return;
+    }
+
+    FileOffset.QuadPart = 0;
+    Status = NtReadFile(FileHandle,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &Iosb,
+                        (PVOID)Mbr,
+                        DiskGeometry.BytesPerSector,
+                        &FileOffset,
+                        NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeHeap(ProcessHeap,
+                    0,
+                    Mbr);
+        DPRINT1("NtReadFile failed, status=%x\n", Status);
+        return;
+    }
+    Signature = Mbr->Signature;
+
+    /* Calculate the MBR checksum */
+    Checksum = 0;
+    Buffer = (PULONG)Mbr;
+    for (i = 0; i < 128; i++)
+    {
+        Checksum += Buffer[i];
+    }
+    Checksum = ~Checksum + 1;
+
     swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
     DPRINT("Identifier: %S\n", Identifier);
 
-    DiskEntry = (PDISKENTRY)RtlAllocateHeap(ProcessHeap,
-                                            0,
-                                            sizeof(DISKENTRY));
+    DiskEntry = RtlAllocateHeap(ProcessHeap,
+                                HEAP_ZERO_MEMORY,
+                                sizeof(DISKENTRY));
     if (DiskEntry == NULL)
     {
         return;
     }
 
-    DiskEntry->Checksum = Checksum;
-    DiskEntry->Signature = Signature;
-    if (Signature == 0)
-    {
-        /* If we have no signature, set the disk to dirty. WritePartitionsToDisk creates a new signature */
-        DiskEntry->Modified = TRUE;
-    }
+//    DiskEntry->Checksum = Checksum;
+//    DiskEntry->Signature = Signature;
     DiskEntry->BiosFound = FALSE;
 
     /* Check if this disk has a valid MBR */
@@ -885,27 +982,27 @@ AddDiskToList(
 #endif
     }
 
-    InitializeListHead(&DiskEntry->PartListHead);
+    InitializeListHead(&DiskEntry->PrimaryPartListHead);
+    InitializeListHead(&DiskEntry->ExtendedPartListHead);
 
     DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
     DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
     DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
     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);
-
-    DiskEntry->TrackSize =
-        (ULONGLONG)DiskGeometry.SectorsPerTrack *
-        (ULONGLONG)DiskGeometry.BytesPerSector;
-    DiskEntry->CylinderSize =
-        (ULONGLONG)DiskGeometry.TracksPerCylinder *
-        DiskEntry->TrackSize;
-    DiskEntry->DiskSize =
-        DiskGeometry.Cylinders.QuadPart *
-        DiskEntry->CylinderSize;
+    DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
+    DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
+    DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
+    DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
+
+    DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
+                                      (ULONGLONG)DiskGeometry.TracksPerCylinder *
+                                      (ULONGLONG)DiskGeometry.SectorsPerTrack;
+
+    DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
+
+    DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount);
+    DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
 
     DiskEntry->DiskNumber = DiskNumber;
     DiskEntry->Port = ScsiAddress.PortNumber;
@@ -922,10 +1019,10 @@ AddDiskToList(
      */
     LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
                        ((56 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
-    LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap,
-                    0,
-                    LayoutBufferSize);
-    if (LayoutBuffer == NULL)
+    DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
+                                              HEAP_ZERO_MEMORY,
+                                              LayoutBufferSize);
+    if (DiskEntry->LayoutBuffer == NULL)
     {
         return;
     }
@@ -938,25 +1035,49 @@ AddDiskToList(
                                    IOCTL_DISK_GET_DRIVE_LAYOUT,
                                    NULL,
                                    0,
-                                   LayoutBuffer,
+                                   DiskEntry->LayoutBuffer,
                                    LayoutBufferSize);
     if (NT_SUCCESS(Status))
     {
-        if (LayoutBuffer->PartitionCount == 0)
+#ifdef DUMP_PARTITION_TABLE
+        DumpPartitionTable(DiskEntry);
+#endif
+
+        if (DiskEntry->LayoutBuffer->PartitionCount == 0)
         {
             DiskEntry->NewDisk = TRUE;
-        }
+            DiskEntry->LayoutBuffer->PartitionCount = 4;
 
-        AddPartitionToList(DiskNumber,
-                           DiskEntry,
-                           LayoutBuffer);
+            for (i = 0; i < 4; i++)
+                DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
+        }
+        else
+        {
+            for (i = 0; i < 4; i++)
+            {
+                if (DiskEntry->LayoutBuffer->PartitionEntry[i].PartitionType != 0)
+                {
+                    AddPrimaryPartitionToDisk(DiskNumber,
+                                              DiskEntry,
+                                              i);
+                }
+            }
 
-        ScanForUnpartitionedDiskSpace(DiskEntry);
+            for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
+            {
+                if (DiskEntry->LayoutBuffer->PartitionEntry[i].PartitionType != 0)
+                {
+#if 0
+                    AddExtendedPartitionToDisk(DiskNumber,
+                                               DiskEntry,
+                                               i);
+#endif
+                }
+            }
+        }
     }
 
-    RtlFreeHeap(ProcessHeap,
-                0,
-                LayoutBuffer);
+    ScanForUnpartitionedDiskSpace(DiskEntry);
 }
 
 
@@ -997,7 +1118,6 @@ CreatePartitionList(
 
     List->CurrentDisk = NULL;
     List->CurrentPartition = NULL;
-    List->CurrentPartitionNumber = 0;
 
     InitializeListHead(&List->DiskListHead);
     InitializeListHead(&List->BiosDiskListHead);
@@ -1044,7 +1164,9 @@ CreatePartitionList(
         }
     }
 
-    AssignDriverLetters(List);
+    UpdateDiskSignatures(List);
+
+    AssignDriveLetters(List);
 
     List->TopDisk = 0;
     List->TopPartition = 0;
@@ -1054,7 +1176,6 @@ CreatePartitionList(
     {
         List->CurrentDisk = NULL;
         List->CurrentPartition = NULL;
-        List->CurrentPartitionNumber = 0;
     }
     else
     {
@@ -1062,17 +1183,15 @@ CreatePartitionList(
                                               DISKENTRY,
                                               ListEntry);
 
-        if (IsListEmpty(&List->CurrentDisk->PartListHead))
+        if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
         {
             List->CurrentPartition = 0;
-            List->CurrentPartitionNumber = 0;
         }
         else
         {
-            List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PartListHead.Flink,
+            List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
                                                        PARTENTRY,
                                                        ListEntry);
-            List->CurrentPartitionNumber = 0;
         }
     }
 
@@ -1098,17 +1217,29 @@ DestroyPartitionList(
         /* Release driver name */
         RtlFreeUnicodeString(&DiskEntry->DriverName);
 
-        /* Release partition array */
-        while (!IsListEmpty(&DiskEntry->PartListHead))
+        /* Release primary partition list */
+        while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
         {
-            Entry = RemoveHeadList(&DiskEntry->PartListHead);
+            Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
             PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
 
-            RtlFreeHeap(ProcessHeap,
-                        0,
-                        PartEntry);
+            RtlFreeHeap(ProcessHeap, 0, PartEntry);
         }
 
+        /* Release extended partition list */
+        while (!IsListEmpty(&DiskEntry->ExtendedPartListHead))
+        {
+            Entry = RemoveHeadList(&DiskEntry->ExtendedPartListHead);
+            PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+            RtlFreeHeap(ProcessHeap, 0, PartEntry);
+        }
+
+        /* Release layout buffer */
+        if (DiskEntry->LayoutBuffer != NULL)
+            RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
+
+
         /* Release disk entry */
         RtlFreeHeap(ProcessHeap, 0, DiskEntry);
     }
@@ -1167,8 +1298,7 @@ VOID
 PrintPartitionData(
     PPARTLIST List,
     PDISKENTRY DiskEntry,
-    PPARTENTRY PartEntry,
-    ULONG PartNumber)
+    PPARTENTRY PartEntry)
 {
     CHAR LineBuffer[128];
     COORD coPos;
@@ -1186,24 +1316,25 @@ PrintPartitionData(
     coPos.X = List->Left + 1;
     coPos.Y = List->Top + 1 + List->Line;
 
-    if (PartEntry->Unpartitioned == TRUE)
+    if (PartEntry->IsPartitioned == FALSE)
     {
+        PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
 #if 0
-        if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
+        if (PartSize.QuadPart >= 10737418240) /* 10 GB */
         {
-            PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
             Unit = MUIGetString(STRING_GB);
         }
         else
 #endif
-        if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
+        if (PartSize.QuadPart >= 10485760) /* 10 MB */
         {
-            PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
             Unit = MUIGetString(STRING_MB);
         }
         else
         {
-            PartSize.QuadPart = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
             Unit = MUIGetString(STRING_KB);
         }
 
@@ -1220,46 +1351,47 @@ PrintPartitionData(
         {
             PartType = MUIGetString(STRING_UNFORMATTED);
         }
-        else if (PartEntry->Unpartitioned == FALSE)
+        else if (PartEntry->IsPartitioned == TRUE)
         {
-            if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_12) ||
-                (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT_16) ||
-                (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_HUGE) ||
-                (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_XINT13))
+            if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
+                (PartEntry->PartitionType == PARTITION_FAT_16) ||
+                (PartEntry->PartitionType == PARTITION_HUGE) ||
+                (PartEntry->PartitionType == PARTITION_XINT13))
             {
                 PartType = "FAT";
             }
-            else if ((PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32) ||
-                     (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_FAT32_XINT13))
+            else if ((PartEntry->PartitionType == PARTITION_FAT32) ||
+                     (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
             {
                 PartType = "FAT32";
             }
-            else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_EXT2)
+            else if (PartEntry->PartitionType == PARTITION_EXT2)
             {
                 PartType = "EXT2";
             }
-            else if (PartEntry->PartInfo[PartNumber].PartitionType == PARTITION_IFS)
+            else if (PartEntry->PartitionType == PARTITION_IFS)
             {
                 PartType = "NTFS"; /* FIXME: Not quite correct! */
             }
         }
 
+        PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
 #if 0
-        if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
+        if (PartSize.QuadPart >= 10737418240) /* 10 GB */
         {
-            PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 29)) >> 30;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
             Unit = MUIGetString(STRING_GB);
         }
         else
 #endif
-        if (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
+        if (PartSize.QuadPart >= 10485760) /* 10 MB */
         {
-            PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 19)) >> 20;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
             Unit = MUIGetString(STRING_MB);
         }
         else
         {
-            PartSize.QuadPart = (PartEntry->PartInfo[PartNumber].PartitionLength.QuadPart + (1 << 9)) >> 10;
+            PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
             Unit = MUIGetString(STRING_KB);
         }
 
@@ -1267,9 +1399,9 @@ PrintPartitionData(
         {
             sprintf(LineBuffer,
                     MUIGetString(STRING_HDDINFOUNK5),
-                    (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                    (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
-                    PartEntry->PartInfo[PartNumber].PartitionType,
+                    (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                    (PartEntry->DriveLetter == 0) ? '-' : ':',
+                    PartEntry->PartitionType,
                     PartSize.u.LowPart,
                     Unit);
         }
@@ -1277,8 +1409,8 @@ PrintPartitionData(
         {
             sprintf(LineBuffer,
                     "%c%c  %-24s         %6lu %s",
-                    (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : PartEntry->DriveLetter[PartNumber],
-                    (PartEntry->DriveLetter[PartNumber] == 0) ? '-' : ':',
+                    (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
+                    (PartEntry->DriveLetter == 0) ? '-' : ':',
                     PartType,
                     PartSize.u.LowPart,
                     Unit);
@@ -1286,8 +1418,7 @@ PrintPartitionData(
     }
 
     Attribute = (List->CurrentDisk == DiskEntry &&
-                 List->CurrentPartition == PartEntry &&
-                 List->CurrentPartitionNumber == PartNumber) ?
+                 List->CurrentPartition == PartEntry) ?
                  FOREGROUND_BLUE | BACKGROUND_WHITE :
                  FOREGROUND_WHITE | BACKGROUND_BLUE;
 
@@ -1339,7 +1470,6 @@ PrintDiskData(
     USHORT Height;
     ULARGE_INTEGER DiskSize;
     PCHAR Unit;
-    ULONG i;
 
     Width = List->Right - List->Left - 1;
     Height = List->Bottom - List->Top - 2;
@@ -1347,16 +1477,15 @@ PrintDiskData(
     coPos.X = List->Left + 1;
     coPos.Y = List->Top + 1 + List->Line;
 
-#if 0
-    if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
+    DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
+    if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
     {
-        DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 29)) >> 30;
+        DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1073741824);
         Unit = MUIGetString(STRING_GB);
     }
     else
-#endif
     {
-        DiskSize.QuadPart = (DiskEntry->DiskSize + (1 << 19)) >> 20;
+        DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1048576);
         if (DiskSize.QuadPart == 0)
             DiskSize.QuadPart = 1;
         Unit = MUIGetString(STRING_MB);
@@ -1417,32 +1546,14 @@ PrintDiskData(
     PrintEmptyLine(List);
 
     /* Print partition lines*/
-    Entry = DiskEntry->PartListHead.Flink;
-    while (Entry != &DiskEntry->PartListHead)
+    Entry = DiskEntry->PrimaryPartListHead.Flink;
+    while (Entry != &DiskEntry->PrimaryPartListHead)
     {
         PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
 
-        /* Print disk entry */
-        for (i = 0; i < 4; i++)
-        {
-            if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED ||
-                PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
-            {
-                PrintPartitionData(List,
-                                   DiskEntry,
-                                   PartEntry,
-                                   i);
-            }
-        }
-
-        /* Print unpartitioned entry */
-        if (PartEntry->Unpartitioned)
-        {
-            PrintPartitionData(List,
-                               DiskEntry,
-                               PartEntry,
-                               0);
-        }
+        PrintPartitionData(List,
+                           DiskEntry,
+                           PartEntry);
 
         Entry = Entry->Flink;
     }
@@ -1484,8 +1595,8 @@ DrawPartitionList(
             CurrentPartLine += 2;
         }
 
-        Entry2 = DiskEntry->PartListHead.Flink;
-        while (Entry2 != &DiskEntry->PartListHead)
+        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+        while (Entry2 != &DiskEntry->PrimaryPartListHead)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
             if (PartEntry == List->CurrentPartition)
@@ -1685,7 +1796,6 @@ SelectPartition(
     PPARTENTRY PartEntry;
     PLIST_ENTRY Entry1;
     PLIST_ENTRY Entry2;
-    UCHAR i;
 
     /* Check for empty disks */
     if (IsListEmpty(&List->DiskListHead))
@@ -1699,21 +1809,17 @@ SelectPartition(
 
         if (DiskEntry->DiskNumber == DiskNumber)
         {
-            Entry2 = DiskEntry->PartListHead.Flink;
-            while (Entry2 != &DiskEntry->PartListHead)
+            Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+            while (Entry2 != &DiskEntry->PrimaryPartListHead)
             {
                 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-                for (i = 0; i < 4; i++)
+                if (PartEntry->PartitionNumber == PartitionNumber)
                 {
-                    if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
-                    {
-                        List->CurrentDisk = DiskEntry;
-                        List->CurrentPartition = PartEntry;
-                        List->CurrentPartitionNumber = i;
-                        DrawPartitionList(List);
-                        return TRUE;
-                    }
+                     List->CurrentDisk = DiskEntry;
+                     List->CurrentPartition = PartEntry;
+                     DrawPartitionList(List);
+                     return TRUE;
                 }
 
                 Entry2 = Entry2->Flink;
@@ -1733,11 +1839,10 @@ VOID
 ScrollDownPartitionList(
     PPARTLIST List)
 {
-    PDISKENTRY DiskEntry;
+//    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
+//    PLIST_ENTRY Entry1;
     PLIST_ENTRY Entry2;
-    UCHAR i;
 
     /* Check for empty disks */
     if (IsListEmpty(&List->DiskListHead))
@@ -1746,46 +1851,18 @@ ScrollDownPartitionList(
     /* Check for next usable entry on current disk */
     if (List->CurrentPartition != NULL)
     {
-        Entry2 = &List->CurrentPartition->ListEntry;
-        PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-
-        /* Check if we can move inside primary partitions */
-        for (i = List->CurrentPartitionNumber + 1; i < 4; i++)
+        Entry2 = List->CurrentPartition->ListEntry.Flink;
+        if (Entry2 != &List->CurrentDisk->PrimaryPartListHead)
         {
-            if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
-                break;
-        }
+            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-        if (i == 4)
-        {
-            /* We're out of partitions in the current partition table.
-               Try to move to the next one if possible. */
-            Entry2 = Entry2->Flink;
-        }
-        else
-        {
-            /* Just advance to the next partition */
-            List->CurrentPartitionNumber = i;
+            List->CurrentPartition = PartEntry;
             DrawPartitionList(List);
             return;
         }
-
-        while (Entry2 != &List->CurrentDisk->PartListHead)
-        {
-            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-
-//            if (PartEntry->HidePartEntry == FALSE)
-            {
-                List->CurrentPartition = PartEntry;
-                List->CurrentPartitionNumber = 0;
-                DrawPartitionList(List);
-                return;
-            }
-
-            Entry2 = Entry2->Flink;
-        }
     }
 
+#if 0
     /* Check for first usable entry on next disk */
     if (List->CurrentDisk != NULL)
     {
@@ -1795,25 +1872,20 @@ ScrollDownPartitionList(
             DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
             Entry2 = DiskEntry->PartListHead.Flink;
-            while (Entry2 != &DiskEntry->PartListHead)
+            if (Entry2 != &DiskEntry->PartListHead)
             {
                 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-//                if (PartEntry->HidePartEntry == FALSE)
-                {
-                    List->CurrentDisk = DiskEntry;
-                    List->CurrentPartition = PartEntry;
-                    List->CurrentPartitionNumber = 0;
-                    DrawPartitionList(List);
-                    return;
-                }
-
-                Entry2 = Entry2->Flink;
+                List->CurrentDisk = DiskEntry;
+                List->CurrentPartition = PartEntry;
+                DrawPartitionList(List);
+                return;
             }
 
             Entry1 = Entry1->Flink;
         }
     }
+#endif
 }
 
 
@@ -1821,11 +1893,10 @@ VOID
 ScrollUpPartitionList(
     PPARTLIST List)
 {
-    PDISKENTRY DiskEntry;
+//    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
+//    PLIST_ENTRY Entry1;
     PLIST_ENTRY Entry2;
-    UCHAR i;
 
     /* Check for empty disks */
     if (IsListEmpty(&List->DiskListHead))
@@ -1834,56 +1905,20 @@ ScrollUpPartitionList(
     /* check for previous usable entry on current disk */
     if (List->CurrentPartition != NULL)
     {
-        Entry2 = &List->CurrentPartition->ListEntry;
-        PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-
-        /* Check if we can move inside primary partitions */
-        if (List->CurrentPartitionNumber > 0)
-        {
-            /* Find a previous partition */
-            for (i = List->CurrentPartitionNumber - 1; i > 0; i--)
-            {
-                if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
-                    break;
-            }
-
-            /* Move to it and return */
-            List->CurrentPartitionNumber = i;
-            DrawPartitionList(List);
-            return;
-        }
-
-        /* Move to the previous entry */
-        Entry2 = Entry2->Blink;
-
-        while (Entry2 != &List->CurrentDisk->PartListHead)
+        Entry2 = List->CurrentPartition->ListEntry.Blink;
+        if (Entry2 != &List->CurrentDisk->PrimaryPartListHead)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-//            if (PartEntry->HidePartEntry == FALSE)
-            {
-                List->CurrentPartition = PartEntry;
+            List->CurrentPartition = PartEntry;
 
-                /* Find last existing partition in the table */
-                for (i = 3; i > 0; i--)
-                {
-                    if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
-                        break;
-                }
-
-                /* Move to it */
-                List->CurrentPartitionNumber = i;
-
-                /* Draw partition list and return */
-                DrawPartitionList(List);
-                return;
-            }
-
-            Entry2 = Entry2->Blink;
+            /* Draw partition list and return */
+            DrawPartitionList(List);
+            return;
         }
     }
 
-
+#if 0
     /* check for last usable entry on previous disk */
     if (List->CurrentDisk != NULL)
     {
@@ -1892,93 +1927,128 @@ ScrollUpPartitionList(
         {
             DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
 
-            Entry2 = DiskEntry->PartListHead.Blink;
-            while (Entry2 != &DiskEntry->PartListHead)
+            Entry2 = DiskEntry->PrimaryPartListHead.Blink;
+            if (Entry2 != &DiskEntry->PrimaryPartListHead)
             {
                 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
 
-//                if (PartEntry->HidePartEntry == FALSE)
-                {
-                    List->CurrentDisk = DiskEntry;
-                    List->CurrentPartition = PartEntry;
-
-                    /* Find last existing partition in the table */
-                    for (i = 3; i > 0; i--)
-                    {
-                        if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED)
-                            break;
-                    }
-
-                    /* Move to it */
-                    List->CurrentPartitionNumber = i;
-
-                    /* Draw partition list and return */
-                    DrawPartitionList(List);
-                    return;
-                }
+                List->CurrentDisk = DiskEntry;
+                List->CurrentPartition = PartEntry;
 
-                Entry2 = Entry2->Blink;
+                /* Draw partition list and return */
+                DrawPartitionList(List);
+                return;
             }
 
             Entry1 = Entry1->Blink;
         }
     }
+#endif
+}
+
+
+static
+BOOLEAN
+IsEmptyLayoutEntry(
+    PPARTITION_INFORMATION PartitionInfo)
+{
+    if (PartitionInfo->StartingOffset.QuadPart == 0 &&
+        PartitionInfo->PartitionLength.QuadPart == 0)
+//        PartitionInfo->PartitionType == 0)
+        return TRUE;
+
+    return FALSE;
+}
+
+
+static
+BOOLEAN
+IsSamePrimaryLayoutEntry(
+    IN PPARTITION_INFORMATION PartitionInfo,
+    IN PDISKENTRY DiskEntry,
+    IN PPARTENTRY PartEntry)
+{
+    if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
+        PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
+//        PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
+//        PartitionInfo->PartitionType == PartEntry->PartitionType
+        return TRUE;
+
+    return FALSE;
 }
 
 
 static
-PPARTENTRY
-GetPrevPartitionedEntry(
-    PDISKENTRY DiskEntry,
-    PPARTENTRY CurrentEntry)
+VOID
+UpdateDiskLayout(
+    IN PDISKENTRY DiskEntry)
 {
-    PPARTENTRY PrevEntry;
-    PLIST_ENTRY Entry;
+    PPARTITION_INFORMATION PartitionInfo;
+    PLIST_ENTRY ListEntry;
+    PPARTENTRY PartEntry;
+    ULONG Index = 0;
+    ULONG PartitionNumber = 1;
 
-    if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
-        return NULL;
+DPRINT1("UpdateDiskLayout()\n");
 
-    Entry = CurrentEntry->ListEntry.Blink;
-    while (Entry != &DiskEntry->PartListHead)
+    ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+    while (ListEntry != &DiskEntry->PrimaryPartListHead)
     {
-        PrevEntry = CONTAINING_RECORD(Entry,
-                                      PARTENTRY,
-                                      ListEntry);
-        if (PrevEntry->Unpartitioned == FALSE)
-            return PrevEntry;
-
-        Entry = Entry->Blink;
-    }
+        PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
 
-    return NULL;
-}
+        if (PartEntry->IsPartitioned == TRUE)
+        {
+            PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
 
+            if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
+            {
+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;
+                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;
+
+                PartitionNumber++;
+            }
+            else if (!IsEmptyLayoutEntry(PartitionInfo))
+            {
+                PartitionNumber++;
+            }
 
-static
-PPARTENTRY
-GetNextPartitionedEntry(
-    PDISKENTRY DiskEntry,
-    PPARTENTRY CurrentEntry)
-{
-    PPARTENTRY NextEntry;
-    PLIST_ENTRY Entry;
+            Index++;
+        }
 
-    if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
-        return NULL;
+        ListEntry = ListEntry->Flink;
+    }
 
-    Entry = CurrentEntry->ListEntry.Flink;
-    while (Entry != &DiskEntry->PartListHead)
+    for (;Index < 4; Index++)
     {
-        NextEntry = CONTAINING_RECORD(Entry,
-                                      PARTENTRY,
-                                      ListEntry);
-        if (NextEntry->Unpartitioned == FALSE)
-            return NextEntry;
+        PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
 
-        Entry = Entry->Flink;
+        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 = 0;
+            PartitionInfo->BootIndicator = FALSE;
+            PartitionInfo->RecognizedPartition = FALSE;
+            PartitionInfo->RewritePartition = TRUE;
+        }
     }
 
-    return NULL;
+#ifdef DUMP_PARTITION_TABLE
+    DumpPartitionTable(DiskEntry);
+#endif
 }
 
 
@@ -1990,12 +2060,12 @@ GetPrevUnpartitionedEntry(
 {
     PPARTENTRY PrevPartEntry;
 
-    if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
+    if (PartEntry->ListEntry.Blink != &DiskEntry->PrimaryPartListHead)
     {
         PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
                                           PARTENTRY,
                                           ListEntry);
-        if (PrevPartEntry->Unpartitioned == TRUE)
+        if (PrevPartEntry->IsPartitioned == FALSE)
             return PrevPartEntry;
     }
 
@@ -2011,12 +2081,12 @@ GetNextUnpartitionedEntry(
 {
     PPARTENTRY NextPartEntry;
 
-    if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
+    if (PartEntry->ListEntry.Flink != &DiskEntry->PrimaryPartListHead)
     {
         NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
                                           PARTENTRY,
                                           ListEntry);
-        if (NextPartEntry->Unpartitioned == TRUE)
+        if (NextPartEntry->IsPartitioned == FALSE)
             return NextPartEntry;
     }
 
@@ -2027,19 +2097,19 @@ GetNextUnpartitionedEntry(
 VOID
 CreateNewPartition(
     PPARTLIST List,
-    ULONGLONG PartitionSize,
+    ULONGLONG SectorCount,
     BOOLEAN AutoCreate)
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PPARTENTRY PrevPartEntry;
-    PPARTENTRY NextPartEntry;
     PPARTENTRY NewPartEntry;
 
+    DPRINT1("CreateNewPartition(%I64u)\n", SectorCount);
+
     if (List == NULL ||
         List->CurrentDisk == NULL ||
         List->CurrentPartition == NULL ||
-        List->CurrentPartition->Unpartitioned == FALSE)
+        List->CurrentPartition->IsPartitioned == TRUE)
     {
         return;
     }
@@ -2047,227 +2117,66 @@ CreateNewPartition(
     DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
+DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+
     if (AutoCreate == TRUE ||
-        PartitionSize == PartEntry->UnpartitionedLength)
+        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->PartInfo[0].StartingOffset.QuadPart =
-            PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
-        PartEntry->PartInfo[0].HiddenSectors = 
-            (ULONG)(PartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-        PartEntry->PartInfo[0].PartitionLength.QuadPart =
-            PartEntry->UnpartitionedLength - DiskEntry->TrackSize;
-        PartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
-        PartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
-        PartEntry->PartInfo[0].RewritePartition = TRUE;
-        PartEntry->PartInfo[1].RewritePartition = TRUE;
-        PartEntry->PartInfo[2].RewritePartition = TRUE;
-        PartEntry->PartInfo[3].RewritePartition = TRUE;
-
-        /* Get previous and next partition entries */
-        PrevPartEntry = GetPrevPartitionedEntry(DiskEntry,
-                                                PartEntry);
-        NextPartEntry = GetNextPartitionedEntry(DiskEntry,
-                                                PartEntry);
-
-        if (PrevPartEntry != NULL && NextPartEntry != NULL)
-        {
-            /* Current entry is in the middle of the list */
-
-            /* Copy previous container partition data to current entry */
-            RtlCopyMemory(&PartEntry->PartInfo[1],
-                          &PrevPartEntry->PartInfo[1],
-                          sizeof(PARTITION_INFORMATION));
-            PartEntry->PartInfo[1].RewritePartition = TRUE;
-
-            /* Update previous container partition data */
-
-            PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
-                PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-            PrevPartEntry->PartInfo[1].HiddenSectors = 
-                (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
-            if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
-            {
-                /* Special case - previous partition is first partition */
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-            }
-
-            PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-        }
-        else if (PrevPartEntry == NULL && NextPartEntry != NULL)
-        {
-            /* Current entry is the first entry */
-            return;
-        }
-        else if (PrevPartEntry != NULL && NextPartEntry == NULL)
-        {
-            /* Current entry is the last entry */
-
-            PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
-                PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-            PrevPartEntry->PartInfo[1].HiddenSectors = 
-                (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
-            if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
-            {
-                /* Special case - previous partition is first partition */
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-            }
-
-            if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
-                 PartEntry->PartInfo[1].PartitionLength.QuadPart) <
-                (1024LL * 255LL * 63LL * 512LL))
-            {
-                PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
-            }
-
-            PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
-            PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-        }
-
         PartEntry->AutoCreate = AutoCreate;
         PartEntry->New = TRUE;
-        PartEntry->Unpartitioned = FALSE;
-        PartEntry->UnpartitionedOffset = 0ULL;
-        PartEntry->UnpartitionedLength = 0ULL;
+        PartEntry->BootIndicator = FALSE; /* FIXME */
+
+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
     {
-        /* Insert an initialize a new partition entry */
-        NewPartEntry = (PPARTENTRY)RtlAllocateHeap(ProcessHeap,
-                                                   0,
-                                                   sizeof(PARTENTRY));
+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;
 
-        RtlZeroMemory(NewPartEntry,
-                      sizeof(PARTENTRY));
-
         /* Insert the new entry into the list */
         InsertTailList(&PartEntry->ListEntry,
                        &NewPartEntry->ListEntry);
 
-        NewPartEntry->New = TRUE;
-
-        NewPartEntry->FormatState = Unformatted;
-        NewPartEntry->PartInfo[0].StartingOffset.QuadPart =
-            PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
-        NewPartEntry->PartInfo[0].HiddenSectors = 
-            (ULONG)(NewPartEntry->PartInfo[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-        NewPartEntry->PartInfo[0].PartitionLength.QuadPart =
-            PartitionSize - DiskEntry->TrackSize;
-        NewPartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
-        NewPartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
-        NewPartEntry->PartInfo[0].RewritePartition = TRUE;
-        NewPartEntry->PartInfo[1].RewritePartition = TRUE;
-        NewPartEntry->PartInfo[2].RewritePartition = TRUE;
-        NewPartEntry->PartInfo[3].RewritePartition = TRUE;
-
-        /* Get previous and next partition entries */
-        PrevPartEntry = GetPrevPartitionedEntry(DiskEntry,
-                                                NewPartEntry);
-        NextPartEntry = GetNextPartitionedEntry(DiskEntry,
-                                                NewPartEntry);
-
-        if (PrevPartEntry != NULL && NextPartEntry != NULL)
-        {
-            /* Current entry is in the middle of the list */
-
-            /* Copy previous container partition data to current entry */
-            RtlCopyMemory(&NewPartEntry->PartInfo[1],
-                          &PrevPartEntry->PartInfo[1],
-                          sizeof(PARTITION_INFORMATION));
-            NewPartEntry->PartInfo[1].RewritePartition = TRUE;
+        NewPartEntry->DiskEntry = DiskEntry;
 
-            /* Update previous container partition data */
-            PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
-                NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-            PrevPartEntry->PartInfo[1].HiddenSectors = 
-                (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
-            if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
-            {
-                /* Special case - previous partition is first partition */
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-            }
-
-            PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-        }
-        else if (PrevPartEntry == NULL && NextPartEntry != NULL)
-        {
-            /* Current entry is the first entry */
-            return;
-        }
-        else if (PrevPartEntry != NULL && NextPartEntry == NULL)
-        {
-            /* Current entry is the last entry */
-
-            PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
-                NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-            PrevPartEntry->PartInfo[1].HiddenSectors = 
-               (ULONG)(PrevPartEntry->PartInfo[1].StartingOffset.QuadPart / DiskEntry->BytesPerSector);
-
-            if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
-            {
-                /* Special case - previous partition is first partition */
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
-                    NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-            }
+        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;
 
-            if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
-                 PartEntry->PartInfo[1].PartitionLength.QuadPart) <
-                (1024LL * 255LL * 63LL * 512LL))
-            {
-                PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
-            }
-            else
-            {
-                PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
-            }
+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);
 
-            PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
-            PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-        }
+        NewPartEntry->New = TRUE;
+        NewPartEntry->FormatState = Unformatted;
+        NewPartEntry->BootIndicator = FALSE; /* FIXME */
 
-        /* Update offset and size of the remaining unpartitioned disk space */
-        PartEntry->UnpartitionedOffset += PartitionSize;
-        PartEntry->UnpartitionedLength -= PartitionSize;
+        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
+        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
     }
 
-    DiskEntry->Modified = TRUE;
+    UpdateDiskLayout(DiskEntry);
+
+    DiskEntry->Dirty = TRUE;
 
     UpdatePartitionNumbers(DiskEntry);
 
-    AssignDriverLetters(List);
+    AssignDriveLetters(List);
 }
 
 
@@ -2283,7 +2192,7 @@ DeleteCurrentPartition(
     if (List == NULL ||
         List->CurrentDisk == NULL ||
         List->CurrentPartition == NULL ||
-        List->CurrentPartition->Unpartitioned == TRUE)
+        List->CurrentPartition->IsPartitioned == FALSE)
     {
         return;
     }
@@ -2291,48 +2200,6 @@ DeleteCurrentPartition(
     DiskEntry = List->CurrentDisk;
     PartEntry = List->CurrentPartition;
 
-    /* Adjust container partition entries */
-
-    /* Get previous and next partition entries */
-    PrevPartEntry = GetPrevPartitionedEntry(DiskEntry,
-                                            PartEntry);
-    NextPartEntry = GetNextPartitionedEntry(DiskEntry,
-                                            PartEntry);
-
-    if (PrevPartEntry != NULL && NextPartEntry != NULL)
-    {
-        /* Current entry is in the middle of the list */
-
-        /*
-         * The first extended partition can not be deleted
-         * as long as other extended partitions are present.
-         */
-        if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
-            return;
-
-        /* Copy previous container partition data to current entry */
-        RtlCopyMemory(&PrevPartEntry->PartInfo[1],
-                      &PartEntry->PartInfo[1],
-                      sizeof(PARTITION_INFORMATION));
-        PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-    }
-    else if (PrevPartEntry == NULL && NextPartEntry != NULL)
-    {
-        /*
-         * A primary partition can not be deleted as long as
-         * extended partitions are present.
-         */
-        return;
-    }
-    else if (PrevPartEntry != NULL && NextPartEntry == NULL)
-    {
-        /* Current entry is the last entry */
-        RtlZeroMemory(&PrevPartEntry->PartInfo[1],
-                      sizeof(PARTITION_INFORMATION));
-        PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
-    }
-
-
     /* Adjust unpartitioned disk space entries */
 
     /* Get pointer to previous and next unpartitioned entries */
@@ -2347,21 +2214,15 @@ DeleteCurrentPartition(
         /* Merge previous, current and next unpartitioned entry */
 
         /* Adjust the previous entries length */
-        PrevPartEntry->UnpartitionedLength +=
-            (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
-             NextPartEntry->UnpartitionedLength);
+        PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
 
         /* Remove the current entry */
         RemoveEntryList(&PartEntry->ListEntry);
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    PartEntry);
+        RtlFreeHeap(ProcessHeap, 0, PartEntry);
 
         /* Remove the next entry */
         RemoveEntryList (&NextPartEntry->ListEntry);
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    NextPartEntry);
+        RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
 
         /* Update current partition */
         List->CurrentPartition = PrevPartEntry;
@@ -2371,14 +2232,11 @@ DeleteCurrentPartition(
         /* Merge current and previous unpartitioned entry */
 
         /* Adjust the previous entries length */
-        PrevPartEntry->UnpartitionedLength +=
-            (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
+        PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
 
         /* Remove the current entry */
         RemoveEntryList(&PartEntry->ListEntry);
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    PartEntry);
+        RtlFreeHeap(ProcessHeap, 0, PartEntry);
 
         /* Update current partition */
         List->CurrentPartition = PrevPartEntry;
@@ -2388,16 +2246,12 @@ DeleteCurrentPartition(
         /* Merge current and next unpartitioned entry */
 
         /* Adjust the next entries offset and length */
-        NextPartEntry->UnpartitionedOffset =
-            PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-        NextPartEntry->UnpartitionedLength +=
-            (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
+        NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
+        NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
 
         /* Remove the current entry */
         RemoveEntryList(&PartEntry->ListEntry);
-        RtlFreeHeap(ProcessHeap,
-                    0,
-                    PartEntry);
+        RtlFreeHeap(ProcessHeap, 0, PartEntry);
 
         /* Update current partition */
         List->CurrentPartition = NextPartEntry;
@@ -2405,23 +2259,18 @@ DeleteCurrentPartition(
     else
     {
         /* Nothing to merge but change current entry */
-        PartEntry->New = FALSE;
-        PartEntry->Unpartitioned = TRUE;
-        PartEntry->UnpartitionedOffset =
-            PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
-        PartEntry->UnpartitionedLength =
-            PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
-
-        /* Wipe the partition table */
-        RtlZeroMemory(&PartEntry->PartInfo,
-                      sizeof(PartEntry->PartInfo));
+        PartEntry->IsPartitioned = FALSE;
+        PartEntry->FormatState = Unformatted;
+        PartEntry->DriveLetter = 0;
     }
 
-    DiskEntry->Modified = TRUE;
+    UpdateDiskLayout(DiskEntry);
+
+    DiskEntry->Dirty = TRUE;
 
     UpdatePartitionNumbers(DiskEntry);
 
-    AssignDriverLetters(List);
+    AssignDriveLetters(List);
 }
 
 
@@ -2432,14 +2281,12 @@ CheckActiveBootPartition(
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
     PLIST_ENTRY ListEntry;
-    UCHAR i;
 
     /* Check for empty disk list */
     if (IsListEmpty (&List->DiskListHead))
     {
         List->ActiveBootDisk = NULL;
         List->ActiveBootPartition = NULL;
-        List->ActiveBootPartitionNumber = 0;
         return;
     }
 
@@ -2456,33 +2303,29 @@ CheckActiveBootPartition(
     DiskEntry = List->CurrentDisk;
 
     /* Check for empty partition list */
-    if (IsListEmpty (&DiskEntry->PartListHead))
+    if (IsListEmpty (&DiskEntry->PrimaryPartListHead))
     {
         List->ActiveBootDisk = NULL;
         List->ActiveBootPartition = NULL;
-        List->ActiveBootPartitionNumber = 0;
         return;
     }
 
-    PartEntry = CONTAINING_RECORD(DiskEntry->PartListHead.Flink,
+    PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
                                   PARTENTRY,
                                   ListEntry);
 
     /* Set active boot partition */
     if ((DiskEntry->NewDisk == TRUE) ||
-        (PartEntry->PartInfo[0].BootIndicator == FALSE &&
-         PartEntry->PartInfo[1].BootIndicator == FALSE &&
-         PartEntry->PartInfo[2].BootIndicator == FALSE &&
-         PartEntry->PartInfo[3].BootIndicator == FALSE))
+        (PartEntry->BootIndicator == FALSE))
     {
-        PartEntry->PartInfo[0].BootIndicator = TRUE;
-        PartEntry->PartInfo[0].RewritePartition = TRUE;
-        DiskEntry->Modified = TRUE;
+        PartEntry->BootIndicator = TRUE;
+        DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
+        DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
+        DiskEntry->Dirty = TRUE;
 
         /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
         List->ActiveBootDisk = DiskEntry;
         List->ActiveBootPartition = PartEntry;
-        List->ActiveBootPartitionNumber = 0;
 
         return;
     }
@@ -2490,34 +2333,27 @@ CheckActiveBootPartition(
     /* Disk is not new, scan all partitions to find a bootable one */
     List->ActiveBootDisk = NULL;
     List->ActiveBootPartition = NULL;
-    List->ActiveBootPartitionNumber = 0;
 
-    ListEntry = DiskEntry->PartListHead.Flink;
-    while (ListEntry != &DiskEntry->PartListHead)
+    ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+    while (ListEntry != &DiskEntry->PrimaryPartListHead)
     {
         PartEntry = CONTAINING_RECORD(ListEntry,
                                       PARTENTRY,
                                       ListEntry);
 
-        /* Check if it's partitioned */
-        if (!PartEntry->Unpartitioned)
+        /* Check if it is partitioned */
+        if (PartEntry->IsPartitioned)
         {
-            /* Go through all of its 4 partitions */
-            for (i = 0; i < 4; i++)
+            if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED &&
+                PartEntry->BootIndicator)
             {
-                if (PartEntry->PartInfo[i].PartitionType != PARTITION_ENTRY_UNUSED &&
-                    PartEntry->PartInfo[i].BootIndicator)
-                {
-                    /* Yes, we found it */
-                    List->ActiveBootDisk = DiskEntry;
-                    List->ActiveBootPartition = PartEntry;
-                    List->ActiveBootPartitionNumber = i;
+                /* Yes, we found it */
+                List->ActiveBootDisk = DiskEntry;
+                List->ActiveBootPartition = PartEntry;
 
-                    DPRINT("Found bootable partition disk %d, drive letter %c\n",
-                           DiskEntry->DiskNumber, PartEntry->DriveLetter[i]);
-
-                    break;
-                }
+                DPRINT("Found bootable partition disk %d, drive letter %c\n",
+                       DiskEntry->DiskNumber, PartEntry->DriveLetter);
+                break;
             }
         }
 
@@ -2531,6 +2367,7 @@ BOOLEAN
 CheckForLinuxFdiskPartitions(
     PPARTLIST List)
 {
+#if 0
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
     PLIST_ENTRY Entry1;
@@ -2576,217 +2413,100 @@ CheckForLinuxFdiskPartitions(
 
         Entry1 = Entry1->Flink;
     }
+#endif
 
     return FALSE;
 }
 
 
-BOOLEAN
-WritePartitionsToDisk(
-    PPARTLIST List)
+static
+NTSTATUS
+WritePartitons(
+    IN PPARTLIST List,
+    IN PDISKENTRY DiskEntry)
 {
-    PDRIVE_LAYOUT_INFORMATION DriveLayout;
+    WCHAR DstPath[MAX_PATH];
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK Iosb;
-    WCHAR DstPath[MAX_PATH];
     UNICODE_STRING Name;
-    HANDLE FileHandle;
-    PDISKENTRY DiskEntry1;
-    PDISKENTRY DiskEntry2;
-    PPARTENTRY PartEntry;
-    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
-    ULONG PartitionCount;
-    ULONG DriveLayoutSize;
-    ULONG Index;
+    ULONG BufferSize;
+    HANDLE FileHandle = NULL;
     NTSTATUS Status;
 
-    if (List == NULL)
+    DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
+
+    swprintf(DstPath,
+             L"\\Device\\Harddisk%d\\Partition0",
+             DiskEntry->DiskNumber);
+    RtlInitUnicodeString(&Name,
+                         DstPath);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &Name,
+                               0,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenFile(&FileHandle,
+                        GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &Iosb,
+                        0,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
     {
-        return TRUE;
+        DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+        return Status;
     }
 
-    Entry1 = List->DiskListHead.Flink;
-    while (Entry1 != &List->DiskListHead)
-    {
-        DiskEntry1 = CONTAINING_RECORD(Entry1,
-                                       DISKENTRY,
-                                       ListEntry);
-
-        if (DiskEntry1->Modified == TRUE)
-        {
-            /* Count partitioned entries */
-            PartitionCount = 0;
-
-            Entry2 = DiskEntry1->PartListHead.Flink;
-            while (Entry2 != &DiskEntry1->PartListHead)
-            {
-                PartEntry = CONTAINING_RECORD(Entry2,
-                                              PARTENTRY,
-                                              ListEntry);
-                if (PartEntry->Unpartitioned == FALSE)
-                {
-                    PartitionCount += 4;
-                }
-
-                Entry2 = Entry2->Flink;
-            }
-
-            if (PartitionCount == 0)
-            {
-                DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
-                                  ((4 - 1) * sizeof (PARTITION_INFORMATION));
-            }
-            else
-            {
-                DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
-                                  ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION));
-            }
-
-            DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap(ProcessHeap,
-                                                                     0,
-                                                                     DriveLayoutSize);
-            if (DriveLayout == NULL)
-            {
-                DPRINT1("RtlAllocateHeap() failed\n");
-                return FALSE;
-            }
-
-            RtlZeroMemory(DriveLayout,
-                          DriveLayoutSize);
-
-            if (PartitionCount == 0)
-            {
-                /* delete all partitions in the mbr */
-                DriveLayout->PartitionCount = 4;
-                for (Index = 0; Index < 4; Index++)
-                {
-                    DriveLayout->PartitionEntry[Index].RewritePartition = TRUE;
-                }
-            }
-            else
-            {
-                DriveLayout->PartitionCount = PartitionCount;
-                Index = 0;
-
-                Entry2 = DiskEntry1->PartListHead.Flink;
-                while (Entry2 != &DiskEntry1->PartListHead)
-                {
-                    PartEntry = CONTAINING_RECORD(Entry2,
-                                                  PARTENTRY,
-                                                  ListEntry);
-                    if (PartEntry->Unpartitioned == FALSE)
-                    {
-                        RtlCopyMemory(&DriveLayout->PartitionEntry[Index],
-                                      &PartEntry->PartInfo[0],
-                                      4 * sizeof (PARTITION_INFORMATION));
-                        Index += 4;
-                    }
-
-                    Entry2 = Entry2->Flink;
-                }
-            }
-
-            if (DiskEntry1->Signature == 0)
-            {
-                LARGE_INTEGER SystemTime;
-                TIME_FIELDS TimeFields;
-                PUCHAR Buffer;
-                Buffer = (PUCHAR)&DiskEntry1->Signature;
-
-                while (1)
-                {
-                    NtQuerySystemTime(&SystemTime);
-                    RtlTimeToTimeFields(&SystemTime, &TimeFields);
-
-                    Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
-                    Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
-                    Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
-                    Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
-
-                    if (DiskEntry1->Signature == 0)
-                    {
-                        continue;
-                    }
+#ifdef DUMP_PARTITION_TABLE
+    DumpPartitionTable(DiskEntry);
+#endif
 
-                    /* check if the signature already exist */
-                    /* FIXME:
-                     *   Check also signatures from disks, which are
-                     *   not visible (bootable) by the bios.
-                     */
-                    Entry2 = List->DiskListHead.Flink;
-                    while (Entry2 != &List->DiskListHead)
-                    {
-                        DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
-                        if (DiskEntry1 != DiskEntry2 &&
-                            DiskEntry1->Signature == DiskEntry2->Signature)
-                        {
-                            break;
-                        }
+    BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+                 ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
+    Status = NtDeviceIoControlFile(FileHandle,
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   &Iosb,
+                                   IOCTL_DISK_SET_DRIVE_LAYOUT,
+                                   DiskEntry->LayoutBuffer,
+                                   BufferSize,
+                                   NULL,
+                                   0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
+    }
 
-                        Entry2 = Entry2->Flink;
-                    }
+    if (FileHandle != NULL)
+        NtClose(FileHandle);
 
-                    if (Entry2 == &List->DiskListHead)
-                    {
-                        break;
-                    }
-                }
+    return Status;
+}
 
-                /* set one partition entry to dirty, this will update the signature */
-                DriveLayout->PartitionEntry[0].RewritePartition = TRUE;
-            }
 
-            DriveLayout->Signature = DiskEntry1->Signature;
-
-            swprintf(DstPath,
-                     L"\\Device\\Harddisk%d\\Partition0",
-                     DiskEntry1->DiskNumber);
-            RtlInitUnicodeString(&Name,
-                                 DstPath);
-            InitializeObjectAttributes(&ObjectAttributes,
-                                       &Name,
-                                       0,
-                                       NULL,
-                                       NULL);
-
-            Status = NtOpenFile(&FileHandle,
-                                FILE_ALL_ACCESS,
-                                &ObjectAttributes,
-                                &Iosb,
-                                0,
-                                FILE_SYNCHRONOUS_IO_NONALERT);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
-                return FALSE;
-            }
+BOOLEAN
+WritePartitionsToDisk(
+    PPARTLIST List)
+{
+    PLIST_ENTRY Entry;
+    PDISKENTRY DiskEntry;
 
-            Status = NtDeviceIoControlFile(FileHandle,
-                                           NULL,
-                                           NULL,
-                                           NULL,
-                                           &Iosb,
-                                           IOCTL_DISK_SET_DRIVE_LAYOUT,
-                                           DriveLayout,
-                                           DriveLayoutSize,
-                                           NULL,
-                                           0);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
-                NtClose(FileHandle);
-                return FALSE;
-            }
+    if (List == NULL)
+        return TRUE;
 
-            RtlFreeHeap(ProcessHeap,
-                        0,
-                        DriveLayout);
+    Entry = List->DiskListHead.Flink;
+    while (Entry != &List->DiskListHead)
+    {
+        DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
 
-            NtClose(FileHandle);
+        if (DiskEntry->Dirty == TRUE)
+        {
+            WritePartitons(List, DiskEntry);
         }
 
-        Entry1 = Entry1->Flink;
+        Entry = Entry->Flink;
     }
 
     return TRUE;
@@ -2800,7 +2520,7 @@ SetMountedDeviceValues(
     PLIST_ENTRY Entry1, Entry2;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    UCHAR i;
+    LARGE_INTEGER StartingOffset;
 
     if (List == NULL)
     {
@@ -2814,22 +2534,20 @@ SetMountedDeviceValues(
                                       DISKENTRY,
                                       ListEntry);
 
-        Entry2 = DiskEntry->PartListHead.Flink;
-        while (Entry2 != &DiskEntry->PartListHead)
+        Entry2 = DiskEntry->PrimaryPartListHead.Flink;
+        while (Entry2 != &DiskEntry->PrimaryPartListHead)
         {
             PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
-            if (!PartEntry->Unpartitioned)
+            if (PartEntry->IsPartitioned)
             {
-                for (i = 0; i < 4; i++)
+                if (PartEntry->DriveLetter)
                 {
-                    if (PartEntry->DriveLetter[i])
+                    StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
+                    if (!SetMountedDeviceValue(PartEntry->DriveLetter,
+                                               DiskEntry->LayoutBuffer->Signature,
+                                               StartingOffset))
                     {
-                        if (!SetMountedDeviceValue(PartEntry->DriveLetter[i],
-                                                   DiskEntry->Signature,
-                                                   PartEntry->PartInfo[i].StartingOffset))
-                        {
-                            return FALSE;
-                        }
+                        return FALSE;
                     }
                 }
             }
index 81282f0..5cf1841 100644 (file)
@@ -42,12 +42,23 @@ typedef struct _PARTENTRY
 {
     LIST_ENTRY ListEntry;
 
-    CHAR DriveLetter[4];
+    struct _DISKENTRY *DiskEntry;
+
+    ULARGE_INTEGER StartSector;
+    ULARGE_INTEGER SectorCount;
+
+    BOOLEAN BootIndicator;
+    UCHAR PartitionType;
+    ULONG HiddenSectors;
+    ULONG PartitionNumber;
+    ULONG PartitionIndex;
+
+    CHAR DriveLetter;
     CHAR VolumeLabel[17];
     CHAR FileSystemName[9];
 
-    /* Partition is unused disk space */
-    BOOLEAN Unpartitioned;
+    /* Partition is partitioned disk space */
+    BOOLEAN IsPartitioned;
 
     /* Partition is new. Table does not exist on disk yet */
     BOOLEAN New;
@@ -57,15 +68,6 @@ typedef struct _PARTENTRY
 
     FORMATSTATE FormatState;
 
-    /*
-     * Raw offset and length of the unpartitioned disk space.
-     * Includes the leading, not yet existing, partition table.
-     */
-    ULONGLONG UnpartitionedOffset;
-    ULONGLONG UnpartitionedLength;
-
-    PARTITION_INFORMATION PartInfo[4];
-
 } PARTENTRY, *PPARTENTRY;
 
 
@@ -86,18 +88,17 @@ typedef struct _DISKENTRY
     LIST_ENTRY ListEntry;
 
     ULONGLONG Cylinders;
-    ULONGLONG TracksPerCylinder;
-    ULONGLONG SectorsPerTrack;
-    ULONGLONG BytesPerSector;
+    ULONG TracksPerCylinder;
+    ULONG SectorsPerTrack;
+    ULONG BytesPerSector;
 
-    ULONGLONG DiskSize;
-    ULONGLONG CylinderSize;
-    ULONGLONG TrackSize;
+    ULARGE_INTEGER SectorCount;
+    ULONG SectorAlignment;
 
     BOOLEAN BiosFound;
     ULONG BiosDiskNumber;
-    ULONG Signature;
-    ULONG Checksum;
+//    ULONG Signature;
+//    ULONG Checksum;
 
     ULONG DiskNumber;
     USHORT Port;
@@ -105,14 +106,17 @@ typedef struct _DISKENTRY
     USHORT Id;
 
     /* Has the partition list been modified? */
-    BOOLEAN Modified;
+    BOOLEAN Dirty;
 
     BOOLEAN NewDisk;
     BOOLEAN NoMbr; /* MBR is absent */
 
     UNICODE_STRING DriverName;
 
-    LIST_ENTRY PartListHead;
+    PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
+
+    LIST_ENTRY PrimaryPartListHead;
+    LIST_ENTRY ExtendedPartListHead;
 
 } DISKENTRY, *PDISKENTRY;
 
@@ -132,11 +136,9 @@ typedef struct _PARTLIST
 
     PDISKENTRY CurrentDisk;
     PPARTENTRY CurrentPartition;
-    UCHAR      CurrentPartitionNumber;
 
     PDISKENTRY ActiveBootDisk;
     PPARTENTRY ActiveBootPartition;
-    UCHAR      ActiveBootPartitionNumber;
 
     LIST_ENTRY DiskListHead;
     LIST_ENTRY BiosDiskListHead;