mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
** WIP ** Stuff of interest for partitioning / FS
- Some more work on the partition list iteration - Several fundamental changes in partition list, iterators, and split the FS volume-specific operations into its own file. The splitting of FS volume-specific functions has been motivated by what has been started in diskpart.
This commit is contained in:
parent
90aee8453f
commit
20d1797e70
9 changed files with 1231 additions and 438 deletions
|
@ -186,24 +186,13 @@ EnumerateInstallations(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the discovered NTOS installation into the list */
|
/* Add the discovered NTOS installation into the list */
|
||||||
NtOsInstall = AddNTOSInstallation(Data->List,
|
AddNTOSInstallation(Data->List,
|
||||||
BootEntry->FriendlyName,
|
BootEntry->FriendlyName,
|
||||||
Machine,
|
Machine,
|
||||||
VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
|
VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
|
||||||
Options->OsLoadPath,
|
Options->OsLoadPath,
|
||||||
&SystemRootPath, PathComponent,
|
&SystemRootPath, PathComponent,
|
||||||
DiskNumber, PartitionNumber);
|
DiskNumber, PartitionNumber);
|
||||||
if (NtOsInstall)
|
|
||||||
{
|
|
||||||
/* Retrieve the volume corresponding to the disk and partition numbers */
|
|
||||||
PPARTENTRY PartEntry = SelectPartition(Data->PartList, DiskNumber, PartitionNumber);
|
|
||||||
if (!PartEntry)
|
|
||||||
{
|
|
||||||
DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
|
|
||||||
DiskNumber, PartitionNumber);
|
|
||||||
}
|
|
||||||
NtOsInstall->Volume = (PartEntry ? PartEntry->Volume : NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Continue the enumeration */
|
/* Continue the enumeration */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
|
@ -22,7 +22,6 @@ typedef struct _NTOS_INSTALLATION
|
||||||
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
|
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
|
||||||
ULONG DiskNumber;
|
ULONG DiskNumber;
|
||||||
ULONG PartitionNumber;
|
ULONG PartitionNumber;
|
||||||
PVOLENTRY Volume; // PVOLINFO
|
|
||||||
WCHAR InstallationName[MAX_PATH];
|
WCHAR InstallationName[MAX_PATH];
|
||||||
WCHAR VendorName[MAX_PATH];
|
WCHAR VendorName[MAX_PATH];
|
||||||
// CHAR Data[ANYSIZE_ARRAY];
|
// CHAR Data[ANYSIZE_ARRAY];
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
// NOTE: They should be moved into some global header.
|
// NOTE: They should be moved into some global header.
|
||||||
|
|
||||||
|
// /* We have to define it there, because it is not in the MS DDK */
|
||||||
|
// #define PARTITION_LINUX 0x83
|
||||||
|
|
||||||
/* OEM MBR partition types recognized by NT (see [MS-DMRP] Appendix B) */
|
/* OEM MBR partition types recognized by NT (see [MS-DMRP] Appendix B) */
|
||||||
#define PARTITION_EISA 0x12 // EISA partition
|
#define PARTITION_EISA 0x12 // EISA partition
|
||||||
#define PARTITION_HIBERNATION 0x84 // Hibernation partition for laptops
|
#define PARTITION_HIBERNATION 0x84 // Hibernation partition for laptops
|
||||||
|
@ -129,8 +132,9 @@ typedef struct _DISKENTRY
|
||||||
ULONG DiskNumber;
|
ULONG DiskNumber;
|
||||||
// SCSI_ADDRESS;
|
// SCSI_ADDRESS;
|
||||||
USHORT Port;
|
USHORT Port;
|
||||||
USHORT Bus;
|
USHORT Bus; // PathId;
|
||||||
USHORT Id;
|
USHORT Id; // TargetId;
|
||||||
|
// USHORT Lun;
|
||||||
|
|
||||||
/* Has the partition list been modified? */
|
/* Has the partition list been modified? */
|
||||||
BOOLEAN Dirty;
|
BOOLEAN Dirty;
|
||||||
|
@ -258,6 +262,51 @@ RoundingDivide(
|
||||||
((DiskEntry)->SectorCount.QuadPart * (DiskEntry)->BytesPerSector)
|
((DiskEntry)->SectorCount.QuadPart * (DiskEntry)->BytesPerSector)
|
||||||
|
|
||||||
|
|
||||||
|
#define ENUM_REGION_NEXT 0x00 //< Enumerate the next region (default)
|
||||||
|
#define ENUM_REGION_PREV 0x01 //< Enumerate the previous region
|
||||||
|
#define ENUM_REGION_PARTITIONED 0x02 //< Enumerate only partitioned regions (otherwise, enumerate all regions, including free space)
|
||||||
|
// 0x04, 0x08 reserved
|
||||||
|
#define ENUM_REGION_MBR_PRIMARY_ONLY 0x10 //< MBR disks only: Enumerate only primary regions
|
||||||
|
#define ENUM_REGION_MBR_LOGICAL_ONLY 0x20 //< MBR disks only: Enumerate only logical regions
|
||||||
|
#define ENUM_REGION_MBR_BY_ORDER 0x40 //< MBR disks only: Enumerate by order on disk (may traverse extended partitions to enumerate the logical ones in-between), instead of by type (first all primary, then all logical)
|
||||||
|
/*
|
||||||
|
they are listed in actual
|
||||||
|
order of appearance on a given disk. For example for MBR disks, all
|
||||||
|
_primary_ partitions are enumerated first, before _logical_ partitions.
|
||||||
|
*/
|
||||||
|
// 0x80 reserved
|
||||||
|
|
||||||
|
PPARTENTRY
|
||||||
|
GetAdjDiskRegion(
|
||||||
|
_In_opt_ PDISKENTRY CurrentDisk,
|
||||||
|
_In_opt_ PPARTENTRY CurrentPart,
|
||||||
|
_In_ ULONG EnumFlags);
|
||||||
|
|
||||||
|
PPARTENTRY
|
||||||
|
GetAdjPartition(
|
||||||
|
_In_ PPARTLIST List,
|
||||||
|
_In_opt_ PPARTENTRY CurrentPart,
|
||||||
|
_In_ ULONG EnumFlags);
|
||||||
|
|
||||||
|
#if 0 // FIXME Temporary
|
||||||
|
PPARTENTRY
|
||||||
|
GetNextPartition(
|
||||||
|
IN PPARTLIST List,
|
||||||
|
IN PPARTENTRY CurrentPart OPTIONAL);
|
||||||
|
|
||||||
|
PPARTENTRY
|
||||||
|
GetPrevPartition(
|
||||||
|
IN PPARTLIST List,
|
||||||
|
IN PPARTENTRY CurrentPart OPTIONAL);
|
||||||
|
|
||||||
|
PPARTENTRY
|
||||||
|
GetAdjUnpartitionedEntry(
|
||||||
|
_In_ PPARTENTRY PartEntry,
|
||||||
|
_In_ BOOLEAN Direction);
|
||||||
|
#endif // FIXME Temporary
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
IsDiskSuperFloppy2(
|
IsDiskSuperFloppy2(
|
||||||
_In_ const DISK_PARTITION_INFO* DiskInfo,
|
_In_ const DISK_PARTITION_INFO* DiskInfo,
|
||||||
|
@ -322,21 +371,6 @@ SelectPartition(
|
||||||
_In_ ULONG DiskNumber,
|
_In_ ULONG DiskNumber,
|
||||||
_In_ ULONG PartitionNumber);
|
_In_ ULONG PartitionNumber);
|
||||||
|
|
||||||
PPARTENTRY
|
|
||||||
GetNextPartition(
|
|
||||||
IN PPARTLIST List,
|
|
||||||
IN PPARTENTRY CurrentPart OPTIONAL);
|
|
||||||
|
|
||||||
PPARTENTRY
|
|
||||||
GetPrevPartition(
|
|
||||||
IN PPARTLIST List,
|
|
||||||
IN PPARTENTRY CurrentPart OPTIONAL);
|
|
||||||
|
|
||||||
PPARTENTRY
|
|
||||||
GetAdjUnpartitionedEntry(
|
|
||||||
_In_ PPARTENTRY PartEntry,
|
|
||||||
_In_ BOOLEAN Direction);
|
|
||||||
|
|
||||||
ERROR_NUMBER
|
ERROR_NUMBER
|
||||||
PartitionCreationChecks(
|
PartitionCreationChecks(
|
||||||
_In_ PPARTENTRY PartEntry);
|
_In_ PPARTENTRY PartEntry);
|
||||||
|
|
|
@ -2,22 +2,261 @@
|
||||||
* PROJECT: ReactOS Setup Library
|
* PROJECT: ReactOS Setup Library
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Volume utility functions
|
* PURPOSE: Volume utility functions
|
||||||
* COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
* COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "diskpart.h"
|
||||||
|
#include <ntddscsi.h>
|
||||||
#include "volutil.h"
|
|
||||||
#include "fsrec.h"
|
|
||||||
#include "devutils.h"
|
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
|
LIST_ENTRY VolumeListHead;
|
||||||
|
|
||||||
|
/* FUNCTIONS THAT CAME FROM PARTLIST TODO USE THEM ****************************/
|
||||||
|
|
||||||
|
// AssignDriveLetters
|
||||||
|
|
||||||
|
// DetectFileSystem
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
#if 0 // FIXME
|
||||||
|
//
|
||||||
|
// FIXME: Improve
|
||||||
|
//
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
GetVolumeExtents(
|
||||||
|
_In_ HANDLE VolumeHandle,
|
||||||
|
_In_ PVOLENTRY VolumeEntry)
|
||||||
|
{
|
||||||
|
DWORD dwBytesReturned = 0, dwLength, i;
|
||||||
|
PVOLUME_DISK_EXTENTS pExtents;
|
||||||
|
BOOL bResult;
|
||||||
|
DWORD dwError;
|
||||||
|
|
||||||
|
dwLength = sizeof(VOLUME_DISK_EXTENTS);
|
||||||
|
pExtents = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, dwLength);
|
||||||
|
if (pExtents == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bResult = DeviceIoControl(VolumeHandle,
|
||||||
|
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
pExtents,
|
||||||
|
dwLength,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bResult)
|
||||||
|
{
|
||||||
|
dwError = GetLastError();
|
||||||
|
|
||||||
|
if (dwError != ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, pExtents);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwLength = sizeof(VOLUME_DISK_EXTENTS) + ((pExtents->NumberOfDiskExtents - 1) * sizeof(DISK_EXTENT));
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, pExtents);
|
||||||
|
pExtents = RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, dwLength);
|
||||||
|
if (pExtents == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bResult = DeviceIoControl(VolumeHandle,
|
||||||
|
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
pExtents,
|
||||||
|
dwLength,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bResult)
|
||||||
|
{
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, pExtents);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pExtents->NumberOfDiskExtents; i++)
|
||||||
|
VolumeEntry->Size.QuadPart += pExtents->Extents[i].ExtentLength.QuadPart;
|
||||||
|
|
||||||
|
VolumeEntry->pExtents = pExtents;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: Improve
|
||||||
|
//
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
GetVolumeType(
|
||||||
|
_In_ HANDLE VolumeHandle,
|
||||||
|
_In_ PVOLENTRY VolumeEntry)
|
||||||
|
{
|
||||||
|
FILE_FS_DEVICE_INFORMATION DeviceInfo;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = NtQueryVolumeInformationFile(VolumeHandle,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&DeviceInfo,
|
||||||
|
sizeof(FILE_FS_DEVICE_INFORMATION),
|
||||||
|
FileFsDeviceInformation);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (DeviceInfo.DeviceType)
|
||||||
|
{
|
||||||
|
case FILE_DEVICE_CD_ROM:
|
||||||
|
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
|
||||||
|
VolumeEntry->VolumeType = VOLUME_TYPE_CDROM;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_DEVICE_DISK:
|
||||||
|
case FILE_DEVICE_DISK_FILE_SYSTEM:
|
||||||
|
if (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)
|
||||||
|
VolumeEntry->VolumeType = VOLUME_TYPE_REMOVABLE;
|
||||||
|
else
|
||||||
|
VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
VolumeEntry->VolumeType = VOLUME_TYPE_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: Improve
|
||||||
|
//
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
AddVolumeToList(
|
||||||
|
ULONG ulVolumeNumber,
|
||||||
|
PWSTR pszVolumeName)
|
||||||
|
{
|
||||||
|
PVOLENTRY VolumeEntry;
|
||||||
|
HANDLE VolumeHandle;
|
||||||
|
|
||||||
|
DWORD dwError, dwLength;
|
||||||
|
WCHAR szPathNames[MAX_PATH + 1];
|
||||||
|
WCHAR szVolumeName[MAX_PATH + 1];
|
||||||
|
WCHAR szFilesystem[MAX_PATH + 1];
|
||||||
|
|
||||||
|
DWORD CharCount = 0;
|
||||||
|
size_t Index = 0;
|
||||||
|
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
UNICODE_STRING Name;
|
||||||
|
IO_STATUS_BLOCK Iosb;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("AddVolumeToList(%S)\n", pszVolumeName);
|
||||||
|
|
||||||
|
VolumeEntry = RtlAllocateHeap(ProcessHeap,
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
sizeof(VOLENTRY));
|
||||||
|
if (VolumeEntry == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VolumeEntry->VolumeNumber = ulVolumeNumber;
|
||||||
|
wcscpy(VolumeEntry->VolumeName, pszVolumeName);
|
||||||
|
|
||||||
|
Index = wcslen(pszVolumeName) - 1;
|
||||||
|
|
||||||
|
pszVolumeName[Index] = L'\0';
|
||||||
|
|
||||||
|
CharCount = QueryDosDeviceW(&pszVolumeName[4], VolumeEntry->DeviceName, ARRAYSIZE(VolumeEntry->DeviceName));
|
||||||
|
|
||||||
|
pszVolumeName[Index] = L'\\';
|
||||||
|
|
||||||
|
if (CharCount == 0)
|
||||||
|
{
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&Name, VolumeEntry->DeviceName);
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&Name,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = NtOpenFile(&VolumeHandle,
|
||||||
|
SYNCHRONIZE,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&Iosb,
|
||||||
|
0,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
GetVolumeType(VolumeHandle, VolumeEntry);
|
||||||
|
GetVolumeExtents(VolumeHandle, VolumeEntry);
|
||||||
|
NtClose(VolumeHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetVolumeInformationW(pszVolumeName,
|
||||||
|
szVolumeName,
|
||||||
|
MAX_PATH + 1,
|
||||||
|
NULL, // [out, optional] LPDWORD lpVolumeSerialNumber,
|
||||||
|
NULL, // [out, optional] LPDWORD lpMaximumComponentLength,
|
||||||
|
NULL, // [out, optional] LPDWORD lpFileSystemFlags,
|
||||||
|
szFilesystem,
|
||||||
|
MAX_PATH + 1))
|
||||||
|
{
|
||||||
|
VolumeEntry->pszLabel = RtlAllocateHeap(ProcessHeap,
|
||||||
|
0,
|
||||||
|
(wcslen(szVolumeName) + 1) * sizeof(WCHAR));
|
||||||
|
if (VolumeEntry->pszLabel)
|
||||||
|
wcscpy(VolumeEntry->pszLabel, szVolumeName);
|
||||||
|
|
||||||
|
VolumeEntry->pszFilesystem = RtlAllocateHeap(ProcessHeap,
|
||||||
|
0,
|
||||||
|
(wcslen(szFilesystem) + 1) * sizeof(WCHAR));
|
||||||
|
if (VolumeEntry->pszFilesystem)
|
||||||
|
wcscpy(VolumeEntry->pszFilesystem, szFilesystem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwError = GetLastError();
|
||||||
|
if (dwError == ERROR_UNRECOGNIZED_VOLUME)
|
||||||
|
{
|
||||||
|
VolumeEntry->pszFilesystem = RtlAllocateHeap(ProcessHeap,
|
||||||
|
0,
|
||||||
|
(3 + 1) * sizeof(WCHAR));
|
||||||
|
if (VolumeEntry->pszFilesystem)
|
||||||
|
wcscpy(VolumeEntry->pszFilesystem, L"RAW");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetVolumePathNamesForVolumeNameW(pszVolumeName,
|
||||||
|
szPathNames,
|
||||||
|
ARRAYSIZE(szPathNames),
|
||||||
|
&dwLength))
|
||||||
|
{
|
||||||
|
VolumeEntry->DriveLetter = szPathNames[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertTailList(&VolumeListHead,
|
||||||
|
&VolumeEntry->ListEntry);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MountVolume(
|
MountVolume(
|
||||||
|
@ -25,11 +264,36 @@ MountVolume(
|
||||||
_In_opt_ UCHAR MbrPartitionType)
|
_In_opt_ UCHAR MbrPartitionType)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
UNICODE_STRING Name;
|
||||||
HANDLE VolumeHandle;
|
HANDLE VolumeHandle;
|
||||||
|
|
||||||
/* If the volume is already mounted, just return success */
|
#if 0
|
||||||
if (*Volume->FileSystem)
|
/* Reset some volume information */
|
||||||
|
Volume->DriveLetter = L'\0';
|
||||||
|
Volume->FileSystem[0] = L'\0';
|
||||||
|
RtlZeroMemory(Volume->VolumeLabel, sizeof(Volume->VolumeLabel));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Specify the partition as initially unformatted */
|
||||||
|
Volume->FileSystem[0] = L'\0';
|
||||||
|
|
||||||
|
/* Initialize the partition volume label */
|
||||||
|
RtlZeroMemory(Volume->VolumeLabel, sizeof(Volume->VolumeLabel));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (!IsRecognizedPartition(MbrPartitionType))
|
||||||
|
{
|
||||||
|
/* Unknown partition, hence unknown format (may or may not be actually formatted) */
|
||||||
|
Volume->FormatState = UnknownFormat;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!*Volume->DeviceName)
|
||||||
|
{
|
||||||
|
/* No volume attached, bail out */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Try to open the volume so as to mount it */
|
/* Try to open the volume so as to mount it */
|
||||||
VolumeHandle = NULL;
|
VolumeHandle = NULL;
|
||||||
|
@ -47,7 +311,7 @@ MountVolume(
|
||||||
}
|
}
|
||||||
ASSERT(VolumeHandle);
|
ASSERT(VolumeHandle);
|
||||||
|
|
||||||
/* We don't have a FS, try to guess one */
|
/* Try to guess the mounted FS */
|
||||||
Status = InferFileSystem(NULL, VolumeHandle,
|
Status = InferFileSystem(NULL, VolumeHandle,
|
||||||
Volume->FileSystem,
|
Volume->FileSystem,
|
||||||
sizeof(Volume->FileSystem));
|
sizeof(Volume->FileSystem));
|
||||||
|
@ -158,7 +422,7 @@ DismountVolume(
|
||||||
HANDLE VolumeHandle;
|
HANDLE VolumeHandle;
|
||||||
|
|
||||||
/* If the volume is not mounted, just return success */
|
/* If the volume is not mounted, just return success */
|
||||||
if (!*Volume->FileSystem)
|
if (!*Volume->DeviceName || !*Volume->FileSystem)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
/* Open the volume */
|
/* Open the volume */
|
||||||
|
@ -223,4 +487,160 @@ DismountVolume(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: Improve; for the moment a temporary function is written below.
|
||||||
|
//
|
||||||
|
#if 0
|
||||||
|
NTSTATUS
|
||||||
|
CreateVolumeList(
|
||||||
|
_Out_ PLIST_ENTRY VolumeListHead)
|
||||||
|
{
|
||||||
|
BOOL Success;
|
||||||
|
HANDLE hVolume = INVALID_HANDLE_VALUE;
|
||||||
|
ULONG ulVolumeNumber = 0;
|
||||||
|
WCHAR szVolumeName[MAX_PATH];
|
||||||
|
|
||||||
|
InitializeListHead(VolumeListHead);
|
||||||
|
|
||||||
|
hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName));
|
||||||
|
if (hVolume == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddVolumeToList(ulVolumeNumber++, szVolumeName);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName));
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddVolumeToList(ulVolumeNumber++, szVolumeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
FindVolumeClose(hVolume);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
NTSTATUS
|
||||||
|
CreateVolumeList(
|
||||||
|
_Out_ PLIST_ENTRY VolumeListHead)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: Improve, see also DestroyVolumeList
|
||||||
|
//
|
||||||
|
#if 0
|
||||||
|
VOID
|
||||||
|
RemoveVolume(
|
||||||
|
_In_ PVOLENTRY VolumeEntry)
|
||||||
|
{
|
||||||
|
RemoveEntryList(&VolumeEntry->ListEntry);
|
||||||
|
|
||||||
|
if (VolumeEntry->pszLabel)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pszLabel);
|
||||||
|
|
||||||
|
if (VolumeEntry->pszFilesystem)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pszFilesystem);
|
||||||
|
|
||||||
|
if (VolumeEntry->pExtents)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pExtents);
|
||||||
|
|
||||||
|
/* Release volume entry */
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
VOID
|
||||||
|
RemoveVolume(
|
||||||
|
_In_ PVOLENTRY VolumeEntry)
|
||||||
|
{
|
||||||
|
// VolumeEntry->FormatState = Unformatted;
|
||||||
|
// VolumeEntry->FileSystem[0] = L'\0';
|
||||||
|
// VolumeEntry->DriveLetter = 0;
|
||||||
|
// RtlZeroMemory(VolumeEntry->VolumeLabel, sizeof(VolumeEntry->VolumeLabel));
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Improve, see also RemoveVolume
|
||||||
|
//
|
||||||
|
VOID
|
||||||
|
DestroyVolumeList(
|
||||||
|
_In_ PLIST_ENTRY VolumeListHead)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PVOLENTRY VolumeEntry;
|
||||||
|
|
||||||
|
/* Release volume info */
|
||||||
|
while (!IsListEmpty(VolumeListHead))
|
||||||
|
{
|
||||||
|
Entry = RemoveHeadList(VolumeListHead);
|
||||||
|
VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
|
||||||
|
|
||||||
|
if (VolumeEntry->pszLabel)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pszLabel);
|
||||||
|
|
||||||
|
if (VolumeEntry->pszFilesystem)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pszFilesystem);
|
||||||
|
|
||||||
|
if (VolumeEntry->pExtents)
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry->pExtents);
|
||||||
|
|
||||||
|
/* Release volume entry */
|
||||||
|
RtlFreeHeap(ProcessHeap, 0, VolumeEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: Improve. For example, do this calculation lookup while
|
||||||
|
// listing the volumes during list creation, then here, just do
|
||||||
|
// a quick lookup (for example each VOLENTRY could contain a
|
||||||
|
// linked-list to the partition(s) on which it is based upon).
|
||||||
|
//
|
||||||
|
PVOLENTRY
|
||||||
|
GetVolumeFromPartition(
|
||||||
|
_In_ PLIST_ENTRY VolumeListHead,
|
||||||
|
_In_ PPARTENTRY PartEntry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PVOLENTRY VolumeEntry;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
if (!PartEntry || !PartEntry->DiskEntry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (Entry = VolumeListHead->Flink;
|
||||||
|
Entry != VolumeListHead;
|
||||||
|
Entry = Entry->Flink)
|
||||||
|
{
|
||||||
|
VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
|
||||||
|
|
||||||
|
if (VolumeEntry->pExtents == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
|
||||||
|
{
|
||||||
|
if (VolumeEntry->pExtents->Extents[i].DiskNumber == PartEntry->DiskEntry->DiskNumber)
|
||||||
|
{
|
||||||
|
if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
|
||||||
|
(VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
|
||||||
|
{
|
||||||
|
return VolumeEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -2,38 +2,106 @@
|
||||||
* PROJECT: ReactOS Setup Library
|
* PROJECT: ReactOS Setup Library
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: Volume utility functions
|
* PURPOSE: Volume utility functions
|
||||||
* COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
* COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
/* EXTRA HANDFUL MACROS *****************************************************/
|
||||||
|
|
||||||
|
// NOTE: They should be moved into some global header.
|
||||||
|
|
||||||
|
// /* We have to define it there, because it is not in the MS DDK */
|
||||||
|
// #define PARTITION_LINUX 0x83
|
||||||
|
|
||||||
|
/* OEM MBR partition types recognized by NT (see [MS-DMRP] Appendix B) */
|
||||||
|
#define PARTITION_EISA 0x12 // EISA partition
|
||||||
|
#define PARTITION_HIBERNATION 0x84 // Hibernation partition for laptops
|
||||||
|
#define PARTITION_DIAGNOSTIC 0xA0 // Diagnostic partition on some Hewlett-Packard (HP) notebooks
|
||||||
|
#define PARTITION_DELL 0xDE // Dell partition
|
||||||
|
#define PARTITION_IBM 0xFE // IBM Initial Microprogram Load (IML) partition
|
||||||
|
|
||||||
|
#define IsOEMPartition(PartitionType) \
|
||||||
|
( ((PartitionType) == PARTITION_EISA) || \
|
||||||
|
((PartitionType) == PARTITION_HIBERNATION) || \
|
||||||
|
((PartitionType) == PARTITION_DIAGNOSTIC) || \
|
||||||
|
((PartitionType) == PARTITION_DELL) || \
|
||||||
|
((PartitionType) == PARTITION_IBM) )
|
||||||
|
|
||||||
|
|
||||||
|
/* VOLUME UTILITY FUNCTIONS *************************************************/
|
||||||
|
|
||||||
|
// FORMATSTATE
|
||||||
|
|
||||||
|
typedef enum _VOLUME_TYPE
|
||||||
|
{
|
||||||
|
VOLUME_TYPE_CDROM,
|
||||||
|
VOLUME_TYPE_PARTITION,
|
||||||
|
VOLUME_TYPE_REMOVABLE,
|
||||||
|
VOLUME_TYPE_UNKNOWN
|
||||||
|
} VOLUME_TYPE, *PVOLUME_TYPE;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//
|
||||||
|
// This is the structure from diskpart
|
||||||
|
//
|
||||||
|
typedef struct _VOLENTRY
|
||||||
|
{
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
ULONG VolumeNumber;
|
||||||
|
WCHAR VolumeName[MAX_PATH];
|
||||||
|
WCHAR DeviceName[MAX_PATH];
|
||||||
|
|
||||||
|
WCHAR DriveLetter;
|
||||||
|
|
||||||
|
PWSTR pszLabel;
|
||||||
|
PWSTR pszFilesystem;
|
||||||
|
VOLUME_TYPE VolumeType;
|
||||||
|
ULARGE_INTEGER Size;
|
||||||
|
|
||||||
|
PVOLUME_DISK_EXTENTS pExtents;
|
||||||
|
|
||||||
|
} VOLENTRY, *PVOLENTRY;
|
||||||
|
#else
|
||||||
|
|
||||||
typedef struct _VOLINFO
|
typedef struct _VOLINFO
|
||||||
{
|
{
|
||||||
// WCHAR VolumeName[MAX_PATH]; ///< Name in the DOS/Win32 namespace: "\??\Volume{GUID}\"
|
// LIST_ENTRY ListEntry;
|
||||||
WCHAR DeviceName[MAX_PATH]; ///< NT device name: "\Device\HarddiskVolumeN"
|
|
||||||
|
// WCHAR VolumeName[MAX_PATH]; // Name in the DOS/Win32 namespace
|
||||||
|
WCHAR DeviceName[MAX_PATH]; // NT device name
|
||||||
|
|
||||||
WCHAR DriveLetter;
|
WCHAR DriveLetter;
|
||||||
WCHAR VolumeLabel[20];
|
WCHAR VolumeLabel[20];
|
||||||
WCHAR FileSystem[MAX_PATH+1];
|
WCHAR FileSystem[MAX_PATH+1];
|
||||||
|
FORMATSTATE FormatState;
|
||||||
|
|
||||||
|
/** The following properties may be replaced by flags **/
|
||||||
|
|
||||||
|
/* Volume is new and has not yet been actually formatted and mounted */
|
||||||
|
BOOLEAN New;
|
||||||
|
|
||||||
|
/* Volume must be checked */
|
||||||
|
BOOLEAN NeedsCheck;
|
||||||
|
|
||||||
// VOLUME_TYPE VolumeType;
|
|
||||||
// ULARGE_INTEGER Size;
|
|
||||||
// PVOLUME_DISK_EXTENTS Extents;
|
|
||||||
} VOLINFO, *PVOLINFO;
|
} VOLINFO, *PVOLINFO;
|
||||||
|
|
||||||
/* RawFS "RAW" file system name */
|
#define VOLENTRY VOLINFO
|
||||||
#define IS_RAWFS(fs) \
|
#define PVOLENTRY PVOLINFO
|
||||||
((fs)[0] == 'R' && (fs)[1] == 'A' && (fs)[2] == 'W' && (fs)[3] == 0)
|
|
||||||
|
|
||||||
#define IsUnknown(VolInfo) \
|
#endif
|
||||||
(!*(VolInfo)->FileSystem)
|
|
||||||
|
|
||||||
#define IsUnformatted(VolInfo) \
|
|
||||||
IS_RAWFS((VolInfo)->FileSystem)
|
|
||||||
|
|
||||||
#define IsFormatted(VolInfo) \
|
// static
|
||||||
(!IsUnknown(VolInfo) && !IsUnformatted(VolInfo))
|
VOID
|
||||||
|
AssignDriveLetters(
|
||||||
|
IN PPARTLIST List);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DetectFileSystem(
|
||||||
|
_Inout_ PPARTENTRY PartEntry) // FIXME: Replace by volume entry
|
||||||
|
;
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
MountVolume(
|
MountVolume(
|
||||||
|
@ -45,4 +113,14 @@ DismountVolume(
|
||||||
_Inout_ PVOLINFO Volume,
|
_Inout_ PVOLINFO Volume,
|
||||||
_In_ BOOLEAN Force);
|
_In_ BOOLEAN Force);
|
||||||
|
|
||||||
|
// BOOLEAN
|
||||||
|
// SetMountedDeviceValue(
|
||||||
|
// IN WCHAR Letter,
|
||||||
|
// IN ULONG Signature,
|
||||||
|
// IN LARGE_INTEGER StartingOffset);
|
||||||
|
|
||||||
|
// BOOLEAN
|
||||||
|
// SetMountedDeviceValues(
|
||||||
|
// IN PPARTLIST List);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -650,7 +650,19 @@ AddNTOSInstallationItem(
|
||||||
IN SIZE_T cchBufferSize)
|
IN SIZE_T cchBufferSize)
|
||||||
{
|
{
|
||||||
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
||||||
PVOLINFO VolInfo = (NtOsInstall->Volume ? &NtOsInstall->Volume->Info : NULL);
|
PPARTENTRY PartEntry;
|
||||||
|
PVOLINFO VolInfo;
|
||||||
|
|
||||||
|
/* Retrieve the volume corresponding to the disk and partition numbers */
|
||||||
|
PartEntry = SelectPartition(SetupData.PartitionList,
|
||||||
|
NtOsInstall->DiskNumber,
|
||||||
|
NtOsInstall->PartitionNumber);
|
||||||
|
if (!PartEntry)
|
||||||
|
{
|
||||||
|
DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
|
||||||
|
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber);
|
||||||
|
}
|
||||||
|
VolInfo = (PartEntry && PartEntry->Volume ? &PartEntry->Volume->Info : NULL);
|
||||||
|
|
||||||
if (VolInfo && VolInfo->DriveLetter)
|
if (VolInfo && VolInfo->DriveLetter)
|
||||||
{
|
{
|
||||||
|
@ -1521,9 +1533,6 @@ FsVolCallback(
|
||||||
// EndFormat(FmtInfo->ErrorStatus);
|
// EndFormat(FmtInfo->ErrorStatus);
|
||||||
if (FmtInfo->FileSystemName)
|
if (FmtInfo->FileSystemName)
|
||||||
*(PWSTR)FmtInfo->FileSystemName = UNICODE_NULL; // FIXME: HACK!
|
*(PWSTR)FmtInfo->FileSystemName = UNICODE_NULL; // FIXME: HACK!
|
||||||
|
|
||||||
// /* Reset the file system list */
|
|
||||||
// ResetFileSystemList();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -559,7 +559,7 @@ PrintDiskData(
|
||||||
DiskEntry,
|
DiskEntry,
|
||||||
PrimaryPartEntry);
|
PrimaryPartEntry);
|
||||||
|
|
||||||
if (IsContainerPartition(PrimaryPartEntry->PartitionType))
|
if (PrimaryPartEntry == DiskEntry->ExtendedPartition)
|
||||||
{
|
{
|
||||||
for (LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
|
for (LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
|
||||||
LogicalEntry != &DiskEntry->LogicalPartListHead;
|
LogicalEntry != &DiskEntry->LogicalPartListHead;
|
||||||
|
@ -843,8 +843,9 @@ ScrollUpDownPartitionList(
|
||||||
_In_ BOOLEAN Direction)
|
_In_ BOOLEAN Direction)
|
||||||
{
|
{
|
||||||
PPARTENTRY PartEntry =
|
PPARTENTRY PartEntry =
|
||||||
(Direction ? GetNextPartition
|
GetAdjPartition(ListUi->List, ListUi->CurrentPartition,
|
||||||
: GetPrevPartition)(ListUi->List, ListUi->CurrentPartition);
|
(Direction ? ENUM_REGION_NEXT : ENUM_REGION_PREV)
|
||||||
|
| ENUM_REGION_MBR_BY_ORDER);
|
||||||
if (PartEntry)
|
if (PartEntry)
|
||||||
{
|
{
|
||||||
ListUi->CurrentPartition = PartEntry;
|
ListUi->CurrentPartition = PartEntry;
|
||||||
|
|
|
@ -512,7 +512,19 @@ GetNTOSInstallationName(
|
||||||
IN SIZE_T cchBufferSize)
|
IN SIZE_T cchBufferSize)
|
||||||
{
|
{
|
||||||
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
PNTOS_INSTALLATION NtOsInstall = (PNTOS_INSTALLATION)GetListEntryData(Entry);
|
||||||
PVOLINFO VolInfo = (NtOsInstall->Volume ? &NtOsInstall->Volume->Info : NULL);
|
PPARTENTRY PartEntry;
|
||||||
|
PVOLINFO VolInfo;
|
||||||
|
|
||||||
|
/* Retrieve the volume corresponding to the disk and partition numbers */
|
||||||
|
PartEntry = SelectPartition(PartitionList,
|
||||||
|
NtOsInstall->DiskNumber,
|
||||||
|
NtOsInstall->PartitionNumber);
|
||||||
|
if (!PartEntry)
|
||||||
|
{
|
||||||
|
DPRINT1("SelectPartition(disk #%d, partition #%d) failed\n",
|
||||||
|
NtOsInstall->DiskNumber, NtOsInstall->PartitionNumber);
|
||||||
|
}
|
||||||
|
VolInfo = (PartEntry && PartEntry->Volume ? &PartEntry->Volume->Info : NULL);
|
||||||
|
|
||||||
if (VolInfo && VolInfo->DriveLetter)
|
if (VolInfo && VolInfo->DriveLetter)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue