** WIP ** NOT COMPILABLE - Continue studying volume/partition stuff

This commit is contained in:
Hermès Bélusca-Maïto 2024-03-25 17:11:57 +01:00
parent 04086cd561
commit 1516759445
No known key found for this signature in database
GPG Key ID: 3B2539C65E7B93D0
3 changed files with 246 additions and 108 deletions

View File

@ -754,38 +754,27 @@ Quit:
//
NTSTATUS
ChkdskPartition(
IN PPARTENTRY PartEntry,
IN BOOLEAN FixErrors,
IN BOOLEAN Verbose,
IN BOOLEAN CheckOnlyIfDirty,
IN BOOLEAN ScanDrive,
IN PFMIFSCALLBACK Callback)
ChkdskVolume(
_In_ PVOLINFO Volume,
_In_ BOOLEAN FixErrors,
_In_ BOOLEAN Verbose,
_In_ BOOLEAN CheckOnlyIfDirty,
_In_ BOOLEAN ScanDrive,
_In_opt_ PFMIFSCALLBACK Callback)
{
NTSTATUS Status;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
// UNICODE_STRING PartitionRootPath;
WCHAR PartitionRootPath[MAX_PATH]; // PathBuffer
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
/* HACK: Do not try to check a partition with an unknown filesystem */
if (!*PartEntry->Volume.FileSystem)
/* HACK: Do not try to check a volume with an unknown filesystem */
if (!*Volume->FileSystem)
{
PartEntry->Volume.NeedsCheck = FALSE;
Volume->NeedsCheck = FALSE;
return STATUS_SUCCESS;
}
/* Set PartitionRootPath */
RtlStringCchPrintfW(PartitionRootPath, ARRAYSIZE(PartitionRootPath),
L"\\Device\\Harddisk%lu\\Partition%lu",
DiskEntry->DiskNumber,
PartEntry->PartitionNumber);
DPRINT("PartitionRootPath: %S\n", PartitionRootPath);
/* Check the partition */
Status = ChkdskFileSystem(PartitionRootPath,
PartEntry->Volume.FileSystem,
/* Check the volume */
DPRINT("Volume->DeviceName: %S\n", Volume->DeviceName);
Status = ChkdskFileSystem(Volume->DeviceName,
Volume->FileSystem,
FixErrors,
Verbose,
CheckOnlyIfDirty,
@ -794,19 +783,93 @@ ChkdskPartition(
if (!NT_SUCCESS(Status))
return Status;
PartEntry->Volume.NeedsCheck = FALSE;
Volume->NeedsCheck = FALSE;
return STATUS_SUCCESS;
}
NTSTATUS
ChkdskPartition(
_In_ PPARTENTRY PartEntry,
_In_ BOOLEAN FixErrors,
_In_ BOOLEAN Verbose,
_In_ BOOLEAN CheckOnlyIfDirty,
_In_ BOOLEAN ScanDrive,
_In_opt_ PFMIFSCALLBACK Callback)
{
NTSTATUS Status;
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
ASSERT(PartEntry->Volume);
// if (!PartEntry->Volume) { check_raw_sectors(); } else { check_FS(); }
/* Check the related volume */
Status = ChkdskVolume(PartEntry->Volume,
FixErrors,
Verbose,
CheckOnlyIfDirty,
ScanDrive,
Callback);
// if (NT_SUCCESS(Status)) PartEntry->Volume->NeedsCheck = FALSE;
return Status;
}
NTSTATUS
FormatVolume(
_In_ PVOLINFO Volume,
_In_ PCWSTR FileSystemName,
_In_ FMIFS_MEDIA_FLAG MediaFlag,
_In_ PCWSTR Label,
_In_ BOOLEAN QuickFormat,
_In_ ULONG ClusterSize,
_In_opt_ PFMIFSCALLBACK Callback)
{
NTSTATUS Status;
if (!FileSystemName || !*FileSystemName)
{
DPRINT1("No file system specified?\n");
return STATUS_UNRECOGNIZED_VOLUME;
}
/* Format the volume */
DPRINT("Volume->DeviceName: %S\n", Volume->DeviceName);
Status = FormatFileSystem(Volume->DeviceName,
FileSystemName,
MediaFlag,
Label,
QuickFormat,
ClusterSize,
Callback);
if (!NT_SUCCESS(Status))
return Status;
//
// TODO: Here, call a partlist.c function that updates
// the actual FS name and the label fields of the volume.
//
Volume->FormatState = Formatted;
/* Set the new partition's file system proper */
RtlStringCbCopyW(Volume->FileSystem,
sizeof(Volume->FileSystem),
FileSystemName);
Volume->New = FALSE;
return STATUS_SUCCESS;
}
NTSTATUS
FormatPartition(
IN PPARTENTRY PartEntry,
IN PCWSTR FileSystemName,
IN FMIFS_MEDIA_FLAG MediaFlag,
IN PCWSTR Label,
IN BOOLEAN QuickFormat,
IN ULONG ClusterSize,
IN PFMIFSCALLBACK Callback)
_In_ PPARTENTRY PartEntry,
_In_ PCWSTR FileSystemName,
_In_ FMIFS_MEDIA_FLAG MediaFlag,
_In_ PCWSTR Label,
_In_ BOOLEAN QuickFormat,
_In_ ULONG ClusterSize,
_In_opt_ PFMIFSCALLBACK Callback)
{
NTSTATUS Status;
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
@ -876,38 +939,36 @@ FormatPartition(
return STATUS_PARTITION_FAILURE;
}
/* Set PartitionRootPath */
RtlStringCchPrintfW(PartitionRootPath, ARRAYSIZE(PartitionRootPath),
L"\\Device\\Harddisk%lu\\Partition%lu",
DiskEntry->DiskNumber,
PartEntry->PartitionNumber);
DPRINT("PartitionRootPath: %S\n", PartitionRootPath);
/* Create volume if necessary */
if (!PartEntry->Volume)
{
PDISKENTRY DiskEntry = PartEntry->DiskEntry;
/* Format the partition */
Status = FormatFileSystem(PartitionRootPath,
FileSystemName,
MediaFlag,
Label,
QuickFormat,
ClusterSize,
Callback);
if (!NT_SUCCESS(Status))
return Status;
CreateVolume(&PartEntry->Volume);
if (!PartEntry->Volume)
{
DPRINT1("Failed to allocate partition volume\n");
return STATUS_UNSUCCESSFUL;
}
//
// TODO: Here, call a partlist.c function that updates
// the actual FS name and the label fields of the volume.
//
PartEntry->Volume.FormatState = Formatted;
// FIXME: Make a device name for the volume
RtlStringCchPrintfW(PartEntry->Volume->DeviceName,
ARRAYSIZE(PartEntry->Volume->DeviceName),
L"\\Device\\Harddisk%lu\\Partition%lu",
DiskEntry->DiskNumber,
PartEntry->PartitionNumber);
}
/* Set the new partition's file system proper */
RtlStringCbCopyW(PartEntry->Volume.FileSystem,
sizeof(PartEntry->Volume.FileSystem),
FileSystemName);
/* Format the related volume */
Status = FormatVolume(PartEntry->Volume,
FileSystemName,
MediaFlag,
Label,
QuickFormat,
ClusterSize,
Callback);
PartEntry->Volume.New = FALSE;
return STATUS_SUCCESS;
return Status;
}
@ -983,16 +1044,17 @@ DoChecking(
CHECK_PARTITION_INFO PartInfo;
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
ASSERT(PartEntry->Volume);
#if 0
/* HACK: Do not try to check a partition with an unknown filesystem */
if (!*PartEntry->Volume.FileSystem)
if (!*PartEntry->Volume->FileSystem)
{
PartEntry->Volume.NeedsCheck = FALSE;
PartEntry->Volume->NeedsCheck = FALSE;
return FSVOL_SKIP;
}
#else
ASSERT(*PartEntry->Volume.FileSystem);
ASSERT(*PartEntry->Volume->FileSystem);
#endif
RtlZeroMemory(&PartInfo, sizeof(PartInfo));
@ -1047,7 +1109,7 @@ GetNextUnformattedPartition(
while ((CurrentPart = GetAdjPartition(List, CurrentPart,
ENUM_REGION_NEXT | ENUM_REGION_PARTITIONED)))
{
if (CurrentPart->Volume.New /**/&& (CurrentPart->Volume.FormatState == Unformatted)/**/)
if (CurrentPart->Volume->New /**/&& (CurrentPart->Volume->FormatState == Unformatted)/**/)
{
/* Found a candidate, return it */
return CurrentPart;
@ -1067,10 +1129,13 @@ GetNextUncheckedPartition(
while ((CurrentPart = GetAdjPartition(List, CurrentPart,
ENUM_REGION_NEXT | ENUM_REGION_PARTITIONED)))
{
if (CurrentPart->Volume.NeedsCheck)
if (!CurrentPart->Volume)
continue;
if (CurrentPart->Volume->NeedsCheck)
{
/* Found a candidate, return it */
ASSERT(CurrentPart->Volume.FormatState == Formatted);
ASSERT(CurrentPart->Volume->FormatState == Formatted);
return CurrentPart;
}
}
@ -1104,6 +1169,8 @@ FsVolCommitOpsQueue(
ASSERT(PartitionList && InstallPartition && SystemPartition);
// TODO: Do all pending volume unmounts.
/* Commit all partition changes to all the disks */
if (!WritePartitionsToDisk(PartitionList))
{
@ -1123,8 +1190,8 @@ FsVolCommitOpsQueue(
* we must perform a filesystem check of both the system and the
* installation partitions.
*/
SystemPartition->Volume.NeedsCheck = TRUE;
InstallPartition->Volume.NeedsCheck = TRUE;
SystemPartition->Volume->NeedsCheck = TRUE;
InstallPartition->Volume->NeedsCheck = TRUE;
Result = FsVolCallback(Context,
FSVOLNOTIFY_STARTQUEUE,
@ -1168,10 +1235,10 @@ NextFormat:
ASSERT(SystemPartition->IsPartitioned);
if ((SystemPartition != InstallPartition) &&
(SystemPartition->Volume.FormatState == Unformatted))
(SystemPartition->Volume->FormatState == Unformatted))
{
PartEntry = SystemPartition;
PartEntry->Volume.NeedsCheck = TRUE;
PartEntry->Volume->NeedsCheck = TRUE;
// TODO: Should we let the user use a custom file-system,
// or should we always use FAT(32) for it?
@ -1183,15 +1250,15 @@ NextFormat:
else
{
PartEntry = InstallPartition;
PartEntry->Volume.NeedsCheck = TRUE;
PartEntry->Volume->NeedsCheck = TRUE;
if (SystemPartition != InstallPartition)
{
/* The system partition is separate, so it had better be formatted! */
ASSERT(SystemPartition->Volume.FormatState == Formatted);
ASSERT(SystemPartition->Volume->FormatState == Formatted);
/* Require a filesystem check on the system partition too */
SystemPartition->Volume.NeedsCheck = TRUE;
SystemPartition->Volume->NeedsCheck = TRUE;
}
DPRINT1("FormatState: Start --> FormatInstallPartition\n");
@ -1203,7 +1270,7 @@ NextFormat:
case FormatSystemPartition:
{
PartEntry = InstallPartition;
PartEntry->Volume.NeedsCheck = TRUE;
PartEntry->Volume->NeedsCheck = TRUE;
DPRINT1("FormatState: FormatSystemPartition --> FormatInstallPartition\n");
FormatState = FormatInstallPartition;
@ -1222,7 +1289,7 @@ NextFormat:
PartEntry = GetNextUnformattedPartition(PartitionList, PartEntry);
if (PartEntry)
{
PartEntry->Volume.NeedsCheck = TRUE;
PartEntry->Volume->NeedsCheck = TRUE;
if (FormatState == FormatInstallPartition)
DPRINT1("FormatState: FormatInstallPartition --> FormatOtherPartition\n");

View File

@ -559,7 +559,7 @@ Quit:
CurrentPart->PartitionType,
CurrentPart->IsPartitioned ? "TRUE" : "FALSE",
CurrentPart->New ? "Yes" : "No",
CurrentPart->Volume.FormatState);
CurrentPart->Volume ? CurrentPart->Volume->FormatState : -1);
}
return CurrentPart;
}
@ -631,7 +631,10 @@ AssignDriveLetters(
while ((PartEntry = GetAdjDiskRegion(DiskEntry, PartEntry,
ENUM_REGION_NEXT /*| ENUM_REGION_PARTITIONED*/ | ENUM_REGION_MBR_PRIMARY_ONLY)))
{
PartEntry->Volume.DriveLetter = 0;
if (!PartEntry->Volume)
continue;
PartEntry->Volume->DriveLetter = 0;
if (PartEntry->IsPartitioned &&
!IsContainerPartition(PartEntry->PartitionType) &&
@ -639,7 +642,7 @@ AssignDriveLetters(
PartEntry->SectorCount.QuadPart != 0LL))
{
if (Letter <= L'Z')
PartEntry->Volume.DriveLetter = Letter++;
PartEntry->Volume->DriveLetter = Letter++;
}
}
}
@ -653,14 +656,17 @@ AssignDriveLetters(
while ((PartEntry = GetAdjDiskRegion(DiskEntry, PartEntry,
ENUM_REGION_NEXT /*| ENUM_REGION_PARTITIONED*/ | ENUM_REGION_MBR_LOGICAL_ONLY)))
{
PartEntry->Volume.DriveLetter = 0;
if (!PartEntry->Volume)
continue;
PartEntry->Volume->DriveLetter = 0;
if (PartEntry->IsPartitioned &&
(IsRecognizedPartition(PartEntry->PartitionType) ||
PartEntry->SectorCount.QuadPart != 0LL))
{
if (Letter <= L'Z')
PartEntry->Volume.DriveLetter = Letter++;
PartEntry->Volume->DriveLetter = Letter++;
}
}
}
@ -1117,7 +1123,8 @@ CreateInsertBlankRegion(
NewPartEntry->LogicalPartition = LogicalSpace;
NewPartEntry->IsPartitioned = FALSE;
NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
RtlZeroMemory(&NewPartEntry->Volume, sizeof(NewPartEntry->Volume));
// RtlZeroMemory(&NewPartEntry->Volume, sizeof(NewPartEntry->Volume));
NewPartEntry->Volume = NULL;
DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
@ -1225,6 +1232,42 @@ InitializePartitionEntry(
}
NTSTATUS
CreateVolume(
_Out_ PVOLINFO* Volume)
{
NTSTATUS Status;
PVOLINFO VolumeEntry;
/* No volume initially */
// RtlZeroMemory(&PartEntry->Volume, sizeof(PartEntry->Volume));
*Volume = RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(VOLINFO));
if (!*Volume)
return STATUS_NO_MEMORY;
VolumeEntry = *Volume;
#if 0
/* Reset some volume information */
VolumeEntry->DriveLetter = L'\0';
VolumeEntry->FormatState = Unformatted;
VolumeEntry->FileSystem[0] = L'\0';
RtlZeroMemory(VolumeEntry->VolumeLabel, sizeof(VolumeEntry->VolumeLabel));
// VolumeEntry->New = FALSE;
VolumeEntry->NeedsCheck = FALSE;
#endif
/* Specify the partition as initially unformatted */
VolumeEntry->FormatState = Unformatted;
VolumeEntry->FileSystem[0] = L'\0';
/* Initialize the partition volume label */
RtlZeroMemory(VolumeEntry->VolumeLabel, sizeof(VolumeEntry->VolumeLabel));
return STATUS_SUCCESS;
}
NTSTATUS
MountVolume(
_Inout_ PVOLINFO VolumeEntry,
@ -1410,7 +1453,7 @@ AddPartitionToDisk(
PartEntry = RtlAllocateHeap(ProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(PARTENTRY));
if (PartEntry == NULL)
if (!PartEntry)
return;
PartEntry->DiskEntry = DiskEntry;
@ -1428,7 +1471,13 @@ AddPartitionToDisk(
PartEntry->PartitionIndex = PartitionIndex;
/* No volume initially */
RtlZeroMemory(&PartEntry->Volume, sizeof(PartEntry->Volume));
CreateVolume(&PartEntry->Volume);
if (!PartEntry->Volume)
{
DPRINT1("Failed to allocate partition volume\n");
RtlFreeHeap(ProcessHeap, 0, PartEntry);
return;
}
if (IsContainerPartition(PartEntry->PartitionType))
{
@ -1449,21 +1498,21 @@ AddPartitionToDisk(
ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
// FIXME: Make a device name for the volume
RtlStringCchPrintfW(PartEntry->Volume.DeviceName,
ARRAYSIZE(PartEntry->Volume.DeviceName),
RtlStringCchPrintfW(PartEntry->Volume->DeviceName,
ARRAYSIZE(PartEntry->Volume->DeviceName),
L"\\Device\\Harddisk%lu\\Partition%lu",
DiskEntry->DiskNumber,
PartEntry->PartitionNumber);
/* Attach and mount the volume */
Status = MountVolume(&PartEntry->Volume,
Status = MountVolume(PartEntry->Volume,
PartEntry->PartitionType);
UNREFERENCED_PARAMETER(Status); // FIXME
}
else
{
/* Unknown partition, hence unknown format (may or may not be actually formatted) */
PartEntry->Volume.FormatState = UnknownFormat;
PartEntry->Volume->FormatState = UnknownFormat;
}
InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
@ -2353,8 +2402,9 @@ GetActiveDiskPartition(
DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
PartEntry->PartitionNumber, DiskEntry->DiskNumber,
(PartEntry->Volume.DriveLetter == 0)
? L'-' : PartEntry->Volume.DriveLetter);
PartEntry->Volume &&
(PartEntry->Volume->DriveLetter == 0)
? L'-' : PartEntry->Volume->DriveLetter);
break;
}
}
@ -3460,7 +3510,7 @@ DeletePartition(
PartEntry->BootIndicator = FALSE;
PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
RtlZeroMemory(&PartEntry->Volume, sizeof(PartEntry->Volume));
PartEntry->Volume = NULL;
/* Optionally return the freed region */
if (FreeRegion)
@ -3493,7 +3543,7 @@ IsSupportedActivePartition(
return FALSE;
}
VolumeEntry = &PartEntry->Volume;
VolumeEntry = PartEntry->Volume;
if (!VolumeEntry)
{
/* Still no recognizable volume mounted: partition not supported */
@ -3625,12 +3675,13 @@ FindSupportedSystemPartition(
if (ActivePartition && IsSupportedActivePartition(ActivePartition))
{
CandidatePartition = ActivePartition;
ASSERT(CandidatePartition->Volume);
DPRINT1("Use the current system partition %lu in disk %lu, drive letter %C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
(CandidatePartition->Volume.DriveLetter == 0)
? L'-' : CandidatePartition->Volume.DriveLetter);
(CandidatePartition->Volume->DriveLetter == 0)
? L'-' : CandidatePartition->Volume->DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@ -3787,8 +3838,9 @@ UseAlternativeDisk:
DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
(CandidatePartition->Volume.DriveLetter == 0)
? L'-' : CandidatePartition->Volume.DriveLetter);
CandidatePartition->Volume &&
(CandidatePartition->Volume->DriveLetter == 0)
? L'-' : CandidatePartition->Volume->DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@ -3832,8 +3884,9 @@ UseAlternativeDisk:
DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
(CandidatePartition->Volume.DriveLetter == 0)
? L'-' : CandidatePartition->Volume.DriveLetter);
CandidatePartition->Volume &&
(CandidatePartition->Volume->DriveLetter == 0)
? L'-' : CandidatePartition->Volume->DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@ -3871,8 +3924,9 @@ UseAlternativePartition:
DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
CandidatePartition->PartitionNumber,
CandidatePartition->DiskEntry->DiskNumber,
(CandidatePartition->Volume.DriveLetter == 0)
? L'-' : CandidatePartition->Volume.DriveLetter);
CandidatePartition->Volume &&
(CandidatePartition->Volume->DriveLetter == 0)
? L'-' : CandidatePartition->Volume->DriveLetter);
/* Return the candidate system partition */
return CandidatePartition;
@ -4229,12 +4283,17 @@ SetMountedDeviceValues(
if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
{
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
if (!PartEntry->Volume)
{
DPRINT1("Partition without recognized volume, ignoring\n");
continue;
}
/* Assign a "\DosDevices\#:" mount point to this partition */
if (PartEntry->Volume.DriveLetter)
if (PartEntry->Volume->DriveLetter)
{
StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
if (!SetMountedDeviceValue(PartEntry->Volume.DriveLetter,
if (!SetMountedDeviceValue(PartEntry->Volume->DriveLetter,
DiskEntry->LayoutBuffer->Signature,
StartingOffset))
{
@ -4250,12 +4309,17 @@ SetMountedDeviceValues(
if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
{
ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
if (!PartEntry->Volume)
{
DPRINT1("Partition without recognized volume, ignoring\n");
continue;
}
/* Assign a "\DosDevices\#:" mount point to this partition */
if (PartEntry->Volume.DriveLetter)
if (PartEntry->Volume->DriveLetter)
{
StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
if (!SetMountedDeviceValue(PartEntry->Volume.DriveLetter,
if (!SetMountedDeviceValue(PartEntry->Volume->DriveLetter,
DiskEntry->LayoutBuffer->Signature,
StartingOffset))
{
@ -4272,12 +4336,17 @@ SetMountedDeviceValues(
// ASSERT(PartEntry->IsPartitioned);
// ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
/**/ASSERT(!IsContainerPartition(PartEntry->PartitionType));/**/
if (!PartEntry->Volume)
{
DPRINT1("Partition without recognized volume, ignoring\n");
continue;
}
/* Assign a "\DosDevices\#:" mount point to this partition */
if (PartEntry->Volume.DriveLetter)
if (PartEntry->Volume->DriveLetter)
{
StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
if (!SetMountedDeviceValue(PartEntry->Volume.DriveLetter,
if (!SetMountedDeviceValue(PartEntry->Volume->DriveLetter,
DiskEntry->LayoutBuffer->Signature,
StartingOffset))
{

View File

@ -42,7 +42,7 @@ typedef enum _FORMATSTATE
typedef struct _VOLINFO
{
// LIST_ENTRY ListEntry;
LIST_ENTRY ListEntry;
// WCHAR VolumeName[MAX_PATH]; // Name in the DOS/Win32 namespace
WCHAR DeviceName[MAX_PATH]; // NT device name
@ -90,7 +90,7 @@ typedef struct _PARTENTRY
BOOLEAN New;
/* Volume-related properties */
VOLINFO Volume; // FIXME: Do it differently later
PVOLINFO Volume; // FIXME: Do it differently later
} PARTENTRY, *PPARTENTRY;
@ -151,6 +151,8 @@ typedef struct _DISKENTRY
/* Pointer to the unique extended partition on this disk (Valid only for MBR-partitioned disks) */
PPARTENTRY ExtendedPartition;
LIST_ENTRY PendingUnmountVolumesList; /* List of volumes to unmount */
} DISKENTRY, *PDISKENTRY;
typedef struct _BIOSDISKENTRY