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 */
|
||||
NtOsInstall = AddNTOSInstallation(Data->List,
|
||||
BootEntry->FriendlyName,
|
||||
Machine,
|
||||
VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
|
||||
Options->OsLoadPath,
|
||||
&SystemRootPath, PathComponent,
|
||||
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);
|
||||
}
|
||||
AddNTOSInstallation(Data->List,
|
||||
BootEntry->FriendlyName,
|
||||
Machine,
|
||||
VendorName.Buffer, // FIXME: What if it's not NULL-terminated?
|
||||
Options->OsLoadPath,
|
||||
&SystemRootPath, PathComponent,
|
||||
DiskNumber, PartitionNumber);
|
||||
|
||||
/* Continue the enumeration */
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -22,7 +22,6 @@ typedef struct _NTOS_INSTALLATION
|
|||
PCWSTR PathComponent; // Pointer inside SystemNtPath.Buffer
|
||||
ULONG DiskNumber;
|
||||
ULONG PartitionNumber;
|
||||
PVOLENTRY Volume; // PVOLINFO
|
||||
WCHAR InstallationName[MAX_PATH];
|
||||
WCHAR VendorName[MAX_PATH];
|
||||
// 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.
|
||||
|
||||
// /* 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
|
||||
|
@ -129,8 +132,9 @@ typedef struct _DISKENTRY
|
|||
ULONG DiskNumber;
|
||||
// SCSI_ADDRESS;
|
||||
USHORT Port;
|
||||
USHORT Bus;
|
||||
USHORT Id;
|
||||
USHORT Bus; // PathId;
|
||||
USHORT Id; // TargetId;
|
||||
// USHORT Lun;
|
||||
|
||||
/* Has the partition list been modified? */
|
||||
BOOLEAN Dirty;
|
||||
|
@ -258,6 +262,51 @@ RoundingDivide(
|
|||
((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
|
||||
IsDiskSuperFloppy2(
|
||||
_In_ const DISK_PARTITION_INFO* DiskInfo,
|
||||
|
@ -322,21 +371,6 @@ SelectPartition(
|
|||
_In_ ULONG DiskNumber,
|
||||
_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
|
||||
PartitionCreationChecks(
|
||||
_In_ PPARTENTRY PartEntry);
|
||||
|
|
|
@ -2,22 +2,261 @@
|
|||
* PROJECT: ReactOS Setup Library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* 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 "volutil.h"
|
||||
#include "fsrec.h"
|
||||
#include "devutils.h"
|
||||
#include "diskpart.h"
|
||||
#include <ntddscsi.h>
|
||||
|
||||
#define NDEBUG
|
||||
#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
|
||||
MountVolume(
|
||||
|
@ -25,11 +264,36 @@ MountVolume(
|
|||
_In_opt_ UCHAR MbrPartitionType)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING Name;
|
||||
HANDLE VolumeHandle;
|
||||
|
||||
/* If the volume is already mounted, just return success */
|
||||
if (*Volume->FileSystem)
|
||||
#if 0
|
||||
/* 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;
|
||||
}
|
||||
#else
|
||||
if (!*Volume->DeviceName)
|
||||
{
|
||||
/* No volume attached, bail out */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try to open the volume so as to mount it */
|
||||
VolumeHandle = NULL;
|
||||
|
@ -47,7 +311,7 @@ MountVolume(
|
|||
}
|
||||
ASSERT(VolumeHandle);
|
||||
|
||||
/* We don't have a FS, try to guess one */
|
||||
/* Try to guess the mounted FS */
|
||||
Status = InferFileSystem(NULL, VolumeHandle,
|
||||
Volume->FileSystem,
|
||||
sizeof(Volume->FileSystem));
|
||||
|
@ -158,7 +422,7 @@ DismountVolume(
|
|||
HANDLE VolumeHandle;
|
||||
|
||||
/* If the volume is not mounted, just return success */
|
||||
if (!*Volume->FileSystem)
|
||||
if (!*Volume->DeviceName || !*Volume->FileSystem)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* Open the volume */
|
||||
|
@ -223,4 +487,160 @@ DismountVolume(
|
|||
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 */
|
||||
|
|
|
@ -2,38 +2,106 @@
|
|||
* PROJECT: ReactOS Setup Library
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* 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
|
||||
|
||||
/* 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
|
||||
{
|
||||
// WCHAR VolumeName[MAX_PATH]; ///< Name in the DOS/Win32 namespace: "\??\Volume{GUID}\"
|
||||
WCHAR DeviceName[MAX_PATH]; ///< NT device name: "\Device\HarddiskVolumeN"
|
||||
// LIST_ENTRY ListEntry;
|
||||
|
||||
// WCHAR VolumeName[MAX_PATH]; // Name in the DOS/Win32 namespace
|
||||
WCHAR DeviceName[MAX_PATH]; // NT device name
|
||||
|
||||
WCHAR DriveLetter;
|
||||
WCHAR VolumeLabel[20];
|
||||
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;
|
||||
|
||||
/* RawFS "RAW" file system name */
|
||||
#define IS_RAWFS(fs) \
|
||||
((fs)[0] == 'R' && (fs)[1] == 'A' && (fs)[2] == 'W' && (fs)[3] == 0)
|
||||
#define VOLENTRY VOLINFO
|
||||
#define PVOLENTRY PVOLINFO
|
||||
|
||||
#define IsUnknown(VolInfo) \
|
||||
(!*(VolInfo)->FileSystem)
|
||||
#endif
|
||||
|
||||
#define IsUnformatted(VolInfo) \
|
||||
IS_RAWFS((VolInfo)->FileSystem)
|
||||
|
||||
#define IsFormatted(VolInfo) \
|
||||
(!IsUnknown(VolInfo) && !IsUnformatted(VolInfo))
|
||||
// static
|
||||
VOID
|
||||
AssignDriveLetters(
|
||||
IN PPARTLIST List);
|
||||
|
||||
NTSTATUS
|
||||
DetectFileSystem(
|
||||
_Inout_ PPARTENTRY PartEntry) // FIXME: Replace by volume entry
|
||||
;
|
||||
|
||||
NTSTATUS
|
||||
MountVolume(
|
||||
|
@ -45,4 +113,14 @@ DismountVolume(
|
|||
_Inout_ PVOLINFO Volume,
|
||||
_In_ BOOLEAN Force);
|
||||
|
||||
// BOOLEAN
|
||||
// SetMountedDeviceValue(
|
||||
// IN WCHAR Letter,
|
||||
// IN ULONG Signature,
|
||||
// IN LARGE_INTEGER StartingOffset);
|
||||
|
||||
// BOOLEAN
|
||||
// SetMountedDeviceValues(
|
||||
// IN PPARTLIST List);
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -650,7 +650,19 @@ AddNTOSInstallationItem(
|
|||
IN SIZE_T cchBufferSize)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -1521,9 +1533,6 @@ FsVolCallback(
|
|||
// EndFormat(FmtInfo->ErrorStatus);
|
||||
if (FmtInfo->FileSystemName)
|
||||
*(PWSTR)FmtInfo->FileSystemName = UNICODE_NULL; // FIXME: HACK!
|
||||
|
||||
// /* Reset the file system list */
|
||||
// ResetFileSystemList();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -559,7 +559,7 @@ PrintDiskData(
|
|||
DiskEntry,
|
||||
PrimaryPartEntry);
|
||||
|
||||
if (IsContainerPartition(PrimaryPartEntry->PartitionType))
|
||||
if (PrimaryPartEntry == DiskEntry->ExtendedPartition)
|
||||
{
|
||||
for (LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
|
||||
LogicalEntry != &DiskEntry->LogicalPartListHead;
|
||||
|
@ -843,8 +843,9 @@ ScrollUpDownPartitionList(
|
|||
_In_ BOOLEAN Direction)
|
||||
{
|
||||
PPARTENTRY PartEntry =
|
||||
(Direction ? GetNextPartition
|
||||
: GetPrevPartition)(ListUi->List, ListUi->CurrentPartition);
|
||||
GetAdjPartition(ListUi->List, ListUi->CurrentPartition,
|
||||
(Direction ? ENUM_REGION_NEXT : ENUM_REGION_PREV)
|
||||
| ENUM_REGION_MBR_BY_ORDER);
|
||||
if (PartEntry)
|
||||
{
|
||||
ListUi->CurrentPartition = PartEntry;
|
||||
|
|
|
@ -512,7 +512,19 @@ GetNTOSInstallationName(
|
|||
IN SIZE_T cchBufferSize)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue