[SETUPLIB][USETUP] Factor out the usage of FS provider structures.

Similarly to FMIFS this structure should be private. Instead file-system
names are passed to the helper functions, allowing to use the names
returned by the FS drivers. The names are then internally mapped to the
corresponding FS providers.

In particular this allows to handle the "RAW" file-system and to assign
the 'Unformatted' flag to partitions having this FS.

Finally this helps us refining the checks performed to see whether the
current "active" system partition uses a supported file-system.
This commit is contained in:
Hermès Bélusca-Maïto 2019-02-24 17:52:33 +01:00
parent b18da6730e
commit c1fbc2d651
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
12 changed files with 765 additions and 414 deletions

View file

@ -2351,24 +2351,20 @@ InstallFatBootcodeToFloppy(
IN PUNICODE_STRING SourceRootPath, IN PUNICODE_STRING SourceRootPath,
IN PUNICODE_STRING DestinationArcPath) IN PUNICODE_STRING DestinationArcPath)
{ {
static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\";
NTSTATUS Status; NTSTATUS Status;
PFILE_SYSTEM FatFS;
UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
WCHAR SrcPath[MAX_PATH]; WCHAR SrcPath[MAX_PATH];
WCHAR DstPath[MAX_PATH]; WCHAR DstPath[MAX_PATH];
/* Verify that the floppy disk is accessible */ /* Verify that the floppy disk is accessible */
if (DoesDirExist(NULL, FloppyDevice.Buffer) == FALSE) if (DoesDirExist(NULL, FloppyDevice) == FALSE)
return STATUS_DEVICE_NOT_READY; return STATUS_DEVICE_NOT_READY;
/* Format the floppy disk */ /* Format the floppy disk */
FatFS = GetFileSystemByName(L"FAT"); // FormatPartition(...)
if (!FatFS) Status = FormatFileSystem(FloppyDevice,
{ L"FAT",
DPRINT1("FAT FS non existent on this system?!\n");
return STATUS_NOT_SUPPORTED;
}
Status = FatFS->FormatFunc(&FloppyDevice,
FMIFS_FLOPPY, FMIFS_FLOPPY,
NULL, NULL,
TRUE, TRUE,
@ -2376,13 +2372,17 @@ InstallFatBootcodeToFloppy(
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
if (Status == STATUS_NOT_SUPPORTED)
DPRINT1("FAT FS non existent on this system?!\n");
else
DPRINT1("VfatFormat() failed (Status %lx)\n", Status); DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
return Status; return Status;
} }
/* Copy FreeLoader to the boot partition */ /* Copy FreeLoader to the boot partition */
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys"); CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\freeldr.sys");
CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice.Buffer, L"freeldr.sys"); CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, FloppyDevice, L"freeldr.sys");
DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath); DPRINT("Copy: %S ==> %S\n", SrcPath, DstPath);
Status = SetupCopyFile(SrcPath, DstPath, FALSE); Status = SetupCopyFile(SrcPath, DstPath, FALSE);
@ -2394,7 +2394,7 @@ InstallFatBootcodeToFloppy(
/* Create new 'freeldr.ini' */ /* Create new 'freeldr.ini' */
DPRINT("Create new 'freeldr.ini'\n"); DPRINT("Create new 'freeldr.ini'\n");
Status = CreateFreeLoaderIniForReactOS(FloppyDevice.Buffer, DestinationArcPath->Buffer); Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status); DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
@ -2403,7 +2403,7 @@ InstallFatBootcodeToFloppy(
/* Install FAT12 boosector */ /* Install FAT12 boosector */
CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin"); CombinePaths(SrcPath, ARRAYSIZE(SrcPath), 2, SourceRootPath->Buffer, L"\\loader\\fat.bin");
CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice.Buffer); CombinePaths(DstPath, ARRAYSIZE(DstPath), 1, FloppyDevice);
DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath); DPRINT("Install FAT bootcode: %S ==> %S\n", SrcPath, DstPath);
Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath); Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);

View file

@ -2,8 +2,8 @@
* PROJECT: ReactOS Setup Library * PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Filesystem support functions * PURPOSE: Filesystem support functions
* COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net) * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2017-2018 Hermes Belusca-Maito * Copyright 2017-2019 Hermes Belusca-Maito
*/ */
// //
@ -28,10 +28,18 @@
#include <debug.h> #include <debug.h>
/* GLOBALS ******************************************************************/ /* LOCALS *******************************************************************/
/** IFS_PROVIDER **/
typedef struct _FILE_SYSTEM
{
PCWSTR FileSystemName;
FORMATEX FormatFunc;
CHKDSKEX ChkdskFunc;
} FILE_SYSTEM, *PFILE_SYSTEM;
/* The list of file systems on which we can install ReactOS */ /* The list of file systems on which we can install ReactOS */
FILE_SYSTEM RegisteredFileSystems[] = static FILE_SYSTEM RegisteredFileSystems[] =
{ {
/* NOTE: The FAT formatter automatically determines /* NOTE: The FAT formatter automatically determines
* whether it will use FAT-16 or FAT-32. */ * whether it will use FAT-16 or FAT-32. */
@ -54,16 +62,24 @@ FILE_SYSTEM RegisteredFileSystems[] =
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
PFILE_SYSTEM /** QueryAvailableFileSystemFormat() **/
GetRegisteredFileSystems(OUT PULONG Count) BOOLEAN
GetRegisteredFileSystems(
IN ULONG Index,
OUT PCWSTR* FileSystemName)
{ {
*Count = ARRAYSIZE(RegisteredFileSystems); if (Index >= ARRAYSIZE(RegisteredFileSystems))
return RegisteredFileSystems; return FALSE;
*FileSystemName = RegisteredFileSystems[Index].FileSystemName;
return TRUE;
} }
PFILE_SYSTEM
/** GetProvider() **/
static PFILE_SYSTEM
GetFileSystemByName( GetFileSystemByName(
// IN PFILE_SYSTEM_LIST List,
IN PCWSTR FileSystemName) IN PCWSTR FileSystemName)
{ {
#if 0 // Reenable when the list of registered FSes will again be dynamic #if 0 // Reenable when the list of registered FSes will again be dynamic
@ -75,25 +91,33 @@ GetFileSystemByName(
while (ListEntry != &List->ListHead) while (ListEntry != &List->ListHead)
{ {
Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry); Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry);
if (Item->FileSystemName && wcsicmp(FileSystemName, Item->FileSystemName) == 0) if (Item->FileSystemName &&
(wcsicmp(FileSystemName, Item->FileSystemName) == 0 ||
/* Map FAT32 back to FAT */
(wcsicmp(FileSystemName, L"FAT32") == 0 && wcsicmp(Item->FileSystemName, L"FAT") == 0)))
{
return Item; return Item;
}
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }
#else #else
ULONG Count; ULONG Count = ARRAYSIZE(RegisteredFileSystems);
PFILE_SYSTEM FileSystems; PFILE_SYSTEM FileSystems = RegisteredFileSystems;
FileSystems = GetRegisteredFileSystems(&Count); ASSERT(FileSystems && Count != 0);
if (!FileSystems || Count == 0)
return NULL;
while (Count--) while (Count--)
{ {
if (FileSystems->FileSystemName && wcsicmp(FileSystemName, FileSystems->FileSystemName) == 0) if (FileSystems->FileSystemName &&
(wcsicmp(FileSystemName, FileSystems->FileSystemName) == 0 ||
/* Map FAT32 back to FAT */
(wcsicmp(FileSystemName, L"FAT32") == 0 && wcsicmp(FileSystems->FileSystemName, L"FAT") == 0)))
{
return FileSystems; return FileSystems;
}
++FileSystems; ++FileSystems;
} }
@ -105,63 +129,30 @@ GetFileSystemByName(
// //
// FileSystem recognition (using NT OS functionality) // FileSystem recognition, using NT OS functionality
// //
/* NOTE: Ripped & adapted from base/system/autochk/autochk.c */ /* NOTE: Ripped & adapted from base/system/autochk/autochk.c */
static NTSTATUS NTSTATUS
_MyGetFileSystem( GetFileSystemNameByHandle(
IN struct _PARTENTRY* PartEntry, IN HANDLE PartitionHandle,
IN OUT PWSTR FileSystemName, IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize) IN SIZE_T FileSystemNameSize)
{ {
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING PartitionRootPath;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
WCHAR PathBuffer[MAX_PATH];
UCHAR Buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)]; UCHAR Buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer; PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
/* Set PartitionRootPath */
RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
L"\\Device\\Harddisk%lu\\Partition%lu",
PartEntry->DiskEntry->DiskNumber,
PartEntry->PartitionNumber);
RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
/* Open the partition */
InitializeObjectAttributes(&ObjectAttributes,
&PartitionRootPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandle, // PartitionHandle,
FILE_GENERIC_READ /* | SYNCHRONIZE */,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionRootPath, Status);
return Status;
}
/* Retrieve the FS attributes */ /* Retrieve the FS attributes */
Status = NtQueryVolumeInformationFile(FileHandle, Status = NtQueryVolumeInformationFile(PartitionHandle,
&IoStatusBlock, &IoStatusBlock,
FileFsAttribute, FileFsAttribute,
sizeof(Buffer), sizeof(Buffer),
FileFsAttributeInformation); FileFsAttributeInformation);
NtClose(FileHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtQueryVolumeInformationFile failed for partition '%wZ', Status 0x%08lx\n", DPRINT1("NtQueryVolumeInformationFile failed, Status 0x%08lx\n", Status);
&PartitionRootPath, Status);
return Status; return Status;
} }
@ -173,45 +164,87 @@ _MyGetFileSystem(
FileFsAttribute->FileSystemNameLength); FileFsAttribute->FileSystemNameLength);
} }
PFILE_SYSTEM NTSTATUS
GetFileSystem( GetFileSystemName_UStr(
// IN PFILE_SYSTEM_LIST FileSystemList, IN PUNICODE_STRING PartitionPath,
IN struct _PARTENTRY* PartEntry) IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{ {
PFILE_SYSTEM CurrentFileSystem;
NTSTATUS Status; NTSTATUS Status;
PWSTR FileSystemName = NULL; OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR FsRecFileSystemName[MAX_PATH]; HANDLE PartitionHandle;
IO_STATUS_BLOCK IoStatusBlock;
CurrentFileSystem = PartEntry->FileSystem; /* Open the partition */
InitializeObjectAttributes(&ObjectAttributes,
/* We have a file system, return it */ PartitionPath,
if (CurrentFileSystem != NULL && CurrentFileSystem->FileSystemName != NULL) OBJ_CASE_INSENSITIVE,
return CurrentFileSystem; NULL,
NULL);
DPRINT1("File system not found, try to guess one...\n"); Status = NtOpenFile(&PartitionHandle,
FILE_GENERIC_READ /* | SYNCHRONIZE */,
CurrentFileSystem = NULL; &ObjectAttributes,
&IoStatusBlock,
/* FILE_SHARE_READ | FILE_SHARE_WRITE,
* We don't have one... 0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
* if (!NT_SUCCESS(Status))
* Try to infer a file system using NT file system recognition.
*/
Status = _MyGetFileSystem(PartEntry, FsRecFileSystemName, sizeof(FsRecFileSystemName));
if (NT_SUCCESS(Status) && *FsRecFileSystemName)
{ {
/* Temporary HACK: map FAT32 back to FAT */ DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", PartitionPath, Status);
if (wcscmp(FsRecFileSystemName, L"FAT32") == 0) return Status;
RtlStringCbCopyW(FsRecFileSystemName, sizeof(FsRecFileSystemName), L"FAT"); }
FileSystemName = FsRecFileSystemName; /* Retrieve the FS attributes */
Status = GetFileSystemNameByHandle(PartitionHandle, FileSystemName, FileSystemNameSize);
if (!NT_SUCCESS(Status))
{
DPRINT1("GetFileSystemNameByHandle() failed for partition '%wZ', Status 0x%08lx\n",
PartitionPath, Status);
}
/* Close the partition */
NtClose(PartitionHandle);
return Status;
}
NTSTATUS
GetFileSystemName(
IN PCWSTR Partition,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{
UNICODE_STRING PartitionPath;
RtlInitUnicodeString(&PartitionPath, Partition);
return GetFileSystemName_UStr(&PartitionPath,
FileSystemName,
FileSystemNameSize);
}
NTSTATUS
InferFileSystemByHandle(
IN HANDLE PartitionHandle,
IN UCHAR PartitionType,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{
NTSTATUS Status;
if (FileSystemNameSize < sizeof(WCHAR))
return STATUS_BUFFER_TOO_SMALL;
*FileSystemName = L'\0';
/* Try to infer a file system using NT file system recognition */
Status = GetFileSystemNameByHandle(PartitionHandle,
FileSystemName,
FileSystemNameSize);
if (NT_SUCCESS(Status) && *FileSystemName)
{
goto Quit; goto Quit;
} }
/* /*
* We don't have one...
*
* Try to infer a preferred file system for this partition, given its ID. * Try to infer a preferred file system for this partition, given its ID.
* *
* WARNING: This is partly a hack, since partitions with the same ID can * WARNING: This is partly a hack, since partitions with the same ID can
@ -224,43 +257,274 @@ GetFileSystem(
* On the contrary, for unformatted partitions with a given ID, the * On the contrary, for unformatted partitions with a given ID, the
* following code is OK. * following code is OK.
*/ */
if ((PartEntry->PartitionType == PARTITION_FAT_12) || if ((PartitionType == PARTITION_FAT_12) ||
(PartEntry->PartitionType == PARTITION_FAT_16) || (PartitionType == PARTITION_FAT_16) ||
(PartEntry->PartitionType == PARTITION_HUGE ) || (PartitionType == PARTITION_HUGE ) ||
(PartEntry->PartitionType == PARTITION_XINT13) || (PartitionType == PARTITION_XINT13))
(PartEntry->PartitionType == PARTITION_FAT32 ) ||
(PartEntry->PartitionType == PARTITION_FAT32_XINT13))
{ {
FileSystemName = L"FAT"; /* FAT12 or FAT16 */
Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"FAT");
} }
else if (PartEntry->PartitionType == PARTITION_LINUX) else if ((PartitionType == PARTITION_FAT32) ||
(PartitionType == PARTITION_FAT32_XINT13))
{
Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"FAT32");
}
else if (PartitionType == PARTITION_LINUX)
{ {
// WARNING: See the warning above. // WARNING: See the warning above.
/* Could also be EXT2/3/4, ReiserFS, ... */ /* Could also be EXT2/3/4, ReiserFS, ... */
FileSystemName = L"BTRFS"; Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"BTRFS");
} }
else if (PartEntry->PartitionType == PARTITION_IFS) else if (PartitionType == PARTITION_IFS)
{ {
// WARNING: See the warning above. // WARNING: See the warning above.
/* Could also be HPFS */ /* Could also be HPFS */
FileSystemName = L"NTFS"; Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"NTFS");
} }
Quit: Quit:
// HACK: WARNING: We cannot write on this FS yet! if (*FileSystemName)
if (FileSystemName)
{ {
if (PartEntry->PartitionType == PARTITION_IFS) // WARNING: We cannot write on this FS yet!
DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName); if (PartitionType == PARTITION_IFS)
{
DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
FileSystemName);
}
} }
DPRINT1("GetFileSystem -- PartitionType: 0x%02X ; FileSystemName (guessed): %S\n", DPRINT1("InferFileSystem -- PartitionType: 0x%02X ; FileSystem (guessed): %S\n",
PartEntry->PartitionType, FileSystemName ? FileSystemName : L"None"); PartitionType, *FileSystemName ? FileSystemName : L"None");
if (FileSystemName) return Status;
CurrentFileSystem = GetFileSystemByName(FileSystemName); }
return CurrentFileSystem; NTSTATUS
InferFileSystem(
IN PCWSTR Partition,
IN UCHAR PartitionType,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{
NTSTATUS Status;
UNICODE_STRING PartitionPath;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE PartitionHandle;
IO_STATUS_BLOCK IoStatusBlock;
/* Open the partition */
RtlInitUnicodeString(&PartitionPath, Partition);
InitializeObjectAttributes(&ObjectAttributes,
&PartitionPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&PartitionHandle,
FILE_GENERIC_READ /* | SYNCHRONIZE */,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionPath, Status);
return Status;
}
/* Retrieve the FS */
Status = InferFileSystemByHandle(PartitionHandle,
PartitionType,
FileSystemName,
FileSystemNameSize);
/* Close the partition */
NtClose(PartitionHandle);
return Status;
}
/** ChkdskEx() **/
NTSTATUS
ChkdskFileSystem_UStr(
IN PUNICODE_STRING DriveRoot,
IN PCWSTR FileSystemName,
IN BOOLEAN FixErrors,
IN BOOLEAN Verbose,
IN BOOLEAN CheckOnlyIfDirty,
IN BOOLEAN ScanDrive,
IN PFMIFSCALLBACK Callback)
{
PFILE_SYSTEM FileSystem;
FileSystem = GetFileSystemByName(FileSystemName);
if (!FileSystem || !FileSystem->ChkdskFunc)
{
// BOOLEAN Argument = FALSE;
// Callback(DONE, 0, &Argument);
return STATUS_NOT_SUPPORTED;
}
return FileSystem->ChkdskFunc(DriveRoot,
FixErrors,
Verbose,
CheckOnlyIfDirty,
ScanDrive,
Callback);
}
NTSTATUS
ChkdskFileSystem(
IN PCWSTR DriveRoot,
IN PCWSTR FileSystemName,
IN BOOLEAN FixErrors,
IN BOOLEAN Verbose,
IN BOOLEAN CheckOnlyIfDirty,
IN BOOLEAN ScanDrive,
IN PFMIFSCALLBACK Callback)
{
UNICODE_STRING DriveRootU;
RtlInitUnicodeString(&DriveRootU, DriveRoot);
return ChkdskFileSystem_UStr(&DriveRootU,
FileSystemName,
FixErrors,
Verbose,
CheckOnlyIfDirty,
ScanDrive,
Callback);
}
/** FormatEx() **/
NTSTATUS
FormatFileSystem_UStr(
IN PUNICODE_STRING DriveRoot,
IN PCWSTR FileSystemName,
IN FMIFS_MEDIA_FLAG MediaFlag,
IN PUNICODE_STRING Label,
IN BOOLEAN QuickFormat,
IN ULONG ClusterSize,
IN PFMIFSCALLBACK Callback)
{
PFILE_SYSTEM FileSystem;
FileSystem = GetFileSystemByName(FileSystemName);
if (!FileSystem || !FileSystem->FormatFunc)
{
// BOOLEAN Argument = FALSE;
// Callback(DONE, 0, &Argument);
return STATUS_NOT_SUPPORTED;
}
return FileSystem->FormatFunc(DriveRoot,
MediaFlag,
Label,
QuickFormat,
ClusterSize,
Callback);
}
NTSTATUS
FormatFileSystem(
IN PCWSTR DriveRoot,
IN PCWSTR FileSystemName,
IN FMIFS_MEDIA_FLAG MediaFlag,
IN PCWSTR Label,
IN BOOLEAN QuickFormat,
IN ULONG ClusterSize,
IN PFMIFSCALLBACK Callback)
{
UNICODE_STRING DriveRootU;
UNICODE_STRING LabelU;
RtlInitUnicodeString(&DriveRootU, DriveRoot);
RtlInitUnicodeString(&LabelU, Label);
return FormatFileSystem_UStr(&DriveRootU,
FileSystemName,
MediaFlag,
&LabelU,
QuickFormat,
ClusterSize,
Callback);
}
UCHAR
FileSystemToPartitionType(
IN PCWSTR FileSystem,
IN PULARGE_INTEGER StartSector,
IN PULARGE_INTEGER SectorCount)
{
ASSERT(FileSystem && StartSector && SectorCount);
if (wcsicmp(FileSystem, L"FAT") == 0 ||
wcsicmp(FileSystem, L"FAT32") == 0 ||
wcsicmp(FileSystem, L"RAW") == 0)
{
if (SectorCount->QuadPart < 8192)
{
/* FAT12 CHS partition (disk is smaller than 4.1MB) */
return PARTITION_FAT_12;
}
else if (StartSector->QuadPart < 1450560)
{
/* Partition starts below the 8.4GB boundary ==> CHS partition */
if (SectorCount->QuadPart < 65536)
{
/* FAT16 CHS partition (partition size < 32MB) */
return PARTITION_FAT_16;
}
else if (SectorCount->QuadPart < 1048576)
{
/* FAT16 CHS partition (partition size < 512MB) */
return PARTITION_HUGE;
}
else
{
/* FAT32 CHS partition (partition size >= 512MB) */
return PARTITION_FAT32;
}
}
else
{
/* Partition starts above the 8.4GB boundary ==> LBA partition */
if (SectorCount->QuadPart < 1048576)
{
/* FAT16 LBA partition (partition size < 512MB) */
return PARTITION_XINT13;
}
else
{
/* FAT32 LBA partition (partition size >= 512MB) */
return PARTITION_FAT32_XINT13;
}
}
}
else if (wcsicmp(FileSystem, L"NTFS") == 0)
{
return PARTITION_IFS;
}
else if (wcsicmp(FileSystem, L"BTRFS") == 0 ||
wcsicmp(FileSystem, L"EXT2") == 0 ||
wcsicmp(FileSystem, L"EXT3") == 0 ||
wcsicmp(FileSystem, L"EXT4") == 0 ||
wcsicmp(FileSystem, L"FFS") == 0 ||
wcsicmp(FileSystem, L"REISERFS") == 0)
{
return PARTITION_LINUX;
}
else
{
/* Unknown file system */
DPRINT1("Unknown file system '%S'\n", FileSystem);
return PARTITION_ENTRY_UNUSED;
}
} }
@ -271,84 +535,35 @@ Quit:
BOOLEAN BOOLEAN
PreparePartitionForFormatting( PreparePartitionForFormatting(
IN struct _PARTENTRY* PartEntry, IN struct _PARTENTRY* PartEntry,
IN PFILE_SYSTEM FileSystem) IN PCWSTR FileSystemName)
{ {
if (!FileSystem) UCHAR PartitionType;
if (!FileSystemName || !*FileSystemName)
{ {
DPRINT1("No file system specified?\n"); DPRINT1("No file system specified?\n");
return FALSE; return FALSE;
} }
if (wcscmp(FileSystem->FileSystemName, L"FAT") == 0) PartitionType = FileSystemToPartitionType(FileSystemName,
&PartEntry->StartSector,
&PartEntry->SectorCount);
if (PartitionType == PARTITION_ENTRY_UNUSED)
{ {
if (PartEntry->SectorCount.QuadPart < 8192) /* Unknown file system */
{ DPRINT1("Unknown file system '%S'\n", FileSystemName);
/* FAT12 CHS partition (disk is smaller than 4.1MB) */
SetPartitionType(PartEntry, PARTITION_FAT_12);
}
else if (PartEntry->StartSector.QuadPart < 1450560)
{
/* Partition starts below the 8.4GB boundary ==> CHS partition */
if (PartEntry->SectorCount.QuadPart < 65536)
{
/* FAT16 CHS partition (partition size < 32MB) */
SetPartitionType(PartEntry, PARTITION_FAT_16);
}
else if (PartEntry->SectorCount.QuadPart < 1048576)
{
/* FAT16 CHS partition (partition size < 512MB) */
SetPartitionType(PartEntry, PARTITION_HUGE);
}
else
{
/* FAT32 CHS partition (partition size >= 512MB) */
SetPartitionType(PartEntry, PARTITION_FAT32);
}
}
else
{
/* Partition starts above the 8.4GB boundary ==> LBA partition */
if (PartEntry->SectorCount.QuadPart < 1048576)
{
/* FAT16 LBA partition (partition size < 512MB) */
SetPartitionType(PartEntry, PARTITION_XINT13);
}
else
{
/* FAT32 LBA partition (partition size >= 512MB) */
SetPartitionType(PartEntry, PARTITION_FAT32_XINT13);
}
}
}
else if (wcscmp(FileSystem->FileSystemName, L"BTRFS") == 0)
{
SetPartitionType(PartEntry, PARTITION_LINUX);
}
#if 0
else if (wcscmp(FileSystem->FileSystemName, L"EXT2") == 0)
{
SetPartitionType(PartEntry, PARTITION_LINUX);
}
else if (wcscmp(FileSystem->FileSystemName, L"NTFS") == 0)
{
SetPartitionType(PartEntry, PARTITION_IFS);
}
#endif
else
{
/* Unknown file system? */
DPRINT1("Unknown file system \"%S\"?\n", FileSystem->FileSystemName);
return FALSE; return FALSE;
} }
SetPartitionType(PartEntry, PartitionType);
// //
// FIXME: Do this now, or after the partition was actually formatted?? // FIXME: Do this now, or after the partition was actually formatted??
// //
/* Set the new partition's file system proper */ /* Set the new partition's file system proper */
PartEntry->FormatState = Formatted; // Well... This may be set after the real formatting takes place (in which case we should change the FormatState to another value) RtlStringCbCopyW(PartEntry->FileSystem,
PartEntry->FileSystem = FileSystem; sizeof(PartEntry->FileSystem),
FileSystemName);
return TRUE; return TRUE;
} }

View file

@ -2,40 +2,113 @@
* PROJECT: ReactOS Setup Library * PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Filesystem support functions * PURPOSE: Filesystem support functions
* COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net) * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2017-2018 Hermes Belusca-Maito * Copyright 2017-2019 Hermes Belusca-Maito
*/ */
#pragma once #pragma once
#include <fmifs/fmifs.h> #include <fmifs/fmifs.h>
typedef struct _FILE_SYSTEM /** QueryAvailableFileSystemFormat() **/
{ BOOLEAN
PCWSTR FileSystemName; GetRegisteredFileSystems(
FORMATEX FormatFunc; IN ULONG Index,
CHKDSKEX ChkdskFunc; OUT PCWSTR* FileSystemName);
} FILE_SYSTEM, *PFILE_SYSTEM;
PFILE_SYSTEM NTSTATUS
GetRegisteredFileSystems(OUT PULONG Count); GetFileSystemNameByHandle(
IN HANDLE PartitionHandle,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize);
PFILE_SYSTEM NTSTATUS
GetFileSystemByName( GetFileSystemName_UStr(
// IN PFILE_SYSTEM_LIST List, IN PUNICODE_STRING PartitionPath,
IN PCWSTR FileSystemName); IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize);
NTSTATUS
GetFileSystemName(
IN PCWSTR Partition,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize);
NTSTATUS
InferFileSystemByHandle(
IN HANDLE PartitionHandle,
IN UCHAR PartitionType,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize);
NTSTATUS
InferFileSystem(
IN PCWSTR Partition,
IN UCHAR PartitionType,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize);
/** ChkdskEx() **/
NTSTATUS
ChkdskFileSystem_UStr(
IN PUNICODE_STRING DriveRoot,
IN PCWSTR FileSystemName,
IN BOOLEAN FixErrors,
IN BOOLEAN Verbose,
IN BOOLEAN CheckOnlyIfDirty,
IN BOOLEAN ScanDrive,
IN PFMIFSCALLBACK Callback);
NTSTATUS
ChkdskFileSystem(
IN PCWSTR DriveRoot,
IN PCWSTR FileSystemName,
IN BOOLEAN FixErrors,
IN BOOLEAN Verbose,
IN BOOLEAN CheckOnlyIfDirty,
IN BOOLEAN ScanDrive,
IN PFMIFSCALLBACK Callback);
/** FormatEx() **/
NTSTATUS
FormatFileSystem_UStr(
IN PUNICODE_STRING DriveRoot,
IN PCWSTR FileSystemName,
IN FMIFS_MEDIA_FLAG MediaFlag,
IN PUNICODE_STRING Label,
IN BOOLEAN QuickFormat,
IN ULONG ClusterSize,
IN PFMIFSCALLBACK Callback);
NTSTATUS
FormatFileSystem(
IN PCWSTR DriveRoot,
IN PCWSTR FileSystemName,
IN FMIFS_MEDIA_FLAG MediaFlag,
IN PCWSTR Label,
IN BOOLEAN QuickFormat,
IN ULONG ClusterSize,
IN PFMIFSCALLBACK Callback);
UCHAR
FileSystemToPartitionType(
IN PCWSTR FileSystem,
IN PULARGE_INTEGER StartSector,
IN PULARGE_INTEGER SectorCount);
//
// Formatting routines
//
struct _PARTENTRY; // Defined in partlist.h struct _PARTENTRY; // Defined in partlist.h
PFILE_SYSTEM
GetFileSystem(
// IN PFILE_SYSTEM_LIST FileSystemList,
IN struct _PARTENTRY* PartEntry);
BOOLEAN BOOLEAN
PreparePartitionForFormatting( PreparePartitionForFormatting(
IN struct _PARTENTRY* PartEntry, IN struct _PARTENTRY* PartEntry,
IN PFILE_SYSTEM FileSystem); IN PCWSTR FileSystemName);
/* EOF */ /* EOF */

View file

@ -2,7 +2,8 @@
* PROJECT: ReactOS Setup Library * PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Partition list functions * PURPOSE: Partition list functions
* COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net) * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2018-2019 Hermes Belusca-Maito
*/ */
#include "precomp.h" #include "precomp.h"
@ -752,18 +753,19 @@ CreateInsertBlankRegion(
NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE;
NewPartEntry->FormatState = Unformatted;
NewPartEntry->FileSystem = NULL;
NewPartEntry->StartSector.QuadPart = StartSector; NewPartEntry->StartSector.QuadPart = StartSector;
NewPartEntry->SectorCount.QuadPart = SectorCount; NewPartEntry->SectorCount.QuadPart = SectorCount;
NewPartEntry->IsPartitioned = FALSE;
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
NewPartEntry->FormatState = Unformatted;
NewPartEntry->FileSystem[0] = L'\0';
DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
/* Insert the table into the list */ /* Insert the new entry into the list */
InsertTailList(ListHead, &NewPartEntry->ListEntry); InsertTailList(ListHead, &NewPartEntry->ListEntry);
return NewPartEntry; return NewPartEntry;
@ -788,17 +790,8 @@ InitializePartitionEntry(
{ {
DPRINT1("Convert existing partition entry\n"); DPRINT1("Convert existing partition entry\n");
/* Convert current entry to 'new (unformatted)' */
PartEntry->IsPartitioned = TRUE;
PartEntry->New = TRUE;
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
PartEntry->FormatState = Unformatted;
PartEntry->FileSystem = NULL;
PartEntry->AutoCreate = AutoCreate;
PartEntry->BootIndicator = FALSE;
PartEntry->LogicalPartition = FALSE;
NewPartEntry = PartEntry; NewPartEntry = PartEntry;
NewPartEntry->AutoCreate = AutoCreate;
} }
else else
{ {
@ -811,28 +804,32 @@ InitializePartitionEntry(
if (NewPartEntry == NULL) if (NewPartEntry == NULL)
return NULL; return NULL;
/* Insert the new entry into the list */
InsertTailList(&PartEntry->ListEntry,
&NewPartEntry->ListEntry);
NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = TRUE;
NewPartEntry->New = TRUE;
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
NewPartEntry->FormatState = Unformatted;
NewPartEntry->FileSystem = NULL;
NewPartEntry->BootIndicator = FALSE;
NewPartEntry->LogicalPartition = FALSE;
NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart; NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
NewPartEntry->StartSector.QuadPart; NewPartEntry->StartSector.QuadPart;
PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart; PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart); PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
/* Insert the new entry into the list */
InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry);
} }
/* Create entry as 'New (Unformatted)' */
NewPartEntry->New = TRUE;
NewPartEntry->IsPartitioned = TRUE;
NewPartEntry->PartitionType = FileSystemToPartitionType(L"RAW", &NewPartEntry->StartSector, &NewPartEntry->SectorCount);
ASSERT(NewPartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
NewPartEntry->FormatState = Unformatted;
NewPartEntry->FileSystem[0] = L'\0';
// NewPartEntry->AutoCreate = AutoCreate;
NewPartEntry->BootIndicator = FALSE;
NewPartEntry->LogicalPartition = FALSE;
DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
@ -852,10 +849,10 @@ AddPartitionToDisk(
NTSTATUS Status; NTSTATUS Status;
PPARTITION_INFORMATION PartitionInfo; PPARTITION_INFORMATION PartitionInfo;
PPARTENTRY PartEntry; PPARTENTRY PartEntry;
HANDLE FileHandle; HANDLE PartitionHandle;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
WCHAR Buffer[MAX_PATH]; WCHAR PathBuffer[MAX_PATH];
UNICODE_STRING Name; UNICODE_STRING Name;
UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)]; UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)LabelBuffer; PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)LabelBuffer;
@ -889,10 +886,16 @@ AddPartitionToDisk(
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
PartEntry->PartitionIndex = PartitionIndex; PartEntry->PartitionIndex = PartitionIndex;
/* 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));
if (IsContainerPartition(PartEntry->PartitionType)) if (IsContainerPartition(PartEntry->PartitionType))
{ {
PartEntry->FormatState = Unformatted; PartEntry->FormatState = Unformatted;
PartEntry->FileSystem = NULL;
if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL) if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
DiskEntry->ExtendedPartition = PartEntry; DiskEntry->ExtendedPartition = PartEntry;
@ -901,28 +904,12 @@ AddPartitionToDisk(
{ {
ASSERT(PartitionInfo->RecognizedPartition); ASSERT(PartitionInfo->RecognizedPartition);
PartEntry->FileSystem = GetFileSystem(PartEntry);
if (PartEntry->FileSystem)
PartEntry->FormatState = Preformatted;
else
PartEntry->FormatState = Unformatted;
// PartEntry->FormatState = UnknownFormat;
}
else
{
/* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
PartEntry->FormatState = UnknownFormat;
}
/* Initialize the partition volume label */
RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
/* Open the volume, ignore any errors */ /* Open the volume, ignore any errors */
RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer), RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
L"\\Device\\Harddisk%lu\\Partition%lu", L"\\Device\\Harddisk%lu\\Partition%lu",
DiskEntry->DiskNumber, DiskEntry->DiskNumber,
PartEntry->PartitionNumber); PartEntry->PartitionNumber);
RtlInitUnicodeString(&Name, Buffer); RtlInitUnicodeString(&Name, PathBuffer);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&Name, &Name,
@ -930,24 +917,48 @@ AddPartitionToDisk(
NULL, NULL,
NULL); NULL);
Status = NtOpenFile(&FileHandle, PartitionHandle = NULL;
Status = NtOpenFile(&PartitionHandle,
FILE_READ_DATA | SYNCHRONIZE, FILE_READ_DATA | SYNCHRONIZE,
&ObjectAttributes, &ObjectAttributes,
&IoStatusBlock, &IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT); FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
}
if (/* NT_SUCCESS(Status) && */ PartitionHandle)
{
/* We don't have a FS, try to guess one */
Status = InferFileSystemByHandle(PartitionHandle,
PartEntry->PartitionType,
PartEntry->FileSystem,
sizeof(PartEntry->FileSystem));
if (!NT_SUCCESS(Status))
DPRINT1("InferFileSystemByHandle() failed, Status 0x%08lx\n", Status);
}
if (*PartEntry->FileSystem)
{
if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
PartEntry->FormatState = Unformatted;
else
PartEntry->FormatState = Preformatted;
}
else
{
PartEntry->FormatState = UnknownFormat;
}
/* Retrieve the partition volume label */ /* Retrieve the partition volume label */
Status = NtQueryVolumeInformationFile(FileHandle, if (PartitionHandle)
{
Status = NtQueryVolumeInformationFile(PartitionHandle,
&IoStatusBlock, &IoStatusBlock,
&LabelBuffer, &LabelBuffer,
sizeof(LabelBuffer), sizeof(LabelBuffer),
FileFsVolumeInformation); FileFsVolumeInformation);
/* Close the handle */
NtClose(FileHandle);
/* Check for success */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Copy the (possibly truncated) volume label and NULL-terminate it */ /* Copy the (possibly truncated) volume label and NULL-terminate it */
@ -959,9 +970,15 @@ AddPartitionToDisk(
DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status); DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
} }
} }
/* Close the partition */
if (PartitionHandle)
NtClose(PartitionHandle);
}
else else
{ {
DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status); /* Unknown partition, hence unknown partition format (may or may not be actually formatted) */
PartEntry->FormatState = UnknownFormat;
} }
InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition); InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
@ -2784,7 +2801,7 @@ DismountVolume(
IsContainerPartition(PartEntry->PartitionType) || IsContainerPartition(PartEntry->PartitionType) ||
!IsRecognizedPartition(PartEntry->PartitionType) || !IsRecognizedPartition(PartEntry->PartitionType) ||
PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ || PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ ||
PartEntry->FileSystem == NULL || !*PartEntry->FileSystem ||
PartEntry->PartitionNumber == 0) PartEntry->PartitionNumber == 0)
{ {
/* The partition is not mounted, so just return success */ /* The partition is not mounted, so just return success */
@ -2981,7 +2998,7 @@ DeleteCurrentPartition(
PartEntry->IsPartitioned = FALSE; PartEntry->IsPartitioned = FALSE;
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED; PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
PartEntry->FormatState = Unformatted; PartEntry->FormatState = Unformatted;
PartEntry->FileSystem = NULL; PartEntry->FileSystem[0] = L'\0';
PartEntry->DriveLetter = 0; PartEntry->DriveLetter = 0;
PartEntry->OnDiskPartitionNumber = 0; PartEntry->OnDiskPartitionNumber = 0;
PartEntry->PartitionNumber = 0; PartEntry->PartitionNumber = 0;
@ -2993,6 +3010,84 @@ DeleteCurrentPartition(
AssignDriveLetters(List); AssignDriveLetters(List);
} }
static
BOOLEAN
IsSupportedActivePartition(
IN PPARTENTRY PartEntry)
{
/* Check the type and the filesystem of this partition */
/*
* We do not support extended partition containers (on MBR disks) marked
* as active, and containing code inside their extended boot records.
*/
if (IsContainerPartition(PartEntry->PartitionType))
{
DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
return FALSE;
}
/*
* ADDITIONAL CHECKS / BIG HACK:
*
* Retrieve its file system and check whether we have
* write support for it. If that is the case we are fine
* and we can use it directly. However if we don't have
* write support we will need to change the active system
* partition.
*
* NOTE that this is completely useless on architectures
* where a real system partition is required, as on these
* architectures the partition uses the FAT FS, for which
* we do have write support.
* NOTE also that for those architectures looking for a
* partition boot indicator is insufficient.
*/
if ((PartEntry->FormatState == Unformatted ) ||
(PartEntry->FormatState == Preformatted) ||
(PartEntry->FormatState == Formatted ))
{
ASSERT(*PartEntry->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 ||
wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
{
return TRUE;
}
else
{
// WARNING: We cannot write on this FS yet!
DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
PartEntry->FileSystem);
return FALSE;
}
}
else // if (PartEntry->FormatState == UnknownFormat)
{
ASSERT(!*PartEntry->FileSystem);
DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
return FALSE;
}
// HACK: WARNING: We cannot write on this FS yet!
// See fsutil.c:InferFileSystem()
if (PartEntry->PartitionType == PARTITION_IFS)
{
DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
PartEntry->FileSystem);
return FALSE;
}
return TRUE;
}
VOID VOID
CheckActiveSystemPartition( CheckActiveSystemPartition(
IN PPARTLIST List) IN PPARTLIST List)
@ -3001,8 +3096,6 @@ CheckActiveSystemPartition(
PPARTENTRY PartEntry; PPARTENTRY PartEntry;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
PFILE_SYSTEM FileSystem;
/* Check for empty disk list */ /* Check for empty disk list */
if (IsListEmpty(&List->DiskListHead)) if (IsListEmpty(&List->DiskListHead))
{ {
@ -3154,36 +3247,9 @@ CheckActiveSystemPartition(
/* Save it */ /* Save it */
List->OriginalSystemPartition = List->SystemPartition; List->OriginalSystemPartition = List->SystemPartition;
/* /* If we get a candidate active partition, validate it */
* ADDITIONAL CHECKS / BIG HACK: if (!IsSupportedActivePartition(List->OriginalSystemPartition))
*
* Retrieve its file system and check whether we have
* write support for it. If that is the case we are fine
* and we can use it directly. However if we don't have
* write support we will need to change the active system
* partition.
*
* NOTE that this is completely useless on architectures
* where a real system partition is required, as on these
* architectures the partition uses the FAT FS, for which
* we do have write support.
* NOTE also that for those architectures looking for a
* partition boot indicator is insufficient.
*/
FileSystem = GetFileSystem(List->OriginalSystemPartition);
if (FileSystem == NULL)
{ {
DPRINT1("System partition %lu in disk %lu with no FS?!\n",
List->OriginalSystemPartition->PartitionNumber,
List->OriginalSystemPartition->DiskEntry->DiskNumber);
goto FindAndUseAlternativeSystemPartition;
}
// HACK: WARNING: We cannot write on this FS yet!
// See fsutil.c:GetFileSystem()
if (List->OriginalSystemPartition->PartitionType == PARTITION_IFS)
{
DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
FileSystem->FileSystemName);
goto FindAndUseAlternativeSystemPartition; goto FindAndUseAlternativeSystemPartition;
} }

View file

@ -2,7 +2,8 @@
* PROJECT: ReactOS Setup Library * PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Partition list functions * PURPOSE: Partition list functions
* COPYRIGHT: Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net) * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2018-2019 Hermes Belusca-Maito
*/ */
#pragma once #pragma once
@ -30,8 +31,6 @@ typedef enum _FORMATSTATE
Formatted Formatted
} FORMATSTATE, *PFORMATSTATE; } FORMATSTATE, *PFORMATSTATE;
struct _FILE_SYSTEM;
typedef struct _PARTENTRY typedef struct _PARTENTRY
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
@ -52,13 +51,16 @@ typedef struct _PARTENTRY
WCHAR DriveLetter; WCHAR DriveLetter;
WCHAR VolumeLabel[20]; WCHAR VolumeLabel[20];
// CHAR FileSystemName[9]; // NOTE: Superseded by the FileSystem member WCHAR FileSystem[MAX_PATH+1];
FORMATSTATE FormatState;
BOOLEAN LogicalPartition; BOOLEAN LogicalPartition;
/* Partition is partitioned disk space */ /* Partition is partitioned disk space */
BOOLEAN IsPartitioned; BOOLEAN IsPartitioned;
/** The following three properties may be replaced by flags **/
/* Partition is new, table does not exist on disk yet */ /* Partition is new, table does not exist on disk yet */
BOOLEAN New; BOOLEAN New;
@ -68,9 +70,6 @@ typedef struct _PARTENTRY
/* Partition must be checked */ /* Partition must be checked */
BOOLEAN NeedsCheck; BOOLEAN NeedsCheck;
FORMATSTATE FormatState;
struct _FILE_SYSTEM* FileSystem;
} PARTENTRY, *PPARTENTRY; } PARTENTRY, *PPARTENTRY;

View file

@ -56,14 +56,9 @@ ChkdskCallback(
NTSTATUS NTSTATUS
ChkdskPartition( ChkdskPartition(
IN PUNICODE_STRING DriveRoot, IN PUNICODE_STRING DriveRoot,
/*IN PFILE_SYSTEM_ITEM FileSystemItem*/ IN PCWSTR FileSystemName)
IN PFILE_SYSTEM FileSystem)
{ {
NTSTATUS Status; NTSTATUS Status;
// PFILE_SYSTEM FileSystem = FileSystemItem->FileSystem;
if (!FileSystem || !FileSystem->ChkdskFunc)
return STATUS_NOT_SUPPORTED;
ChkdskProgressBar = CreateProgressBar(6, ChkdskProgressBar = CreateProgressBar(6,
yScreen - 14, yScreen - 14,
@ -76,7 +71,8 @@ ChkdskPartition(
ProgressSetStepCount(ChkdskProgressBar, 100); ProgressSetStepCount(ChkdskProgressBar, 100);
Status = FileSystem->ChkdskFunc(DriveRoot, Status = ChkdskFileSystem_UStr(DriveRoot,
FileSystemName,
TRUE, /* FixErrors */ TRUE, /* FixErrors */
FALSE, /* Verbose */ FALSE, /* Verbose */
TRUE, /* CheckOnlyIfDirty */ TRUE, /* CheckOnlyIfDirty */

View file

@ -28,7 +28,6 @@
NTSTATUS NTSTATUS
ChkdskPartition( ChkdskPartition(
IN PUNICODE_STRING DriveRoot, IN PUNICODE_STRING DriveRoot,
/*IN PFILE_SYSTEM_ITEM FileSystemItem*/ IN PCWSTR FileSystemName);
IN PFILE_SYSTEM FileSystem);
/* EOF */ /* EOF */

View file

@ -88,13 +88,10 @@ FormatCallback(
NTSTATUS NTSTATUS
FormatPartition( FormatPartition(
IN PUNICODE_STRING DriveRoot, IN PUNICODE_STRING DriveRoot,
IN PFILE_SYSTEM_ITEM FileSystemItem) IN PCWSTR FileSystemName,
IN BOOLEAN QuickFormat)
{ {
NTSTATUS Status; NTSTATUS Status;
PFILE_SYSTEM FileSystem = FileSystemItem->FileSystem;
if (!FileSystem || !FileSystem->FormatFunc)
return STATUS_NOT_SUPPORTED;
FormatProgressBar = CreateProgressBar(6, FormatProgressBar = CreateProgressBar(6,
yScreen - 14, yScreen - 14,
@ -107,10 +104,11 @@ FormatPartition(
ProgressSetStepCount(FormatProgressBar, 100); ProgressSetStepCount(FormatProgressBar, 100);
Status = FileSystem->FormatFunc(DriveRoot, Status = FormatFileSystem_UStr(DriveRoot,
FileSystemName,
FMIFS_HARDDISK, /* MediaFlag */ FMIFS_HARDDISK, /* MediaFlag */
NULL, /* Label */ NULL, /* Label */
FileSystemItem->QuickFormat, /* QuickFormat */ QuickFormat, /* QuickFormat */
0, /* ClusterSize */ 0, /* ClusterSize */
FormatCallback); /* Callback */ FormatCallback); /* Callback */

View file

@ -29,6 +29,7 @@
NTSTATUS NTSTATUS
FormatPartition( FormatPartition(
IN PUNICODE_STRING DriveRoot, IN PUNICODE_STRING DriveRoot,
IN PFILE_SYSTEM_ITEM FileSystemItem); IN PCWSTR FileSystemName,
IN BOOLEAN QuickFormat);
/* EOF */ /* EOF */

View file

@ -34,8 +34,7 @@
static VOID static VOID
AddProvider( AddProvider(
IN OUT PFILE_SYSTEM_LIST List, IN OUT PFILE_SYSTEM_LIST List,
IN PCWSTR FileSystemName, // Redundant, I need to check whether this is reaaaaally needed.... IN PCWSTR FileSystem)
IN PFILE_SYSTEM FileSystem)
{ {
PFILE_SYSTEM_ITEM Item; PFILE_SYSTEM_ITEM Item;
@ -43,7 +42,6 @@ AddProvider(
if (!Item) if (!Item)
return; return;
Item->FileSystemName = FileSystemName;
Item->FileSystem = FileSystem; Item->FileSystem = FileSystem;
Item->QuickFormat = TRUE; Item->QuickFormat = TRUE;
InsertTailList(&List->ListHead, &Item->ListEntry); InsertTailList(&List->ListHead, &Item->ListEntry);
@ -55,7 +53,6 @@ AddProvider(
if (!Item) if (!Item)
return; return;
Item->FileSystemName = FileSystemName;
Item->FileSystem = FileSystem; Item->FileSystem = FileSystem;
Item->QuickFormat = FALSE; Item->QuickFormat = FALSE;
InsertTailList(&List->ListHead, &Item->ListEntry); InsertTailList(&List->ListHead, &Item->ListEntry);
@ -63,19 +60,21 @@ AddProvider(
static VOID static VOID
InitializeFileSystemList( InitializeFileSystemList(
IN PFILE_SYSTEM_LIST List) IN PFILE_SYSTEM_LIST List,
IN BOOLEAN ForceFormat)
{ {
ULONG Count; ULONG Index = 0;
PFILE_SYSTEM FileSystems; PCWSTR FileSystemName;
FileSystems = GetRegisteredFileSystems(&Count); while (GetRegisteredFileSystems(Index++, &FileSystemName))
if (!FileSystems || Count == 0)
return;
while (Count--)
{ {
AddProvider(List, FileSystems->FileSystemName, FileSystems); AddProvider(List, FileSystemName);
++FileSystems; }
if (!ForceFormat)
{
/* Add the 'Keep existing filesystem' dummy provider */
AddProvider(List, NULL);
} }
} }
@ -99,19 +98,14 @@ CreateFileSystemList(
List->Selected = NULL; List->Selected = NULL;
InitializeListHead(&List->ListHead); InitializeListHead(&List->ListHead);
InitializeFileSystemList(List); InitializeFileSystemList(List, ForceFormat);
if (!ForceFormat)
{
/* Add the 'Keep existing filesystem' dummy provider */
AddProvider(List, NULL, NULL);
}
/* Search for SelectFileSystem in list */ /* Search for SelectFileSystem in list */
ListEntry = List->ListHead.Flink; ListEntry = List->ListHead.Flink;
while (ListEntry != &List->ListHead) while (ListEntry != &List->ListHead)
{ {
Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry); Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry);
if (Item->FileSystemName && wcscmp(SelectFileSystem, Item->FileSystemName) == 0) if (Item->FileSystem && wcsicmp(SelectFileSystem, Item->FileSystem) == 0)
{ {
List->Selected = Item; List->Selected = Item;
break; break;
@ -171,12 +165,12 @@ DrawFileSystemList(
coPos, coPos,
&Written); &Written);
if (Item->FileSystemName) if (Item->FileSystem)
{ {
if (Item->QuickFormat) snprintf(Buffer, sizeof(Buffer),
snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK1), Item->FileSystemName); MUIGetString(Item->QuickFormat ? STRING_FORMATDISK1
else : STRING_FORMATDISK2),
snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK2), Item->FileSystemName); Item->FileSystem);
} }
else else
{ {
@ -184,13 +178,17 @@ DrawFileSystemList(
} }
if (ListEntry == &List->Selected->ListEntry) if (ListEntry == &List->Selected->ListEntry)
{
CONSOLE_SetInvertedTextXY(List->Left, CONSOLE_SetInvertedTextXY(List->Left,
List->Top + (SHORT)Index, List->Top + (SHORT)Index,
Buffer); Buffer);
}
else else
{
CONSOLE_SetTextXY(List->Left, CONSOLE_SetTextXY(List->Left,
List->Top + (SHORT)Index, List->Top + (SHORT)Index,
Buffer); Buffer);
}
Index++; Index++;
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }

View file

@ -16,7 +16,8 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
/* COPYRIGHT: See COPYING in the top level directory /*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup * PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/fslist.h * FILE: base/setup/usetup/fslist.h
* PURPOSE: Filesystem list functions * PURPOSE: Filesystem list functions
@ -30,8 +31,7 @@
typedef struct _FILE_SYSTEM_ITEM typedef struct _FILE_SYSTEM_ITEM
{ {
LIST_ENTRY ListEntry; LIST_ENTRY ListEntry;
PCWSTR FileSystemName; /* Not owned by the item */ // Redundant, I need to check whether this is reaaaaally needed.... PCWSTR FileSystem;
PFILE_SYSTEM FileSystem;
BOOLEAN QuickFormat; BOOLEAN QuickFormat;
} FILE_SYSTEM_ITEM, *PFILE_SYSTEM_ITEM; } FILE_SYSTEM_ITEM, *PFILE_SYSTEM_ITEM;

View file

@ -22,7 +22,7 @@
* FILE: base/setup/usetup/usetup.c * FILE: base/setup/usetup/usetup.c
* PURPOSE: Text-mode setup * PURPOSE: Text-mode setup
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Hervé Poussineau (hpoussin@reactos.org) * Hervé Poussineau (hpoussin@reactos.org)
*/ */
#include <usetup.h> #include <usetup.h>
@ -3071,7 +3071,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
if (SelectedFileSystem->FileSystem) if (SelectedFileSystem->FileSystem)
{ {
Status = FormatPartition(&PartitionRootPath, Status = FormatPartition(&PartitionRootPath,
SelectedFileSystem); SelectedFileSystem->FileSystem,
SelectedFileSystem->QuickFormat);
if (Status == STATUS_NOT_SUPPORTED) if (Status == STATUS_NOT_SUPPORTED)
{ {
sprintf(Buffer, sprintf(Buffer,
@ -3079,7 +3080,7 @@ FormatPartitionPage(PINPUT_RECORD Ir)
"\n" "\n"
" \x07 Press ENTER to continue Setup.\n" " \x07 Press ENTER to continue Setup.\n"
" \x07 Press F3 to quit Setup.", " \x07 Press F3 to quit Setup.",
SelectedFileSystem->FileSystem->FileSystemName); SelectedFileSystem->FileSystem);
PopupError(Buffer, PopupError(Buffer,
MUIGetString(STRING_QUITCONTINUE), MUIGetString(STRING_QUITCONTINUE),
@ -3147,7 +3148,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
NTSTATUS Status; NTSTATUS Status;
PDISKENTRY DiskEntry; PDISKENTRY DiskEntry;
PPARTENTRY PartEntry; PPARTENTRY PartEntry;
PFILE_SYSTEM CurrentFileSystem;
UNICODE_STRING PartitionRootPath; UNICODE_STRING PartitionRootPath;
WCHAR PathBuffer[MAX_PATH]; WCHAR PathBuffer[MAX_PATH];
CHAR Buffer[MAX_PATH]; CHAR Buffer[MAX_PATH];
@ -3163,6 +3163,20 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
return INSTALL_DIRECTORY_PAGE; return INSTALL_DIRECTORY_PAGE;
} }
CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystem: %S\n",
PartEntry->PartitionType, (*PartEntry->FileSystem ? PartEntry->FileSystem : L"n/a"));
/* HACK: Do not try to check a partition with an unknown filesystem */
if (!*PartEntry->FileSystem)
{
PartEntry->NeedsCheck = FALSE;
return CHECK_FILE_SYSTEM_PAGE;
}
/* Set PartitionRootPath */ /* Set PartitionRootPath */
RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
L"\\Device\\Harddisk%lu\\Partition%lu", L"\\Device\\Harddisk%lu\\Partition%lu",
@ -3171,30 +3185,22 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
RtlInitUnicodeString(&PartitionRootPath, PathBuffer); RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath); DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART)); /* Check the partition */
Status = ChkdskPartition(&PartitionRootPath, PartEntry->FileSystem);
CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
CurrentFileSystem = PartEntry->FileSystem;
DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a"));
/* HACK: Do not try to check a partition with an unknown filesystem */
if (CurrentFileSystem == NULL)
{
PartEntry->NeedsCheck = FALSE;
return CHECK_FILE_SYSTEM_PAGE;
}
Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
if (Status == STATUS_NOT_SUPPORTED) if (Status == STATUS_NOT_SUPPORTED)
{ {
/*
* Partition checking is not supported with the current filesystem,
* so disable FS checks on it.
*/
PartEntry->NeedsCheck = FALSE;
sprintf(Buffer, sprintf(Buffer,
"Setup is currently unable to check a partition formatted in %S.\n" "Setup is currently unable to check a partition formatted in %S.\n"
"\n" "\n"
" \x07 Press ENTER to continue Setup.\n" " \x07 Press ENTER to continue Setup.\n"
" \x07 Press F3 to quit Setup.", " \x07 Press F3 to quit Setup.",
CurrentFileSystem->FileSystemName); PartEntry->FileSystem);
PopupError(Buffer, PopupError(Buffer,
MUIGetString(STRING_QUITCONTINUE), MUIGetString(STRING_QUITCONTINUE),
@ -4204,7 +4210,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER, MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
PartitionList->SystemPartition->FileSystem->FileSystemName); PartitionList->SystemPartition->FileSystem);
return QUIT_PAGE; return QUIT_PAGE;
} }
@ -4241,7 +4247,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER, MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
PartitionList->SystemPartition->FileSystem->FileSystemName); PartitionList->SystemPartition->FileSystem);
return QUIT_PAGE; return QUIT_PAGE;
} }