reactos/base/setup/usetup/fslist.c
Hermès Bélusca-Maïto 56ea51bbe4
[USETUP] Enhancements for filesystem utility functions.
- Introduce code that detects the filesystem of a (mounted?) partition, using NtQueryVolumeInformationFile() with FileFsAttributeInformation class,
  aka. rely on ReactOS itself (kernel, storage stack, filesystem drivers...) to recognize the FS on a partition that should normally be seen by the system.
  This currently half-works for whatever reason (to be insvestigated), while it works on Windows.
- Fix few comments & a function parameter name.
- Use NT string pointer types.

svn path=/branches/setup_improvements/; revision=74529
2018-05-26 19:09:38 +02:00

410 lines
12 KiB
C

/*
* ReactOS kernel
* Copyright (C) 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* 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
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/fslist.c
* PURPOSE: Filesystem list functions
* PROGRAMMER: Eric Kohl
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
VOID
AddProvider(
IN OUT PFILE_SYSTEM_LIST List,
IN PCWSTR FileSystemName,
IN FORMATEX FormatFunc,
IN CHKDSKEX ChkdskFunc)
{
PFILE_SYSTEM_ITEM Item;
Item = (PFILE_SYSTEM_ITEM)RtlAllocateHeap(ProcessHeap, 0, sizeof(FILE_SYSTEM_ITEM));
if (!Item)
return;
Item->FileSystemName = FileSystemName;
Item->FormatFunc = FormatFunc;
Item->ChkdskFunc = ChkdskFunc;
Item->QuickFormat = TRUE;
InsertTailList(&List->ListHead, &Item->ListEntry);
if (!FormatFunc)
return;
Item = (PFILE_SYSTEM_ITEM)RtlAllocateHeap(ProcessHeap, 0, sizeof(FILE_SYSTEM_ITEM));
if (!Item)
return;
Item->FileSystemName = FileSystemName;
Item->FormatFunc = FormatFunc;
Item->ChkdskFunc = ChkdskFunc;
Item->QuickFormat = FALSE;
InsertTailList(&List->ListHead, &Item->ListEntry);
}
PFILE_SYSTEM_ITEM
GetFileSystemByName(
IN PFILE_SYSTEM_LIST List,
IN PWSTR FileSystemName)
{
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;
}
return NULL;
}
#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_ITEM
GetFileSystem(
IN PFILE_SYSTEM_LIST FileSystemList,
IN struct _PARTENTRY* PartEntry)
{
PFILE_SYSTEM_ITEM 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;
}
PFILE_SYSTEM_LIST
CreateFileSystemList(
IN SHORT Left,
IN SHORT Top,
IN BOOLEAN ForceFormat,
IN PCWSTR SelectFileSystem)
{
PFILE_SYSTEM_LIST List;
PFILE_SYSTEM_ITEM Item;
PLIST_ENTRY ListEntry;
List = (PFILE_SYSTEM_LIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(FILE_SYSTEM_LIST));
if (List == NULL)
return NULL;
List->Left = Left;
List->Top = Top;
List->Selected = NULL;
InitializeListHead(&List->ListHead);
AddProvider(List, L"FAT", VfatFormat, VfatChkdsk);
#if 0
AddProvider(List, L"EXT2", Ext2Format, Ext2Chkdsk);
AddProvider(List, L"NTFS", NtfsFormat, NtfsChkdsk);
#endif
if (!ForceFormat)
{
/* Add the 'Keep existing filesystem' dummy provider */
AddProvider(List, NULL, NULL, NULL);
}
/* 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)
{
List->Selected = Item;
break;
}
ListEntry = ListEntry->Flink;
}
if (!List->Selected)
List->Selected = CONTAINING_RECORD(List->ListHead.Flink, FILE_SYSTEM_ITEM, ListEntry);
return List;
}
VOID
DestroyFileSystemList(
IN PFILE_SYSTEM_LIST List)
{
PLIST_ENTRY ListEntry = List->ListHead.Flink;
PFILE_SYSTEM_ITEM Item;
PLIST_ENTRY Next;
while (ListEntry != &List->ListHead)
{
Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry);
Next = ListEntry->Flink;
RtlFreeHeap(ProcessHeap, 0, Item);
ListEntry = Next;
}
RtlFreeHeap(ProcessHeap, 0, List);
}
VOID
DrawFileSystemList(
IN PFILE_SYSTEM_LIST List)
{
PLIST_ENTRY ListEntry;
PFILE_SYSTEM_ITEM Item;
COORD coPos;
DWORD Written;
ULONG Index = 0;
CHAR Buffer[128];
ListEntry = List->ListHead.Flink;
while (ListEntry != &List->ListHead)
{
Item = CONTAINING_RECORD(ListEntry, FILE_SYSTEM_ITEM, ListEntry);
coPos.X = List->Left;
coPos.Y = List->Top + (SHORT)Index;
FillConsoleOutputAttribute(StdOutput,
FOREGROUND_WHITE | BACKGROUND_BLUE,
sizeof(Buffer),
coPos,
&Written);
FillConsoleOutputCharacterA(StdOutput,
' ',
sizeof(Buffer),
coPos,
&Written);
if (Item->FileSystemName)
{
if (Item->QuickFormat)
snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK1), Item->FileSystemName);
else
snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_FORMATDISK2), Item->FileSystemName);
}
else
{
snprintf(Buffer, sizeof(Buffer), MUIGetString(STRING_KEEPFORMAT));
}
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;
}
}
VOID
ScrollDownFileSystemList(
IN PFILE_SYSTEM_LIST List)
{
if (List->Selected->ListEntry.Flink != &List->ListHead)
{
List->Selected = CONTAINING_RECORD(List->Selected->ListEntry.Flink, FILE_SYSTEM_ITEM, ListEntry);
DrawFileSystemList(List);
}
}
VOID
ScrollUpFileSystemList(
IN PFILE_SYSTEM_LIST List)
{
if (List->Selected->ListEntry.Blink != &List->ListHead)
{
List->Selected = CONTAINING_RECORD(List->Selected->ListEntry.Blink, FILE_SYSTEM_ITEM, ListEntry);
DrawFileSystemList(List);
}
}
/* EOF */