From 0a8b421d53303c0a66a7bf57db19da35a5d1f6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 19 May 2024 20:28:15 +0200 Subject: [PATCH] [PARTMGR] Implement IOCTL_VOLUME_QUERY_VOLUME_NUMBER and IOCTL_VOLUME_IS_PARTITION (#6911) - Implement IOCTL_VOLUME_QUERY_VOLUME_NUMBER: See usage example in: https://github.com/dansdrivers/ndas4windows/blob/7241cebfa2a2076de546b8841c2ccda8ca599a8d/mayfield/branches/spr/src/umapps/ndassvc/service/drivematch.cpp#L627 - Stubplement IOCTL_VOLUME_IS_PARTITION: The only type of volume we support right now is disk partition so we just return success. A more robust algorithm would be to check whether the volume has only one single extent, that covers the whole partition on which it lies upon. If this is not the case, return STATUS_UNSUCCESSFUL instead. --- drivers/storage/partmgr/partition.c | 43 ++++++++++++++++++++++++++--- drivers/storage/partmgr/partmgr.h | 1 + 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/storage/partmgr/partition.c b/drivers/storage/partmgr/partition.c index cfd00fa5ce5..8e72d397daa 100644 --- a/drivers/storage/partmgr/partition.c +++ b/drivers/storage/partmgr/partition.c @@ -7,7 +7,7 @@ #include "partmgr.h" -static const WCHAR PartitionSymLinkFormat[] = L"\\Device\\Harddisk%u\\Partition%u"; +static const WCHAR PartitionSymLinkFormat[] = L"\\Device\\Harddisk%lu\\Partition%lu"; CODE_SEG("PAGE") @@ -25,10 +25,12 @@ PartitionCreateDevice( WCHAR nameBuf[64]; UNICODE_STRING deviceName; + UINT32 volumeNum; // create the device object - swprintf(nameBuf, L"\\Device\\HarddiskVolume%u", HarddiskVolumeNextId++); + volumeNum = HarddiskVolumeNextId++; + swprintf(nameBuf, L"\\Device\\HarddiskVolume%lu", volumeNum); RtlCreateUnicodeString(&deviceName, nameBuf); PDEVICE_OBJECT partitionDevice; @@ -74,6 +76,7 @@ PartitionCreateDevice( partExt->PartitionLength = PartitionEntry->PartitionLength.QuadPart; partExt->OnDiskNumber = PartitionEntry->PartitionNumber; // the "physical" partition number partExt->DetectedNumber = PdoNumber; // counts only partitions with PDO created + partExt->VolumeNumber = volumeNum; partExt->DeviceObject = partitionDevice; partExt->LowerDevice = FDObject; @@ -99,7 +102,7 @@ PartitionHandleStartDevice( UNICODE_STRING partitionSymlink, interfaceName; PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension; - // \\Device\\Harddisk%u\\Partition%u + // \\Device\\Harddisk%lu\\Partition%lu swprintf(nameBuf, PartitionSymLinkFormat, fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber); @@ -662,7 +665,7 @@ PartitionHandleDeviceControl( { return ForwardIrpAndForget(DeviceObject, Irp); } - // volume stuff (most of that should be in volmgr.sys one it is implemented) + // volume stuff (most of that should be in volmgr.sys once it is implemented) case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: { PVOLUME_DISK_EXTENTS volExts = Irp->AssociatedIrp.SystemBuffer; @@ -694,6 +697,38 @@ PartitionHandleDeviceControl( Irp->IoStatus.Information = sizeof(*volExts); break; } + case IOCTL_VOLUME_QUERY_VOLUME_NUMBER: + { + PVOLUME_NUMBER volNum = Irp->AssociatedIrp.SystemBuffer; + if (!VerifyIrpOutBufferSize(Irp, sizeof(*volNum))) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + PartMgrAcquireLayoutLock(fdoExtension); + + volNum->VolumeNumber = partExt->VolumeNumber; + RtlCopyMemory(volNum->VolumeManagerName, + L"VOLMGR ", // Must be 8 space-padded characters + sizeof(volNum->VolumeManagerName)); + + PartMgrReleaseLayoutLock(fdoExtension); + + status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(*volNum); + break; + } + case IOCTL_VOLUME_IS_PARTITION: + { + // The only type of volume we support right now is disk partition + // so we just return success. A more robust algorithm would be + // to check whether the volume has only one single extent, that + // covers the whole partition on which it lies upon. If this is + // not the case, return STATUS_UNSUCCESSFUL instead. + status = STATUS_SUCCESS; + break; + } case IOCTL_VOLUME_ONLINE: { status = STATUS_SUCCESS; diff --git a/drivers/storage/partmgr/partmgr.h b/drivers/storage/partmgr/partmgr.h index 5bdc30a40cf..ff4b369d877 100644 --- a/drivers/storage/partmgr/partmgr.h +++ b/drivers/storage/partmgr/partmgr.h @@ -73,6 +73,7 @@ typedef struct _PARTITION_EXTENSION UINT64 PartitionLength; SINGLE_LIST_ENTRY ListEntry; + UINT32 VolumeNumber; // Volume number in the "\Device\HarddiskVolumeN" device name UINT32 DetectedNumber; UINT32 OnDiskNumber; // partition number for issuing Io requests to the kernel BOOLEAN IsEnumerated; // reported via IRP_MN_QUERY_DEVICE_RELATIONS