/* * PROJECT: ReactOS Setup Library * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Filesystem support functions * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net) * Copyright 2017-2019 Hermes Belusca-Maito */ // // See also: https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/dll/win32/fmifs/init.c;h=e895f5ef9cae4806123f6bbdd3dfed37ec1c8d33;hb=b9db9a4e377a2055f635b2fb69fef4e1750d219c // for how to get FS providers in a dynamic way. In the (near) future we may // consider merging some of this code with us into a fmifs / fsutil / fslib library... // /* INCLUDES *****************************************************************/ #include "precomp.h" #include "partlist.h" #include "fsrec.h" #include "fsutil.h" #include #include // #include // #include #define NDEBUG #include /* 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 */ static FILE_SYSTEM RegisteredFileSystems[] = { /* NOTE: The FAT formatter automatically determines * whether it will use FAT-16 or FAT-32. */ { L"FAT" , VfatFormat, VfatChkdsk }, #if 0 { L"FAT32", VfatFormat, VfatChkdsk }, // Do we support specific FAT sub-formats specifications? { L"FATX" , VfatxFormat, VfatxChkdsk }, { L"NTFS" , NtfsFormat, NtfsChkdsk }, #endif { L"BTRFS", BtrfsFormatEx, BtrfsChkdskEx }, #if 0 { L"EXT2" , Ext2Format, Ext2Chkdsk }, { L"EXT3" , Ext2Format, Ext2Chkdsk }, { L"EXT4" , Ext2Format, Ext2Chkdsk }, { L"FFS" , FfsFormat , FfsChkdsk }, { L"REISERFS", ReiserfsFormat, ReiserfsChkdsk }, #endif }; /* FUNCTIONS ****************************************************************/ /** QueryAvailableFileSystemFormat() **/ BOOLEAN GetRegisteredFileSystems( IN ULONG Index, OUT PCWSTR* FileSystemName) { if (Index >= ARRAYSIZE(RegisteredFileSystems)) return FALSE; *FileSystemName = RegisteredFileSystems[Index].FileSystemName; return TRUE; } /** GetProvider() **/ static PFILE_SYSTEM GetFileSystemByName( IN PCWSTR FileSystemName) { #if 0 // Reenable when the list of registered FSes will again be dynamic PLIST_ENTRY ListEntry; PFILE_SYSTEM_ITEM Item; ListEntry = List->ListHead.Flink; while (ListEntry != &List->ListHead) { Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry); 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 = ARRAYSIZE(RegisteredFileSystems); PFILE_SYSTEM FileSystems = RegisteredFileSystems; ASSERT(FileSystems && Count != 0); while (Count--) { 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; } #endif return NULL; } /** 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); } // // 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", 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 */ RtlStringCbCopyW(PartEntry->FileSystem, sizeof(PartEntry->FileSystem), FileSystemName); return TRUE; } /* EOF */