https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6f15802af7948d912be03…
commit 6f15802af7948d912be038cfc6083ba14acb4ae6
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat May 18 23:09:16 2024 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Aug 26 16:42:47 2024 +0200
[SETUPLIB][REACTOS][USETUP] Split FS-volume-specific functionality from partitions
(#7258)
CORE-13525
This greatly helps in reducing code complexity in some areas: code that
previously iterated over all partitions of a given disk, just to find
which ones were partitioned and contained a valid file system, now just
have to iterate over mounted volumes.
See in particular, `lib/utils/osdetect.c` and `lib/fsutil.c` .
- Remove FORMATSTATE "Preformatted" enum value;
- Cleanup osdetect code after introducing Volume support;
- Some simplifications for FormatState.
- Differentiate between 'new' partition and 'new' volume:
* "New" partition: it has been created and added in the cached list,
but not yet actually written into the disk.
* "New" volume: newly-created volume (may be backed by a partition or
not), not yet formatted. May exist on either new, or not new partition,
or elsewhere.
- Cache partition and volume NT device names.
These do not change across repartitioning operations, as long as the
partition or the filesystem volume hasn't been deleted/recreated.
This avoids doing \Device\Harddisk%u\Partition%u sprintf's everytime
we need to retrieve the given partition or volume device name.
When a partition/fileysystem volume is "virtually" created (i.e. in
the partition list, but not yet committed to disk and exposed to the
OS), no device partition number and device name are available yet.
In particular, validate that no manipulation of \Device\HarddiskM\Partition0
(i.e. the whole disk) is being made.
---
base/setup/lib/CMakeLists.txt | 1 +
base/setup/lib/fsutil.c | 358 +++++++++-----------
base/setup/lib/fsutil.h | 8 +-
base/setup/lib/setuplib.c | 19 +-
base/setup/lib/setuplib.h | 6 +-
base/setup/lib/utils/osdetect.c | 241 ++++++-------
base/setup/lib/utils/osdetect.h | 8 +-
base/setup/lib/utils/partlist.c | 734 +++++++++++++++++++---------------------
base/setup/lib/utils/partlist.h | 62 ++--
base/setup/lib/utils/volutil.c | 226 +++++++++++++
base/setup/lib/utils/volutil.h | 48 +++
base/setup/reactos/drivepage.c | 14 +-
base/setup/reactos/reactos.c | 6 +-
base/setup/usetup/partlist.c | 16 +-
base/setup/usetup/usetup.c | 143 ++++----
15 files changed, 1018 insertions(+), 872 deletions(-)
diff --git a/base/setup/lib/CMakeLists.txt b/base/setup/lib/CMakeLists.txt
index 57eae6b3a6e..836c9ef5967 100644
--- a/base/setup/lib/CMakeLists.txt
+++ b/base/setup/lib/CMakeLists.txt
@@ -21,6 +21,7 @@ list(APPEND SOURCE
utils/partinfo.c
utils/partlist.c
utils/regutil.c
+ utils/volutil.c
bootcode.c
bootsup.c
fsutil.c
diff --git a/base/setup/lib/fsutil.c b/base/setup/lib/fsutil.c
index c4a1f02fa16..875e8ec7f9d 100644
--- a/base/setup/lib/fsutil.c
+++ b/base/setup/lib/fsutil.c
@@ -754,34 +754,22 @@ Quit:
//
NTSTATUS
-ChkdskPartition(
- _In_ PPARTENTRY PartEntry,
+ChkdskVolume(
+ _In_ PVOLINFO Volume,
_In_ BOOLEAN FixErrors,
_In_ BOOLEAN Verbose,
_In_ BOOLEAN CheckOnlyIfDirty,
_In_ BOOLEAN ScanDrive,
_In_opt_ PFMIFSCALLBACK Callback)
{
- PDISKENTRY DiskEntry = PartEntry->DiskEntry;
- // UNICODE_STRING PartitionRootPath;
- WCHAR PartitionRootPath[MAX_PATH]; // PathBuffer
-
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
-
- /* Do not check a partition with an unknown file system */
- if (!*PartEntry->FileSystem)
- return STATUS_UNRECOGNIZED_VOLUME; // STATUS_NOT_SUPPORTED;
-
- /* Set PartitionRootPath */
- RtlStringCchPrintfW(PartitionRootPath, ARRAYSIZE(PartitionRootPath),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- DiskEntry->DiskNumber,
- PartEntry->PartitionNumber);
- DPRINT("PartitionRootPath: %S\n", PartitionRootPath);
+ /* Do not check a volume with an unknown file system */
+ if (!*Volume->FileSystem)
+ return STATUS_UNRECOGNIZED_VOLUME;
- /* Check the partition */
- return ChkdskFileSystem(PartitionRootPath,
- PartEntry->FileSystem,
+ /* Check the volume */
+ DPRINT("Volume->DeviceName: %S\n", Volume->DeviceName);
+ return ChkdskFileSystem(Volume->DeviceName,
+ Volume->FileSystem,
FixErrors,
Verbose,
CheckOnlyIfDirty,
@@ -789,6 +777,67 @@ ChkdskPartition(
Callback);
}
+NTSTATUS
+ChkdskPartition(
+ _In_ PPARTENTRY PartEntry,
+ _In_ BOOLEAN FixErrors,
+ _In_ BOOLEAN Verbose,
+ _In_ BOOLEAN CheckOnlyIfDirty,
+ _In_ BOOLEAN ScanDrive,
+ _In_opt_ PFMIFSCALLBACK Callback)
+{
+ ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+ ASSERT(PartEntry->Volume);
+
+ // if (!PartEntry->Volume) { check_raw_sectors(); } else { check_FS(); }
+
+ /* Check the associated volume */
+ return ChkdskVolume(&PartEntry->Volume->Info,
+ FixErrors,
+ Verbose,
+ CheckOnlyIfDirty,
+ ScanDrive,
+ Callback);
+}
+
+NTSTATUS
+FormatVolume(
+ _In_ PVOLINFO Volume,
+ _In_ PCWSTR FileSystemName,
+ _In_ FMIFS_MEDIA_FLAG MediaFlag,
+ _In_opt_ PCWSTR Label,
+ _In_ BOOLEAN QuickFormat,
+ _In_ ULONG ClusterSize,
+ _In_opt_ PFMIFSCALLBACK Callback)
+{
+ NTSTATUS Status;
+
+ if (!FileSystemName || !*FileSystemName)
+ {
+ DPRINT1("No file system specified\n");
+ return STATUS_UNRECOGNIZED_VOLUME;
+ }
+
+ /* Format the volume */
+ DPRINT("Volume->DeviceName: %S\n", Volume->DeviceName);
+ Status = FormatFileSystem(Volume->DeviceName,
+ FileSystemName,
+ MediaFlag,
+ Label,
+ QuickFormat,
+ ClusterSize,
+ Callback);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Set the new volume's file system and label */
+ RtlStringCbCopyW(Volume->FileSystem, sizeof(Volume->FileSystem),
FileSystemName);
+ if (!Label) Label = L"";
+ RtlStringCbCopyW(Volume->VolumeLabel, sizeof(Volume->VolumeLabel), Label);
+
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
FormatPartition(
_In_ PPARTENTRY PartEntry,
@@ -802,14 +851,12 @@ FormatPartition(
NTSTATUS Status;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
UCHAR PartitionType;
- // UNICODE_STRING PartitionRootPath;
- WCHAR PartitionRootPath[MAX_PATH]; // PathBuffer
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
if (!FileSystemName || !*FileSystemName)
{
- DPRINT1("No file system specified?\n");
+ DPRINT1("No file system specified\n");
return STATUS_UNRECOGNIZED_VOLUME;
}
@@ -867,37 +914,22 @@ FormatPartition(
return STATUS_PARTITION_FAILURE;
}
- /* Set PartitionRootPath */
- RtlStringCchPrintfW(PartitionRootPath, ARRAYSIZE(PartitionRootPath),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- DiskEntry->DiskNumber,
- PartEntry->PartitionNumber);
- DPRINT("PartitionRootPath: %S\n", PartitionRootPath);
-
- /* Format the partition */
- Status = FormatFileSystem(PartitionRootPath,
- FileSystemName,
- MediaFlag,
- Label,
- QuickFormat,
- ClusterSize,
- Callback);
+ /* We must have an associated volume now */
+ ASSERT(PartEntry->Volume);
+
+ /* Format the associated volume */
+ Status = FormatVolume(&PartEntry->Volume->Info,
+ FileSystemName,
+ MediaFlag,
+ Label,
+ QuickFormat,
+ ClusterSize,
+ Callback);
if (!NT_SUCCESS(Status))
return Status;
-//
-// TODO: Here, call a partlist.c function that update the actual
-// FS name and the label fields of the volume.
-//
- PartEntry->FormatState = Formatted;
-
- /* Set the new partition's file system proper */
- RtlStringCbCopyW(PartEntry->FileSystem,
- sizeof(PartEntry->FileSystem),
- FileSystemName);
-
- PartEntry->New = FALSE;
-
+ PartEntry->Volume->FormatState = Formatted;
+ PartEntry->Volume->New = FALSE;
return STATUS_SUCCESS;
}
@@ -908,17 +940,19 @@ FormatPartition(
static FSVOL_OP
DoFormatting(
- _In_ PPARTENTRY PartEntry,
+ _In_ PVOLENTRY Volume,
_In_opt_ PVOID Context,
_In_opt_ PFSVOL_CALLBACK FsVolCallback)
{
FSVOL_OP Result;
NTSTATUS Status = STATUS_SUCCESS;
+ PPARTENTRY PartEntry;
FORMAT_VOLUME_INFO FmtInfo = {0};
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+ PartEntry = Volume->PartEntry;
+ ASSERT(PartEntry && (PartEntry->Volume == Volume));
- FmtInfo.PartEntry = PartEntry;
+ FmtInfo.Volume = Volume;
RetryFormat:
Result = FsVolCallback(Context,
@@ -964,7 +998,7 @@ EndFormat:
static FSVOL_OP
DoChecking(
- _In_ PPARTENTRY PartEntry,
+ _In_ PVOLENTRY Volume,
_In_opt_ PVOID Context,
_In_opt_ PFSVOL_CALLBACK FsVolCallback)
{
@@ -972,11 +1006,9 @@ DoChecking(
NTSTATUS Status = STATUS_SUCCESS;
CHECK_VOLUME_INFO ChkInfo = {0};
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
-
- ASSERT(*PartEntry->FileSystem);
+ ASSERT(*Volume->Info.FileSystem);
- ChkInfo.PartEntry = PartEntry;
+ ChkInfo.Volume = Volume;
RetryCheck:
Result = FsVolCallback(Context,
@@ -986,18 +1018,18 @@ RetryCheck:
if (Result != FSVOL_DOIT)
goto EndCheck;
- /* Check the partition */
- Status = ChkdskPartition(PartEntry,
- ChkInfo.FixErrors,
- ChkInfo.Verbose,
- ChkInfo.CheckOnlyIfDirty,
- ChkInfo.ScanDrive,
- ChkInfo.Callback);
+ /* Check the volume */
+ Status = ChkdskVolume(&Volume->Info,
+ ChkInfo.FixErrors,
+ ChkInfo.Verbose,
+ ChkInfo.CheckOnlyIfDirty,
+ ChkInfo.ScanDrive,
+ ChkInfo.Callback);
/* If volume checking succeeded, or if it is not supported
* with the current file system, disable checks on the volume */
if (NT_SUCCESS(Status) || (Status == STATUS_NOT_SUPPORTED))
- PartEntry->NeedsCheck = FALSE;
+ Volume->NeedsCheck = FALSE;
if (!NT_SUCCESS(Status))
{
@@ -1012,7 +1044,7 @@ RetryCheck:
goto RetryCheck;
// else if (Result == FSVOL_ABORT || Result == FSVOL_SKIP), stop.
- // PartEntry->NeedsCheck = FALSE;
+ // Volume->NeedsCheck = FALSE;
}
EndCheck:
@@ -1025,125 +1057,44 @@ EndCheck:
return Result;
}
-static BOOLEAN
-GetNextUnformattedPartition(
- IN PPARTLIST List,
- OUT PPARTENTRY *pPartEntry)
+static
+PVOLENTRY
+GetNextUnformattedVolume(
+ _In_ PPARTLIST List,
+ _In_opt_ PVOLENTRY Volume)
{
- PLIST_ENTRY Entry1, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
- for (Entry1 = List->DiskListHead.Flink;
- Entry1 != &List->DiskListHead;
- Entry1 = Entry1->Flink)
+ for (;;)
{
- DiskEntry = CONTAINING_RECORD(Entry1,
- DISKENTRY,
- ListEntry);
+ /* If we have a current volume, get the next one, otherwise get the first */
+ Entry = (Volume ? &Volume->ListEntry : &List->VolumesList);
+ Entry = Entry->Flink;
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
- {
- DPRINT("GPT-partitioned disk detected, not currently supported by
SETUP!\n");
- continue;
- }
+ if (Entry == &List->VolumesList)
+ return NULL;
- for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- Entry2 != &DiskEntry->PrimaryPartListHead;
- Entry2 = Entry2->Flink)
+ Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
+ if (Volume->New && (Volume->FormatState == Unformatted))
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned && PartEntry->New)
- {
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- *pPartEntry = PartEntry;
- return TRUE;
- }
- }
-
- for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
- Entry2 != &DiskEntry->LogicalPartListHead;
- Entry2 = Entry2->Flink)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned && PartEntry->New)
- {
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- *pPartEntry = PartEntry;
- return TRUE;
- }
+ /* Found a candidate, return it */
+ return Volume;
}
}
-
- *pPartEntry = NULL;
- return FALSE;
-}
-
-static BOOLEAN
-GetNextUncheckedPartition(
- IN PPARTLIST List,
- OUT PPARTENTRY *pPartEntry)
-{
- PLIST_ENTRY Entry1, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
-
- for (Entry1 = List->DiskListHead.Flink;
- Entry1 != &List->DiskListHead;
- Entry1 = Entry1->Flink)
- {
- DiskEntry = CONTAINING_RECORD(Entry1,
- DISKENTRY,
- ListEntry);
-
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
- {
- DPRINT("GPT-partitioned disk detected, not currently supported by
SETUP!\n");
- continue;
- }
-
- for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- Entry2 != &DiskEntry->PrimaryPartListHead;
- Entry2 = Entry2->Flink)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
- {
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- *pPartEntry = PartEntry;
- return TRUE;
- }
- }
-
- for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
- Entry2 != &DiskEntry->LogicalPartListHead;
- Entry2 = Entry2->Flink)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
- {
- ASSERT(DiskEntry == PartEntry->DiskEntry);
- *pPartEntry = PartEntry;
- return TRUE;
- }
- }
- }
-
- *pPartEntry = NULL;
- return FALSE;
}
BOOLEAN
FsVolCommitOpsQueue(
_In_ PPARTLIST PartitionList,
- _In_ PPARTENTRY SystemPartition,
- _In_ PPARTENTRY InstallPartition,
+ _In_ PVOLENTRY SystemVolume,
+ _In_ PVOLENTRY InstallVolume,
_In_opt_ PFSVOL_CALLBACK FsVolCallback,
_In_opt_ PVOID Context)
{
BOOLEAN Success = TRUE; // Suppose success originally.
FSVOL_OP Result;
- PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+ PVOLENTRY Volume;
/* Machine state for the format step */
typedef enum _FORMATMACHINESTATE
@@ -1163,7 +1114,7 @@ FsVolCommitOpsQueue(
"FormatDone"
};
- ASSERT(PartitionList && InstallPartition && SystemPartition);
+ ASSERT(PartitionList && SystemVolume && InstallVolume);
/* Commit all partition changes to all the disks */
if (!WritePartitionsToDisk(PartitionList))
@@ -1184,8 +1135,8 @@ FsVolCommitOpsQueue(
* we must perform a file system check of both the system and the
* installation volumes.
*/
- SystemPartition->NeedsCheck = TRUE;
- InstallPartition->NeedsCheck = TRUE;
+ SystemVolume->NeedsCheck = TRUE;
+ InstallVolume->NeedsCheck = TRUE;
Result = FsVolCallback(Context,
FSVOLNOTIFY_STARTQUEUE,
@@ -1210,8 +1161,8 @@ FsVolCommitOpsQueue(
/* Reset the formatter machine state */
FormatState = Start;
+ Volume = NULL;
NextFormat:
- PartEntry = NULL;
OldFormatState = FormatState;
switch (FormatState)
{
@@ -1223,12 +1174,11 @@ NextFormat:
* volume. Otherwise we just require a file system check on it,
* and start by formatting the installation volume instead.
*/
- ASSERT(SystemPartition->IsPartitioned);
- if (SystemPartition != InstallPartition)
+ if (SystemVolume != InstallVolume)
{
- PartEntry = SystemPartition;
+ Volume = SystemVolume;
- if (PartEntry->FormatState == Unformatted)
+ if (Volume->FormatState == Unformatted)
{
// TODO: Should we let the user use a custom file system,
// or should we always use FAT(32) for it?
@@ -1241,18 +1191,17 @@ NextFormat:
}
/* The system volume is separate, so it had better be formatted! */
- ASSERT((PartEntry->FormatState == Preformatted) ||
- (PartEntry->FormatState == Formatted));
+ ASSERT(Volume->FormatState == Formatted);
/* Require a file system check on the system volume too */
- PartEntry->NeedsCheck = TRUE;
+ Volume->NeedsCheck = TRUE;
}
__fallthrough;
}
case FormatSystemVolume:
{
- PartEntry = InstallPartition;
+ Volume = InstallVolume;
FormatState = FormatInstallVolume;
DPRINT1("FormatState: %s --> %s\n",
@@ -1261,15 +1210,16 @@ NextFormat:
}
case FormatInstallVolume:
+ /* Restart volume enumeration */
+ Volume = NULL;
case FormatOtherVolume:
{
- BOOLEAN Found = GetNextUnformattedPartition(PartitionList, &PartEntry);
- if (Found) ASSERT(PartEntry);
+ Volume = GetNextUnformattedVolume(PartitionList, Volume);
- FormatState = (PartEntry ? FormatOtherVolume : FormatDone);
+ FormatState = (Volume ? FormatOtherVolume : FormatDone);
DPRINT1("FormatState: %s --> %s\n",
FormatStateNames[OldFormatState], FormatStateNames[FormatState]);
- if (Found)
+ if (Volume)
break;
__fallthrough;
}
@@ -1283,15 +1233,14 @@ NextFormat:
DEFAULT_UNREACHABLE;
}
- ASSERT(PartEntry);
- Result = DoFormatting(PartEntry, Context, FsVolCallback);
+ Result = DoFormatting(Volume, Context, FsVolCallback);
if (Result == FSVOL_ABORT)
{
Success = FALSE;
goto Quit;
}
/* Schedule a check for this volume */
- PartEntry->NeedsCheck = TRUE;
+ Volume->NeedsCheck = TRUE;
/* Go to the next volume to be formatted */
goto NextFormat;
@@ -1314,24 +1263,27 @@ StartCheckQueue:
if (Result == FSVOL_ABORT)
return FALSE;
-NextCheck:
- if (!GetNextUncheckedPartition(PartitionList, &PartEntry))
+ /* Loop through each unchecked volume and do the check */
+ for (Entry = PartitionList->VolumesList.Flink;
+ Entry != &PartitionList->VolumesList;
+ Entry = Entry->Flink)
{
- Success = TRUE;
- goto EndCheck;
- }
+ Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
+ if (!Volume->NeedsCheck)
+ continue;
- ASSERT(PartEntry);
- Result = DoChecking(PartEntry, Context, FsVolCallback);
- if (Result == FSVOL_ABORT)
- {
- Success = FALSE;
- goto Quit;
+ /* Found a candidate */
+ ASSERT(Volume->FormatState == Formatted);
+ Result = DoChecking(Volume, Context, FsVolCallback);
+ if (Result == FSVOL_ABORT)
+ {
+ Success = FALSE;
+ goto Quit;
+ }
+ /* Go to the next volume to be checked */
}
- /* Go to the next volume to be checked */
- goto NextCheck;
+ Success = TRUE;
-EndCheck:
FsVolCallback(Context,
FSVOLNOTIFY_ENDSUBQUEUE,
FSVOL_CHECK,
diff --git a/base/setup/lib/fsutil.h b/base/setup/lib/fsutil.h
index b132148a1f2..5af0a4265f5 100644
--- a/base/setup/lib/fsutil.h
+++ b/base/setup/lib/fsutil.h
@@ -163,7 +163,7 @@ typedef enum _FSVOL_OP
typedef struct _FORMAT_VOLUME_INFO
{
- PPARTENTRY PartEntry;
+ PVOLENTRY Volume;
// PCWSTR NtPathPartition;
NTSTATUS ErrorStatus;
@@ -179,7 +179,7 @@ typedef struct _FORMAT_VOLUME_INFO
typedef struct _CHECK_VOLUME_INFO
{
- PPARTENTRY PartEntry;
+ PVOLENTRY Volume;
// PCWSTR NtPathPartition;
NTSTATUS ErrorStatus;
@@ -202,8 +202,8 @@ typedef FSVOL_OP
BOOLEAN
FsVolCommitOpsQueue(
_In_ PPARTLIST PartitionList,
- _In_ PPARTENTRY SystemPartition,
- _In_ PPARTENTRY InstallPartition,
+ _In_ PVOLENTRY SystemVolume,
+ _In_ PVOLENTRY InstallVolume,
_In_opt_ PFSVOL_CALLBACK FsVolCallback,
_In_opt_ PVOID Context);
diff --git a/base/setup/lib/setuplib.c b/base/setup/lib/setuplib.c
index ea190cece3c..f8a961ab3c1 100644
--- a/base/setup/lib/setuplib.c
+++ b/base/setup/lib/setuplib.c
@@ -695,7 +695,8 @@ InitSystemPartition(
* In all cases, whether or not we are going to perform a formatting,
* we must perform a filesystem check of the system partition.
*/
- SystemPartition->NeedsCheck = TRUE;
+ if (SystemPartition->Volume)
+ SystemPartition->Volume->NeedsCheck = TRUE;
return TRUE;
}
@@ -794,23 +795,21 @@ IsValidInstallDirectory(
NTSTATUS
InitDestinationPaths(
- IN OUT PUSETUP_DATA pSetupData,
- IN PCWSTR InstallationDir,
- IN PPARTENTRY PartEntry) // FIXME: HACK!
+ _Inout_ PUSETUP_DATA pSetupData,
+ _In_ PCWSTR InstallationDir,
+ _In_ PVOLENTRY Volume)
{
NTSTATUS Status;
+ PPARTENTRY PartEntry = Volume->PartEntry;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
- WCHAR PathBuffer[MAX_PATH];
+ WCHAR PathBuffer[RTL_NUMBER_OF_FIELD(VOLINFO, DeviceName) + 1];
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
/* Create 'pSetupData->DestinationRootPath' string */
RtlFreeUnicodeString(&pSetupData->DestinationRootPath);
- Status = RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu\\",
- DiskEntry->DiskNumber,
- PartEntry->PartitionNumber);
-
+ Status = RtlStringCchPrintfW(PathBuffer, _countof(PathBuffer),
+ L"%s\\", Volume->Info.DeviceName);
if (!NT_SUCCESS(Status))
{
DPRINT1("RtlStringCchPrintfW() failed with status 0x%08lx\n",
Status);
diff --git a/base/setup/lib/setuplib.h b/base/setup/lib/setuplib.h
index 99c02ba86a1..02abdedc658 100644
--- a/base/setup/lib/setuplib.h
+++ b/base/setup/lib/setuplib.h
@@ -204,9 +204,9 @@ IsValidInstallDirectory(
NTSTATUS
InitDestinationPaths(
- IN OUT PUSETUP_DATA pSetupData,
- IN PCWSTR InstallationDir,
- IN PPARTENTRY PartEntry); // FIXME: HACK!
+ _Inout_ PUSETUP_DATA pSetupData,
+ _In_ PCWSTR InstallationDir,
+ _In_ PVOLENTRY Volume);
// NTSTATUS
ERROR_NUMBER
diff --git a/base/setup/lib/utils/osdetect.c b/base/setup/lib/utils/osdetect.c
index 2512cfbe26f..1a4abd5cb6a 100644
--- a/base/setup/lib/utils/osdetect.c
+++ b/base/setup/lib/utils/osdetect.c
@@ -1,9 +1,9 @@
/*
* PROJECT: ReactOS Setup Library
- * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: NT 5.x family (MS Windows <= 2003, and ReactOS)
* operating systems detection code.
- * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito
+ * COPYRIGHT: Copyright 2017-2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
*/
/* INCLUDES *****************************************************************/
@@ -46,22 +46,20 @@ FindExistingNTOSInstall(
static PNTOS_INSTALLATION
AddNTOSInstallation(
- IN PGENERIC_LIST List,
- IN PCWSTR InstallationName,
- IN USHORT Machine,
- IN PCWSTR VendorName,
- IN PCWSTR SystemRootArcPath,
- IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
- IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
- IN ULONG DiskNumber,
- IN ULONG PartitionNumber,
- IN PPARTENTRY PartEntry OPTIONAL);
+ _In_ PGENERIC_LIST List,
+ _In_ PCWSTR InstallationName,
+ _In_ USHORT Machine,
+ _In_ PCWSTR VendorName,
+ _In_ PCWSTR SystemRootArcPath,
+ _In_ PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
+ _In_ PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
+ _In_ ULONG DiskNumber,
+ _In_ ULONG PartitionNumber);
typedef struct _ENUM_INSTALLS_DATA
{
- IN OUT PGENERIC_LIST List;
- IN PPARTLIST PartList;
- // IN PPARTENTRY PartEntry;
+ _Inout_ PGENERIC_LIST List;
+ _In_ PPARTLIST PartList;
} ENUM_INSTALLS_DATA, *PENUM_INSTALLS_DATA;
// PENUM_BOOT_ENTRIES_ROUTINE
@@ -78,7 +76,6 @@ EnumerateInstallations(
ULONG DiskNumber = 0, PartitionNumber = 0;
PCWSTR PathComponent = NULL;
- PPARTENTRY PartEntry = NULL;
UNICODE_STRING SystemRootPath;
WCHAR SystemRoot[MAX_PATH];
@@ -136,9 +133,9 @@ EnumerateInstallations(
}
/*
- * Convert the ARC path into an NT path, from which we will deduce
- * the real disk drive & partition on which the candidate installation
- * resides, as well verifying whether it is indeed an NTOS installation.
+ * Convert the ARC path into an NT path, from which we will deduce the
+ * real disk & partition on which the candidate installation resides,
+ * as well as verifying whether it is indeed an NTOS installation.
*/
RtlInitEmptyUnicodeString(&SystemRootPath, SystemRoot, sizeof(SystemRoot));
if (!ArcPathToNtPath(&SystemRootPath, Options->OsLoadPath,
Data->PartList))
@@ -182,14 +179,6 @@ EnumerateInstallations(
{
DPRINT("SystemRootPath = '%wZ' points to disk #%d, partition #%d,
path '%S'\n",
&SystemRootPath, DiskNumber, PartitionNumber, PathComponent);
-
- /* Retrieve the corresponding partition */
- PartEntry = SelectPartition(Data->PartList, DiskNumber, PartitionNumber);
- if (!PartEntry)
- {
- DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
- DiskNumber, PartitionNumber);
- }
}
else
{
@@ -197,13 +186,24 @@ EnumerateInstallations(
}
/* Add the discovered NTOS installation into the list */
- AddNTOSInstallation(Data->List,
- BootEntry->FriendlyName,
- Machine,
- VendorName.Buffer, // FIXME: What if it's not
NULL-terminated?
- Options->OsLoadPath,
- &SystemRootPath, PathComponent,
- DiskNumber, PartitionNumber, PartEntry);
+ NtOsInstall = AddNTOSInstallation(Data->List,
+ BootEntry->FriendlyName,
+ Machine,
+ VendorName.Buffer, // FIXME: What if it's not
NULL-terminated?
+ Options->OsLoadPath,
+ &SystemRootPath, PathComponent,
+ DiskNumber, PartitionNumber);
+ if (NtOsInstall)
+ {
+ /* Retrieve the volume corresponding to the disk and partition numbers */
+ PPARTENTRY PartEntry = SelectPartition(Data->PartList, DiskNumber,
PartitionNumber);
+ if (!PartEntry)
+ {
+ DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
+ DiskNumber, PartitionNumber);
+ }
+ NtOsInstall->Volume = (PartEntry ? PartEntry->Volume : NULL);
+ }
/* Continue the enumeration */
return STATUS_SUCCESS;
@@ -607,16 +607,15 @@ FindExistingNTOSInstall(
static PNTOS_INSTALLATION
AddNTOSInstallation(
- IN PGENERIC_LIST List,
- IN PCWSTR InstallationName,
- IN USHORT Machine,
- IN PCWSTR VendorName,
- IN PCWSTR SystemRootArcPath,
- IN PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
- IN PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
- IN ULONG DiskNumber,
- IN ULONG PartitionNumber,
- IN PPARTENTRY PartEntry OPTIONAL)
+ _In_ PGENERIC_LIST List,
+ _In_ PCWSTR InstallationName,
+ _In_ USHORT Machine,
+ _In_ PCWSTR VendorName,
+ _In_ PCWSTR SystemRootArcPath,
+ _In_ PUNICODE_STRING SystemRootNtPath, // or PCWSTR ?
+ _In_ PCWSTR PathComponent, // Pointer inside SystemRootNtPath buffer
+ _In_ ULONG DiskNumber,
+ _In_ ULONG PartitionNumber)
{
PNTOS_INSTALLATION NtOsInstall;
SIZE_T ArcPathLength, NtPathLength;
@@ -648,8 +647,6 @@ AddNTOSInstallation(
NtOsInstall->DiskNumber = DiskNumber;
NtOsInstall->PartitionNumber = PartitionNumber;
- NtOsInstall->PartEntry = PartEntry;
-
NtOsInstall->Machine = Machine;
RtlInitEmptyUnicodeString(&NtOsInstall->SystemArcPath,
@@ -680,39 +677,34 @@ AddNTOSInstallation(
static VOID
FindNTOSInstallations(
- IN OUT PGENERIC_LIST List,
- IN PPARTLIST PartList,
- IN PPARTENTRY PartEntry)
+ _Inout_ PGENERIC_LIST List,
+ _In_ PPARTLIST PartList,
+ _In_ PVOLENTRY Volume)
{
NTSTATUS Status;
- ULONG DiskNumber = PartEntry->DiskEntry->DiskNumber;
- ULONG PartitionNumber = PartEntry->PartitionNumber;
- HANDLE PartitionDirectoryHandle;
+ HANDLE VolumeRootDirHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
- UNICODE_STRING PartitionRootPath;
+ UNICODE_STRING VolumeRootPath;
BOOT_STORE_TYPE Type;
PVOID BootStoreHandle;
ENUM_INSTALLS_DATA Data;
ULONG Version;
- WCHAR PathBuffer[MAX_PATH];
-
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+ WCHAR PathBuffer[RTL_NUMBER_OF_FIELD(VOLINFO, DeviceName) + 1];
- /* Set PartitionRootPath */
- RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu\\",
- DiskNumber, PartitionNumber);
- RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
- DPRINT("FindNTOSInstallations: PartitionRootPath: '%wZ'\n",
&PartitionRootPath);
+ /* Set VolumeRootPath */
+ RtlStringCchPrintfW(PathBuffer, _countof(PathBuffer),
+ L"%s\\", Volume->Info.DeviceName);
+ RtlInitUnicodeString(&VolumeRootPath, PathBuffer);
+ DPRINT("FindNTOSInstallations(%wZ)\n", &VolumeRootPath);
- /* Open the partition */
+ /* Open the volume */
InitializeObjectAttributes(&ObjectAttributes,
- &PartitionRootPath,
+ &VolumeRootPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
- Status = NtOpenFile(&PartitionDirectoryHandle,
+ Status = NtOpenFile(&VolumeRootDirHandle,
FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
@@ -720,7 +712,7 @@ FindNTOSInstallations(
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
- DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n",
&PartitionRootPath, Status);
+ DPRINT1("Failed to open volume '%wZ', Status 0x%08lx\n",
&VolumeRootPath, Status);
return;
}
@@ -730,7 +722,7 @@ FindNTOSInstallations(
/* Try to see whether we recognize some NT boot loaders */
for (Type = FreeLdr; Type < BldrTypeMax; ++Type)
{
- Status = FindBootStore(PartitionDirectoryHandle, Type, &Version);
+ Status = FindBootStore(VolumeRootDirHandle, Type, &Version);
if (!NT_SUCCESS(Status))
{
/* The loader does not exist, continue with another one */
@@ -740,10 +732,12 @@ FindNTOSInstallations(
}
/* The loader exists, try to enumerate its boot entries */
- DPRINT("Analyze the OS installations for loader type '%d' in disk
#%d, partition #%d\n",
- Type, DiskNumber, PartitionNumber);
+ DPRINT("Analyze the OS installations for loader type '%d' in Volume
%wZ (Disk #%d, Partition #%d)\n",
+ Type, &VolumeRootPath,
+ Volume->PartEntry->DiskEntry->DiskNumber,
+ Volume->PartEntry->PartitionNumber);
- Status = OpenBootStoreByHandle(&BootStoreHandle, PartitionDirectoryHandle,
Type,
+ Status = OpenBootStoreByHandle(&BootStoreHandle, VolumeRootDirHandle, Type,
BS_OpenExisting, BS_ReadAccess);
if (!NT_SUCCESS(Status))
{
@@ -755,90 +749,63 @@ FindNTOSInstallations(
CloseBootStore(BootStoreHandle);
}
- /* Close the partition */
- NtClose(PartitionDirectoryHandle);
-}
-
-// static
-FORCEINLINE BOOLEAN
-ShouldICheckThisPartition(
- IN PPARTENTRY PartEntry)
-{
- if (!PartEntry)
- return FALSE;
-
- return PartEntry->IsPartitioned &&
- !IsContainerPartition(PartEntry->PartitionType) /* alternatively:
PartEntry->PartitionNumber != 0 */ &&
- !PartEntry->New &&
- (PartEntry->FormatState == Preformatted /* || PartEntry->FormatState ==
Formatted */);
+ /* Close the volume */
+ NtClose(VolumeRootDirHandle);
}
+/**
+ * @brief
+ * Create a list of available NT OS installations on the computer,
+ * by searching for recognized ones on each recognized storage volume.
+ **/
// EnumerateNTOSInstallations
PGENERIC_LIST
CreateNTOSInstallationsList(
- IN PPARTLIST PartList)
+ _In_ PPARTLIST PartList)
{
PGENERIC_LIST List;
- PLIST_ENTRY Entry, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
+ PLIST_ENTRY Entry;
+ PVOLENTRY Volume;
+ BOOLEAN CheckVolume;
List = CreateGenericList();
- if (List == NULL)
+ if (!List)
return NULL;
- /* Loop each available disk ... */
- Entry = PartList->DiskListHead.Flink;
- while (Entry != &PartList->DiskListHead)
+ /* Loop each available volume */
+ for (Entry = PartList->VolumesList.Flink;
+ Entry != &PartList->VolumesList;
+ Entry = Entry->Flink)
{
- DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
- Entry = Entry->Flink;
-
- DPRINT("Disk #%d\n", DiskEntry->DiskNumber);
+ Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
+ /* Valid OS installations can be found only on basic volumes */
+ if (!Volume->PartEntry) // TODO: In the future: (!Volume->IsSimpleVolume)
+ continue;
- /* ... and for each disk, loop each available partition */
+ CheckVolume = (!Volume->New && (Volume->FormatState ==
Formatted));
- /* First, the primary partitions */
- Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- while (Entry2 != &DiskEntry->PrimaryPartListHead)
+#ifndef NDEBUG
{
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- Entry2 = Entry2->Flink;
-
- ASSERT(PartEntry->DiskEntry == DiskEntry);
-
- DPRINT(" Primary Partition #%d, index %d - Type 0x%02x, IsLogical =
%s, IsPartitioned = %s, IsNew = %s, FormatState = %lu -- Should I check it? %s\n",
- PartEntry->PartitionNumber, PartEntry->PartitionIndex,
- PartEntry->PartitionType, PartEntry->LogicalPartition ?
"TRUE" : "FALSE",
- PartEntry->IsPartitioned ? "TRUE" : "FALSE",
- PartEntry->New ? "Yes" : "No",
- PartEntry->FormatState,
- ShouldICheckThisPartition(PartEntry) ? "YES!" :
"NO!");
-
- if (ShouldICheckThisPartition(PartEntry))
- FindNTOSInstallations(List, PartList, PartEntry);
+ PPARTENTRY PartEntry = Volume->PartEntry;
+ ASSERT(PartEntry->Volume == Volume);
+ DPRINT("Volume %S (%c%c) on Disk #%d, Partition #%d (%s), "
+ "index %d - Type 0x%02x, IsVolNew = %s, FormatState = %lu -- Should I
check it? %s\n",
+ Volume->Info.DeviceName,
+ !Volume->Info.DriveLetter ? '-' :
(CHAR)Volume->Info.DriveLetter,
+ !Volume->Info.DriveLetter ? '-' : ':',
+ PartEntry->DiskEntry->DiskNumber,
+ PartEntry->PartitionNumber,
+ PartEntry->LogicalPartition ? "Logical" :
"Primary",
+ PartEntry->PartitionIndex,
+ PartEntry->PartitionType,
+ Volume->New ? "Yes" : "No",
+ Volume->FormatState,
+ CheckVolume ? "YES!" : "NO!");
}
+#endif
- /* Then, the logical partitions (present in the extended partition) */
- Entry2 = DiskEntry->LogicalPartListHead.Flink;
- while (Entry2 != &DiskEntry->LogicalPartListHead)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- Entry2 = Entry2->Flink;
-
- ASSERT(PartEntry->DiskEntry == DiskEntry);
-
- DPRINT(" Logical Partition #%d, index %d - Type 0x%02x, IsLogical =
%s, IsPartitioned = %s, IsNew = %s, FormatState = %lu -- Should I check it? %s\n",
- PartEntry->PartitionNumber, PartEntry->PartitionIndex,
- PartEntry->PartitionType, PartEntry->LogicalPartition ?
"TRUE" : "FALSE",
- PartEntry->IsPartitioned ? "TRUE" : "FALSE",
- PartEntry->New ? "Yes" : "No",
- PartEntry->FormatState,
- ShouldICheckThisPartition(PartEntry) ? "YES!" :
"NO!");
-
- if (ShouldICheckThisPartition(PartEntry))
- FindNTOSInstallations(List, PartList, PartEntry);
- }
+ if (CheckVolume)
+ FindNTOSInstallations(List, PartList, Volume);
}
#ifndef NDEBUG
diff --git a/base/setup/lib/utils/osdetect.h b/base/setup/lib/utils/osdetect.h
index e8b54496011..e329b1c32f4 100644
--- a/base/setup/lib/utils/osdetect.h
+++ b/base/setup/lib/utils/osdetect.h
@@ -1,9 +1,9 @@
/*
* PROJECT: ReactOS Setup Library
- * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: NT 5.x family (MS Windows <= 2003, and ReactOS)
* operating systems detection code.
- * COPYRIGHT: Copyright 2017-2018 Hermes Belusca-Maito
+ * COPYRIGHT: Copyright 2017-2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
*/
#pragma once
@@ -22,7 +22,7 @@ typedef struct _NTOS_INSTALLATION
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
ULONG DiskNumber;
ULONG PartitionNumber;
- PPARTENTRY PartEntry;
+ PVOLENTRY Volume; // PVOLINFO
WCHAR InstallationName[MAX_PATH];
WCHAR VendorName[MAX_PATH];
// CHAR Data[ANYSIZE_ARRAY];
@@ -31,7 +31,7 @@ typedef struct _NTOS_INSTALLATION
// EnumerateNTOSInstallations
PGENERIC_LIST
CreateNTOSInstallationsList(
- IN PPARTLIST List);
+ _In_ PPARTLIST PartList);
/*
* FindSubStrI(PCWSTR str, PCWSTR strSearch) :
diff --git a/base/setup/lib/utils/partlist.c b/base/setup/lib/utils/partlist.c
index 914fe69ccb3..466a1826979 100644
--- a/base/setup/lib/utils/partlist.c
+++ b/base/setup/lib/utils/partlist.c
@@ -1,31 +1,31 @@
/*
* PROJECT: ReactOS Setup Library
- * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Partition list functions
* COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns(a)users.sourceforge.net)
- * Copyright 2018-2019 Hermes Belusca-Maito
+ * Copyright 2018-2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
*/
#include "precomp.h"
#include <ntddscsi.h>
#include "partlist.h"
-#include "fsrec.h"
+#include "volutil.h"
+#include "fsrec.h" // For FileSystemToMBRPartitionType()
+
#include "registry.h"
#define NDEBUG
#include <debug.h>
-//#define DUMP_PARTITION_TABLE
+// #define DUMP_PARTITION_TABLE
#include <pshpack1.h>
-
typedef struct _REG_DISK_MOUNT_INFO
{
ULONG Signature;
- LARGE_INTEGER StartingOffset;
+ ULONGLONG StartingOffset;
} REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
-
#include <poppack.h>
@@ -159,22 +159,17 @@ AssignDriveLetters(
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- PartEntry->DriveLetter = 0;
+ if (!PartEntry->Volume)
+ continue;
+ PartEntry->Volume->Info.DriveLetter = UNICODE_NULL;
if (PartEntry->IsPartitioned &&
- !IsContainerPartition(PartEntry->PartitionType))
+ !IsContainerPartition(PartEntry->PartitionType) &&
+ (IsRecognizedPartition(PartEntry->PartitionType) ||
+ PartEntry->SectorCount.QuadPart != 0LL))
{
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
-
- if (IsRecognizedPartition(PartEntry->PartitionType) ||
- PartEntry->SectorCount.QuadPart != 0LL)
- {
- if (Letter <= L'Z')
- {
- PartEntry->DriveLetter = Letter;
- Letter++;
- }
- }
+ if (Letter <= L'Z')
+ PartEntry->Volume->Info.DriveLetter = Letter++;
}
}
}
@@ -192,21 +187,16 @@ AssignDriveLetters(
{
PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- PartEntry->DriveLetter = 0;
+ if (!PartEntry->Volume)
+ continue;
+ PartEntry->Volume->Info.DriveLetter = UNICODE_NULL;
- if (PartEntry->IsPartitioned)
+ if (PartEntry->IsPartitioned &&
+ (IsRecognizedPartition(PartEntry->PartitionType) ||
+ PartEntry->SectorCount.QuadPart != 0LL))
{
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
-
- if (IsRecognizedPartition(PartEntry->PartitionType) ||
- PartEntry->SectorCount.QuadPart != 0LL)
- {
- if (Letter <= L'Z')
- {
- PartEntry->DriveLetter = Letter;
- Letter++;
- }
- }
+ if (Letter <= L'Z')
+ PartEntry->Volume->Info.DriveLetter = Letter++;
}
}
}
@@ -564,8 +554,8 @@ IsSuperFloppy(
/*
- * Inserts the disk region represented by PartEntry into either the primary
- * or the logical partition list of the given disk.
+ * Inserts the disk region represented by PartEntry into either
+ * the primary or the logical partition list of the given disk.
* The lists are kept sorted by increasing order of start sectors.
* Of course no disk region should overlap at all with one another.
*/
@@ -649,7 +639,7 @@ CreateInsertBlankRegion(
NewPartEntry = RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(PARTENTRY));
- if (NewPartEntry == NULL)
+ if (!NewPartEntry)
return NULL;
NewPartEntry->DiskEntry = DiskEntry;
@@ -660,8 +650,7 @@ CreateInsertBlankRegion(
NewPartEntry->LogicalPartition = LogicalSpace;
NewPartEntry->IsPartitioned = FALSE;
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
- NewPartEntry->FormatState = Unformatted;
- NewPartEntry->FileSystem[0] = L'\0';
+ NewPartEntry->Volume = NULL;
DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart +
NewPartEntry->SectorCount.QuadPart - 1);
@@ -673,6 +662,17 @@ CreateInsertBlankRegion(
return NewPartEntry;
}
+static
+VOID
+DestroyRegion(
+ _Inout_ PPARTENTRY PartEntry)
+{
+ // RemoveEntryList(&PartEntry->Volume->ListEntry);
+ if (PartEntry->Volume)
+ RtlFreeHeap(ProcessHeap, 0, PartEntry->Volume);
+ RtlFreeHeap(ProcessHeap, 0, PartEntry);
+}
+
static
VOID
AddLogicalDiskSpace(
@@ -719,6 +719,7 @@ InitializePartitionEntry(
/* The entry must not be already partitioned and not be void */
ASSERT(!PartEntry->IsPartitioned);
ASSERT(PartEntry->SectorCount.QuadPart);
+ ASSERT(!PartEntry->Volume);
/* Either we create a primary/logical partition, or we create an
* extended partition but the entry must not be logical space */
@@ -780,7 +781,7 @@ InitializePartitionEntry(
PartEntry->SectorCount.QuadPart = StartSector -
PartEntry->StartSector.QuadPart;
}
- /* Convert the partition entry to 'New (Unformatted)' */
+ /* Convert to a new partition entry */
PartEntry->New = TRUE;
PartEntry->IsPartitioned = TRUE;
@@ -819,9 +820,6 @@ InitializePartitionEntry(
}
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
- PartEntry->FormatState = Unformatted;
- PartEntry->FileSystem[0] = L'\0';
-
if (isContainer)
{
DiskEntry->ExtendedPartition = PartEntry;
@@ -835,6 +833,90 @@ InitializePartitionEntry(
return TRUE;
}
+static
+VOID
+InitPartitionDeviceName(
+ _Inout_ PPARTENTRY PartEntry)
+{
+ NTSTATUS Status;
+
+ /* Ignore if this is a container partition */
+ if (IsContainerPartition(PartEntry->PartitionType))
+ return;
+ ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+
+ /* Make a device name for the partition */
+ Status = RtlStringCchPrintfW(PartEntry->DeviceName,
+ _countof(PartEntry->DeviceName),
+ L"\\Device\\Harddisk%lu\\Partition%lu",
+ PartEntry->DiskEntry->DiskNumber,
+ PartEntry->PartitionNumber);
+ ASSERT(NT_SUCCESS(Status));
+}
+
+static
+VOID
+InitVolumeDeviceName(
+ _Inout_ PVOLENTRY Volume)
+{
+ NTSTATUS Status;
+ PPARTENTRY PartEntry;
+
+ /* If we already have a volume device name, do nothing more */
+ if (*Volume->Info.DeviceName)
+ return;
+
+ /* Use the partition device name as a temporary volume device name */
+ // TODO: Ask instead the MOUNTMGR for the name.
+ PartEntry = Volume->PartEntry;
+ ASSERT(PartEntry);
+ ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+
+ /* Copy the volume device name */
+ Status = RtlStringCchCopyW(Volume->Info.DeviceName,
+ _countof(Volume->Info.DeviceName),
+ PartEntry->DeviceName);
+ ASSERT(NT_SUCCESS(Status));
+}
+
+static
+PVOLENTRY
+InitVolume(
+ _In_ PPARTLIST List,
+ _In_opt_ PPARTENTRY PartEntry)
+{
+ PVOLENTRY Volume;
+
+ Volume = RtlAllocateHeap(ProcessHeap,
+ HEAP_ZERO_MEMORY,
+ sizeof(VOLENTRY));
+ if (!Volume)
+ return NULL;
+
+ /* Reset some volume information */
+
+ /* No device name for now */
+ Volume->Info.DeviceName[0] = UNICODE_NULL;
+ // Volume->Info.VolumeName[0] = UNICODE_NULL;
+
+ /* Initialize the volume letter and label */
+ Volume->Info.DriveLetter = UNICODE_NULL;
+ Volume->Info.VolumeLabel[0] = UNICODE_NULL;
+
+ /* Specify the volume as initially unformatted */
+ Volume->Info.FileSystem[0] = UNICODE_NULL;
+ Volume->FormatState = Unformatted;
+ Volume->NeedsCheck = FALSE;
+ Volume->New = TRUE;
+
+ if (PartEntry)
+ {
+ ASSERT(PartEntry->DiskEntry->PartList == List);
+ Volume->PartEntry = PartEntry;
+ }
+ InsertTailList(&List->VolumesList, &Volume->ListEntry);
+ return Volume;
+}
static
VOID
@@ -844,29 +926,21 @@ AddPartitionToDisk(
IN ULONG PartitionIndex,
IN BOOLEAN LogicalPartition)
{
- NTSTATUS Status;
PPARTITION_INFORMATION PartitionInfo;
PPARTENTRY PartEntry;
- HANDLE PartitionHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- WCHAR PathBuffer[MAX_PATH];
- UNICODE_STRING Name;
- UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
- PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)LabelBuffer;
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
- if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED ||
- ((LogicalPartition != FALSE) &&
IsContainerPartition(PartitionInfo->PartitionType)))
- {
+ /* Ignore empty partitions */
+ if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED)
return;
- }
+ /* Request must be consistent, though! */
+ ASSERT(!(LogicalPartition &&
IsContainerPartition(PartitionInfo->PartitionType)));
PartEntry = RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(PARTENTRY));
- if (PartEntry == NULL)
+ if (!PartEntry)
return;
PartEntry->DiskEntry = DiskEntry;
@@ -882,146 +956,73 @@ AddPartitionToDisk(
PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
PartEntry->PartitionIndex = PartitionIndex;
+ InitPartitionDeviceName(PartEntry);
- /* Specify the partition as initially unformatted */
- PartEntry->FormatState = Unformatted;
- PartEntry->FileSystem[0] = L'\0';
-
- /* Initialize the partition volume label */
- RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+ /* No volume initially */
+ PartEntry->Volume = NULL;
if (IsContainerPartition(PartEntry->PartitionType))
{
- PartEntry->FormatState = Unformatted;
-
- if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition ==
NULL)
+ if (!LogicalPartition && DiskEntry->ExtendedPartition == NULL)
DiskEntry->ExtendedPartition = PartEntry;
}
- else if (IsRecognizedPartition(PartEntry->PartitionType))
+ else if (IsRecognizedPartition(PartEntry->PartitionType) || //
PartitionInfo->RecognizedPartition
+ IsOEMPartition(PartEntry->PartitionType))
{
- ASSERT(PartitionInfo->RecognizedPartition);
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber !=
0);
-
- /* Try to open the volume so as to mount it */
- RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- DiskEntry->DiskNumber,
- PartEntry->PartitionNumber);
- RtlInitUnicodeString(&Name, PathBuffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- PartitionHandle = NULL;
- Status = NtOpenFile(&PartitionHandle,
- FILE_READ_DATA | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
- }
+ PVOLENTRY Volume;
+ NTSTATUS Status;
- if (PartitionHandle)
- {
- ASSERT(NT_SUCCESS(Status));
+ ASSERT(PartEntry->PartitionNumber != 0);
- /* We don't have a FS, try to guess one */
- Status = InferFileSystem(NULL, PartitionHandle,
- PartEntry->FileSystem,
- sizeof(PartEntry->FileSystem));
- if (!NT_SUCCESS(Status))
- DPRINT1("InferFileSystem() failed, Status 0x%08lx\n",
Status);
- }
- 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)
- {
- /*
- * 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
+ /* The PARTMGR should have notified the MOUNTMGR that a volume
+ * associated with this partition had to be created */
+ Volume = InitVolume(DiskEntry->PartList, PartEntry);
+ if (!Volume)
{
- PartEntry->FormatState = UnknownFormat;
+ DPRINT1("Couldn't allocate a volume for device
'%S'\n",
+ PartEntry->DeviceName);
+ goto SkipVolume;
}
+ PartEntry->Volume = Volume;
+ InitVolumeDeviceName(Volume);
+ Volume->New = FALSE;
- /* Retrieve the partition volume label */
- if (PartitionHandle)
+ /* Attach and mount the volume */
+ Status = MountVolume(&Volume->Info, PartEntry->PartitionType);
+ if (!NT_SUCCESS(Status))
{
- Status = NtQueryVolumeInformationFile(PartitionHandle,
- &IoStatusBlock,
- &LabelBuffer,
- sizeof(LabelBuffer),
- FileFsVolumeInformation);
- if (NT_SUCCESS(Status))
- {
- /* Copy the (possibly truncated) volume label and NULL-terminate it */
- RtlStringCbCopyNW(PartEntry->VolumeLabel,
sizeof(PartEntry->VolumeLabel),
- LabelInfo->VolumeLabel,
LabelInfo->VolumeLabelLength);
- }
- else
- {
- DPRINT1("NtQueryVolumeInformationFile() failed, Status
0x%08lx\n", Status);
- }
+ DPRINT1("Failed to mount volume '%S', Status 0x%08lx\n",
+ Volume->Info.DeviceName, Status);
}
- /* Close the partition */
- if (PartitionHandle)
- NtClose(PartitionHandle);
+ //
+ // FIXME: TEMP Backward-compatibility: Set the FormatState
+ // flag in accordance with the FileSystem volume value.
+ //
+ /*
+ * MountVolume() determines whether the given volume is actually
+ * unformatted, if it was mounted with RawFS and the partition
+ * type has specific values for FAT volumes. If so, the volume
+ * stays mounted with RawFS (the FileSystem is "RAW"). However,
+ * if the partition type has different values, the volume is
+ * considered as having an unknown format (it may or may not be
+ * formatted) and the FileSystem value has been emptied.
+ */
+ if (IsUnknown(&Volume->Info))
+ Volume->FormatState = UnknownFormat;
+ else if (IsUnformatted(&Volume->Info)) // FileSystem is "RAW"
+ Volume->FormatState = Unformatted;
+ else // !IsUnknown && !IsUnformatted == IsFormatted
+ Volume->FormatState = Formatted;
+SkipVolume:;
}
else
{
- /* Unknown partition, hence unknown format (may or may not be actually formatted)
*/
- PartEntry->FormatState = UnknownFormat;
+ /* Unknown partition (may or may not be actually formatted):
+ * the partition is hidden, hence no volume */
+ DPRINT1("Disk %lu Partition %lu is not recognized (Type 0x%02x)\n",
+ DiskEntry->DiskNumber, PartEntry->PartitionNumber,
+ PartEntry->PartitionType);
}
InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
@@ -1262,7 +1263,7 @@ SetDiskSignature(
/* Check if the signature already exist */
/* FIXME:
* Check also signatures from disks, which are
- * not visible (bootable) by the bios.
+ * not visible (bootable) by the BIOS.
*/
for (Entry2 = List->DiskListHead.Flink;
Entry2 != &List->DiskListHead;
@@ -1569,7 +1570,7 @@ AddDiskToList(
{
BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
/* FIXME:
- * Compare the size from bios and the reported size from driver.
+ * Compare the size from BIOS and the reported size from driver.
* If we have more than one disk with a zero or with the same signature
* we must create new signatures and reboot. After the reboot,
* it is possible to identify the disks.
@@ -1898,12 +1899,13 @@ GetActiveDiskPartition(
/* Yes, we've found it */
ASSERT(DiskEntry == PartEntry->DiskEntry);
ASSERT(PartEntry->IsPartitioned);
+ ASSERT(PartEntry->Volume);
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);
+ !PartEntry->Volume->Info.DriveLetter ? L'-' :
PartEntry->Volume->Info.DriveLetter);
break;
}
}
@@ -1937,13 +1939,14 @@ CreatePartitionList(VOID)
List = (PPARTLIST)RtlAllocateHeap(ProcessHeap,
0,
sizeof(PARTLIST));
- if (List == NULL)
+ if (!List)
return NULL;
List->SystemPartition = NULL;
InitializeListHead(&List->DiskListHead);
InitializeListHead(&List->BiosDiskListHead);
+ InitializeListHead(&List->VolumesList);
/*
* Enumerate the disks seen by the BIOS; this will be used later
@@ -2026,8 +2029,7 @@ DestroyPartitionList(
{
Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-
- RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ DestroyRegion(PartEntry);
}
/* Release logical partition list */
@@ -2035,8 +2037,7 @@ DestroyPartitionList(
{
Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
-
- RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ DestroyRegion(PartEntry);
}
/* Release layout buffer */
@@ -2047,12 +2048,11 @@ DestroyPartitionList(
RtlFreeHeap(ProcessHeap, 0, DiskEntry);
}
- /* Release the bios disk info */
+ /* Release the BIOS disk info */
while (!IsListEmpty(&List->BiosDiskListHead))
{
Entry = RemoveHeadList(&List->BiosDiskListHead);
BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
-
RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
}
@@ -2540,7 +2540,7 @@ UpdateDiskLayout(
}
/* Resize the layout buffer if necessary */
- if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
+ if (!ReAllocateLayoutBuffer(DiskEntry))
{
DPRINT("ReAllocateLayoutBuffer() failed.\n");
return;
@@ -2561,7 +2561,7 @@ UpdateDiskLayout(
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
PartEntry->PartitionIndex = Index;
- /* Reset the current partition number only for newly-created (unmounted)
partitions */
+ /* Reset the current partition number only for not-yet written partitions
*/
if (PartEntry->New)
PartEntry->PartitionNumber = 0;
@@ -2606,7 +2606,7 @@ UpdateDiskLayout(
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
PartEntry->PartitionIndex = Index;
- /* Reset the current partition number only for newly-created (unmounted)
partitions */
+ /* Reset the current partition number only for not-yet written partitions
*/
if (PartEntry->New)
PartEntry->PartitionNumber = 0;
@@ -2849,6 +2849,7 @@ CreatePartition(
{
ERROR_NUMBER Error;
BOOLEAN isContainer = IsContainerPartition((UCHAR)PartitionInfo);
+ PDISKENTRY DiskEntry;
PCSTR mainType = "Primary";
if (isContainer)
@@ -2878,39 +2879,42 @@ CreatePartition(
if (!InitializePartitionEntry(PartEntry, SizeBytes, PartitionInfo))
return FALSE;
- if (isContainer)
+ DiskEntry = PartEntry->DiskEntry;
+ UpdateDiskLayout(DiskEntry);
+
+ ASSERT(!PartEntry->Volume);
+ if (!isContainer)
{
- // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the
extended partition container)
- PartEntry->New = FALSE;
- PartEntry->FormatState = Formatted;
+ /* We create a primary/logical partition: initialize a new basic
+ * volume entry. When the partition will actually be written onto
+ * the disk, the PARTMGR will notify the MOUNTMGR that a volume
+ * associated with this partition has to be created. */
+ PartEntry->Volume = InitVolume(DiskEntry->PartList, PartEntry);
+ ASSERT(PartEntry->Volume);
}
- UpdateDiskLayout(PartEntry->DiskEntry);
AssignDriveLetters(List);
return TRUE;
}
-NTSTATUS
-DismountVolume(
- IN PPARTENTRY PartEntry)
+static NTSTATUS
+DismountPartition(
+ _In_ PPARTLIST List,
+ _In_ PPARTENTRY PartEntry)
{
NTSTATUS Status;
- NTSTATUS LockStatus;
- UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE PartitionHandle;
- WCHAR Buffer[MAX_PATH];
+ PVOLENTRY Volume = PartEntry->Volume;
+
+ ASSERT(PartEntry->DiskEntry->PartList == List);
/* Check whether the partition is valid and was mounted by the system */
if (!PartEntry->IsPartitioned ||
IsContainerPartition(PartEntry->PartitionType) ||
!IsRecognizedPartition(PartEntry->PartitionType) ||
- PartEntry->FormatState == UnknownFormat ||
+ !Volume || Volume->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)
{
/* The partition is not mounted, so just return success */
@@ -2918,83 +2922,14 @@ DismountVolume(
}
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
-
- /* Open the volume */
- RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- PartEntry->DiskEntry->DiskNumber,
- PartEntry->PartitionNumber);
- RtlInitUnicodeString(&Name, Buffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &Name,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&PartitionHandle,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_SYNCHRONOUS_IO_NONALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status
0x%lx)\n", &Name, Status);
- return Status;
- }
-
- /* Lock the volume */
- LockStatus = NtFsControlFile(PartitionHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_LOCK_VOLUME,
- NULL,
- 0,
- NULL,
- 0);
- if (!NT_SUCCESS(LockStatus))
- {
- DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status
0x%lx)\n", LockStatus);
- }
-
- /* Dismount the volume */
- Status = NtFsControlFile(PartitionHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_DISMOUNT_VOLUME,
- NULL,
- 0,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
- }
-
- /* Unlock the volume */
- LockStatus = NtFsControlFile(PartitionHandle,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_UNLOCK_VOLUME,
- NULL,
- 0,
- NULL,
- 0);
- if (!NT_SUCCESS(LockStatus))
- {
- DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
- }
-
- /* Close the volume */
- NtClose(PartitionHandle);
-
+ ASSERT(Volume->PartEntry == PartEntry);
+
+ /* Unlink the basic volume from the volumes list and dismount it */
+ PartEntry->Volume = NULL;
+ Volume->PartEntry = NULL;
+ RemoveEntryList(&Volume->ListEntry);
+ Status = DismountVolume(&Volume->Info, TRUE);
+ RtlFreeHeap(ProcessHeap, 0, Volume);
return Status;
}
@@ -3016,6 +2951,7 @@ DeletePartition(
return FALSE;
}
+ ASSERT(PartEntry->DiskEntry->PartList == List);
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
/* Clear the system partition if it is being deleted */
@@ -3036,19 +2972,17 @@ DeletePartition(
Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
- /* Dismount the logical partition */
- DismountVolume(LogicalPartEntry);
-
- /* Delete it */
- RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
+ /* Dismount the logical partition and delete it */
+ DismountPartition(List, LogicalPartEntry);
+ DestroyRegion(LogicalPartEntry);
}
DiskEntry->ExtendedPartition = NULL;
}
else
{
- /* A primary partition is being deleted: dismount it */
- DismountVolume(PartEntry);
+ /* A primary/logical partition is being deleted: dismount it */
+ DismountPartition(List, PartEntry);
}
/* Adjust the unpartitioned disk space entries */
@@ -3066,9 +3000,9 @@ DeletePartition(
/* Remove the current and next entries */
RemoveEntryList(&PartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ DestroyRegion(PartEntry);
RemoveEntryList(&NextPartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
+ DestroyRegion(NextPartEntry);
/* Optionally return the freed region */
if (FreeRegion)
@@ -3083,7 +3017,7 @@ DeletePartition(
/* Remove the current entry */
RemoveEntryList(&PartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ DestroyRegion(PartEntry);
/* Optionally return the freed region */
if (FreeRegion)
@@ -3099,7 +3033,7 @@ DeletePartition(
/* Remove the current entry */
RemoveEntryList(&PartEntry->ListEntry);
- RtlFreeHeap(ProcessHeap, 0, PartEntry);
+ DestroyRegion(PartEntry);
/* Optionally return the freed region */
if (FreeRegion)
@@ -3108,16 +3042,21 @@ DeletePartition(
else
{
/* Nothing to merge but change the current entry */
+ PartEntry->New = FALSE;
PartEntry->IsPartitioned = FALSE;
+ PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
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;
- RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
+ PartEntry->DeviceName[0] = UNICODE_NULL;
+
+ if (PartEntry->Volume)
+ {
+ RemoveEntryList(&PartEntry->Volume->ListEntry);
+ RtlFreeHeap(ProcessHeap, 0, PartEntry->Volume);
+ }
+ PartEntry->Volume = NULL;
/* Optionally return the freed region */
if (FreeRegion)
@@ -3135,6 +3074,8 @@ BOOLEAN
IsSupportedActivePartition(
IN PPARTENTRY PartEntry)
{
+ PVOLENTRY Volume;
+
/* Check the type and the file system of this partition */
/*
@@ -3148,6 +3089,13 @@ IsSupportedActivePartition(
return FALSE;
}
+ Volume = PartEntry->Volume;
+ if (!Volume)
+ {
+ /* Still no recognizable volume mounted: partition not supported */
+ return FALSE;
+ }
+
/*
* ADDITIONAL CHECKS / BIG HACK:
*
@@ -3164,21 +3112,20 @@ IsSupportedActivePartition(
* NOTE also that for those architectures looking for a
* partition boot indicator is insufficient.
*/
- if (PartEntry->FormatState == Unformatted)
+ if (Volume->FormatState == Unformatted)
{
/* If this partition is mounted, it would use RawFS ("RAW") */
return TRUE;
}
- else if ((PartEntry->FormatState == Preformatted) ||
- (PartEntry->FormatState == Formatted))
+ else if (Volume->FormatState == Formatted)
{
- ASSERT(*PartEntry->FileSystem);
+ ASSERT(*Volume->Info.FileSystem);
/* NOTE: Please keep in sync with the RegisteredFileSystems list! */
- 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)
+ if (wcsicmp(Volume->Info.FileSystem, L"FAT") == 0 ||
+ wcsicmp(Volume->Info.FileSystem, L"FAT32") == 0 ||
+ // wcsicmp(Volume->Info.FileSystem, L"NTFS") == 0 ||
+ wcsicmp(Volume->Info.FileSystem, L"BTRFS") == 0)
{
return TRUE;
}
@@ -3186,13 +3133,13 @@ IsSupportedActivePartition(
{
// WARNING: We cannot write on this FS yet!
DPRINT1("Recognized file system '%S' that doesn't have write
support yet!\n",
- PartEntry->FileSystem);
+ Volume->Info.FileSystem);
return FALSE;
}
}
- else // if (PartEntry->FormatState == UnknownFormat)
+ else // if (Volume->FormatState == UnknownFormat)
{
- ASSERT(!*PartEntry->FileSystem);
+ ASSERT(!*Volume->Info.FileSystem);
DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
@@ -3204,7 +3151,7 @@ IsSupportedActivePartition(
if (PartEntry->PartitionType == PARTITION_IFS)
{
DPRINT1("Recognized file system '%S' that doesn't have write
support yet!\n",
- PartEntry->FileSystem);
+ Volume->Info.FileSystem);
return FALSE;
}
@@ -3278,7 +3225,7 @@ FindSupportedSystemPartition(
DPRINT1("Use the current system partition %lu in disk %lu, drive letter
%C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
- (CandidatePartition->DriveLetter == 0) ? L'-' :
CandidatePartition->DriveLetter);
+ !CandidatePartition->Volume->Info.DriveLetter ? L'-' :
CandidatePartition->Volume->Info.DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@@ -3427,7 +3374,7 @@ UseAlternativeDisk:
DPRINT1("Use new first active system partition %lu in disk %lu, drive
letter %C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
- (CandidatePartition->DriveLetter == 0) ? L'-' :
CandidatePartition->DriveLetter);
+ !CandidatePartition->Volume->Info.DriveLetter ? L'-' :
CandidatePartition->Volume->Info.DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@@ -3467,7 +3414,7 @@ UseAlternativeDisk:
DPRINT1("Use first active system partition %lu in disk %lu, drive letter
%C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
- (CandidatePartition->DriveLetter == 0) ? L'-' :
CandidatePartition->DriveLetter);
+ !CandidatePartition->Volume->Info.DriveLetter ? L'-' :
CandidatePartition->Volume->Info.DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@@ -3505,7 +3452,7 @@ UseAlternativePartition:
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter
%C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
- (CandidatePartition->DriveLetter == 0) ? L'-' :
CandidatePartition->DriveLetter);
+ !CandidatePartition->Volume->Info.DriveLetter ? L'-' :
CandidatePartition->Volume->Info.DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@@ -3543,7 +3490,7 @@ SetActivePartition(
/*
* If the user provided an old active partition hint, verify that it is
- * indeeed active and belongs to the same disk where the new partition
+ * indeed active and belongs to the same disk where the new partition
* belongs. Otherwise determine the current active partition on the disk
* where the new partition belongs.
*/
@@ -3633,7 +3580,9 @@ WritePartitions(
/* Save the original partition count to be restored later (see comment below) */
PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
- /* Set the new disk layout and retrieve its updated version with possibly modified
partition numbers */
+ /* Set the new disk layout and retrieve its updated version with
+ * new partition numbers for the new partitions. The PARTMGR will
+ * automatically notify the MOUNTMGR of new or deleted volumes. */
BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
Status = NtDeviceIoControlFile(FileHandle,
@@ -3668,7 +3617,7 @@ WritePartitions(
DumpPartitionTable(DiskEntry);
#endif
- /* Update the partition numbers */
+ /* Update the partition numbers and device names */
/* Update the primary partition table */
for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
@@ -3676,13 +3625,25 @@ WritePartitions(
ListEntry = ListEntry->Flink)
{
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+ if (!PartEntry->IsPartitioned)
+ continue;
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
- if (PartEntry->IsPartitioned)
+ /*
+ * Initialize the partition's number and its device name only
+ * if the partition was new. Note that the partition number
+ * should not change if this partition has not been deleted
+ * during repartitioning.
+ */
+ // FIXME: Our PartMgr currently returns modified numbers
+ // in the layout, this needs to be investigated and fixed.
+ if (PartEntry->New)
{
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
PartitionInfo =
&DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ InitPartitionDeviceName(PartEntry);
}
+ PartEntry->New = FALSE;
}
/* Update the logical partition table */
@@ -3691,13 +3652,18 @@ WritePartitions(
ListEntry = ListEntry->Flink)
{
PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
+ if (!PartEntry->IsPartitioned)
+ continue;
+ ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
- if (PartEntry->IsPartitioned)
+ /* See comment above */
+ if (PartEntry->New)
{
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
PartitionInfo =
&DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
+ InitPartitionDeviceName(PartEntry);
}
+ PartEntry->New = FALSE;
}
//
@@ -3726,10 +3692,12 @@ WritePartitionsToDisk(
NTSTATUS Status;
PLIST_ENTRY Entry;
PDISKENTRY DiskEntry;
+ PVOLENTRY Volume;
- if (List == NULL)
+ if (!List)
return TRUE;
+ /* Write all the partitions to all the disks */
for (Entry = List->DiskListHead.Flink;
Entry != &List->DiskListHead;
Entry = Entry->Flink)
@@ -3753,26 +3721,48 @@ WritePartitionsToDisk(
}
}
+ /* The PARTMGR should have notified the MOUNTMGR that new volumes
+ * associated with the new partitions had to be created */
+
+ /* Assign valid device names to new volumes */
+ for (Entry = List->VolumesList.Flink;
+ Entry != &List->VolumesList;
+ Entry = Entry->Flink)
+ {
+ Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
+ InitVolumeDeviceName(Volume);
+ }
+
return TRUE;
}
-BOOLEAN
+
+/**
+ * @brief
+ * Assign a "\DosDevices\#:" mount point drive letter to a disk partition or
+ * volume, specified by a given disk signature and starting partition offset.
+ **/
+static BOOLEAN
SetMountedDeviceValue(
- IN WCHAR Letter,
- IN ULONG Signature,
- IN LARGE_INTEGER StartingOffset)
+ _In_ PVOLENTRY Volume)
{
+ PPARTENTRY PartEntry = Volume->PartEntry;
+ WCHAR Letter = Volume->Info.DriveLetter;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SYSTEM\\MountedDevices");
UNICODE_STRING ValueName;
- WCHAR ValueNameBuffer[16];
+ WCHAR Buffer[16];
HANDLE KeyHandle;
REG_DISK_MOUNT_INFO MountInfo;
- RtlStringCchPrintfW(ValueNameBuffer, ARRAYSIZE(ValueNameBuffer),
+ /* Ignore no letter */
+ if (!Letter)
+ return TRUE;
+
+ RtlStringCchPrintfW(Buffer, _countof(Buffer),
L"\\DosDevices\\%c:", Letter);
- RtlInitUnicodeString(&ValueName, ValueNameBuffer);
+ RtlInitUnicodeString(&ValueName, Buffer);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
@@ -3799,8 +3789,8 @@ SetMountedDeviceValue(
return FALSE;
}
- MountInfo.Signature = Signature;
- MountInfo.StartingOffset = StartingOffset;
+ MountInfo.Signature = PartEntry->DiskEntry->LayoutBuffer->Signature;
+ MountInfo.StartingOffset = GetPartEntryOffsetInBytes(PartEntry);
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
@@ -3819,75 +3809,23 @@ SetMountedDeviceValue(
BOOLEAN
SetMountedDeviceValues(
- IN PPARTLIST List)
+ _In_ PPARTLIST List)
{
- PLIST_ENTRY Entry1, Entry2;
- PDISKENTRY DiskEntry;
- PPARTENTRY PartEntry;
- LARGE_INTEGER StartingOffset;
+ PLIST_ENTRY Entry;
+ PVOLENTRY Volume;
- if (List == NULL)
+ if (!List)
return FALSE;
- for (Entry1 = List->DiskListHead.Flink;
- Entry1 != &List->DiskListHead;
- Entry1 = Entry1->Flink)
+ for (Entry = List->VolumesList.Flink;
+ Entry != &List->VolumesList;
+ Entry = Entry->Flink)
{
- DiskEntry = CONTAINING_RECORD(Entry1,
- DISKENTRY,
- ListEntry);
-
- if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
- {
- DPRINT("GPT-partitioned disk detected, not currently supported by
SETUP!\n");
- continue;
- }
-
- for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
- Entry2 != &DiskEntry->PrimaryPartListHead;
- Entry2 = Entry2->Flink)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned) // &&
!IsContainerPartition(PartEntry->PartitionType)
- {
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
-
- /* Assign a "\DosDevices\#:" mount point to this partition */
- if (PartEntry->DriveLetter)
- {
- StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
- if (!SetMountedDeviceValue(PartEntry->DriveLetter,
-
DiskEntry->LayoutBuffer->Signature,
- StartingOffset))
- {
- return FALSE;
- }
- }
- }
- }
-
- for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
- Entry2 != &DiskEntry->LogicalPartListHead;
- Entry2 = Entry2->Flink)
- {
- PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
- if (PartEntry->IsPartitioned) // &&
!IsContainerPartition(PartEntry->PartitionType)
- {
- ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
+ Volume = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
- /* Assign a "\DosDevices\#:" mount point to this partition */
- if (PartEntry->DriveLetter)
- {
- StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
- if (!SetMountedDeviceValue(PartEntry->DriveLetter,
-
DiskEntry->LayoutBuffer->Signature,
- StartingOffset))
- {
- return FALSE;
- }
- }
- }
- }
+ /* Assign a "\DosDevices\#:" mount point to this volume */
+ if (!SetMountedDeviceValue(Volume))
+ return FALSE;
}
return TRUE;
@@ -3902,6 +3840,12 @@ SetMBRPartitionType(
ASSERT(DiskEntry->DiskStyle == PARTITION_STYLE_MBR);
+ /* Nothing to do if we assign the same type */
+ if (PartitionType == PartEntry->PartitionType)
+ return;
+
+ // TODO: We might need to remount the associated basic volume...
+
PartEntry->PartitionType = PartitionType;
DiskEntry->Dirty = TRUE;
diff --git a/base/setup/lib/utils/partlist.h b/base/setup/lib/utils/partlist.h
index 9654baf3839..967c8385b4d 100644
--- a/base/setup/lib/utils/partlist.h
+++ b/base/setup/lib/utils/partlist.h
@@ -1,9 +1,9 @@
/*
* PROJECT: ReactOS Setup Library
- * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Partition list functions
* COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns(a)users.sourceforge.net)
- * Copyright 2018-2019 Hermes Belusca-Maito
+ * Copyright 2018-2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
*/
#pragma once
@@ -34,10 +34,30 @@ typedef enum _FORMATSTATE
Unformatted,
UnformattedOrDamaged,
UnknownFormat,
- Preformatted,
Formatted
} FORMATSTATE, *PFORMATSTATE;
+#include "volutil.h"
+
+typedef struct _PARTENTRY PARTENTRY, *PPARTENTRY;
+typedef struct _VOLENTRY
+{
+ LIST_ENTRY ListEntry; ///< Entry in VolumesList
+
+ VOLINFO Info;
+ FORMATSTATE FormatState;
+
+ /* Volume must be checked */
+ BOOLEAN NeedsCheck;
+ /* Volume is new and has not yet been actually formatted and mounted */
+ BOOLEAN New;
+
+ // union {
+ // PVOLUME_DISK_EXTENTS pExtents;
+ PPARTENTRY PartEntry;
+ // };
+} VOLENTRY, *PVOLENTRY;
+
typedef struct _PARTENTRY
{
LIST_ENTRY ListEntry;
@@ -54,24 +74,25 @@ typedef struct _PARTENTRY
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 */
-
- WCHAR DriveLetter;
- WCHAR VolumeLabel[20];
- WCHAR FileSystem[MAX_PATH+1];
- FORMATSTATE FormatState;
+ WCHAR DeviceName[MAX_PATH]; ///< NT device name:
"\Device\HarddiskM\PartitionN"
BOOLEAN LogicalPartition;
/* Partition is partitioned disk space */
BOOLEAN IsPartitioned;
-/** The following three properties may be replaced by flags **/
-
/* Partition is new, table does not exist on disk yet */
BOOLEAN New;
- /* Partition must be checked */
- BOOLEAN NeedsCheck;
+ /*
+ * Volume-related properties:
+ * NULL: No volume is associated to this partition (either because it is
+ * an empty disk region, or the partition type is unrecognized).
+ * 0x1 : TBD.
+ * Valid pointer: A basic volume associated to this partition is (or will)
+ * be mounted by the PARTMGR and enumerated by the MOUNTMGR.
+ */
+ PVOLENTRY Volume;
} PARTENTRY, *PPARTENTRY;
@@ -162,9 +183,12 @@ typedef struct _PARTLIST
LIST_ENTRY DiskListHead;
LIST_ENTRY BiosDiskListHead;
+ /* (Basic) Volumes management */
+ LIST_ENTRY VolumesList;
+
} PARTLIST, *PPARTLIST;
-#define PARTITION_TBL_SIZE 4
+#define PARTITION_TBL_SIZE 4
#define PARTITION_MAGIC 0xAA55
@@ -307,10 +331,6 @@ CreatePartition(
_In_opt_ ULONGLONG SizeBytes,
_In_opt_ ULONG_PTR PartitionInfo);
-NTSTATUS
-DismountVolume(
- IN PPARTENTRY PartEntry);
-
BOOLEAN
DeletePartition(
_In_ PPARTLIST List,
@@ -338,15 +358,9 @@ BOOLEAN
WritePartitionsToDisk(
IN PPARTLIST List);
-BOOLEAN
-SetMountedDeviceValue(
- IN WCHAR Letter,
- IN ULONG Signature,
- IN LARGE_INTEGER StartingOffset);
-
BOOLEAN
SetMountedDeviceValues(
- IN PPARTLIST List);
+ _In_ PPARTLIST List);
VOID
SetMBRPartitionType(
diff --git a/base/setup/lib/utils/volutil.c b/base/setup/lib/utils/volutil.c
new file mode 100644
index 00000000000..153488542a0
--- /dev/null
+++ b/base/setup/lib/utils/volutil.c
@@ -0,0 +1,226 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Volume utility functions
+ * COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "precomp.h"
+
+#include "volutil.h"
+#include "fsrec.h"
+#include "devutils.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS
+MountVolume(
+ _Inout_ PVOLINFO Volume,
+ _In_opt_ UCHAR MbrPartitionType)
+{
+ NTSTATUS Status;
+ HANDLE VolumeHandle;
+
+ /* If the volume is already mounted, just return success */
+ if (*Volume->FileSystem)
+ return STATUS_SUCCESS;
+
+ /* Try to open the volume so as to mount it */
+ VolumeHandle = NULL;
+ Status = pOpenDevice(Volume->DeviceName, &VolumeHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("pOpenDevice() failed, Status 0x%08lx\n", Status);
+
+ /* We failed, reset some data and bail out */
+ Volume->DriveLetter = UNICODE_NULL;
+ Volume->VolumeLabel[0] = UNICODE_NULL;
+ Volume->FileSystem[0] = UNICODE_NULL;
+
+ return Status;
+ }
+ ASSERT(VolumeHandle);
+
+ /* We don't have a FS, try to guess one */
+ Status = InferFileSystem(NULL, VolumeHandle,
+ Volume->FileSystem,
+ sizeof(Volume->FileSystem));
+ if (!NT_SUCCESS(Status))
+ DPRINT1("InferFileSystem() failed, Status 0x%08lx\n", Status);
+
+ if (*Volume->FileSystem)
+ {
+ /*
+ * Handle volume mounted with RawFS: it is
+ * either unformatted or has an unknown format.
+ */
+ if (IsUnformatted(Volume)) // FileSystem is "RAW"
+ {
+ /*
+ * 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 (MbrPartitionType == PARTITION_FAT_12 ||
+ MbrPartitionType == PARTITION_FAT_16 ||
+ MbrPartitionType == PARTITION_HUGE ||
+ MbrPartitionType == PARTITION_XINT13 ||
+ MbrPartitionType == PARTITION_FAT32 ||
+ MbrPartitionType == PARTITION_FAT32_XINT13)
+ {
+ /* The volume is unformatted */
+ }
+ else
+ {
+ /* Close the volume before dismounting */
+ NtClose(VolumeHandle);
+ VolumeHandle = NULL;
+ /*
+ * Dismount the volume since RawFS owns it, and reset its
+ * format (it is unknown, may or may not be actually formatted).
+ */
+ DismountVolume(Volume, TRUE);
+ Volume->FileSystem[0] = UNICODE_NULL;
+ }
+ }
+ /* Else, the volume is formatted */
+ }
+ /* Else, the volume has an unknown format */
+
+ /* Retrieve the volume label */
+ if (VolumeHandle)
+ {
+ IO_STATUS_BLOCK IoStatusBlock;
+ struct
+ {
+ FILE_FS_VOLUME_INFORMATION;
+ WCHAR Data[255];
+ } LabelInfo;
+
+ Status = NtQueryVolumeInformationFile(VolumeHandle,
+ &IoStatusBlock,
+ &LabelInfo,
+ sizeof(LabelInfo),
+ FileFsVolumeInformation);
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy the (possibly truncated) volume label and NULL-terminate it */
+ RtlStringCbCopyNW(Volume->VolumeLabel, sizeof(Volume->VolumeLabel),
+ LabelInfo.VolumeLabel, LabelInfo.VolumeLabelLength);
+ }
+ else
+ {
+ DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n",
Status);
+ }
+ }
+
+ /* Close the volume */
+ if (VolumeHandle)
+ NtClose(VolumeHandle);
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @brief
+ * Attempts to dismount the designated volume.
+ *
+ * @param[in,out] Volume
+ * The volume to dismount.
+ *
+ * @param[in] Force
+ * Whether the volume is forcibly dismounted, even
+ * if there are open handles to files on this volume.
+ *
+ * @return An NTSTATUS code indicating success or failure.
+ **/
+NTSTATUS
+DismountVolume(
+ _Inout_ PVOLINFO Volume,
+ _In_ BOOLEAN Force)
+{
+ NTSTATUS Status, LockStatus;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE VolumeHandle;
+
+ /* If the volume is not mounted, just return success */
+ if (!*Volume->FileSystem)
+ return STATUS_SUCCESS;
+
+ /* Open the volume */
+ Status = pOpenDeviceEx(Volume->DeviceName, &VolumeHandle,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ERROR: Cannot open volume %S for dismounting! (Status
0x%lx)\n",
+ Volume->DeviceName, Status);
+ return Status;
+ }
+
+ /* Lock the volume (succeeds only if there are no open handles to files) */
+ LockStatus = NtFsControlFile(VolumeHandle,
+ NULL, NULL, NULL,
+ &IoStatusBlock,
+ FSCTL_LOCK_VOLUME,
+ NULL, 0,
+ NULL, 0);
+ if (!NT_SUCCESS(LockStatus))
+ DPRINT1("WARNING: Failed to lock volume (Status 0x%lx)\n",
LockStatus);
+
+ /* Dismount the volume (succeeds even when lock fails and there are open handles)
*/
+ Status = STATUS_ACCESS_DENIED; // Suppose dismount failure.
+ if (NT_SUCCESS(LockStatus) || Force)
+ {
+ Status = NtFsControlFile(VolumeHandle,
+ NULL, NULL, NULL,
+ &IoStatusBlock,
+ FSCTL_DISMOUNT_VOLUME,
+ NULL, 0,
+ NULL, 0);
+ if (!NT_SUCCESS(Status))
+ DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
+ }
+
+ /* Unlock the volume */
+ if (NT_SUCCESS(LockStatus))
+ {
+ LockStatus = NtFsControlFile(VolumeHandle,
+ NULL, NULL, NULL,
+ &IoStatusBlock,
+ FSCTL_UNLOCK_VOLUME,
+ NULL, 0,
+ NULL, 0);
+ if (!NT_SUCCESS(LockStatus))
+ DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
+ }
+
+ /* Close the volume */
+ NtClose(VolumeHandle);
+
+ /* Reset some data only if dismount succeeded */
+ if (NT_SUCCESS(Status))
+ {
+ Volume->DriveLetter = UNICODE_NULL;
+ Volume->VolumeLabel[0] = UNICODE_NULL;
+ Volume->FileSystem[0] = UNICODE_NULL;
+ }
+
+ return Status;
+}
+
+/* EOF */
diff --git a/base/setup/lib/utils/volutil.h b/base/setup/lib/utils/volutil.h
new file mode 100644
index 00000000000..2763bb89844
--- /dev/null
+++ b/base/setup/lib/utils/volutil.h
@@ -0,0 +1,48 @@
+/*
+ * PROJECT: ReactOS Setup Library
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Volume utility functions
+ * COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto
<hermes.belusca-maito(a)reactos.org>
+ */
+
+#pragma once
+
+typedef struct _VOLINFO
+{
+ // WCHAR VolumeName[MAX_PATH]; ///< Name in the DOS/Win32 namespace:
"\??\Volume{GUID}\"
+ WCHAR DeviceName[MAX_PATH]; ///< NT device name:
"\Device\HarddiskVolumeN"
+
+ WCHAR DriveLetter;
+ WCHAR VolumeLabel[20];
+ WCHAR FileSystem[MAX_PATH+1];
+
+ // VOLUME_TYPE VolumeType;
+ // ULARGE_INTEGER Size;
+ // PVOLUME_DISK_EXTENTS Extents;
+} VOLINFO, *PVOLINFO;
+
+/* RawFS "RAW" file system name */
+#define IS_RAWFS(fs) \
+ ((fs)[0] == 'R' && (fs)[1] == 'A' && (fs)[2] ==
'W' && (fs)[3] == 0)
+
+#define IsUnknown(VolInfo) \
+ (!*(VolInfo)->FileSystem)
+
+#define IsUnformatted(VolInfo) \
+ IS_RAWFS((VolInfo)->FileSystem)
+
+#define IsFormatted(VolInfo) \
+ (!IsUnknown(VolInfo) && !IsUnformatted(VolInfo))
+
+
+NTSTATUS
+MountVolume(
+ _Inout_ PVOLINFO Volume,
+ _In_opt_ UCHAR MbrPartitionType);
+
+NTSTATUS
+DismountVolume(
+ _Inout_ PVOLINFO Volume,
+ _In_ BOOLEAN Force);
+
+/* EOF */
diff --git a/base/setup/reactos/drivepage.c b/base/setup/reactos/drivepage.c
index 320e0c62fa3..6c9bcc2a963 100644
--- a/base/setup/reactos/drivepage.c
+++ b/base/setup/reactos/drivepage.c
@@ -571,6 +571,7 @@ PrintPartitionData(
IN PDISKENTRY DiskEntry,
IN PPARTENTRY PartEntry)
{
+ PVOLINFO VolInfo = (PartEntry->Volume ? &PartEntry->Volume->Info :
NULL);
LARGE_INTEGER PartSize;
HTLITEM htiPart;
CHAR PartTypeString[32];
@@ -589,9 +590,9 @@ PrintPartitionData(
StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer),
// MUIGetString(STRING_HDDINFOUNK5),
L"%s (%c%c)",
- *PartEntry->VolumeLabel ? PartEntry->VolumeLabel :
L"Partition",
- (PartEntry->DriveLetter == 0) ? L'-' :
PartEntry->DriveLetter,
- (PartEntry->DriveLetter == 0) ? L'-' :
L':');
+ (VolInfo && *VolInfo->VolumeLabel) ?
VolInfo->VolumeLabel : L"Partition",
+ !(VolInfo && VolInfo->DriveLetter) ? L'-' :
VolInfo->DriveLetter,
+ !(VolInfo && VolInfo->DriveLetter) ? L'-' :
L':');
}
htiPart = TreeListAddItem(hWndList, htiParent, LineBuffer,
@@ -1001,8 +1002,8 @@ DriveDlgProc(
if (PartEntry->IsPartitioned &&
!IsContainerPartition(PartEntry->PartitionType) /*
alternatively: PartEntry->PartitionNumber != 0 */ &&
- // !PartEntry->New &&
- (PartEntry->FormatState == Preformatted /* ||
PartEntry->FormatState == Formatted */))
+ PartEntry->Volume && //
!PartEntry->Volume->New &&
+ (PartEntry->Volume->FormatState == Formatted))
{
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK |
PSWIZB_NEXT);
}
@@ -1079,11 +1080,12 @@ DisableWizNext:
DiskEntry.HwFixedDiskNumber = 0;
PartEntry.DiskEntry = &DiskEntry;
PartEntry.PartitionNumber = 1; // 4;
+ PartEntry.Volume = NULL;
/****/
Status = InitDestinationPaths(&pSetupData->USetupData,
NULL, //
pSetupData->USetupData.InstallationDirectory,
- &PartEntry);
+ PartEntry.Volume);
if (!NT_SUCCESS(Status))
{
diff --git a/base/setup/reactos/reactos.c b/base/setup/reactos/reactos.c
index 67034f93ea5..ee4f3cc8a2b 100644
--- a/base/setup/reactos/reactos.c
+++ b/base/setup/reactos/reactos.c
@@ -596,14 +596,14 @@ AddNTOSInstallationItem(
IN SIZE_T cchBufferSize)
{
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
- PPARTENTRY PartEntry = NtOsInstall->PartEntry;
+ PVOLINFO VolInfo = (NtOsInstall->Volume ? &NtOsInstall->Volume->Info :
NULL);
- if (PartEntry && PartEntry->DriveLetter)
+ if (VolInfo && VolInfo->DriveLetter)
{
/* We have retrieved a partition that is mounted */
StringCchPrintfW(Buffer, cchBufferSize,
L"%c:%s",
- PartEntry->DriveLetter,
+ VolInfo->DriveLetter,
NtOsInstall->PathComponent);
}
else
diff --git a/base/setup/usetup/partlist.c b/base/setup/usetup/partlist.c
index 570008638b2..a7eb50a8b59 100644
--- a/base/setup/usetup/partlist.c
+++ b/base/setup/usetup/partlist.c
@@ -154,6 +154,7 @@ PartitionDescription(
size_t cchBufferSize = cchBuffer;
ULONGLONG PartSize;
PCSTR Unit;
+ PVOLINFO VolInfo = (PartEntry->Volume ? &PartEntry->Volume->Info :
NULL);
/* Get the partition size */
PartSize = GetPartEntrySizeInBytes(PartEntry);
@@ -204,8 +205,8 @@ PartitionDescription(
RtlStringCchPrintfExA(pBuffer, cchBufferSize,
&pBuffer, &cchBufferSize, 0,
"%c%c %c %s(%lu) ",
- (PartEntry->DriveLetter == 0) ? '-' :
(CHAR)PartEntry->DriveLetter,
- (PartEntry->DriveLetter == 0) ? '-' : ':',
+ !(VolInfo && VolInfo->DriveLetter) ? '-' :
(CHAR)VolInfo->DriveLetter,
+ !(VolInfo && VolInfo->DriveLetter) ? '-' :
':',
PartEntry->BootIndicator ? '*' : ' ',
PartEntry->LogicalPartition ? " " : "",
// Optional indentation
PartEntry->PartitionNumber);
@@ -215,16 +216,15 @@ PartitionDescription(
* (if any) and the file system name. Otherwise, display the partition
* type if it's not a new partition.
*/
- if (!PartEntry->New && *PartEntry->FileSystem &&
- _wcsicmp(PartEntry->FileSystem, L"RAW") != 0)
+ if (VolInfo && IsFormatted(VolInfo))
{
size_t cchLabelSize = 0;
- if (*PartEntry->VolumeLabel)
+ if (*VolInfo->VolumeLabel)
{
RtlStringCchPrintfExA(pBuffer, cchBufferSize,
&pBuffer, &cchLabelSize, 0,
"\"%-.11S\" ",
- PartEntry->VolumeLabel);
+ VolInfo->VolumeLabel);
cchLabelSize = cchBufferSize - cchLabelSize; // Actual length of the label
part.
cchBufferSize -= cchLabelSize; // And reset cchBufferSize to what it should
be.
}
@@ -237,7 +237,7 @@ PartitionDescription(
/* The minimum length can be at most 11 since
* cchLabelSize can be at most == 11 + 3 == 14 */
25 - min(cchLabelSize, 25),
- PartEntry->FileSystem);
+ VolInfo->FileSystem);
}
else
{
@@ -275,7 +275,7 @@ PartitionDescription(
/* Show the remaining free space only if a FS is mounted */
// FIXME: We don't support that yet!
#if 0
- if (*PartEntry->FileSystem)
+ if (VolInfo && *VolInfo->FileSystem)
{
RtlStringCchPrintfA(pBuffer, cchBufferSize,
"%*s%6I64u %s (%6I64u %s %s)",
diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c
index fb6de2eb614..7dd30bf468f 100644
--- a/base/setup/usetup/usetup.c
+++ b/base/setup/usetup/usetup.c
@@ -46,6 +46,8 @@ static USETUP_DATA USetupData;
/* The partition where to perform the installation */
static PPARTENTRY InstallPartition = NULL;
+// static PVOLENTRY InstallVolume = NULL;
+#define InstallVolume (InstallPartition->Volume)
/*
* The system partition we will actually use. It can be different from
* PartitionList->SystemPartition in case we don't support it, or we install
@@ -57,6 +59,8 @@ static PPARTENTRY InstallPartition = NULL;
* operation on them).
*/
static PPARTENTRY SystemPartition = NULL;
+// static PVOLENTRY SystemVolume = NULL;
+#define SystemVolume (SystemPartition->Volume)
/* OTHER Stuff *****/
@@ -77,8 +81,8 @@ static enum {
PartTypeExtended // MBR-disk container
} PartCreateType = PartTypeData;
-/* Flag set in PARTENTRY::New when a partition is created automatically */
-#define PARTITION_NEW_AUTOCREATE 0x80
+/* Flag set in VOLENTRY::New when a partition/volume is created automatically */
+#define VOLUME_NEW_AUTOCREATE 0x80
/* List of supported file systems for the partition to be formatted */
static PFILE_SYSTEM_LIST FileSystemList = NULL;
@@ -508,14 +512,14 @@ GetNTOSInstallationName(
IN SIZE_T cchBufferSize)
{
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
- PPARTENTRY PartEntry = NtOsInstall->PartEntry;
+ PVOLINFO VolInfo = (NtOsInstall->Volume ? &NtOsInstall->Volume->Info :
NULL);
- if (PartEntry && PartEntry->DriveLetter)
+ if (VolInfo && VolInfo->DriveLetter)
{
/* We have retrieved a partition that is mounted */
return RtlStringCchPrintfA(Buffer, cchBufferSize,
"%C:%S \"%S\"",
- PartEntry->DriveLetter,
+ VolInfo->DriveLetter,
NtOsInstall->PathComponent,
NtOsInstall->InstallationName);
}
@@ -1568,7 +1572,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
DPRINT1("RepairUpdateFlag == TRUE, SelectPartition() returned FALSE,
assert!\n");
ASSERT(FALSE);
}
- ASSERT(!IsContainerPartition(InstallPartition->PartitionType));
return START_PARTITION_OPERATIONS_PAGE;
}
@@ -1603,7 +1606,8 @@ SelectPartitionPage(PINPUT_RECORD Ir)
CurrentPartition,
0ULL,
0);
- CurrentPartition->New |= PARTITION_NEW_AUTOCREATE;
+ if (CurrentPartition->Volume)
+ CurrentPartition->Volume->New |= VOLUME_NEW_AUTOCREATE;
// FIXME?? Aren't we going to enter an infinite loop, if this test fails??
if (!IsPartitionLargeEnough(CurrentPartition))
@@ -1735,7 +1739,8 @@ SelectPartitionPage(PINPUT_RECORD Ir)
CurrentPartition,
0ULL,
0);
- CurrentPartition->New |= PARTITION_NEW_AUTOCREATE;
+ if (CurrentPartition->Volume)
+ CurrentPartition->Volume->New |= VOLUME_NEW_AUTOCREATE;
}
if (!IsPartitionLargeEnough(CurrentPartition))
@@ -1781,28 +1786,23 @@ SelectPartitionPage(PINPUT_RECORD Ir)
}
else if (Ir->Event.KeyEvent.wVirtualKeyCode == 'D') /* D */
{
- UNICODE_STRING CurrentPartitionU;
- WCHAR PathBuffer[MAX_PATH];
-
ASSERT(CurrentPartition != NULL);
/* Ignore deletion in case this is not a partitioned entry */
if (!CurrentPartition->IsPartitioned)
- {
continue;
- }
// TODO: Do something similar before trying to format the partition?
- if (!CurrentPartition->New &&
- !IsContainerPartition(CurrentPartition->PartitionType) &&
- CurrentPartition->FormatState != Unformatted)
+ if (CurrentPartition->Volume &&
!CurrentPartition->Volume->New &&
+ (CurrentPartition->Volume->FormatState != Unformatted))
{
+ UNICODE_STRING CurrentPartitionU;
+ WCHAR PathBuffer[RTL_NUMBER_OF_FIELD(VOLINFO, DeviceName) + 1];
+
ASSERT(CurrentPartition->PartitionNumber != 0);
- RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu\\",
- CurrentPartition->DiskEntry->DiskNumber,
- CurrentPartition->PartitionNumber);
+ RtlStringCchPrintfW(PathBuffer, _countof(PathBuffer),
+ L"%s\\",
CurrentPartition->Volume->Info.DeviceName);
RtlInitUnicodeString(&CurrentPartitionU, PathBuffer);
/*
@@ -2286,16 +2286,16 @@ StartPartitionOperationsPage(PINPUT_RECORD Ir)
//
/* Set the AUTOCREATE flag if the system partition was automatically created */
- if (SystemPartition->New)
- SystemPartition->New |= PARTITION_NEW_AUTOCREATE;
+ if (SystemPartition->New && SystemVolume)
+ SystemVolume->New |= VOLUME_NEW_AUTOCREATE;
CONSOLE_ClearScreen();
CONSOLE_Flush();
/* Apply all pending operations on partitions: formatting and checking */
Success = FsVolCommitOpsQueue(PartitionList,
- SystemPartition,
- InstallPartition,
+ SystemVolume,
+ InstallVolume,
FsVolCallback,
&FsVolContext);
if (!Success)
@@ -2358,41 +2358,43 @@ ResetFileSystemList(VOID)
static FSVOL_OP
SelectFileSystemPage(
- IN PFSVOL_CONTEXT FsVolContext,
- IN PPARTENTRY PartEntry)
+ _In_ PFSVOL_CONTEXT FsVolContext,
+ _In_ PVOLENTRY Volume)
{
PINPUT_RECORD Ir = FsVolContext->Ir;
+ PPARTENTRY PartEntry = Volume->PartEntry;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
PCWSTR DefaultFs;
+ BOOLEAN ForceFormat;
CHAR LineBuffer[100];
DPRINT("SelectFileSystemPage()\n");
- ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
+ ForceFormat = (Volume->New || Volume->FormatState == Unformatted);
Restart:
- /* Reset the file system list for each partition that is to be formatted */
+ /* Reset the file system list for each volume that is to be formatted */
ResetFileSystemList();
CONSOLE_ClearScreen();
CONSOLE_Flush();
MUIDisplayPage(SELECT_FILE_SYSTEM_PAGE);
- if (PartEntry->New & PARTITION_NEW_AUTOCREATE)
+ if (Volume->New & VOLUME_NEW_AUTOCREATE)
{
- PartEntry->New &= ~PARTITION_NEW_AUTOCREATE;
+ Volume->New &= ~VOLUME_NEW_AUTOCREATE;
CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_NEWPARTITION));
}
- else if (PartEntry->New)
+ else if (Volume->New)
{
ULONG uID;
- if (PartEntry == SystemPartition) // FormatSystemPartition
+ if (Volume == SystemVolume)
uID = STRING_NONFORMATTEDSYSTEMPART;
- else if (PartEntry == InstallPartition) // FormatInstallPartition
+ else if (Volume == InstallVolume)
uID = STRING_NONFORMATTEDPART;
- else // FormatOtherPartition
+ else
uID = STRING_NONFORMATTEDOTHERPART;
CONSOLE_SetTextXY(6, 8, MUIGetString(uID));
@@ -2410,7 +2412,7 @@ Restart:
LineBuffer);
/* Show "This Partition will be formatted next" only if it is unformatted
*/
- if (PartEntry->New || PartEntry->FormatState == Unformatted)
+ if (ForceFormat)
CONSOLE_SetTextXY(6, 14, MUIGetString(STRING_PARTFORMAT));
ASSERT(!FileSystemList);
@@ -2439,11 +2441,8 @@ Restart:
}
/* 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);
+ // TODO: Display only the FSes compatible with the selected volume!
+ FileSystemList = CreateFileSystemList(6, 26, ForceFormat, DefaultFs);
if (!FileSystemList)
{
/* FIXME: show an error dialog */
@@ -2493,23 +2492,21 @@ Restart:
{
if (!FileSystemList->Selected->FileSystem)
{
- ASSERT(!PartEntry->New && PartEntry->FormatState !=
Unformatted);
+ /* The 'Keep existing filesystem' entry was chosen,
+ * the volume must be already formatted */
+ ASSERT(!ForceFormat);
- /*
- * Skip formatting this partition. We will also ignore
+ /* Skip formatting this volume. We will also ignore
* file system checks on it, unless it is either the
- * system or the installation partition.
- */
- if (PartEntry != SystemPartition &&
- PartEntry != InstallPartition)
- {
- PartEntry->NeedsCheck = FALSE;
- }
+ * system or the installation volume. */
+ if ((Volume != SystemVolume) && (Volume != InstallVolume))
+ Volume->NeedsCheck = FALSE;
+
return FSVOL_SKIP;
}
else
{
- /* Format this partition */
+ /* Format this volume */
return FSVOL_DOIT;
}
}
@@ -2520,10 +2517,11 @@ Restart:
static FSVOL_OP
FormatPartitionPage(
- IN PFSVOL_CONTEXT FsVolContext,
- IN PPARTENTRY PartEntry)
+ _In_ PFSVOL_CONTEXT FsVolContext,
+ _In_ PVOLENTRY Volume)
{
PINPUT_RECORD Ir = FsVolContext->Ir;
+ PPARTENTRY PartEntry = Volume->PartEntry;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
CHAR LineBuffer[100];
@@ -2571,8 +2569,9 @@ Restart:
static VOID
CheckFileSystemPage(
- IN PPARTENTRY PartEntry)
+ _In_ PVOLENTRY Volume)
{
+ PPARTENTRY PartEntry = Volume->PartEntry;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
CHAR LineBuffer[100];
@@ -2693,7 +2692,8 @@ FsVolCallback(
if (FmtInfo->ErrorStatus == STATUS_UNRECOGNIZED_VOLUME)
{
/* FIXME: show an error dialog */
- // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY,
PathBuffer);
+ // MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY,
+ // FmtInfo->Volume->Info.DeviceName);
FsVolContext->NextPageOnAbort = QUIT_PAGE;
return FSVOL_ABORT;
}
@@ -2737,16 +2737,9 @@ FsVolCallback(
}
else if (!NT_SUCCESS(FmtInfo->ErrorStatus))
{
- WCHAR PathBuffer[MAX_PATH];
-
- /** HACK!! **/
- RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
- L"\\Device\\Harddisk%lu\\Partition%lu",
- FmtInfo->PartEntry->DiskEntry->DiskNumber,
- FmtInfo->PartEntry->PartitionNumber);
-
DPRINT1("FormatPartition() failed: Status 0x%08lx\n",
FmtInfo->ErrorStatus);
- MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY,
PathBuffer);
+ MUIDisplayError(ERROR_FORMATTING_PARTITION, Ir, POPUP_WAIT_ANY_KEY,
+ FmtInfo->Volume->Info.DeviceName);
FsVolContext->NextPageOnAbort = QUIT_PAGE;
return FSVOL_ABORT;
}
@@ -2766,7 +2759,7 @@ FsVolCallback(
"\n"
" \x07 Press ENTER to continue Setup.\n"
" \x07 Press F3 to quit Setup.",
- ChkInfo->PartEntry->FileSystem);
+ ChkInfo->Volume->Info.FileSystem);
PopupError(Buffer,
MUIGetString(STRING_QUITCONTINUE),
@@ -2820,12 +2813,12 @@ FsVolCallback(
ASSERT((FSVOL_OP)Param2 == FSVOL_FORMAT);
/* Select the file system */
- Result = SelectFileSystemPage(FsVolContext, FmtInfo->PartEntry);
+ Result = SelectFileSystemPage(FsVolContext, FmtInfo->Volume);
if (Result != FSVOL_DOIT)
return Result;
/* Display the formatting page */
- Result = FormatPartitionPage(FsVolContext, FmtInfo->PartEntry);
+ Result = FormatPartitionPage(FsVolContext, FmtInfo->Volume);
if (Result != FSVOL_DOIT)
return Result;
@@ -2849,7 +2842,7 @@ FsVolCallback(
ASSERT((FSVOL_OP)Param2 == FSVOL_CHECK);
- CheckFileSystemPage(ChkInfo->PartEntry);
+ CheckFileSystemPage(ChkInfo->Volume);
StartCheck(ChkInfo);
return FSVOL_DOIT;
}
@@ -2907,7 +2900,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
*/
if ((RepairUpdateFlag || IsUnattendedSetup) &&
IsValidInstallDirectory(InstallDir))
{
- Status = InitDestinationPaths(&USetupData, InstallDir, InstallPartition);
+ Status = InitDestinationPaths(&USetupData, InstallDir, InstallVolume);
if (!NT_SUCCESS(Status))
{
DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n", Status);
@@ -3019,7 +3012,7 @@ InstallDirectoryPage(PINPUT_RECORD Ir)
return INSTALL_DIRECTORY_PAGE;
}
- Status = InitDestinationPaths(&USetupData, InstallDir,
InstallPartition);
+ Status = InitDestinationPaths(&USetupData, InstallDir, InstallVolume);
if (!NT_SUCCESS(Status))
{
DPRINT1("InitDestinationPaths() failed: Status 0x%lx\n",
Status);
@@ -3426,7 +3419,7 @@ RegistryPage(PINPUT_RECORD Ir)
Error = UpdateRegistry(&USetupData,
RepairUpdateFlag,
PartitionList,
- InstallPartition->DriveLetter,
+ InstallVolume->Info.DriveLetter,
SelectedLanguageId,
RegistryStatus,
&s_SubstSettings);
@@ -3667,11 +3660,11 @@ BootLoaderHardDiskPage(PINPUT_RECORD Ir)
Status = InstallVBRToPartition(&USetupData.SystemRootPath,
&USetupData.SourceRootPath,
&USetupData.DestinationArcPath,
- SystemPartition->FileSystem);
+ SystemVolume->Info.FileSystem);
if (!NT_SUCCESS(Status))
{
MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
- SystemPartition->FileSystem);
+ SystemVolume->Info.FileSystem);
return FALSE;
}
@@ -3697,11 +3690,11 @@ BootLoaderHardDiskPage(PINPUT_RECORD Ir)
Status = InstallVBRToPartition(&USetupData.SystemRootPath,
&USetupData.SourceRootPath,
&USetupData.DestinationArcPath,
- SystemPartition->FileSystem);
+ SystemVolume->Info.FileSystem);
if (!NT_SUCCESS(Status))
{
MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
- SystemPartition->FileSystem);
+ SystemVolume->Info.FileSystem);
return FALSE;
}
}