[SETUPLIB][USETUP] Code simplifications & fixes.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 24 Aug 2019 23:32:46 +0000 (01:32 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 25 Aug 2019 00:38:52 +0000 (02:38 +0200)
SETUPLIB:
=========

- Remove useless HiddenSectors member in PARTENTRY structure.
- InsertDiskRegion() helper returns a BOOLEAN success.
- CreateInsertBlankRegion() helper sets LogicalPartition.

- Simplify the InitializePartitionEntry() helper so that its PartEntry
  parameter is clearly the one that is being initialized (i.e. converted
  from a blank region to) an actual partition, and use the helper
  CreateInsertBlankRegion(). The calculations for the StartSector and
  SectorCount are exactly equivalent with the old version of this
  function. Also make it return a BOOLEAN success instead.
  + Add some extra validation checks.
  + Adjust CreatePrimaryPartition(), CreateExtendedPartition() and
    CreateLogicalPartition() in this regard.

- Better handling of "RAW"-mounted partitions: treat them as
  "Unformatted" only if they are RAW *AND* their PartitionType is one of
  those associated with FAT file-system. Otherwise we cannot decide
  whether they are indeed unformatted or have an unknown file-system on
  them, therefore treat them as the latter.
  In this regard, the IsSupportedActivePartition() helper should not
  look for FileSystem == RAW but instead only look whether the partition
  is Unformatted.

  This should help with situations similar to the one described in CORE-16274
  where a partition with a genuine file-system but not recognized by
  ReactOS (because we currently do not have the EXT2/3/4 filesystem
  driver loaded during 1st-stage setup due to commit 5a650f6b) and
  therefore mounted as RAW, was thought to be unformatted.

USETUP:
=======
- Use the "global" SystemPartition pointer: this is the "system"
  partition we will actually use. It can be different from the actual
  one of the computer, for example when we install ReactOS on a
  removable disk. This allows also to simplify the code.

- Remove the single-used DestinationDriveLetter variable.

- Remove BuildInstallPaths() helper and use InitDestinationPaths()
  directly instead.

- Always mention the disk where the partition being formatted is.
- Cleanup old code comments, add assertions here & there...

base/setup/lib/utils/partlist.c
base/setup/lib/utils/partlist.h
base/setup/usetup/usetup.c

index 1930748..19b49a6 100644 (file)
@@ -748,7 +748,7 @@ IsSuperFloppy(
  * Of course no disk region should overlap at all with one another.
  */
 static
-VOID
+BOOLEAN
 InsertDiskRegion(
     IN PDISKENTRY DiskEntry,
     IN PPARTENTRY PartEntry,
@@ -801,7 +801,7 @@ InsertDiskRegion(
                      PartEntry->StartSector.QuadPart +  PartEntry->SectorCount.QuadPart - 1,
                     PartEntry2->StartSector.QuadPart,
                     PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1);
-            return;
+            return FALSE;
         }
 
         /* We have found the first region before which the new one has to be inserted */
@@ -810,6 +810,7 @@ InsertDiskRegion(
 
     /* Insert the disk region */
     InsertTailList(Entry, &PartEntry->ListEntry);
+    return TRUE;
 }
 
 static
@@ -834,6 +835,7 @@ CreateInsertBlankRegion(
     NewPartEntry->StartSector.QuadPart = StartSector;
     NewPartEntry->SectorCount.QuadPart = SectorCount;
 
+    NewPartEntry->LogicalPartition = LogicalSpace;
     NewPartEntry->IsPartitioned = FALSE;
     NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
     NewPartEntry->FormatState = Unformatted;
@@ -850,69 +852,72 @@ CreateInsertBlankRegion(
 }
 
 static
-// BOOLEAN
-PPARTENTRY
+BOOLEAN
 InitializePartitionEntry(
-    IN PDISKENTRY DiskEntry,
-    IN PPARTENTRY PartEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
-    PPARTENTRY NewPartEntry;
+    PDISKENTRY DiskEntry = PartEntry->DiskEntry;
 
     DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
 
+    /* Fail if we try to initialize this partition entry with more sectors than what it actually contains */
+    if (SectorCount > PartEntry->SectorCount.QuadPart)
+        return FALSE;
+
+    /* Fail if the partition is already in use */
+    ASSERT(!PartEntry->IsPartitioned);
+
     if ((AutoCreate != FALSE) ||
         (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
                    PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
     {
-        DPRINT1("Convert existing partition entry\n");
-
-        NewPartEntry = PartEntry;
-        NewPartEntry->AutoCreate = AutoCreate;
+        PartEntry->AutoCreate = AutoCreate;
     }
     else
     {
-        DPRINT1("Add new partition entry\n");
-
-        /* Insert and initialize a new partition entry */
-        NewPartEntry = RtlAllocateHeap(ProcessHeap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof(PARTENTRY));
-        if (NewPartEntry == NULL)
-            return NULL;
+        ULONGLONG StartSector;
+        ULONGLONG SectorCount2;
+        PPARTENTRY NewPartEntry;
 
-        NewPartEntry->DiskEntry = DiskEntry;
+        /* Create a partition entry that represents the remaining space after the partition to be initialized */
 
-        NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
-        NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
-                                             NewPartEntry->StartSector.QuadPart;
+        StartSector = AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment);
+        SectorCount2 = PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - StartSector;
 
-        PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
-        PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
+        NewPartEntry = CreateInsertBlankRegion(DiskEntry,
+                                               PartEntry->ListEntry.Flink,
+                                               StartSector,
+                                               SectorCount2,
+                                               PartEntry->LogicalPartition);
+        if (NewPartEntry == NULL)
+        {
+            DPRINT1("Failed to create a new empty region for disk space!\n");
+            return FALSE;
+        }
 
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry);
+        /* Resize down the partition entry; its StartSector remains the same */
+        PartEntry->SectorCount.QuadPart = StartSector - PartEntry->StartSector.QuadPart;
     }
 
-    /* Create entry as 'New (Unformatted)' */
-    NewPartEntry->New = TRUE;
-    NewPartEntry->IsPartitioned = TRUE;
+    /* Convert the partition entry to 'New (Unformatted)' */
+    PartEntry->New = TRUE;
+    PartEntry->IsPartitioned = TRUE;
 
-    NewPartEntry->PartitionType = FileSystemToPartitionType(L"RAW", &NewPartEntry->StartSector, &NewPartEntry->SectorCount);
-    ASSERT(NewPartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+    PartEntry->PartitionType = FileSystemToPartitionType(L"RAW", &PartEntry->StartSector, &PartEntry->SectorCount);
+    ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
 
-    NewPartEntry->FormatState = Unformatted;
-    NewPartEntry->FileSystem[0] = L'\0';
-    // NewPartEntry->AutoCreate = AutoCreate;
-    NewPartEntry->BootIndicator = FALSE;
-    NewPartEntry->LogicalPartition = FALSE;
+    PartEntry->FormatState = Unformatted;
+    PartEntry->FileSystem[0] = L'\0';
+    // PartEntry->AutoCreate = AutoCreate;
+    PartEntry->BootIndicator = FALSE;
 
-    DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
-    DPRINT1("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
-    DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
+    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);
 
-    return NewPartEntry;
+    return TRUE;
 }
 
 
@@ -956,7 +961,6 @@ AddPartitionToDisk(
 
     PartEntry->BootIndicator = PartitionInfo->BootIndicator;
     PartEntry->PartitionType = PartitionInfo->PartitionType;
-    PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
 
     PartEntry->LogicalPartition = LogicalPartition;
     PartEntry->IsPartitioned = TRUE;
@@ -983,7 +987,7 @@ AddPartitionToDisk(
         ASSERT(PartitionInfo->RecognizedPartition);
         ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
 
-        /* Open the volume, ignore any errors */
+        /* Try to open the volume so as to mount it */
         RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
                             L"\\Device\\Harddisk%lu\\Partition%lu",
                             DiskEntry->DiskNumber,
@@ -1008,8 +1012,10 @@ AddPartitionToDisk(
             DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
         }
 
-        if (/* NT_SUCCESS(Status) && */ PartitionHandle)
+        if (PartitionHandle)
         {
+            ASSERT(NT_SUCCESS(Status));
+
             /* We don't have a FS, try to guess one */
             Status = InferFileSystemByHandle(PartitionHandle,
                                              PartEntry->PartitionType,
@@ -1020,10 +1026,54 @@ AddPartitionToDisk(
         }
         if (*PartEntry->FileSystem)
         {
+            ASSERT(PartitionHandle);
+
+            /*
+             * Handle partition mounted with RawFS: it is
+             * either unformatted or has an unknown format.
+             */
             if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
-                PartEntry->FormatState = Unformatted;
+            {
+                /*
+                 * True unformatted partitions on NT are created with their
+                 * partition type set to either one of the following values,
+                 * and are mounted with RawFS. This is done this way since we
+                 * are assured to have FAT support, which is the only FS that
+                 * uses these partition types. Therefore, having a partition
+                 * mounted with RawFS and with these partition types means that
+                 * the FAT FS was unable to mount it beforehand and thus the
+                 * partition is unformatted.
+                 * However, any partition mounted by RawFS that does NOT have
+                 * any of these partition types must be considered as having
+                 * an unknown format.
+                 */
+                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)
+                {
+                    PartEntry->FormatState = Unformatted;
+                }
+                else
+                {
+                    /* Close the partition before dismounting */
+                    NtClose(PartitionHandle);
+                    PartitionHandle = NULL;
+                    /*
+                     * Dismount the partition since RawFS owns it, and set its
+                     * format to unknown (may or may not be actually formatted).
+                     */
+                    DismountVolume(PartEntry);
+                    PartEntry->FormatState = UnknownFormat;
+                    PartEntry->FileSystem[0] = L'\0';
+                }
+            }
             else
+            {
                 PartEntry->FormatState = Preformatted;
+            }
         }
         else
         {
@@ -1056,7 +1106,7 @@ AddPartitionToDisk(
     }
     else
     {
-        /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
+        /* Unknown partition, hence unknown format (may or may not be actually formatted) */
         PartEntry->FormatState = UnknownFormat;
     }
 
@@ -1195,7 +1245,6 @@ ScanForUnpartitionedDiskSpace(
                 DPRINT1("Failed to create a new empty region for full extended partition space!\n");
                 return;
             }
-            NewPartEntry->LogicalPartition = TRUE;
 
             return;
         }
@@ -1236,7 +1285,6 @@ ScanForUnpartitionedDiskSpace(
                         DPRINT1("Failed to create a new empty region for extended partition space!\n");
                         return;
                     }
-                    NewPartEntry->LogicalPartition = TRUE;
                 }
 
                 LastStartSector = PartEntry->StartSector.QuadPart;
@@ -1269,7 +1317,6 @@ ScanForUnpartitionedDiskSpace(
                     DPRINT1("Failed to create a new empty region for extended partition space!\n");
                     return;
                 }
-                NewPartEntry->LogicalPartition = TRUE;
             }
         }
     }
@@ -1846,9 +1893,9 @@ CreatePartitionList(VOID)
     ULONG ReturnSize;
     NTSTATUS Status;
     ULONG DiskNumber;
-    WCHAR Buffer[MAX_PATH];
-    UNICODE_STRING Name;
     HANDLE FileHandle;
+    UNICODE_STRING Name;
+    WCHAR Buffer[MAX_PATH];
 
     List = (PPARTLIST)RtlAllocateHeap(ProcessHeap,
                                       0,
@@ -2768,37 +2815,34 @@ GetNextUnpartitionedEntry(
 BOOLEAN
 CreatePrimaryPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PPARTENTRY PartEntry;
 
     DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
 
-    if (List == NULL ||
-        SelectedEntry == NULL ||
-        SelectedEntry->DiskEntry == NULL ||
-        SelectedEntry->IsPartitioned)
+    if (List == NULL || PartEntry == NULL ||
+        PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = PrimaryPartitionCreationChecks(SelectedEntry);
+    Error = PrimaryPartitionCreationChecks(PartEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("PrimaryPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
-    if (PartEntry == NULL)
+    /* Initialize the partition entry, inserting a new blank region if needed */
+    if (!InitializePartitionEntry(PartEntry, SectorCount, AutoCreate))
         return FALSE;
 
-    UpdateDiskLayout(PartEntry->DiskEntry);
+    ASSERT(PartEntry->LogicalPartition == FALSE);
 
+    UpdateDiskLayout(PartEntry->DiskEntry);
     AssignDriveLetters(List);
 
     return TRUE;
@@ -2830,40 +2874,37 @@ AddLogicalDiskSpace(
         DPRINT1("Failed to create a new empty region for extended partition space!\n");
         return;
     }
-    NewPartEntry->LogicalPartition = TRUE;
 }
 
 BOOLEAN
 CreateExtendedPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount)
 {
     ERROR_NUMBER Error;
-    PPARTENTRY PartEntry;
 
     DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
 
-    if (List == NULL ||
-        SelectedEntry == NULL ||
-        SelectedEntry->DiskEntry == NULL ||
-        SelectedEntry->IsPartitioned)
+    if (List == NULL || PartEntry == NULL ||
+        PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = ExtendedPartitionCreationChecks(SelectedEntry);
+    Error = ExtendedPartitionCreationChecks(PartEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("ExtendedPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, FALSE);
-    if (PartEntry == NULL)
+    /* Initialize the partition entry, inserting a new blank region if needed */
+    if (!InitializePartitionEntry(PartEntry, SectorCount, FALSE))
         return FALSE;
 
+    ASSERT(PartEntry->LogicalPartition == FALSE);
+
     if (PartEntry->StartSector.QuadPart < 1450560)
     {
         /* Partition starts below the 8.4GB boundary ==> CHS partition */
@@ -2884,7 +2925,6 @@ CreateExtendedPartition(
     AddLogicalDiskSpace(PartEntry->DiskEntry);
 
     UpdateDiskLayout(PartEntry->DiskEntry);
-
     AssignDriveLetters(List);
 
     return TRUE;
@@ -2893,45 +2933,39 @@ CreateExtendedPartition(
 BOOLEAN
 CreateLogicalPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate)
 {
     ERROR_NUMBER Error;
-    PPARTENTRY PartEntry;
 
     DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
 
-    if (List == NULL ||
-        SelectedEntry == NULL ||
-        SelectedEntry->DiskEntry == NULL ||
-        SelectedEntry->IsPartitioned)
+    if (List == NULL || PartEntry == NULL ||
+        PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
     {
         return FALSE;
     }
 
-    Error = LogicalPartitionCreationChecks(SelectedEntry);
+    Error = LogicalPartitionCreationChecks(PartEntry);
     if (Error != NOT_AN_ERROR)
     {
         DPRINT1("LogicalPartitionCreationChecks() failed with error %lu\n", Error);
         return FALSE;
     }
 
-    /* Convert the current entry, or insert and initialize a new partition entry */
-    PartEntry = InitializePartitionEntry(SelectedEntry->DiskEntry, SelectedEntry, SectorCount, AutoCreate);
-    if (PartEntry == NULL)
+    /* Initialize the partition entry, inserting a new blank region if needed */
+    if (!InitializePartitionEntry(PartEntry, SectorCount, AutoCreate))
         return FALSE;
 
-    PartEntry->LogicalPartition = TRUE;
+    ASSERT(PartEntry->LogicalPartition == TRUE);
 
     UpdateDiskLayout(PartEntry->DiskEntry);
-
     AssignDriveLetters(List);
 
     return TRUE;
 }
 
-static
 NTSTATUS
 DismountVolume(
     IN PPARTENTRY PartEntry)
@@ -2948,7 +2982,9 @@ DismountVolume(
     if (!PartEntry->IsPartitioned ||
         IsContainerPartition(PartEntry->PartitionType)   ||
         !IsRecognizedPartition(PartEntry->PartitionType) ||
-        PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ ||
+        PartEntry->FormatState == UnknownFormat ||
+        // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
+        // it has been usually mounted with RawFS and thus needs to be dismounted.
         !*PartEntry->FileSystem ||
         PartEntry->PartitionNumber == 0)
     {
@@ -3049,10 +3085,8 @@ DeletePartition(
     PPARTENTRY LogicalPartEntry;
     PLIST_ENTRY Entry;
 
-    if (List == NULL ||
-        PartEntry == NULL ||
-        PartEntry->DiskEntry == NULL ||
-        PartEntry->IsPartitioned == FALSE)
+    if (List == NULL || PartEntry == NULL ||
+        PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned == FALSE)
     {
         return FALSE;
     }
@@ -3154,13 +3188,15 @@ DeletePartition(
     {
         /* Nothing to merge but change the current entry */
         PartEntry->IsPartitioned = FALSE;
+        PartEntry->OnDiskPartitionNumber = 0;
+        PartEntry->PartitionNumber = 0;
+        // PartEntry->PartitionIndex = 0;
+        PartEntry->BootIndicator = FALSE;
         PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
         PartEntry->FormatState = Unformatted;
         PartEntry->FileSystem[0] = L'\0';
         PartEntry->DriveLetter = 0;
-        PartEntry->OnDiskPartitionNumber = 0;
-        PartEntry->PartitionNumber = 0;
-        // PartEntry->PartitionIndex = 0;
+        RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
 
         /* Optionally return the freed region */
         if (FreeRegion)
@@ -3168,7 +3204,6 @@ DeletePartition(
     }
 
     UpdateDiskLayout(DiskEntry);
-
     AssignDriveLetters(List);
 
     return TRUE;
@@ -3179,6 +3214,28 @@ DeletePartition(
  * On MBR disks, partition with the Active/Boot flag set;
  * on GPT disks, partition with the correct GUID.
  */
+BOOLEAN
+IsPartitionActive(
+    IN PPARTENTRY PartEntry)
+{
+    // TODO: Support for GPT disks!
+
+    if (IsContainerPartition(PartEntry->PartitionType))
+        return FALSE;
+
+    /* Check if the partition is partitioned, used and active */
+    if (PartEntry->IsPartitioned &&
+        // !IsContainerPartition(PartEntry->PartitionType) &&
+        PartEntry->BootIndicator)
+    {
+        /* Yes it is */
+        ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 static
 PPARTENTRY
 GetActiveDiskPartition(
@@ -3210,17 +3267,11 @@ GetActiveDiskPartition(
     {
         /* Retrieve the partition */
         PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
-
-        // TODO: Support for GPT disks!
-
-        /* Check if the partition is partitioned, used and active */
-        if (PartEntry->IsPartitioned &&
-            // !IsContainerPartition(PartEntry->PartitionType) &&
-            PartEntry->BootIndicator)
+        if (IsPartitionActive(PartEntry))
         {
-            /* Yes, we found it */
+            /* Yes, we've found it */
             ASSERT(DiskEntry == PartEntry->DiskEntry);
-            ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+            ASSERT(PartEntry->IsPartitioned);
 
             ActivePartition = PartEntry;
 
@@ -3247,7 +3298,7 @@ BOOLEAN
 IsSupportedActivePartition(
     IN PPARTENTRY PartEntry)
 {
-    /* Check the type and the filesystem of this partition */
+    /* Check the type and the file system of this partition */
 
     /*
      * We do not support extended partition containers (on MBR disks) marked
@@ -3276,9 +3327,13 @@ IsSupportedActivePartition(
      * NOTE also that for those architectures looking for a
      * partition boot indicator is insufficient.
      */
-    if ((PartEntry->FormatState == Unformatted ) ||
-        (PartEntry->FormatState == Preformatted) ||
-        (PartEntry->FormatState == Formatted   ))
+    if (PartEntry->FormatState == Unformatted)
+    {
+        /* If this partition is mounted, it would use RawFS ("RAW") */
+        return TRUE;
+    }
+    else if ((PartEntry->FormatState == Preformatted) ||
+             (PartEntry->FormatState == Formatted))
     {
         ASSERT(*PartEntry->FileSystem);
 
@@ -3286,8 +3341,7 @@ IsSupportedActivePartition(
         if (wcsicmp(PartEntry->FileSystem, L"FAT")   == 0 ||
             wcsicmp(PartEntry->FileSystem, L"FAT32") == 0 ||
          // wcsicmp(PartEntry->FileSystem, L"NTFS")  == 0 ||
-            wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0 ||
-            wcsicmp(PartEntry->FileSystem, L"RAW")   == 0)
+            wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0)
         {
             return TRUE;
         }
index fc31cc1..19c24e1 100644 (file)
@@ -44,7 +44,6 @@ typedef struct _PARTENTRY
 
     BOOLEAN BootIndicator;
     UCHAR PartitionType;
-    ULONG HiddenSectors;
     ULONG OnDiskPartitionNumber; /* Enumerated partition number (primary partitions first, excluding the extended partition container, then the logical partitions) */
     ULONG PartitionNumber;       /* Current partition number, only valid for the currently running NTOS instance */
     ULONG PartitionIndex;        /* Index in the LayoutBuffer->PartitionEntry[] cached array of the corresponding DiskEntry */
@@ -231,6 +230,9 @@ BOOLEAN
 IsSuperFloppy(
     IN PDISKENTRY DiskEntry);
 
+BOOLEAN
+IsPartitionActive(
+    IN PPARTENTRY PartEntry);
 
 PPARTLIST
 CreatePartitionList(VOID);
@@ -294,23 +296,27 @@ GetPrevPartition(
 BOOLEAN
 CreatePrimaryPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate);
 
 BOOLEAN
 CreateExtendedPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount);
 
 BOOLEAN
 CreateLogicalPartition(
     IN PPARTLIST List,
-    IN PPARTENTRY SelectedEntry,
+    IN OUT PPARTENTRY PartEntry,
     IN ULONGLONG SectorCount,
     IN BOOLEAN AutoCreate);
 
+NTSTATUS
+DismountVolume(
+    IN PPARTENTRY PartEntry);
+
 BOOLEAN
 DeletePartition(
     IN PPARTLIST List,
index 8aaf3cc..daf786d 100644 (file)
@@ -46,12 +46,19 @@ BOOLEAN IsUnattendedSetup = FALSE;
 
 static USETUP_DATA USetupData;
 
-/* Partition where to perform the installation */
+/* The partition where to perform the installation */
 static PPARTENTRY InstallPartition = NULL;
-// static PPARTENTRY SystemPartition = NULL;    // The system partition we will actually use (can be different from PartitionList->SystemPartition in case we install on removable disk)
-
-// FIXME: Is it really useful?? Just used for SetDefaultPagefile...
-static WCHAR DestinationDriveLetter;
+/*
+ * The system partition we will actually use. It can be different from
+ * PartitionList->SystemPartition in case we don't support it, or we install
+ * on a removable disk.
+ * We may indeed not support the original system partition in case we do not
+ * have write support on it. Please note that this situation is partly a HACK
+ * and MUST NEVER happen on architectures where real system partitions are
+ * mandatory (because then they are formatted in FAT FS and we support write
+ * operation on them).
+ */
+static PPARTENTRY SystemPartition = NULL;
 
 
 /* OTHER Stuff *****/
@@ -1465,7 +1472,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
         PartitionList = CreatePartitionList();
         if (PartitionList == NULL)
         {
-            /* FIXME: show an error dialog */
             MUIDisplayError(ERROR_DRIVE_INFORMATION, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
@@ -1784,7 +1790,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
 
 // FIXME TODO: PartitionList->SystemPartition is not yet initialized!!!!
             if (CurrentPartition == PartitionList->SystemPartition ||
-                CurrentPartition->BootIndicator)
+                IsPartitionActive(CurrentPartition))
             {
                 return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
             }
@@ -1879,7 +1885,7 @@ ShowPartitionSizeInputBox(SHORT Left,
             CONSOLE_SetCursorType(TRUE, FALSE);
             break;
         }
-        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)    /* ESCAPE */
+        else if (Ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)    /* ESC */
         {
             if (Cancel != NULL)
                 *Cancel = TRUE;
@@ -2733,20 +2739,21 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
             //
             return QUIT_PAGE;
         }
+        SystemPartition = PartitionList->SystemPartition;
 
         /*
          * If the system partition can be created in some
          * non-partitioned space, create it now.
          */
-        if (!PartitionList->SystemPartition->IsPartitioned)
+        if (!SystemPartition->IsPartitioned)
         {
             // if (IsUnattendedSetup)
             {
                 CreatePrimaryPartition(PartitionList,
-                                       PartitionList->SystemPartition,
-                                       0LL, // PartitionList->SystemPartition->SectorCount.QuadPart,
+                                       SystemPartition,
+                                       0LL, // SystemPartition->SectorCount.QuadPart,
                                        TRUE);
-                ASSERT(PartitionList->SystemPartition->IsPartitioned);
+                ASSERT(SystemPartition->IsPartitioned);
             }
             // else
             {
@@ -2767,8 +2774,8 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
          * installation partitions.
          */
         InstallPartition->NeedsCheck = TRUE;
-        if (PartitionList->SystemPartition != InstallPartition)
-            PartitionList->SystemPartition->NeedsCheck = TRUE;
+        if (SystemPartition != InstallPartition)
+            SystemPartition->NeedsCheck = TRUE;
 
         /*
          * In case we just repair an existing installation, or make
@@ -2782,7 +2789,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
             return CHECK_FILE_SYSTEM_PAGE;
     }
 
-    // ASSERT(PartitionList->SystemPartition->IsPartitioned);
+    // ASSERT(SystemPartition->IsPartitioned);
 
     /* Reset the filesystem list for each partition that is to be formatted */
     ResetFileSystemList();
@@ -2799,12 +2806,12 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
              * and start by formatting the installation partition instead.
              */
 
-            ASSERT(PartitionList->SystemPartition->IsPartitioned);
+            ASSERT(SystemPartition->IsPartitioned);
 
-            if ((PartitionList->SystemPartition != InstallPartition) &&
-                (PartitionList->SystemPartition->FormatState == Unformatted))
+            if ((SystemPartition != InstallPartition) &&
+                (SystemPartition->FormatState == Unformatted))
             {
-                TempPartition = PartitionList->SystemPartition;
+                TempPartition = SystemPartition;
                 TempPartition->NeedsCheck = TRUE;
 
                 // TODO: Should we let the user using a custom file-system,
@@ -2819,14 +2826,14 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                 TempPartition = InstallPartition;
                 TempPartition->NeedsCheck = TRUE;
 
-                if (PartitionList->SystemPartition != InstallPartition)
+                if (SystemPartition != InstallPartition)
                 {
                     /* The system partition is separate, so it had better be formatted! */
-                    ASSERT((PartitionList->SystemPartition->FormatState == Preformatted) ||
-                           (PartitionList->SystemPartition->FormatState == Formatted));
+                    ASSERT((SystemPartition->FormatState == Preformatted) ||
+                           (SystemPartition->FormatState == Formatted));
 
                     /* Require a filesystem check on the system partition too */
-                    PartitionList->SystemPartition->NeedsCheck = TRUE;
+                    SystemPartition->NeedsCheck = TRUE;
                 }
 
                 FormatState = FormatInstallPartition;
@@ -2883,7 +2890,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
         default:
         {
             DPRINT1("FormatState: Invalid value %ld\n", FormatState);
-            /* FIXME: show an error dialog */
+            ASSERT(FALSE);
             return QUIT_PAGE;
         }
     }
@@ -2971,10 +2978,23 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                 break;
 
             default:
+                ASSERT(FALSE);
                 break;
         }
 
-        CONSOLE_SetTextXY(6, 10, MUIGetString(STRING_PARTFORMAT));
+        CONSOLE_PrintTextXY(8, 10, MUIGetString(STRING_HDINFOPARTZEROED_1),
+                            DiskEntry->DiskNumber,
+                            DiskSize,
+                            DiskUnit,
+                            DiskEntry->Port,
+                            DiskEntry->Bus,
+                            DiskEntry->Id,
+                            &DiskEntry->DriverName,
+                            DiskEntry->DiskStyle == PARTITION_STYLE_MBR ? "MBR" :
+                            DiskEntry->DiskStyle == PARTITION_STYLE_GPT ? "GPT" :
+                                                                          "RAW");
+
+        CONSOLE_SetTextXY(6, 12, MUIGetString(STRING_PARTFORMAT));
     }
     else
     {
@@ -3108,7 +3128,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
                  * filesystem checks on it, unless it is either the system
                  * or the installation partition.
                  */
-                if (TempPartition != PartitionList->SystemPartition &&
+                if (TempPartition != SystemPartition &&
                     TempPartition != InstallPartition)
                 {
                     PartEntry->NeedsCheck = FALSE;
@@ -3435,15 +3455,10 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     else if (!NT_SUCCESS(Status))
     {
         DPRINT("ChkdskPartition() failed with status 0x%08lx\n", Status);
-        // sprintf(Buffer, "Setup failed to verify the selected partition.\n"
-        sprintf(Buffer, "ChkDsk detected some disk errors.\n"
-                "(Status 0x%08lx).\n", Status);
+        sprintf(Buffer, "ChkDsk detected some disk errors.\n(Status 0x%08lx).\n", Status);
         PopupError(Buffer,
-                   // MUIGetString(STRING_REBOOTCOMPUTER),
                    MUIGetString(STRING_CONTINUE),
                    Ir, POPUP_WAIT_ENTER);
-
-        // return QUIT_PAGE;
     }
 
     PartEntry->NeedsCheck = FALSE;
@@ -3451,28 +3466,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
 }
 
 
-static NTSTATUS
-BuildInstallPaths(
-    IN PCWSTR InstallDir,
-    IN PPARTENTRY PartEntry)
-{
-    NTSTATUS Status;
-
-    Status = InitDestinationPaths(&USetupData, InstallDir, PartEntry);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("InitDestinationPaths() failed with status 0x%08lx\n", Status);
-        return Status;
-    }
-
-    /* Initialize DestinationDriveLetter */
-    DestinationDriveLetter = PartEntry->DriveLetter;
-
-    return STATUS_SUCCESS;
-}
-
-
 static BOOLEAN
 IsValidPath(
     IN PCWSTR InstallDir)
@@ -3563,10 +3556,10 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
      */
     if ((RepairUpdateFlag || IsUnattendedSetup) && IsValidPath(InstallDir))
     {
-        Status = BuildInstallPaths(InstallDir, InstallPartition);
+        Status = InitDestinationPaths(&USetupData, InstallDir, InstallPartition);
         if (!NT_SUCCESS(Status))
         {
-            DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status);
+            DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
             MUIDisplayError(ERROR_NO_BUILD_PATH, Ir, POPUP_WAIT_ENTER);
             return QUIT_PAGE;
         }
@@ -3667,10 +3660,10 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
                 return INSTALL_DIRECTORY_PAGE;
             }
 
-            Status = BuildInstallPaths(InstallDir, InstallPartition);
+            Status = InitDestinationPaths(&USetupData, InstallDir, InstallPartition);
             if (!NT_SUCCESS(Status))
             {
-                DPRINT1("BuildInstallPaths() failed. Status code: 0x%lx", Status);
+                DPRINT1("InitDestinationPaths() failed. Status code: 0x%lx", Status);
                 MUIDisplayError(ERROR_NO_BUILD_PATH, Ir, POPUP_WAIT_ENTER);
                 return QUIT_PAGE;
             }
@@ -4068,7 +4061,7 @@ RegistryPage(PINPUT_RECORD Ir)
     Error = UpdateRegistry(&USetupData,
                            RepairUpdateFlag,
                            PartitionList,
-                           DestinationDriveLetter,
+                           InstallPartition->DriveLetter,
                            SelectedLanguageId,
                            RegistryStatus);
     if (Error != ERROR_SUCCESS)
@@ -4114,17 +4107,17 @@ BootLoaderPage(PINPUT_RECORD Ir)
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-    ASSERT(PartitionList->SystemPartition->IsPartitioned && PartitionList->SystemPartition->PartitionNumber != 0);
+    ASSERT(SystemPartition->IsPartitioned && SystemPartition->PartitionNumber != 0);
 
     RtlFreeUnicodeString(&USetupData.SystemRootPath);
     RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
-            PartitionList->SystemPartition->DiskEntry->DiskNumber,
-            PartitionList->SystemPartition->PartitionNumber);
+            SystemPartition->DiskEntry->DiskNumber,
+            SystemPartition->PartitionNumber);
     RtlCreateUnicodeString(&USetupData.SystemRootPath, PathBuffer);
     DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
 
-    PartitionType = PartitionList->SystemPartition->PartitionType;
+    PartitionType = SystemPartition->PartitionType;
 
     /* For unattended setup, skip MBR installation or install on floppy if needed */
     if (IsUnattendedSetup)
@@ -4392,11 +4385,11 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
     Status = InstallVBRToPartition(&USetupData.SystemRootPath,
                                    &USetupData.SourceRootPath,
                                    &USetupData.DestinationArcPath,
-                                   PartitionList->SystemPartition->PartitionType);
+                                   SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem);
+                        SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
@@ -4429,20 +4422,20 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     Status = InstallVBRToPartition(&USetupData.SystemRootPath,
                                    &USetupData.SourceRootPath,
                                    &USetupData.DestinationArcPath,
-                                   PartitionList->SystemPartition->PartitionType);
+                                   SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem);
+                        SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
     /* Step 2: Write the MBR if the disk containing the system partition is not a super-floppy */
-    if (!IsSuperFloppy(PartitionList->SystemPartition->DiskEntry))
+    if (!IsSuperFloppy(SystemPartition->DiskEntry))
     {
         RtlStringCchPrintfW(DestinationDevicePathBuffer, ARRAYSIZE(DestinationDevicePathBuffer),
                 L"\\Device\\Harddisk%d\\Partition0",
-                PartitionList->SystemPartition->DiskEntry->DiskNumber);
+                SystemPartition->DiskEntry->DiskNumber);
         Status = InstallMbrBootCodeToDisk(&USetupData.SystemRootPath,
                                           &USetupData.SourceRootPath,
                                           DestinationDevicePathBuffer);