[USETUP]
[reactos.git] / reactos / base / setup / usetup / partlist.c
index 051d02c..0e28213 100644 (file)
@@ -530,7 +530,8 @@ AddPartitionToDisk(
     PPARTENTRY PartEntry;
 
     PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
-    if (PartitionInfo->PartitionType == 0)
+    if (PartitionInfo->PartitionType == 0 ||
+        (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType)))
         return;
 
     PartEntry = RtlAllocateHeap(ProcessHeap,
@@ -752,6 +753,125 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
         }
     }
 
+    if (DiskEntry->ExtendedPartition != NULL)
+    {
+        if (IsListEmpty(&DiskEntry->LogicalPartListHead))
+        {
+            DPRINT1("No logical partition!\n");
+
+            /* Create a partition table entry that represents the empty extended partition */
+            NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           sizeof(PARTENTRY));
+            if (NewPartEntry == NULL)
+                return;
+
+            NewPartEntry->DiskEntry = DiskEntry;
+            NewPartEntry->LogicalPartition = TRUE;
+
+            NewPartEntry->IsPartitioned = FALSE;
+            NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+            NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack;
+
+            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->LogicalPartListHead,
+                           &NewPartEntry->ListEntry);
+
+            return;
+        }
+
+        /* Start partition at head 1, cylinder 0 */
+        LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorsPerTrack;
+        LastSectorCount = 0ULL;
+        LastUnusedSectorCount = 0ULL;
+
+        Entry = DiskEntry->LogicalPartListHead.Flink;
+        while (Entry != &DiskEntry->LogicalPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
+
+            if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
+                PartEntry->SectorCount.QuadPart != 0ULL)
+            {
+                LastUnusedSectorCount =
+                    PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack - (LastStartSector + LastSectorCount);
+
+                if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorsPerTrack) > (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->LogicalPartition = TRUE;
+
+                    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->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
+        {
+            LastUnusedSectorCount = Align(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
+
+            if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
+            {
+                DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
+
+                NewPartEntry = RtlAllocateHeap(ProcessHeap,
+                                               HEAP_ZERO_MEMORY,
+                                               sizeof(PARTENTRY));
+                if (NewPartEntry == NULL)
+                    return;
+
+                NewPartEntry->DiskEntry = DiskEntry;
+                NewPartEntry->LogicalPartition = TRUE;
+
+                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->LogicalPartListHead,
+                               &NewPartEntry->ListEntry);
+            }
+        }
+    }
+
     DPRINT1("ScanForUnpartitionedDiskSpace() done\n");
 }
 
@@ -1054,6 +1174,29 @@ AddDiskToList(
         DumpPartitionTable(DiskEntry);
 #endif
 
+        if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
+            DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
+            DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
+        {
+            if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
+            {
+                DPRINT1("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
+            }
+            else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % 1048756 == 0)
+            {
+                DPRINT1("Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+            }
+            else
+            {
+                DPRINT1("No matching aligment found! Partiton 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
+            }
+        }
+        else
+        {
+            DPRINT1("No valid partiton table found! Use megabyte (%lu Sectors) alignment!\n", 1048756 / DiskEntry->BytesPerSector);
+        }
+
+
         if (DiskEntry->LayoutBuffer->PartitionCount == 0)
         {
             DiskEntry->NewDisk = TRUE;
@@ -1866,115 +2009,192 @@ SelectPartition(
 }
 
 
-VOID
+BOOL
 ScrollDownPartitionList(
     PPARTLIST List)
 {
-//    PDISKENTRY DiskEntry;
+    PLIST_ENTRY DiskListEntry;
+    PLIST_ENTRY PartListEntry;
+    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-//    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
 
-    /* Check for empty disks */
+    /* Fail, if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
-        return;
+        return FALSE;
 
     /* Check for next usable entry on current disk */
     if (List->CurrentPartition != NULL)
     {
-        Entry2 = List->CurrentPartition->ListEntry.Flink;
-        if (Entry2 != &List->CurrentDisk->PrimaryPartListHead)
+        if (List->CurrentPartition->LogicalPartition)
         {
-            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            /* Logical partition */
 
-            List->CurrentPartition = PartEntry;
-            DrawPartitionList(List);
-            return;
-        }
-    }
+            PartListEntry = List->CurrentPartition->ListEntry.Flink;
+            if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+            {
+                /* Next logical partition */
+                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-#if 0
-    /* Check for first usable entry on next disk */
-    if (List->CurrentDisk != NULL)
-    {
-        Entry1 = List->CurrentDisk->ListEntry.Flink;
-        while (Entry1 != &List->DiskListHead)
+                List->CurrentPartition = PartEntry;
+                return TRUE;
+            }
+            else
+            {
+                PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
+                if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+                {
+                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+                    List->CurrentPartition = PartEntry;
+                    return TRUE;
+                }
+            }
+        }
+        else
         {
-            DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+            /* Primary or extended partition */
 
-            Entry2 = DiskEntry->PartListHead.Flink;
-            if (Entry2 != &DiskEntry->PartListHead)
+            if (IsContainerPartition(List->CurrentPartition->PartitionType))
             {
-                PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+                /* First logical partition */
+                PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
+                if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+                {
+                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-                List->CurrentDisk = DiskEntry;
-                List->CurrentPartition = PartEntry;
-                DrawPartitionList(List);
-                return;
+                    List->CurrentPartition = PartEntry;
+                    return TRUE;
+                }
+            }
+            else
+            {
+                /* Next primary partition */
+                PartListEntry = List->CurrentPartition->ListEntry.Flink;
+                if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+                {
+                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+                    List->CurrentPartition = PartEntry;
+                    return TRUE;
+                }
             }
+        }
+    }
+
+    /* Search for the first partition entry on the next disk */
+    DiskListEntry = List->CurrentDisk->ListEntry.Flink;
+    while (DiskListEntry != &List->DiskListHead)
+    {
+        DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+
+        PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
+        if (PartListEntry != &DiskEntry->PrimaryPartListHead)
+        {
+            PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-            Entry1 = Entry1->Flink;
+            List->CurrentDisk = DiskEntry;
+            List->CurrentPartition = PartEntry;
+            return TRUE;
         }
+
+        DiskListEntry = DiskListEntry->Flink;
     }
-#endif
+
+    return FALSE;
 }
 
 
-VOID
+BOOL
 ScrollUpPartitionList(
     PPARTLIST List)
 {
-//    PDISKENTRY DiskEntry;
+    PLIST_ENTRY DiskListEntry;
+    PLIST_ENTRY PartListEntry;
+    PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-//    PLIST_ENTRY Entry1;
-    PLIST_ENTRY Entry2;
 
-    /* Check for empty disks */
+    /* Fail, if no disks are available */
     if (IsListEmpty(&List->DiskListHead))
-        return;
+        return FALSE;
 
-    /* check for previous usable entry on current disk */
+    /* Check for previous usable entry on current disk */
     if (List->CurrentPartition != NULL)
     {
-        Entry2 = List->CurrentPartition->ListEntry.Blink;
-        if (Entry2 != &List->CurrentDisk->PrimaryPartListHead)
+        if (List->CurrentPartition->LogicalPartition)
         {
-            PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+            /* Logical partition */
+            PartListEntry = List->CurrentPartition->ListEntry.Blink;
+            if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
+            {
+                /* Previous logical partition */
+                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+            }
+            else
+            {
+                /* Extended partition*/
+                PartEntry = List->CurrentDisk->ExtendedPartition;
+            }
 
             List->CurrentPartition = PartEntry;
+            return TRUE;
+        }
+        else
+        {
+            /* Primary or extended partition */
+
+            PartListEntry = List->CurrentPartition->ListEntry.Blink;
+            if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
+            {
+                PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+
+                if (IsContainerPartition(PartEntry->PartitionType))
+                {
+                    PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
+                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
+                }
+
+                List->CurrentPartition = PartEntry;
+                return TRUE;
+            }
 
-            /* Draw partition list and return */
-            DrawPartitionList(List);
-            return;
         }
     }
 
-#if 0
-    /* check for last usable entry on previous disk */
-    if (List->CurrentDisk != NULL)
+    /* Search for the last partition entry on the previous disk */
+    DiskListEntry = List->CurrentDisk->ListEntry.Blink;
+    while (DiskListEntry != &List->DiskListHead)
     {
-        Entry1 = List->CurrentDisk->ListEntry.Blink;
-        while (Entry1 != &List->DiskListHead)
+        DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
+
+        PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
+        if (PartListEntry != &DiskEntry->PrimaryPartListHead)
         {
-            DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
+            PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
-            Entry2 = DiskEntry->PrimaryPartListHead.Blink;
-            if (Entry2 != &DiskEntry->PrimaryPartListHead)
+            if (IsContainerPartition(PartEntry->PartitionType))
             {
-                PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
+                PartListEntry = DiskEntry->LogicalPartListHead.Blink;
+                if (PartListEntry != &DiskEntry->LogicalPartListHead)
+                {
+                    PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
 
+                    List->CurrentDisk = DiskEntry;
+                    List->CurrentPartition = PartEntry;
+                    return TRUE;
+                }
+            }
+            else
+            {
                 List->CurrentDisk = DiskEntry;
                 List->CurrentPartition = PartEntry;
-
-                /* Draw partition list and return */
-                DrawPartitionList(List);
-                return;
+                return TRUE;
             }
-
-            Entry1 = Entry1->Blink;
         }
+
+        DiskListEntry = DiskListEntry->Blink;
     }
-#endif
+
+    return FALSE;
 }
 
 
@@ -2355,6 +2575,32 @@ DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
 }
 
 
+VOID
+CreateLogicalPartition(
+    PPARTLIST List,
+    ULONGLONG SectorCount)
+{
+//    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
+//    PPARTENTRY NewPartEntry;
+
+    DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
+
+    if (List == NULL ||
+        List->CurrentDisk == NULL ||
+        List->CurrentPartition == NULL ||
+        List->CurrentPartition->IsPartitioned == TRUE)
+    {
+        return;
+    }
+
+//    DiskEntry = List->CurrentDisk;
+    PartEntry = List->CurrentPartition;
+
+    DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
+}
+
+
 VOID
 DeleteCurrentPartition(
     PPARTLIST List)
@@ -2866,4 +3112,22 @@ ExtendedPartitionCreationChecks(
     return ERROR_SUCCESS;
 }
 
+
+ULONG
+LogicalPartitionCreationChecks(
+    IN PPARTLIST List)
+{
+//    PDISKENTRY DiskEntry;
+    PPARTENTRY PartEntry;
+
+//    DiskEntry = List->CurrentDisk;
+    PartEntry = List->CurrentPartition;
+
+    /* Fail if partition is already in use */
+    if (PartEntry->IsPartitioned == TRUE)
+        return ERROR_NEW_PARTITION;
+
+    return ERROR_SUCCESS;
+}
+
 /* EOF */