[SETUPLIB][USETUP] Factor out the usage of FS provider structures.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 24 Feb 2019 16:52:33 +0000 (17:52 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 10 Mar 2019 14:41:05 +0000 (15:41 +0100)
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.

12 files changed:
base/setup/lib/bootsup.c
base/setup/lib/fsutil.c
base/setup/lib/fsutil.h
base/setup/lib/utils/partlist.c
base/setup/lib/utils/partlist.h
base/setup/usetup/chkdsk.c
base/setup/usetup/chkdsk.h
base/setup/usetup/format.c
base/setup/usetup/format.h
base/setup/usetup/fslist.c
base/setup/usetup/fslist.h
base/setup/usetup/usetup.c

index 3d494c9..ec9a1a4 100644 (file)
@@ -2351,38 +2351,38 @@ InstallFatBootcodeToFloppy(
     IN PUNICODE_STRING SourceRootPath,
     IN PUNICODE_STRING DestinationArcPath)
 {
+    static const PCWSTR FloppyDevice = L"\\Device\\Floppy0\\";
+
     NTSTATUS Status;
-    PFILE_SYSTEM FatFS;
-    UNICODE_STRING FloppyDevice = RTL_CONSTANT_STRING(L"\\Device\\Floppy0\\");
     WCHAR SrcPath[MAX_PATH];
     WCHAR DstPath[MAX_PATH];
 
     /* Verify that the floppy disk is accessible */
-    if (DoesDirExist(NULL, FloppyDevice.Buffer) == FALSE)
+    if (DoesDirExist(NULL, FloppyDevice) == FALSE)
         return STATUS_DEVICE_NOT_READY;
 
     /* Format the floppy disk */
-    FatFS = GetFileSystemByName(L"FAT");
-    if (!FatFS)
-    {
-        DPRINT1("FAT FS non existent on this system?!\n");
-        return STATUS_NOT_SUPPORTED;
-    }
-    Status = FatFS->FormatFunc(&FloppyDevice,
-                               FMIFS_FLOPPY,
-                               NULL,
-                               TRUE,
-                               0,
-                               NULL);
+    // FormatPartition(...)
+    Status = FormatFileSystem(FloppyDevice,
+                              L"FAT",
+                              FMIFS_FLOPPY,
+                              NULL,
+                              TRUE,
+                              0,
+                              NULL);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
+        if (Status == STATUS_NOT_SUPPORTED)
+            DPRINT1("FAT FS non existent on this system?!\n");
+        else
+            DPRINT1("VfatFormat() failed (Status %lx)\n", Status);
+
         return Status;
     }
 
     /* Copy FreeLoader to the boot partition */
     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);
     Status = SetupCopyFile(SrcPath, DstPath, FALSE);
@@ -2394,7 +2394,7 @@ InstallFatBootcodeToFloppy(
 
     /* Create new 'freeldr.ini' */
     DPRINT("Create new 'freeldr.ini'\n");
-    Status = CreateFreeLoaderIniForReactOS(FloppyDevice.Buffer, DestinationArcPath->Buffer);
+    Status = CreateFreeLoaderIniForReactOS(FloppyDevice, DestinationArcPath->Buffer);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("CreateFreeLoaderIniForReactOS() failed (Status %lx)\n", Status);
@@ -2403,7 +2403,7 @@ InstallFatBootcodeToFloppy(
 
     /* Install FAT12 boosector */
     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);
     Status = InstallFat12BootCodeToFloppy(SrcPath, DstPath);
index b9d0ed8..8955518 100644 (file)
@@ -2,8 +2,8 @@
  * PROJECT:     ReactOS Setup Library
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Filesystem support functions
- * COPYRIGHT:   Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
- *              Copyright 2017-2018 Hermes Belusca-Maito
+ * COPYRIGHT:   Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Copyright 2017-2019 Hermes Belusca-Maito
  */
 
 //
 #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 */
-FILE_SYSTEM RegisteredFileSystems[] =
+static FILE_SYSTEM RegisteredFileSystems[] =
 {
     /* NOTE: The FAT formatter automatically determines
      * whether it will use FAT-16 or FAT-32. */
@@ -54,16 +62,24 @@ FILE_SYSTEM RegisteredFileSystems[] =
 
 /* FUNCTIONS ****************************************************************/
 
-PFILE_SYSTEM
-GetRegisteredFileSystems(OUT PULONG Count)
+/** QueryAvailableFileSystemFormat() **/
+BOOLEAN
+GetRegisteredFileSystems(
+    IN ULONG Index,
+    OUT PCWSTR* FileSystemName)
 {
-    *Count = ARRAYSIZE(RegisteredFileSystems);
-    return RegisteredFileSystems;
+    if (Index >= ARRAYSIZE(RegisteredFileSystems))
+        return FALSE;
+
+    *FileSystemName = RegisteredFileSystems[Index].FileSystemName;
+
+    return TRUE;
 }
 
-PFILE_SYSTEM
+
+/** GetProvider() **/
+static PFILE_SYSTEM
 GetFileSystemByName(
-    // IN PFILE_SYSTEM_LIST List,
     IN PCWSTR FileSystemName)
 {
 #if 0 // Reenable when the list of registered FSes will again be dynamic
@@ -75,25 +91,33 @@ GetFileSystemByName(
     while (ListEntry != &List->ListHead)
     {
         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;
+        }
 
         ListEntry = ListEntry->Flink;
     }
 
 #else
 
-    ULONG Count;
-    PFILE_SYSTEM FileSystems;
+    ULONG Count = ARRAYSIZE(RegisteredFileSystems);
+    PFILE_SYSTEM FileSystems = RegisteredFileSystems;
 
-    FileSystems = GetRegisteredFileSystems(&Count);
-    if (!FileSystems || Count == 0)
-        return NULL;
+    ASSERT(FileSystems && Count != 0);
 
     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;
+        }
 
         ++FileSystems;
     }
@@ -105,40 +129,59 @@ GetFileSystemByName(
 
 
 //
-// FileSystem recognition (using NT OS functionality)
+// FileSystem recognition, using NT OS functionality
 //
 
 /* NOTE: Ripped & adapted from base/system/autochk/autochk.c */
-static NTSTATUS
-_MyGetFileSystem(
-    IN struct _PARTENTRY* PartEntry,
+NTSTATUS
+GetFileSystemNameByHandle(
+    IN HANDLE PartitionHandle,
     IN OUT PWSTR FileSystemName,
     IN SIZE_T FileSystemNameSize)
 {
     NTSTATUS Status;
-    UNICODE_STRING PartitionRootPath;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE FileHandle;
     IO_STATUS_BLOCK IoStatusBlock;
-    WCHAR PathBuffer[MAX_PATH];
     UCHAR Buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
     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);
+    /* Retrieve the FS attributes */
+    Status = NtQueryVolumeInformationFile(PartitionHandle,
+                                          &IoStatusBlock,
+                                          FileFsAttribute,
+                                          sizeof(Buffer),
+                                          FileFsAttributeInformation);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtQueryVolumeInformationFile failed, Status 0x%08lx\n", Status);
+        return Status;
+    }
+
+    if (FileSystemNameSize < FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
+        return STATUS_BUFFER_TOO_SMALL;
+
+    return RtlStringCbCopyNW(FileSystemName, FileSystemNameSize,
+                             FileFsAttribute->FileSystemName,
+                             FileFsAttribute->FileSystemNameLength);
+}
+
+NTSTATUS
+GetFileSystemName_UStr(
+    IN PUNICODE_STRING PartitionPath,
+    IN OUT PWSTR FileSystemName,
+    IN SIZE_T FileSystemNameSize)
+{
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE PartitionHandle;
+    IO_STATUS_BLOCK IoStatusBlock;
 
     /* Open the partition */
     InitializeObjectAttributes(&ObjectAttributes,
-                               &PartitionRootPath,
+                               PartitionPath,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL);
-    Status = NtOpenFile(&FileHandle, // PartitionHandle,
+    Status = NtOpenFile(&PartitionHandle,
                         FILE_GENERIC_READ /* | SYNCHRONIZE */,
                         &ObjectAttributes,
                         &IoStatusBlock,
@@ -146,72 +189,62 @@ _MyGetFileSystem(
                         0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionRootPath, Status);
+        DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", PartitionPath, Status);
         return Status;
     }
 
     /* Retrieve the FS attributes */
-    Status = NtQueryVolumeInformationFile(FileHandle,
-                                          &IoStatusBlock,
-                                          FileFsAttribute,
-                                          sizeof(Buffer),
-                                          FileFsAttributeInformation);
-    NtClose(FileHandle);
-
+    Status = GetFileSystemNameByHandle(PartitionHandle, FileSystemName, FileSystemNameSize);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("NtQueryVolumeInformationFile failed for partition '%wZ', Status 0x%08lx\n",
-                &PartitionRootPath, Status);
-        return Status;
+        DPRINT1("GetFileSystemNameByHandle() failed for partition '%wZ', Status 0x%08lx\n",
+                PartitionPath, Status);
     }
 
-    if (FileSystemNameSize < FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
-        return STATUS_BUFFER_TOO_SMALL;
+    /* Close the partition */
+    NtClose(PartitionHandle);
 
-    return RtlStringCbCopyNW(FileSystemName, FileSystemNameSize,
-                             FileFsAttribute->FileSystemName,
-                             FileFsAttribute->FileSystemNameLength);
+    return Status;
 }
 
-PFILE_SYSTEM
-GetFileSystem(
-    // IN PFILE_SYSTEM_LIST FileSystemList,
-    IN struct _PARTENTRY* PartEntry)
+NTSTATUS
+GetFileSystemName(
+    IN PCWSTR Partition,
+    IN OUT PWSTR FileSystemName,
+    IN SIZE_T FileSystemNameSize)
 {
-    PFILE_SYSTEM CurrentFileSystem;
-    NTSTATUS Status;
-    PWSTR FileSystemName = NULL;
-    WCHAR FsRecFileSystemName[MAX_PATH];
+    UNICODE_STRING PartitionPath;
 
-    CurrentFileSystem = PartEntry->FileSystem;
+    RtlInitUnicodeString(&PartitionPath, Partition);
+    return GetFileSystemName_UStr(&PartitionPath,
+                                  FileSystemName,
+                                  FileSystemNameSize);
+}
 
-    /* We have a file system, return it */
-    if (CurrentFileSystem != NULL && CurrentFileSystem->FileSystemName != NULL)
-        return CurrentFileSystem;
+NTSTATUS
+InferFileSystemByHandle(
+    IN HANDLE PartitionHandle,
+    IN UCHAR PartitionType,
+    IN OUT PWSTR FileSystemName,
+    IN SIZE_T FileSystemNameSize)
+{
+    NTSTATUS Status;
 
-    DPRINT1("File system not found, try to guess one...\n");
+    if (FileSystemNameSize < sizeof(WCHAR))
+        return STATUS_BUFFER_TOO_SMALL;
 
-    CurrentFileSystem = NULL;
+    *FileSystemName = L'\0';
 
-    /*
-     * We don't have one...
-     *
-     * Try to infer a file system using NT file system recognition.
-     */
-    Status = _MyGetFileSystem(PartEntry, FsRecFileSystemName, sizeof(FsRecFileSystemName));
-    if (NT_SUCCESS(Status) && *FsRecFileSystemName)
+    /* Try to infer a file system using NT file system recognition */
+    Status = GetFileSystemNameByHandle(PartitionHandle,
+                                       FileSystemName,
+                                       FileSystemNameSize);
+    if (NT_SUCCESS(Status) && *FileSystemName)
     {
-        /* Temporary HACK: map FAT32 back to FAT */
-        if (wcscmp(FsRecFileSystemName, L"FAT32") == 0)
-            RtlStringCbCopyW(FsRecFileSystemName, sizeof(FsRecFileSystemName), L"FAT");
-
-        FileSystemName = FsRecFileSystemName;
         goto Quit;
     }
 
     /*
-     * We don't have one...
-     *
      * 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
@@ -224,131 +257,313 @@ GetFileSystem(
      * On the contrary, for unformatted partitions with a given ID, the
      * following code is OK.
      */
-    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))
+    if ((PartitionType == PARTITION_FAT_12) ||
+        (PartitionType == PARTITION_FAT_16) ||
+        (PartitionType == PARTITION_HUGE  ) ||
+        (PartitionType == PARTITION_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.
         /* 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.
         /* Could also be HPFS */
-        FileSystemName = L"NTFS";
+        Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"NTFS");
     }
 
 Quit:
-    // HACK: WARNING: We cannot write on this FS yet!
-    if (FileSystemName)
+    if (*FileSystemName)
     {
-        if (PartEntry->PartitionType == PARTITION_IFS)
-            DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName);
+        // WARNING: We cannot write on this FS yet!
+        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",
-            PartEntry->PartitionType, FileSystemName ? FileSystemName : L"None");
+    DPRINT1("InferFileSystem -- PartitionType: 0x%02X ; FileSystem (guessed): %S\n",
+            PartitionType, *FileSystemName ? FileSystemName : L"None");
 
-    if (FileSystemName)
-        CurrentFileSystem = GetFileSystemByName(FileSystemName);
+    return Status;
+}
 
-    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;
 
-//
-// Formatting routines
-//
+    FileSystem = GetFileSystemByName(FileSystemName);
 
-BOOLEAN
-PreparePartitionForFormatting(
-    IN struct _PARTENTRY* PartEntry,
-    IN PFILE_SYSTEM FileSystem)
+    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)
 {
-    if (!FileSystem)
+    PFILE_SYSTEM FileSystem;
+
+    FileSystem = GetFileSystemByName(FileSystemName);
+
+    if (!FileSystem || !FileSystem->FormatFunc)
     {
-        DPRINT1("No file system specified?\n");
-        return FALSE;
+        // BOOLEAN Argument = FALSE;
+        // Callback(DONE, 0, &Argument);
+        return STATUS_NOT_SUPPORTED;
     }
 
-    if (wcscmp(FileSystem->FileSystemName, L"FAT") == 0)
+    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 (PartEntry->SectorCount.QuadPart < 8192)
+        if (SectorCount->QuadPart < 8192)
         {
             /* FAT12 CHS partition (disk is smaller than 4.1MB) */
-            SetPartitionType(PartEntry, PARTITION_FAT_12);
+            return PARTITION_FAT_12;
         }
-        else if (PartEntry->StartSector.QuadPart < 1450560)
+        else if (StartSector->QuadPart < 1450560)
         {
             /* Partition starts below the 8.4GB boundary ==> CHS partition */
 
-            if (PartEntry->SectorCount.QuadPart < 65536)
+            if (SectorCount->QuadPart < 65536)
             {
                 /* FAT16 CHS partition (partition size < 32MB) */
-                SetPartitionType(PartEntry, PARTITION_FAT_16);
+                return PARTITION_FAT_16;
             }
-            else if (PartEntry->SectorCount.QuadPart < 1048576)
+            else if (SectorCount->QuadPart < 1048576)
             {
                 /* FAT16 CHS partition (partition size < 512MB) */
-                SetPartitionType(PartEntry, PARTITION_HUGE);
+                return PARTITION_HUGE;
             }
             else
             {
                 /* FAT32 CHS partition (partition size >= 512MB) */
-                SetPartitionType(PartEntry, PARTITION_FAT32);
+                return PARTITION_FAT32;
             }
         }
         else
         {
             /* Partition starts above the 8.4GB boundary ==> LBA partition */
 
-            if (PartEntry->SectorCount.QuadPart < 1048576)
+            if (SectorCount->QuadPart < 1048576)
             {
                 /* FAT16 LBA partition (partition size < 512MB) */
-                SetPartitionType(PartEntry, PARTITION_XINT13);
+                return PARTITION_XINT13;
             }
             else
             {
                 /* FAT32 LBA partition (partition size >= 512MB) */
-                SetPartitionType(PartEntry, PARTITION_FAT32_XINT13);
+                return PARTITION_FAT32_XINT13;
             }
         }
     }
-    else if (wcscmp(FileSystem->FileSystemName, L"BTRFS") == 0)
+    else if (wcsicmp(FileSystem, L"NTFS") == 0)
     {
-        SetPartitionType(PartEntry, PARTITION_LINUX);
+        return PARTITION_IFS;
     }
-#if 0
-    else if (wcscmp(FileSystem->FileSystemName, L"EXT2") == 0)
+    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)
     {
-        SetPartitionType(PartEntry, PARTITION_LINUX);
+        return PARTITION_LINUX;
     }
-    else if (wcscmp(FileSystem->FileSystemName, L"NTFS") == 0)
+    else
     {
-        SetPartitionType(PartEntry, PARTITION_IFS);
+        /* Unknown file system */
+        DPRINT1("Unknown file system '%S'\n", FileSystem);
+        return PARTITION_ENTRY_UNUSED;
     }
-#endif
-    else
+}
+
+
+//
+// Formatting routines
+//
+
+BOOLEAN
+PreparePartitionForFormatting(
+    IN struct _PARTENTRY* PartEntry,
+    IN PCWSTR FileSystemName)
+{
+    UCHAR PartitionType;
+
+    if (!FileSystemName || !*FileSystemName)
+    {
+        DPRINT1("No file system specified?\n");
+        return FALSE;
+    }
+
+    PartitionType = FileSystemToPartitionType(FileSystemName,
+                                              &PartEntry->StartSector,
+                                              &PartEntry->SectorCount);
+    if (PartitionType == PARTITION_ENTRY_UNUSED)
     {
-        /* Unknown file system? */
-        DPRINT1("Unknown file system \"%S\"?\n", FileSystem->FileSystemName);
+        /* Unknown file system */
+        DPRINT1("Unknown file system '%S'\n", FileSystemName);
         return FALSE;
     }
 
+    SetPartitionType(PartEntry, PartitionType);
+
 //
 // FIXME: Do this now, or after the partition was actually formatted??
 //
     /* 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)
-    PartEntry->FileSystem  = FileSystem;
+    RtlStringCbCopyW(PartEntry->FileSystem,
+                     sizeof(PartEntry->FileSystem),
+                     FileSystemName);
 
     return TRUE;
 }
index bb10c4a..f6c83e9 100644 (file)
  * PROJECT:     ReactOS Setup Library
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * PURPOSE:     Filesystem support functions
- * COPYRIGHT:   Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
- *              Copyright 2017-2018 Hermes Belusca-Maito
+ * COPYRIGHT:   Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Copyright 2017-2019 Hermes Belusca-Maito
  */
 
 #pragma once
 
 #include <fmifs/fmifs.h>
 
-typedef struct _FILE_SYSTEM
-{
-    PCWSTR FileSystemName;
-    FORMATEX FormatFunc;
-    CHKDSKEX ChkdskFunc;
-} FILE_SYSTEM, *PFILE_SYSTEM;
+/** QueryAvailableFileSystemFormat() **/
+BOOLEAN
+GetRegisteredFileSystems(
+    IN ULONG Index,
+    OUT PCWSTR* FileSystemName);
 
-PFILE_SYSTEM
-GetRegisteredFileSystems(OUT PULONG Count);
+NTSTATUS
+GetFileSystemNameByHandle(
+    IN HANDLE PartitionHandle,
+    IN OUT PWSTR FileSystemName,
+    IN SIZE_T FileSystemNameSize);
 
-PFILE_SYSTEM
-GetFileSystemByName(
-    // IN PFILE_SYSTEM_LIST List,
-    IN PCWSTR FileSystemName);
+NTSTATUS
+GetFileSystemName_UStr(
+    IN PUNICODE_STRING PartitionPath,
+    IN OUT PWSTR FileSystemName,
+    IN SIZE_T FileSystemNameSize);
 
-struct _PARTENTRY; // Defined in partlist.h
+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);
 
-PFILE_SYSTEM
-GetFileSystem(
-    // IN PFILE_SYSTEM_LIST FileSystemList,
-    IN struct _PARTENTRY* PartEntry);
 
+/** 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
 
 BOOLEAN
 PreparePartitionForFormatting(
     IN struct _PARTENTRY* PartEntry,
-    IN PFILE_SYSTEM FileSystem);
+    IN PCWSTR FileSystemName);
 
 /* EOF */
index aee3c3c..5c20c4b 100644 (file)
@@ -2,7 +2,8 @@
  * PROJECT:     ReactOS Setup Library
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * 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"
@@ -752,18 +753,19 @@ CreateInsertBlankRegion(
 
     NewPartEntry->DiskEntry = DiskEntry;
 
-    NewPartEntry->IsPartitioned = FALSE;
-    NewPartEntry->FormatState = Unformatted;
-    NewPartEntry->FileSystem  = NULL;
-
     NewPartEntry->StartSector.QuadPart = StartSector;
     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("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
     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);
 
     return NewPartEntry;
@@ -788,17 +790,8 @@ InitializePartitionEntry(
     {
         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->AutoCreate = AutoCreate;
     }
     else
     {
@@ -811,28 +804,32 @@ InitializePartitionEntry(
         if (NewPartEntry == NULL)
             return NULL;
 
-        /* Insert the new entry into the list */
-        InsertTailList(&PartEntry->ListEntry,
-                       &NewPartEntry->ListEntry);
-
         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->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
                                              NewPartEntry->StartSector.QuadPart;
 
         PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.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("Last Sector  : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
     DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
@@ -852,10 +849,10 @@ AddPartitionToDisk(
     NTSTATUS Status;
     PPARTITION_INFORMATION PartitionInfo;
     PPARTENTRY PartEntry;
-    HANDLE FileHandle;
+    HANDLE PartitionHandle;
     OBJECT_ATTRIBUTES ObjectAttributes;
     IO_STATUS_BLOCK IoStatusBlock;
-    WCHAR Buffer[MAX_PATH];
+    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;
@@ -889,10 +886,16 @@ AddPartitionToDisk(
     PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
     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))
     {
         PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
 
         if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
             DiskEntry->ExtendedPartition = PartEntry;
@@ -901,67 +904,81 @@ AddPartitionToDisk(
     {
         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;
-    }
+        /* Open the volume, ignore any errors */
+        RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                            L"\\Device\\Harddisk%lu\\Partition%lu",
+                            DiskEntry->DiskNumber,
+                            PartEntry->PartitionNumber);
+        RtlInitUnicodeString(&Name, PathBuffer);
 
-    /* Initialize the partition volume label */
-    RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
-
-    /* Open the volume, ignore any errors */
-    RtlStringCchPrintfW(Buffer, ARRAYSIZE(Buffer),
-                        L"\\Device\\Harddisk%lu\\Partition%lu",
-                        DiskEntry->DiskNumber,
-                        PartEntry->PartitionNumber);
-    RtlInitUnicodeString(&Name, Buffer);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &Name,
+                                   OBJ_CASE_INSENSITIVE,
+                                   NULL,
+                                   NULL);
 
-    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);
+        }
 
-    Status = NtOpenFile(&FileHandle,
-                        FILE_READ_DATA | SYNCHRONIZE,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        FILE_SYNCHRONOUS_IO_NONALERT);
-    if (NT_SUCCESS(Status))
-    {
-        /* Retrieve the partition volume label */
-        Status = NtQueryVolumeInformationFile(FileHandle,
-                                              &IoStatusBlock,
-                                              &LabelBuffer,
-                                              sizeof(LabelBuffer),
-                                              FileFsVolumeInformation);
-        /* Close the handle */
-        NtClose(FileHandle);
-
-        /* Check for success */
-        if (NT_SUCCESS(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)
         {
-            /* Copy the (possibly truncated) volume label and NULL-terminate it */
-            RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
-                              LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
+            if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
+                PartEntry->FormatState = Unformatted;
+            else
+                PartEntry->FormatState = Preformatted;
         }
         else
         {
-            DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
+            PartEntry->FormatState = UnknownFormat;
+        }
+
+        /* Retrieve the partition volume label */
+        if (PartitionHandle)
+        {
+            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);
+            }
         }
+
+        /* Close the partition */
+        if (PartitionHandle)
+            NtClose(PartitionHandle);
     }
     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);
@@ -2784,7 +2801,7 @@ DismountVolume(
         IsContainerPartition(PartEntry->PartitionType)     ||
         !IsRecognizedPartition(PartEntry->PartitionType)   ||
         PartEntry->FormatState == Unformatted /* || PartEntry->FormatState == UnknownFormat */ ||
-        PartEntry->FileSystem == NULL ||
+        !*PartEntry->FileSystem ||
         PartEntry->PartitionNumber == 0)
     {
         /* The partition is not mounted, so just return success */
@@ -2981,7 +2998,7 @@ DeleteCurrentPartition(
         PartEntry->IsPartitioned = FALSE;
         PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
         PartEntry->FormatState = Unformatted;
-        PartEntry->FileSystem  = NULL;
+        PartEntry->FileSystem[0] = L'\0';
         PartEntry->DriveLetter = 0;
         PartEntry->OnDiskPartitionNumber = 0;
         PartEntry->PartitionNumber = 0;
@@ -2993,6 +3010,84 @@ DeleteCurrentPartition(
     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
 CheckActiveSystemPartition(
     IN PPARTLIST List)
@@ -3001,8 +3096,6 @@ CheckActiveSystemPartition(
     PPARTENTRY PartEntry;
     PLIST_ENTRY ListEntry;
 
-    PFILE_SYSTEM FileSystem;
-
     /* Check for empty disk list */
     if (IsListEmpty(&List->DiskListHead))
     {
@@ -3154,36 +3247,9 @@ CheckActiveSystemPartition(
     /* Save it */
     List->OriginalSystemPartition = List->SystemPartition;
 
-    /*
-     * 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.
-     */
-    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)
+    /* If we get a candidate active partition, validate it */
+    if (!IsSupportedActivePartition(List->OriginalSystemPartition))
     {
-        DPRINT1("Recognized file system %S that doesn't support write support yet!\n",
-                FileSystem->FileSystemName);
         goto FindAndUseAlternativeSystemPartition;
     }
 
index a27454b..57873a4 100644 (file)
@@ -2,7 +2,8 @@
  * PROJECT:     ReactOS Setup Library
  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
  * 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
@@ -30,8 +31,6 @@ typedef enum _FORMATSTATE
     Formatted
 } FORMATSTATE, *PFORMATSTATE;
 
-struct _FILE_SYSTEM;
-
 typedef struct _PARTENTRY
 {
     LIST_ENTRY ListEntry;
@@ -52,13 +51,16 @@ typedef struct _PARTENTRY
 
     WCHAR DriveLetter;
     WCHAR VolumeLabel[20];
-    // CHAR FileSystemName[9];  // NOTE: Superseded by the FileSystem member
+    WCHAR FileSystem[MAX_PATH+1];
+    FORMATSTATE FormatState;
 
     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;
 
@@ -68,9 +70,6 @@ typedef struct _PARTENTRY
     /* Partition must be checked */
     BOOLEAN NeedsCheck;
 
-    FORMATSTATE FormatState;
-    struct _FILE_SYSTEM* FileSystem;
-
 } PARTENTRY, *PPARTENTRY;
 
 
index 26f9b79..615e702 100644 (file)
@@ -56,14 +56,9 @@ ChkdskCallback(
 NTSTATUS
 ChkdskPartition(
     IN PUNICODE_STRING DriveRoot,
-    /*IN PFILE_SYSTEM_ITEM FileSystemItem*/
-    IN PFILE_SYSTEM FileSystem)
+    IN PCWSTR FileSystemName)
 {
     NTSTATUS Status;
-    // PFILE_SYSTEM FileSystem = FileSystemItem->FileSystem;
-
-    if (!FileSystem || !FileSystem->ChkdskFunc)
-        return STATUS_NOT_SUPPORTED;
 
     ChkdskProgressBar = CreateProgressBar(6,
                                           yScreen - 14,
@@ -76,12 +71,13 @@ ChkdskPartition(
 
     ProgressSetStepCount(ChkdskProgressBar, 100);
 
-    Status = FileSystem->ChkdskFunc(DriveRoot,
-                                    TRUE,            /* FixErrors */
-                                    FALSE,           /* Verbose */
-                                    TRUE,            /* CheckOnlyIfDirty */
-                                    FALSE,           /* ScanDrive */
-                                    ChkdskCallback); /* Callback */
+    Status = ChkdskFileSystem_UStr(DriveRoot,
+                                   FileSystemName,
+                                   TRUE,            /* FixErrors */
+                                   FALSE,           /* Verbose */
+                                   TRUE,            /* CheckOnlyIfDirty */
+                                   FALSE,           /* ScanDrive */
+                                   ChkdskCallback); /* Callback */
 
     DestroyProgressBar(ChkdskProgressBar);
     ChkdskProgressBar = NULL;
index 0eb2bed..3207d2f 100644 (file)
@@ -28,7 +28,6 @@
 NTSTATUS
 ChkdskPartition(
     IN PUNICODE_STRING DriveRoot,
-    /*IN PFILE_SYSTEM_ITEM FileSystemItem*/
-    IN PFILE_SYSTEM FileSystem);
+    IN PCWSTR FileSystemName);
 
 /* EOF */
index db8c14d..08e029c 100644 (file)
@@ -88,13 +88,10 @@ FormatCallback(
 NTSTATUS
 FormatPartition(
     IN PUNICODE_STRING DriveRoot,
-    IN PFILE_SYSTEM_ITEM FileSystemItem)
+    IN PCWSTR FileSystemName,
+    IN BOOLEAN QuickFormat)
 {
     NTSTATUS Status;
-    PFILE_SYSTEM FileSystem = FileSystemItem->FileSystem;
-
-    if (!FileSystem || !FileSystem->FormatFunc)
-        return STATUS_NOT_SUPPORTED;
 
     FormatProgressBar = CreateProgressBar(6,
                                           yScreen - 14,
@@ -107,12 +104,13 @@ FormatPartition(
 
     ProgressSetStepCount(FormatProgressBar, 100);
 
-    Status = FileSystem->FormatFunc(DriveRoot,
-                                    FMIFS_HARDDISK,              /* MediaFlag */
-                                    NULL,                        /* Label */
-                                    FileSystemItem->QuickFormat, /* QuickFormat */
-                                    0,                           /* ClusterSize */
-                                    FormatCallback);             /* Callback */
+    Status = FormatFileSystem_UStr(DriveRoot,
+                                   FileSystemName,
+                                   FMIFS_HARDDISK,  /* MediaFlag */
+                                   NULL,            /* Label */
+                                   QuickFormat,     /* QuickFormat */
+                                   0,               /* ClusterSize */
+                                   FormatCallback); /* Callback */
 
     DestroyProgressBar(FormatProgressBar);
     FormatProgressBar = NULL;
index 3032f49..b84ae57 100644 (file)
@@ -29,6 +29,7 @@
 NTSTATUS
 FormatPartition(
     IN PUNICODE_STRING DriveRoot,
-    IN PFILE_SYSTEM_ITEM FileSystemItem);
+    IN PCWSTR FileSystemName,
+    IN BOOLEAN QuickFormat);
 
 /* EOF */
index 6aa8c4e..75c9fbf 100644 (file)
@@ -34,8 +34,7 @@
 static VOID
 AddProvider(
     IN OUT PFILE_SYSTEM_LIST List,
-    IN PCWSTR FileSystemName, // Redundant, I need to check whether this is reaaaaally needed....
-    IN PFILE_SYSTEM FileSystem)
+    IN PCWSTR FileSystem)
 {
     PFILE_SYSTEM_ITEM Item;
 
@@ -43,7 +42,6 @@ AddProvider(
     if (!Item)
         return;
 
-    Item->FileSystemName = FileSystemName;
     Item->FileSystem = FileSystem;
     Item->QuickFormat = TRUE;
     InsertTailList(&List->ListHead, &Item->ListEntry);
@@ -55,7 +53,6 @@ AddProvider(
     if (!Item)
         return;
 
-    Item->FileSystemName = FileSystemName;
     Item->FileSystem = FileSystem;
     Item->QuickFormat = FALSE;
     InsertTailList(&List->ListHead, &Item->ListEntry);
@@ -63,19 +60,21 @@ AddProvider(
 
 static VOID
 InitializeFileSystemList(
-    IN PFILE_SYSTEM_LIST List)
+    IN PFILE_SYSTEM_LIST List,
+    IN BOOLEAN ForceFormat)
 {
-    ULONG Count;
-    PFILE_SYSTEM FileSystems;
+    ULONG Index = 0;
+    PCWSTR FileSystemName;
 
-    FileSystems = GetRegisteredFileSystems(&Count);
-    if (!FileSystems || Count == 0)
-        return;
+    while (GetRegisteredFileSystems(Index++, &FileSystemName))
+    {
+        AddProvider(List, FileSystemName);
+    }
 
-    while (Count--)
+    if (!ForceFormat)
     {
-        AddProvider(List, FileSystems->FileSystemName, FileSystems);
-        ++FileSystems;
+        /* Add the 'Keep existing filesystem' dummy provider */
+        AddProvider(List, NULL);
     }
 }
 
@@ -99,19 +98,14 @@ CreateFileSystemList(
     List->Selected = NULL;
     InitializeListHead(&List->ListHead);
 
-    InitializeFileSystemList(List);
-    if (!ForceFormat)
-    {
-        /* Add the 'Keep existing filesystem' dummy provider */
-        AddProvider(List, NULL, NULL);
-    }
+    InitializeFileSystemList(List, ForceFormat);
 
     /* Search for SelectFileSystem in list */
     ListEntry = List->ListHead.Flink;
     while (ListEntry != &List->ListHead)
     {
         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;
             break;
@@ -171,12 +165,12 @@ DrawFileSystemList(
                                     coPos,
                                     &Written);
 
-        if (Item->FileSystemName)
+        if (Item->FileSystem)
         {
-            if (Item->QuickFormat)
-                snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK1), Item->FileSystemName);
-            else
-                snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK2), Item->FileSystemName);
+            snprintf(Buffer, sizeof(Buffer),
+                     MUIGetString(Item->QuickFormat ? STRING_FORMATDISK1
+                                                    : STRING_FORMATDISK2),
+                     Item->FileSystem);
         }
         else
         {
@@ -184,13 +178,17 @@ DrawFileSystemList(
         }
 
         if (ListEntry == &List->Selected->ListEntry)
+        {
             CONSOLE_SetInvertedTextXY(List->Left,
                                       List->Top + (SHORT)Index,
                                       Buffer);
+        }
         else
+        {
             CONSOLE_SetTextXY(List->Left,
                               List->Top + (SHORT)Index,
                               Buffer);
+        }
         Index++;
         ListEntry = ListEntry->Flink;
     }
index d5f8b4c..fc4a8b2 100644 (file)
@@ -16,7 +16,8 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-/* COPYRIGHT:       See COPYING in the top level directory
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS text-mode setup
  * FILE:            base/setup/usetup/fslist.h
  * PURPOSE:         Filesystem list functions
@@ -30,8 +31,7 @@
 typedef struct _FILE_SYSTEM_ITEM
 {
     LIST_ENTRY ListEntry;
-    PCWSTR FileSystemName; /* Not owned by the item */ // Redundant, I need to check whether this is reaaaaally needed....
-    PFILE_SYSTEM FileSystem;
+    PCWSTR FileSystem;
     BOOLEAN QuickFormat;
 } FILE_SYSTEM_ITEM, *PFILE_SYSTEM_ITEM;
 
index f10effd..b8df7c9 100644 (file)
@@ -22,7 +22,7 @@
  * FILE:            base/setup/usetup/usetup.c
  * PURPOSE:         Text-mode setup
  * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
- *                  Hervé Poussineau (hpoussin@reactos.org)
+ *                  Hervé Poussineau (hpoussin@reactos.org)
  */
 
 #include <usetup.h>
@@ -3071,7 +3071,8 @@ FormatPartitionPage(PINPUT_RECORD Ir)
             if (SelectedFileSystem->FileSystem)
             {
                 Status = FormatPartition(&PartitionRootPath,
-                                         SelectedFileSystem);
+                                         SelectedFileSystem->FileSystem,
+                                         SelectedFileSystem->QuickFormat);
                 if (Status == STATUS_NOT_SUPPORTED)
                 {
                     sprintf(Buffer,
@@ -3079,7 +3080,7 @@ FormatPartitionPage(PINPUT_RECORD Ir)
                             "\n"
                             "  \x07  Press ENTER to continue Setup.\n"
                             "  \x07  Press F3 to quit Setup.",
-                            SelectedFileSystem->FileSystem->FileSystemName);
+                            SelectedFileSystem->FileSystem);
 
                     PopupError(Buffer,
                                MUIGetString(STRING_QUITCONTINUE),
@@ -3147,7 +3148,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
     NTSTATUS Status;
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    PFILE_SYSTEM CurrentFileSystem;
     UNICODE_STRING PartitionRootPath;
     WCHAR PathBuffer[MAX_PATH];
     CHAR Buffer[MAX_PATH];
@@ -3163,38 +3163,44 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
         return INSTALL_DIRECTORY_PAGE;
     }
 
-    /* Set PartitionRootPath */
-    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
-            L"\\Device\\Harddisk%lu\\Partition%lu",
-            DiskEntry->DiskNumber,
-            PartEntry->PartitionNumber);
-    RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
-    DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
-
     CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-    CurrentFileSystem = PartEntry->FileSystem;
-    DPRINT1("CheckFileSystemPage -- PartitionType: 0x%02X ; FileSystemName: %S\n",
-            PartEntry->PartitionType, (CurrentFileSystem ? CurrentFileSystem->FileSystemName : L"n/a"));
+    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 (CurrentFileSystem == NULL)
+    if (!*PartEntry->FileSystem)
     {
         PartEntry->NeedsCheck = FALSE;
         return CHECK_FILE_SYSTEM_PAGE;
     }
 
-    Status = ChkdskPartition(&PartitionRootPath, CurrentFileSystem);
+    /* Set PartitionRootPath */
+    RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+            L"\\Device\\Harddisk%lu\\Partition%lu",
+            DiskEntry->DiskNumber,
+            PartEntry->PartitionNumber);
+    RtlInitUnicodeString(&PartitionRootPath, PathBuffer);
+    DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath);
+
+    /* Check the partition */
+    Status = ChkdskPartition(&PartitionRootPath, PartEntry->FileSystem);
     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,
                 "Setup is currently unable to check a partition formatted in %S.\n"
                 "\n"
                 "  \x07  Press ENTER to continue Setup.\n"
                 "  \x07  Press F3 to quit Setup.",
-                CurrentFileSystem->FileSystemName);
+                PartEntry->FileSystem);
 
         PopupError(Buffer,
                    MUIGetString(STRING_QUITCONTINUE),
@@ -4204,7 +4210,7 @@ BootLoaderHarddiskVbrPage(PINPUT_RECORD Ir)
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem->FileSystemName);
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }
 
@@ -4241,7 +4247,7 @@ BootLoaderHarddiskMbrPage(PINPUT_RECORD Ir)
     if (!NT_SUCCESS(Status))
     {
         MUIDisplayError(ERROR_WRITE_BOOT, Ir, POPUP_WAIT_ENTER,
-                        PartitionList->SystemPartition->FileSystem->FileSystemName);
+                        PartitionList->SystemPartition->FileSystem);
         return QUIT_PAGE;
     }