https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0d9ebb67ce6a762f8f3f2…
commit 0d9ebb67ce6a762f8f3f29db9ec39c2aaee3dc3a
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Feb 25 23:43:20 2019 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Mar 11 00:05:36 2019 +0100
[SETUPLIB] Improve the discovery of the active system partition.
CORE-7749, CORE-6305, CORE-13205
---
base/setup/lib/utils/partlist.c | 354 +++++++++++++++++++++++++++++++---------
1 file changed, 274 insertions(+), 80 deletions(-)
diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c
index 269bb99b2f..32adeda7c0 100644
--- a/base/setup/lib/utils/partlist.c
+++ b/base/setup/lib/utils/partlist.c
@@ -3037,6 +3037,74 @@ DeleteCurrentPartition(
DeletePartition(List, List->CurrentPartition);
}
+/*
+ * Retrieve the actual "active" partition of the given disk.
+ * On MBR disks, partition with the Active/Boot flag set;
+ * on GPT disks, partition with the correct GUID.
+ */
+static
+PPARTENTRY
+GetActiveDiskPartition(
+ IN PDISKENTRY DiskEntry)
+{
+ PLIST_ENTRY ListEntry;
+ PPARTENTRY PartEntry;
+ PPARTENTRY ActivePartition = NULL;
+
+ /* Check for empty disk list */
+ // ASSERT(DiskEntry);
+ if (!DiskEntry)
+ return NULL;
+
+ /* Check for empty partition list */
+ if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
+ return NULL;
+
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ return NULL;
+ }
+
+ /* Scan all (primary) partitions to find the active disk partition */
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* 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)
+ {
+ /* Yes, we found it */
+ ASSERT(DiskEntry == PartEntry->DiskEntry);
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ ActivePartition = PartEntry;
+
+ DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
+ PartEntry->PartitionNumber, DiskEntry->DiskNumber,
+ (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
+ break;
+ }
+ }
+
+ /* Check if the disk is new and if so, use its first partition as the active system partition */
+ if (DiskEntry->NewDisk && ActivePartition != NULL)
+ {
+ // FIXME: What to do??
+ DPRINT1("NewDisk TRUE but already existing active partition?\n");
+ }
+
+ /* Return the active partition found (or none) */
+ return ActivePartition;
+}
+
static
BOOLEAN
IsSupportedActivePartition(
@@ -3119,24 +3187,16 @@ VOID
CheckActiveSystemPartition(
IN PPARTLIST List)
{
+ PLIST_ENTRY ListEntry;
PDISKENTRY DiskEntry;
PPARTENTRY PartEntry;
- PLIST_ENTRY ListEntry;
+ PPARTENTRY ActivePartition;
+ PPARTENTRY CandidatePartition = NULL;
/* Check for empty disk list */
if (IsListEmpty(&List->DiskListHead))
{
- List->SystemPartition = NULL;
- List->OriginalSystemPartition = NULL;
- return;
- }
-
- /* Choose the currently selected disk */
- DiskEntry = List->CurrentDisk;
-
- /* Check for empty partition list */
- if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
- {
+ /* No system partition! */
List->SystemPartition = NULL;
List->OriginalSystemPartition = NULL;
return;
@@ -3152,17 +3212,182 @@ CheckActiveSystemPartition(
return;
}
- DPRINT("We are here (1)!\n");
-
+ /* Start fresh */
List->SystemPartition = NULL;
List->OriginalSystemPartition = NULL;
+
+//
+// Pass == 1 : Checking the first disk.
+//
+ DPRINT("We are here (1)!\n");
+
+ /*
+ * First, check whether the first disk (the one that will be booted
+ * by default by the hardware) contains an active partition. If so
+ * this should be our system partition.
+ */
+ DiskEntry = CONTAINING_RECORD(List->DiskListHead.Flink,
+ DISKENTRY, ListEntry);
+
+ // if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ // {
+ // DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ // continue;
+ // }
+
+ DPRINT("We are here (1a)!\n");
+
+ ActivePartition = GetActiveDiskPartition(DiskEntry);
+ if (ActivePartition)
+ {
+ /* Save the actual system partition */
+ List->OriginalSystemPartition = ActivePartition;
+
+ /* If we get a candidate active partition in the first disk, validate it */
+ if (IsSupportedActivePartition(ActivePartition))
+ {
+ CandidatePartition = ActivePartition;
+ goto SystemPartitionFound;
+ }
+ }
+
+ DPRINT("We are here (1b)!\n");
+
+ /* If this first disk is not the current installation disk, do the minimal checks */
+ if (DiskEntry != List->CurrentDisk)
+ {
+ /*
+ * We don't. Enumerate all the (primary) partitions in the first disk,
+ * excluding the current active partition, to find a candidate new one.
+ */
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ /* Skip the current active partition */
+ if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+ continue;
+
+ /* Check if the partition is partitioned and used */
+ if (PartEntry->IsPartitioned &&
+ !IsContainerPartition(PartEntry->PartitionType))
+ {
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+
+ /* If we get a candidate active partition in the first disk, validate it */
+ if (IsSupportedActivePartition(PartEntry))
+ {
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+
+#if 0
+ /* Check if the partition is partitioned and used */
+ if (!PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+ // TODO: Check for minimal size!!
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+#endif
+ }
+
+ /*
+ * Still nothing, look whether there is some free space that we can use
+ * for the new system partition. We must be sure that the total number
+ * of partition is less than the maximum allowed, and that the minimal
+ * size is fine.
+ */
+//
+// TODO: Fix the handling of system partition being created in unpartitioned space!!
+// --> When to partition it? etc...
+//
+ if (GetPrimaryPartitionCount(DiskEntry) < 4)
+ {
+ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
+ ListEntry != &DiskEntry->PrimaryPartListHead;
+ ListEntry = ListEntry->Flink)
+ {
+ /* Retrieve the partition */
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+
+ /* Skip the current active partition */
+ if (/* ActivePartition != NULL && */ PartEntry == ActivePartition)
+ continue;
+
+ /* Check for unpartitioned space */
+ if (!PartEntry->IsPartitioned)
+ {
+ ASSERT(PartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
+
+ // TODO: Check for minimal size!!
+ CandidatePartition = PartEntry;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+ }
+ }
+
+
+ /**** Case where we don't have an active partition on the first disk ****/
+
+//
+// Pass == 2 : Checking the CurrentDisk on which we install.
+//
+ DPRINT("We are here (2)!\n");
+
+ if (DiskEntry != List->CurrentDisk)
+ {
+ /* Choose the currently selected disk */
+ DiskEntry = List->CurrentDisk;
+
+ if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
+ {
+ DPRINT1("Current disk?! -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
+ DPRINT1("No supported active partition found on this system!\n");
+ return;
+ }
+
+ DPRINT("We are here (2x)!\n");
+
+ ActivePartition = GetActiveDiskPartition(DiskEntry);
+ if (ActivePartition)
+ {
+ /* If we get a candidate active partition, validate it */
+ if (IsSupportedActivePartition(ActivePartition))
+ {
+ CandidatePartition = ActivePartition;
+ goto FindAndUseAlternativeSystemPartition;
+ }
+ }
+ }
+
+
+ /**** Here, we either don't have an active partition, or we have one BUT it is not supported ****/
+
+/***
+ *** TODO: Improve the selection:
+ *** - If we want a really separate system partition from the partition where
+ *** we install, do something similar to what's done below in the code.
+ *** - Otherwise if we allow for the system partition to be also the partition
+ *** where we install, just directly fall down to List->CurrentPartition.
+ ***/
+
+ DPRINT("We are here (2a)!\n");
+
/* Retrieve the first partition of the disk */
PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
- PARTENTRY,
- ListEntry);
+ PARTENTRY, ListEntry);
ASSERT(DiskEntry == PartEntry->DiskEntry);
- List->SystemPartition = PartEntry;
+
+ CandidatePartition = PartEntry;
//
// See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlis…
@@ -3171,11 +3396,12 @@ CheckActiveSystemPartition(
/* Check if the disk is new and if so, use its first partition as the active system partition */
if (DiskEntry->NewDisk)
{
- if (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator == FALSE)
+ // !IsContainerPartition(PartEntry->PartitionType);
+ if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
{
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- List->SystemPartition = PartEntry;
+ ASSERT(DiskEntry == CandidatePartition->DiskEntry);
+ List->SystemPartition = CandidatePartition;
List->OriginalSystemPartition = List->SystemPartition;
DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
@@ -3190,7 +3416,7 @@ CheckActiveSystemPartition(
DPRINT1("NewDisk TRUE but first partition is used?\n");
}
- DPRINT("We are here (2)!\n");
+ DPRINT("We are here (3)!\n");
/*
* The disk is not new, check if any partition is initialized;
@@ -3201,12 +3427,12 @@ CheckActiveSystemPartition(
ListEntry = ListEntry->Flink)
{
/* Retrieve the partition */
- PartEntry = CONTAINING_RECORD(ListEntry,
- PARTENTRY,
- ListEntry);
+ PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
/* Check if the partition is partitioned and is used */
- if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator != FALSE)
+ // !IsContainerPartition(PartEntry->PartitionType);
+ if (/* PartEntry->IsPartitioned && */
+ PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
{
break;
}
@@ -3217,8 +3443,9 @@ CheckActiveSystemPartition(
* OK we haven't encountered any used and active partition,
* so use the first one as the system partition.
*/
- ASSERT(DiskEntry == List->SystemPartition->DiskEntry);
- List->OriginalSystemPartition = List->SystemPartition; // First PartEntry
+ ASSERT(DiskEntry == CandidatePartition->DiskEntry);
+ List->SystemPartition = CandidatePartition; // The first PartEntry
+ List->OriginalSystemPartition = List->SystemPartition;
DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
@@ -3228,57 +3455,21 @@ CheckActiveSystemPartition(
goto SetSystemPartition;
}
- List->SystemPartition = NULL;
- List->OriginalSystemPartition = NULL;
-
- DPRINT("We are here (3)!\n");
-
- /* The disk is not new, scan all partitions to find the (active) system partition */
- for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
- ListEntry != &DiskEntry->PrimaryPartListHead;
- ListEntry = ListEntry->Flink)
- {
- /* Retrieve the partition */
- PartEntry = CONTAINING_RECORD(ListEntry,
- PARTENTRY,
- ListEntry);
-
- /* Check if the partition is partitioned and used */
- if (PartEntry->IsPartitioned &&
- PartEntry->PartitionType != PARTITION_ENTRY_UNUSED)
- {
- /* Check if the partition is active */
- if (PartEntry->BootIndicator)
- {
- /* Yes, we found it */
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- List->SystemPartition = PartEntry;
-
- DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
- PartEntry->PartitionNumber,
- DiskEntry->DiskNumber,
- (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
- break;
- }
- }
- }
+ DPRINT("We are here (4)!\n");
- /* Check if we have found the system partition */
- if (List->SystemPartition == NULL)
- {
- /* Nothing, use the alternative system partition */
- DPRINT1("No system partition found, use the alternative partition!\n");
- goto UseAlternativeSystemPartition;
- }
+ /*
+ * The disk is not new, we did not find any actual active partition,
+ * or the one we found was not supported, or any possible other canditate
+ * is not supported. We then use the current (installation) partition.
+ */
+ /* Nothing, use the alternative system partition */
+ DPRINT1("No system partition found, use the alternative partition!\n");
+ CandidatePartition = List->CurrentPartition;
+ goto UseAlternativeSystemPartition;
- /* Save it */
- List->OriginalSystemPartition = List->SystemPartition;
- /* If we get a candidate active partition, validate it */
- if (!IsSupportedActivePartition(List->OriginalSystemPartition))
- {
- goto FindAndUseAlternativeSystemPartition;
- }
+SystemPartitionFound:
+ List->SystemPartition = CandidatePartition;
DPRINT1("Use existing active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
@@ -3298,13 +3489,16 @@ FindAndUseAlternativeSystemPartition:
*/
/* Unset the old system partition */
- List->SystemPartition->BootIndicator = FALSE;
- List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].BootIndicator = FALSE;
- List->SystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->SystemPartition->PartitionIndex].RewritePartition = TRUE;
- List->SystemPartition->DiskEntry->Dirty = TRUE;
+ if (List->OriginalSystemPartition)
+ {
+ List->OriginalSystemPartition->BootIndicator = FALSE;
+ List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].BootIndicator = FALSE;
+ List->OriginalSystemPartition->DiskEntry->LayoutBuffer->PartitionEntry[List->OriginalSystemPartition->PartitionIndex].RewritePartition = TRUE;
+ List->OriginalSystemPartition->DiskEntry->Dirty = TRUE;
+ }
UseAlternativeSystemPartition:
- List->SystemPartition = List->CurrentPartition;
+ List->SystemPartition = CandidatePartition;
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
List->SystemPartition->PartitionNumber,
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a5431030681038941cff3…
commit a5431030681038941cff3037a6b48c35e1ac1b2a
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Feb 25 20:29:16 2019 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Mar 10 15:41:25 2019 +0100
[USETUP] Improve the formatter & check-disk state machine. CORE-7749
- Find or set the active system partition only once, when we start the
formatting stage. If the system partition is to be created in some
non-partitioned space, we create it.
- A file-system check is always scheduled for both the system and the
installation partitions.
- If the system partition was already formatted (which usually means
that it already existed on the system), don't ask for formatting it.
CORE-13205
- For each partition to be formatted, the file-system menu list is
re-created, in order to display only the FSes that are compatible
with the selected partition, and allow to give the user the choice
to keep the existing file-system only if the selected partition was
already formatted.
- Check whether the user attempts to delete the partition on which
the installation source is present, only if it is not "new" and is
formatted.
- Check first whether the current partition is the system partition,
before displaying the CONFIRM_DELETE_SYSTEM_PARTITION_PAGE.
---
base/setup/usetup/partlist.c | 3 +-
base/setup/usetup/partlist.h | 11 +-
base/setup/usetup/usetup.c | 419 ++++++++++++++++++++++++++++---------------
3 files changed, 287 insertions(+), 146 deletions(-)
diff --git a/base/setup/usetup/partlist.c b/base/setup/usetup/partlist.c
index 7ad044c1c6..2c0cd5a55a 100644
--- a/base/setup/usetup/partlist.c
+++ b/base/setup/usetup/partlist.c
@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* COPYRIGHT: See COPYING in the top level directory
+/*
+ * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/partlist.c
* PURPOSE: Partition list functions
diff --git a/base/setup/usetup/partlist.h b/base/setup/usetup/partlist.h
index c07b993497..87c9959854 100644
--- a/base/setup/usetup/partlist.h
+++ b/base/setup/usetup/partlist.h
@@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* COPYRIGHT: See COPYING in the top level directory
+/*
+ * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/partlist.h
* PURPOSE: Partition list functions
@@ -34,10 +35,10 @@ typedef enum _FORMATMACHINESTATE
FormatInstallPartition,
FormatOtherPartition,
FormatDone,
- CheckSystemPartition,
- CheckInstallPartition,
- CheckOtherPartition,
- CheckDone
+ // CheckSystemPartition,
+ // CheckInstallPartition,
+ // CheckOtherPartition,
+ // CheckDone
} FORMATMACHINESTATE, *PFORMATMACHINESTATE;
typedef struct _PARTLIST_UI
diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c
index 555d37e83a..c030d07ff3 100644
--- a/base/setup/usetup/usetup.c
+++ b/base/setup/usetup/usetup.c
@@ -57,9 +57,14 @@ static WCHAR DefaultKBLayout[20]; // Copy of string inside KeyboardList
static BOOLEAN RepairUpdateFlag = FALSE;
+/* Global partition list on the system */
static PPARTLIST PartitionList = NULL;
-static PPARTENTRY TempPartition = NULL;
+
+/* List of currently supported file systems for the partition to be formatted */
static PFILE_SYSTEM_LIST FileSystemList = NULL;
+
+/* Machine state for the formatter */
+static PPARTENTRY TempPartition = NULL;
static FORMATMACHINESTATE FormatState = Start;
/*****************************************************/
@@ -798,7 +803,7 @@ RepairIntroPage(PINPUT_RECORD Ir)
{
MUIDisplayPage(REPAIR_INTRO_PAGE);
- while(TRUE)
+ while (TRUE)
{
CONSOLE_ConInKey(Ir);
@@ -858,6 +863,7 @@ UpgradeRepairPage(PINPUT_RECORD Ir)
return QUIT_PAGE;
}
+ /* Reset the formatter machine state */
TempPartition = NULL;
FormatState = Start;
}
@@ -1461,6 +1467,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
return QUIT_PAGE;
}
+ /* Reset the formatter machine state */
TempPartition = NULL;
FormatState = Start;
}
@@ -1690,8 +1697,8 @@ SelectPartitionPage(PINPUT_RECORD Ir)
}
else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
{
- WCHAR PathBuffer[MAX_PATH];
UNICODE_STRING CurrentPartition;
+ WCHAR PathBuffer[MAX_PATH];
if (PartitionList->CurrentPartition->IsPartitioned == FALSE)
{
@@ -1699,27 +1706,34 @@ SelectPartitionPage(PINPUT_RECORD Ir)
return SELECT_PARTITION_PAGE;
}
- RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu\\",
- PartitionList->CurrentDisk->DiskNumber,
- PartitionList->CurrentPartition->PartitionNumber);
- RtlInitUnicodeString(&CurrentPartition, PathBuffer);
-
- /*
- * Check whether the user attempts to delete the partition on which
- * the installation source is present. If so, fail with an error.
- */
- // &USetupData.SourceRootPath
- if (RtlPrefixUnicodeString(&CurrentPartition, &USetupData.SourcePath, TRUE))
+// TODO: Do something similar before trying to format the partition?
+ if (!PartitionList->CurrentPartition->New &&
+ PartitionList->CurrentPartition->FormatState != Unformatted)
{
- PopupError("You cannot delete the partition containing the installation source!",
- MUIGetString(STRING_CONTINUE),
- Ir, POPUP_WAIT_ENTER);
- return SELECT_PARTITION_PAGE;
+ ASSERT(PartitionList->CurrentPartition->PartitionNumber != 0);
+
+ RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+ L"\\Device\\Harddisk%lu\\Partition%lu\\",
+ PartitionList->CurrentDisk->DiskNumber,
+ PartitionList->CurrentPartition->PartitionNumber);
+ RtlInitUnicodeString(&CurrentPartition, PathBuffer);
+
+ /*
+ * Check whether the user attempts to delete the partition on which
+ * the installation source is present. If so, fail with an error.
+ */
+ // &USetupData.SourceRootPath
+ if (RtlPrefixUnicodeString(&CurrentPartition, &USetupData.SourcePath, TRUE))
+ {
+ PopupError("You cannot delete the partition containing the installation source!",
+ MUIGetString(STRING_CONTINUE),
+ Ir, POPUP_WAIT_ENTER);
+ return SELECT_PARTITION_PAGE;
+ }
}
- if (PartitionList->CurrentPartition->BootIndicator ||
- PartitionList->CurrentPartition == PartitionList->SystemPartition)
+ if (PartitionList->CurrentPartition == PartitionList->SystemPartition ||
+ PartitionList->CurrentPartition->BootIndicator)
{
return CONFIRM_DELETE_SYSTEM_PARTITION_PAGE;
}
@@ -1733,7 +1747,7 @@ SelectPartitionPage(PINPUT_RECORD Ir)
#define PARTITION_SIZE_INPUT_FIELD_LENGTH 9
-/* Restriction for MaxSize: pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1 */
+/* Restriction for MaxSize */
#define PARTITION_MAXSIZE (pow(10, (PARTITION_SIZE_INPUT_FIELD_LENGTH - 1)) - 1)
static VOID
@@ -2485,6 +2499,7 @@ DeletePartitionPage(PINPUT_RECORD Ir)
MUIDisplayPage(DELETE_PARTITION_PAGE);
+ /* Adjust partition type */
GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
PartTypeString,
ARRAYSIZE(PartTypeString));
@@ -2596,7 +2611,6 @@ DeletePartitionPage(PINPUT_RECORD Ir)
else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
{
DeleteCurrentPartition(PartitionList);
-
return SELECT_PARTITION_PAGE;
}
}
@@ -2605,6 +2619,16 @@ DeletePartitionPage(PINPUT_RECORD Ir)
}
+static VOID
+ResetFileSystemList(VOID)
+{
+ if (!FileSystemList)
+ return;
+
+ DestroyFileSystemList(FileSystemList);
+ FileSystemList = NULL;
+}
+
/*
* Displays the SelectFileSystemPage.
*
@@ -2634,6 +2658,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
PCHAR PartUnit;
CHAR PartTypeString[32];
FORMATMACHINESTATE PreviousFormatState;
+ PCWSTR DefaultFs;
DPRINT("SelectFileSystemPage()\n");
@@ -2645,31 +2670,101 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
return QUIT_PAGE;
}
- /* Find or set the active system partition */
- CheckActiveSystemPartition(PartitionList);
- if (PartitionList->SystemPartition == NULL)
+ /* Find or set the active system partition when starting formatting */
+ if (FormatState == Start)
{
- /* FIXME: show an error dialog */
- //
- // Error dialog should say that we cannot find a suitable
- // system partition and create one on the system. At this point,
- // it may be nice to ask the user whether he wants to continue,
- // or use an external drive as the system drive/partition
- // (e.g. floppy, USB drive, etc...)
- //
- return QUIT_PAGE;
+ /* Find or set the active system partition */
+ CheckActiveSystemPartition(PartitionList);
+ if (PartitionList->SystemPartition == NULL)
+ {
+ /* FIXME: show an error dialog */
+ //
+ // Error dialog should say that we cannot find a suitable
+ // system partition and create one on the system. At this point,
+ // it may be nice to ask the user whether he wants to continue,
+ // or use an external drive as the system drive/partition
+ // (e.g. floppy, USB drive, etc...)
+ //
+ return QUIT_PAGE;
+ }
+
+ /*
+ * If the system partition can be created in some
+ * non-partitioned space, create it now.
+ */
+ if (!PartitionList->SystemPartition->IsPartitioned)
+ {
+ // if (IsUnattendedSetup)
+ {
+ CreatePrimaryPartition(PartitionList,
+ PartitionList->SystemPartition,
+ 0LL, // PartitionList->SystemPartition->SectorCount.QuadPart,
+ TRUE);
+ ASSERT(PartitionList->SystemPartition->IsPartitioned);
+ }
+ // else
+ {
+ }
+ }
+
+ /* Commit all partition changes to all the disks */
+ if (!WritePartitionsToDisk(PartitionList))
+ {
+ DPRINT("WritePartitionsToDisk() failed\n");
+ MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
+ return QUIT_PAGE;
+ }
+
+ /*
+ * In all cases, whether or not we are going to perform a formatting,
+ * we must perform a filesystem check of both the system and the
+ * installation partitions.
+ */
+ PartitionList->CurrentPartition->NeedsCheck = TRUE;
+ if (PartitionList->SystemPartition != PartitionList->CurrentPartition)
+ PartitionList->SystemPartition->NeedsCheck = TRUE;
+
+ /*
+ * In case we just repair an existing installation, or make
+ * an unattended setup without formatting, just go to the
+ * filesystem check step.
+ */
+ if (RepairUpdateFlag)
+ return CHECK_FILE_SYSTEM_PAGE;
+
+ if (IsUnattendedSetup && !USetupData.FormatPartition)
+ return CHECK_FILE_SYSTEM_PAGE;
}
+ // ASSERT(PartitionList->SystemPartition->IsPartitioned);
+
+ /* Reset the filesystem list for each partition that is to be formatted */
+ ResetFileSystemList();
+
PreviousFormatState = FormatState;
switch (FormatState)
{
case Start:
{
- if (PartitionList->CurrentPartition != PartitionList->SystemPartition)
+ /*
+ * We start by formatting the system partition in case it is new
+ * (it didn't exist before) and is not the same as the installation
+ * partition. Otherwise we just require a filesystem check on it,
+ * and start by formatting the installation partition instead.
+ */
+
+ ASSERT(PartitionList->SystemPartition->IsPartitioned);
+
+ if ((PartitionList->SystemPartition != PartitionList->CurrentPartition) &&
+ (PartitionList->SystemPartition->FormatState == Unformatted))
{
TempPartition = PartitionList->SystemPartition;
TempPartition->NeedsCheck = TRUE;
+ // TODO: Should we let the user using a custom file-system,
+ // or should we always use FAT(32) for it?
+ // For "compatibility", FAT(32) would be best indeed.
+
FormatState = FormatSystemPartition;
DPRINT1("FormatState: Start --> FormatSystemPartition\n");
}
@@ -2678,6 +2773,16 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
TempPartition = PartitionList->CurrentPartition;
TempPartition->NeedsCheck = TRUE;
+ if (PartitionList->SystemPartition != PartitionList->CurrentPartition)
+ {
+ /* The system partition is separate, so it had better be formatted! */
+ ASSERT((PartitionList->SystemPartition->FormatState == Preformatted) ||
+ (PartitionList->SystemPartition->FormatState == Formatted));
+
+ /* Require a filesystem check on the system partition too */
+ PartitionList->SystemPartition->NeedsCheck = TRUE;
+ }
+
FormatState = FormatInstallPartition;
DPRINT1("FormatState: Start --> FormatInstallPartition\n");
}
@@ -2695,6 +2800,7 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
}
case FormatInstallPartition:
+ case FormatOtherPartition:
{
if (GetNextUnformattedPartition(PartitionList,
NULL,
@@ -2702,34 +2808,30 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
{
FormatState = FormatOtherPartition;
TempPartition->NeedsCheck = TRUE;
- DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
+
+ if (FormatState == FormatInstallPartition)
+ DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");
+ else
+ DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
}
else
{
FormatState = FormatDone;
- DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
+
+ if (FormatState == FormatInstallPartition)
+ DPRINT1("FormatState: FormatInstallPartition --> FormatDone\n");
+ else
+ DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
+
return CHECK_FILE_SYSTEM_PAGE;
}
break;
}
- case FormatOtherPartition:
+ case FormatDone:
{
- if (GetNextUnformattedPartition(PartitionList,
- NULL,
- &TempPartition))
- {
- FormatState = FormatOtherPartition;
- TempPartition->NeedsCheck = TRUE;
- DPRINT1("FormatState: FormatOtherPartition --> FormatOtherPartition\n");
- }
- else
- {
- FormatState = FormatDone;
- DPRINT1("FormatState: FormatOtherPartition --> FormatDone\n");
- return CHECK_FILE_SYSTEM_PAGE;
- }
- break;
+ DPRINT1("FormatState: FormatDone\n");
+ return CHECK_FILE_SYSTEM_PAGE;
}
default:
@@ -2866,54 +2968,47 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
"RAW");
}
- if (FileSystemList == NULL)
+ ASSERT(FileSystemList == NULL);
+
+ if (IsUnattendedSetup)
{
- PWSTR DefaultFs;
+ ASSERT(USetupData.FormatPartition);
- if (IsUnattendedSetup)
+ switch (USetupData.FsType)
{
- switch (USetupData.FsType)
- {
- /* 1 is for BtrFS */
- case 1:
- DefaultFs = L"BTRFS";
- break;
-
- /* If we don't understand input, default to FAT */
- default:
- DefaultFs = L"FAT";
- break;
- }
- }
- else
- {
- /* By default select the "FAT" file system */
- DefaultFs = L"FAT";
- }
+ /* 1 is for BtrFS */
+ case 1:
+ DefaultFs = L"BTRFS";
+ break;
- /* Create the file system list */
- FileSystemList = CreateFileSystemList(6, 26, PartEntry->New, DefaultFs);
- if (FileSystemList == NULL)
- {
- /* FIXME: show an error dialog */
- return QUIT_PAGE;
+ /* If we don't understand input, default to FAT */
+ default:
+ DefaultFs = L"FAT";
+ break;
}
}
+ else
+ {
+ /* By default select the "FAT" file system */
+ DefaultFs = L"FAT";
+ }
- if (RepairUpdateFlag)
+ /* Create the file system list */
+ // TODO: Display only the FSes compatible with the selected partition!
+ FileSystemList = CreateFileSystemList(6, 26,
+ PartEntry->New ||
+ PartEntry->FormatState == Unformatted,
+ DefaultFs);
+ if (FileSystemList == NULL)
{
- return CHECK_FILE_SYSTEM_PAGE;
- //return SELECT_PARTITION_PAGE;
+ /* FIXME: show an error dialog */
+ return QUIT_PAGE;
}
if (IsUnattendedSetup)
{
- if (USetupData.FormatPartition)
- {
- return FORMAT_PARTITION_PAGE;
- }
-
- return CHECK_FILE_SYSTEM_PAGE;
+ ASSERT(USetupData.FormatPartition);
+ return FORMAT_PARTITION_PAGE;
}
DrawFileSystemList(FileSystemList);
@@ -2926,14 +3021,24 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
(Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
{
if (ConfirmQuit(Ir))
+ {
+ /* Reset the filesystem list */
+ ResetFileSystemList();
return QUIT_PAGE;
+ }
break;
}
else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
(Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */
{
+ /* Reset the formatter machine state */
+ TempPartition = NULL;
FormatState = Start;
+
+ /* Reset the filesystem list */
+ ResetFileSystemList();
+
return SELECT_PARTITION_PAGE;
}
else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
@@ -2949,9 +3054,27 @@ SelectFileSystemPage(PINPUT_RECORD Ir)
else if (Ir->Event.KeyEvent.wVirtualKeyCode == VK_RETURN) /* ENTER */
{
if (!FileSystemList->Selected->FileSystem)
+ {
+ ASSERT(!TempPartition->New && TempPartition->FormatState != Unformatted);
+
+ /*
+ * Skip formatting this partition. We will also ignore
+ * filesystem checks on it, unless it is either the system
+ * or the installation partition.
+ */
+ if (TempPartition != PartitionList->SystemPartition &&
+ TempPartition != PartitionList->CurrentPartition)
+ {
+ PartEntry->NeedsCheck = FALSE;
+ }
+
return SELECT_FILE_SYSTEM_PAGE;
+ }
else
+ {
+ /* Format this partition */
return FORMAT_PARTITION_PAGE;
+ }
}
}
@@ -3014,15 +3137,17 @@ FormatPartitionPage(PINPUT_RECORD Ir)
while (TRUE)
{
if (!IsUnattendedSetup)
- {
CONSOLE_ConInKey(Ir);
- }
if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) &&
(Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */
{
if (ConfirmQuit(Ir))
+ {
+ /* Reset the filesystem list */
+ ResetFileSystemList();
return QUIT_PAGE;
+ }
break;
}
@@ -3033,6 +3158,10 @@ FormatPartitionPage(PINPUT_RECORD Ir)
if (!PreparePartitionForFormatting(PartEntry, SelectedFileSystem->FileSystem))
{
/* FIXME: show an error dialog */
+
+ /* Reset the filesystem list */
+ ResetFileSystemList();
+
return QUIT_PAGE;
}
@@ -3064,10 +3193,17 @@ FormatPartitionPage(PINPUT_RECORD Ir)
#endif
/* Commit the partition changes to the disk */
- if (!WritePartitionsToDisk(PartitionList))
+ Status = WritePartitions(DiskEntry);
+ if (!NT_SUCCESS(Status))
{
- DPRINT("WritePartitionsToDisk() failed\n");
+ DPRINT1("WritePartitions(disk %lu) failed, Status 0x%08lx\n",
+ DiskEntry->DiskNumber, Status);
+
MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
+
+ /* Reset the filesystem list */
+ ResetFileSystemList();
+
return QUIT_PAGE;
}
@@ -3080,54 +3216,65 @@ FormatPartitionPage(PINPUT_RECORD Ir)
DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
/* Format the partition */
- if (SelectedFileSystem->FileSystem)
+ Status = FormatPartition(&PartitionRootPath,
+ SelectedFileSystem->FileSystem,
+ SelectedFileSystem->QuickFormat);
+ if (Status == STATUS_NOT_SUPPORTED)
{
- Status = FormatPartition(&PartitionRootPath,
- SelectedFileSystem->FileSystem,
- SelectedFileSystem->QuickFormat);
- if (Status == STATUS_NOT_SUPPORTED)
+ sprintf(Buffer,
+ "Setup is currently unable to format a partition in %S.\n"
+ "\n"
+ " \x07 Press ENTER to continue Setup.\n"
+ " \x07 Press F3 to quit Setup.",
+ SelectedFileSystem->FileSystem);
+
+ PopupError(Buffer,
+ MUIGetString(STRING_QUITCONTINUE),
+ NULL, POPUP_WAIT_NONE);
+
+ while (TRUE)
{
- sprintf(Buffer,
- "Setup is currently unable to format a partition in %S.\n"
- "\n"
- " \x07 Press ENTER to continue Setup.\n"
- " \x07 Press F3 to quit Setup.",
- SelectedFileSystem->FileSystem);
-
- PopupError(Buffer,
- MUIGetString(STRING_QUITCONTINUE),
- NULL, POPUP_WAIT_NONE);
-
- while (TRUE)
- {
- CONSOLE_ConInKey(Ir);
+ CONSOLE_ConInKey(Ir);
- if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
- Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
+ if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x00 &&
+ Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3) /* F3 */
+ {
+ if (ConfirmQuit(Ir))
{
- if (ConfirmQuit(Ir))
- return QUIT_PAGE;
- else
- return SELECT_FILE_SYSTEM_PAGE;
+ /* Reset the filesystem list */
+ ResetFileSystemList();
+ return QUIT_PAGE;
}
- else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
+ else
{
return SELECT_FILE_SYSTEM_PAGE;
}
}
+ else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
+ {
+ return SELECT_FILE_SYSTEM_PAGE;
+ }
}
- else if (!NT_SUCCESS(Status))
- {
- DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
- MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
- return QUIT_PAGE;
- }
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("FormatPartition() failed with status 0x%08lx\n", Status);
+ MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY, PathBuffer);
+
+ /* Reset the filesystem list */
+ ResetFileSystemList();
- PartEntry->FormatState = Formatted;
- // PartEntry->FileSystem = FileSystem;
- PartEntry->New = FALSE;
+ return QUIT_PAGE;
}
+//
+// TODO: Here, call a partlist.c function that update the actual FS name
+// and the label fields of the volume.
+//
+ PartEntry->FormatState = Formatted;
+ // PartEntry->FileSystem = FileSystem;
+ PartEntry->New = FALSE;
+
#ifndef NDEBUG
CONSOLE_SetStatusText(" Done. Press any key ...");
CONSOLE_ConInKey(Ir);
@@ -3234,7 +3381,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
}
else if (Ir->Event.KeyEvent.uChar.AsciiChar == VK_RETURN) /* ENTER */
{
- PartEntry->NeedsCheck = FALSE;
return CHECK_FILE_SYSTEM_PAGE;
}
}
@@ -3347,11 +3493,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
NTSTATUS Status;
/* We do not need the filesystem list anymore */
- if (FileSystemList != NULL)
- {
- DestroyFileSystemList(FileSystemList);
- FileSystemList = NULL;
- }
+ ResetFileSystemList();
if (PartitionList == NULL ||
PartitionList->CurrentDisk == NULL ||
@@ -4511,15 +4653,12 @@ QuitPage(PINPUT_RECORD Ir)
PartitionList = NULL;
}
+ /* Reset the formatter machine state */
TempPartition = NULL;
FormatState = Start;
/* Destroy the filesystem list */
- if (FileSystemList != NULL)
- {
- DestroyFileSystemList(FileSystemList);
- FileSystemList = NULL;
- }
+ ResetFileSystemList();
CONSOLE_SetStatusText(MUIGetString(STRING_REBOOTCOMPUTER2));