reactos/base/setup/lib/fsutil.c
Hermès Bélusca-Maïto 3a19ee6a96
[SETUPLIB][USETUP] Introduce a 'SetupLib' library. CORE-13544
- Create the beginnings of a "setuplib" library, whose aim is to be shared between the (currently existing) 1st-stage text-mode installer, and the (future) 1st-stage GUI installer.
- Finish to split the GenList and PartList codes into their UI part, which remain in usetup, and their algorithmic part, which go into setuplib.
- Move SetMountedDeviceValue into the PartList module.
- Split the FileSystem list code into its UI and the algorithmic part (which goes into setuplib under the name fsutil.c).
  * The algo part is meant to be able to manage the filesystems available on the running system, similarly to what is mostly done (in scattered form) in fmifs, format, chkdsk / autochk codes...
    It also manages the partition filesystem recognition, using OS routines.
  * The UI part manages the FS list as it appears on screen, showing only the possible FSes that can be used to format the selected partition (a bit similar to what we do in the shell32's drive.c, etc...).
- Adapt the calling code to these changes.
- Remove some "host" code that was dating back from the dark old times.

svn path=/branches/setup_improvements/; revision=74570
svn path=/branches/setup_improvements/; revision=74659
2018-05-27 20:18:50 +02:00

277 lines
8.5 KiB
C

/*
* PROJECT: ReactOS Setup Library
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Filesystem support functions
* COPYRIGHT: Copyright 2002-2018 Eric Kohl
* Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
* Copyright 2017-2018 Hermes Belusca-Maito
*/
//
// This is basically the code for listing available FileSystem providers
// (currently hardcoded in a list), and for performing a basic FileSystem
// recognition for a given disk partition.
//
// 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 "fsutil.h"
#include "partlist.h"
/** For FileSystems **/
#include <fslib/vfatlib.h>
#include <fslib/ext2lib.h>
// #include <fslib/ntfslib.h>
#define NDEBUG
#include <debug.h>
FILE_SYSTEM RegisteredFileSystems[] =
{
{ L"FAT" , VfatFormat, VfatChkdsk },
// { L"FAT32", VfatFormat, VfatChkdsk },
#if 0
{ L"EXT2" , Ext2Format, Ext2Chkdsk },
{ L"NTFS" , NtfsFormat, NtfsChkdsk }
#endif
};
/* FUNCTIONS ****************************************************************/
PFILE_SYSTEM
GetRegisteredFileSystems(OUT PULONG Count)
{
*Count = ARRAYSIZE(RegisteredFileSystems);
return RegisteredFileSystems;
}
PFILE_SYSTEM
GetFileSystemByName(
// IN PFILE_SYSTEM_LIST List,
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)
return Item;
ListEntry = ListEntry->Flink;
}
#else
ULONG Count;
PFILE_SYSTEM FileSystems;
FileSystems = GetRegisteredFileSystems(&Count);
if (!FileSystems || Count == 0)
return NULL;
while (Count--)
{
if (FileSystems->FileSystemName && wcsicmp(FileSystemName, FileSystems->FileSystemName) == 0)
return FileSystems;
++FileSystems;
}
#endif
return NULL;
}
//
// FileSystem recognition (using NT OS functionality)
//
#if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
/* NOTE: Ripped & adapted from base/system/autochk/autochk.c */
static NTSTATUS
_MyGetFileSystem(
IN struct _PARTENTRY* PartEntry,
IN OUT PWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{
NTSTATUS Status;
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatusBlock;
PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
UCHAR Buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING PartitionRootPath;
WCHAR PathBuffer[MAX_PATH];
FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
/* Set PartitionRootPath */
swprintf(PathBuffer,
// L"\\Device\\Harddisk%lu\\Partition%lu", // Should work! But because ReactOS sucks atm. it actually doesn't work!!
L"\\Device\\Harddisk%lu\\Partition%lu\\", // HACK: Use this as a temporary hack!
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,
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 */
Status = NtQueryVolumeInformationFile(FileHandle,
&IoStatusBlock,
FileFsAttribute,
sizeof(Buffer),
FileFsAttributeInformation);
NtClose(FileHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtQueryVolumeInformationFile failed for partition %wZ, Status 0x%08lx\n", &PartitionRootPath, Status);
return Status;
}
if (FileSystemNameSize * sizeof(WCHAR) < FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
return STATUS_BUFFER_TOO_SMALL;
RtlCopyMemory(FileSystemName,
FileFsAttribute->FileSystemName,
FileFsAttribute->FileSystemNameLength);
FileSystemName[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = UNICODE_NULL;
return STATUS_SUCCESS;
}
#endif
PFILE_SYSTEM
GetFileSystem(
// IN PFILE_SYSTEM_LIST FileSystemList,
IN struct _PARTENTRY* PartEntry)
{
PFILE_SYSTEM CurrentFileSystem;
PWSTR FileSystemName = NULL;
#if 0 // For code temporarily disabled below
NTSTATUS Status;
WCHAR FsRecFileSystemName[MAX_PATH];
#endif
CurrentFileSystem = PartEntry->FileSystem;
/* We have a file system, return it */
if (CurrentFileSystem != NULL && CurrentFileSystem->FileSystemName != NULL)
return CurrentFileSystem;
DPRINT1("File system not found, try to guess one...\n");
CurrentFileSystem = NULL;
#if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
/*
* We don't have one...
*
* Try to infer one using NT file system recognition.
*/
Status = _MyGetFileSystem(PartEntry, FsRecFileSystemName, ARRAYSIZE(FsRecFileSystemName));
if (NT_SUCCESS(Status) && *FsRecFileSystemName)
{
/* Temporary HACK: map FAT32 back to FAT */
if (wcscmp(FsRecFileSystemName, L"FAT32") == 0)
wcscpy(FsRecFileSystemName, L"FAT");
FileSystemName = FsRecFileSystemName;
goto Quit;
}
#endif
/*
* 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
* be formatted with different file systems: for example, usual Linux
* partitions that are formatted in EXT2/3/4, ReiserFS, etc... have the
* same partition ID 0x83.
*
* The proper fix is to make a function that detects the existing FS
* from a given partition (not based on the partition ID).
* 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))
{
FileSystemName = L"FAT";
}
else if (PartEntry->PartitionType == PARTITION_EXT2)
{
// WARNING: See the warning above.
FileSystemName = L"EXT2";
}
else if (PartEntry->PartitionType == PARTITION_IFS)
{
// WARNING: See the warning above.
FileSystemName = L"NTFS"; /* FIXME: Not quite correct! */
}
#if 0
Quit: // For code temporarily disabled above
#endif
// HACK: WARNING: We cannot write on this FS yet!
if (FileSystemName)
{
if (PartEntry->PartitionType == PARTITION_EXT2 || PartEntry->PartitionType == PARTITION_IFS)
DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName);
}
DPRINT1("GetFileSystem -- PartitionType: 0x%02X ; FileSystemName (guessed): %S\n",
PartEntry->PartitionType, FileSystemName ? FileSystemName : L"None");
if (FileSystemName != NULL)
CurrentFileSystem = GetFileSystemByName(/*FileSystemList,*/ FileSystemName);
return CurrentFileSystem;
}
/* EOF */