https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dac991c056c718fdd1572…
commit dac991c056c718fdd1572582af5755803ab5359a
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Dec 27 17:48:04 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon Jan 6 21:26:43 2025 +0100
[PARTMGR] Implement support for IOCTL_STORAGE_GET_DEVICE_NUMBER (#7591)
CORE-13525
Now, sending the IOCTL_STORAGE_GET_DEVICE_NUMBER to a disk partition
correctly returns a non-zero STORAGE_DEVICE_NUMBER::PartitionNumber
value. This is used by the BTRFS filesystem driver and other modules.
When the STORAGE_DEVICE_NUMBER DeviceType member equals FILE_DEVICE_DISK,
the DeviceNumber and PartitionNumber correspond respectively to the
X and Y values in the \Device\Harddisk<X>\Partition<Y> device name.
References:
https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-io…
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddstor/ni-…
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddstor/ns-…
---
drivers/storage/partmgr/partition.c | 40 ++++++++++++++++++++++++++++++++++---
drivers/storage/partmgr/partmgr.c | 12 ++++++++++-
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/drivers/storage/partmgr/partition.c b/drivers/storage/partmgr/partition.c
index e8a38e728ca..3551898389f 100644
--- a/drivers/storage/partmgr/partition.c
+++ b/drivers/storage/partmgr/partition.c
@@ -27,17 +27,26 @@ PartitionCreateDevice(
UNICODE_STRING deviceName;
UINT32 volumeNum;
- // Create the partition/volume device object
-
volumeNum = HarddiskVolumeNextId++;
swprintf(nameBuf, L"\\Device\\HarddiskVolume%lu", volumeNum);
RtlCreateUnicodeString(&deviceName, nameBuf);
+ /*
+ * Create the partition/volume device object.
+ *
+ * Due to the fact we are also a (basic) volume manager, this device is
+ * ALSO a volume device. Because of this, we need to assign it a device
+ * name, and a specific device type for IoCreateDevice() to create a VPB
+ * for this device, so that a filesystem can be mounted on it.
+ * Once we get a separate volume manager, this partition DO can become
+ * anonymous, have a different device type, and without any associated VPB.
+ * (The attached volume, on the contrary, would require a VPB.)
+ */
PDEVICE_OBJECT partitionDevice;
NTSTATUS status = IoCreateDevice(FDObject->DriverObject,
sizeof(PARTITION_EXTENSION),
&deviceName,
- FILE_DEVICE_DISK,
+ FILE_DEVICE_DISK, // FILE_DEVICE_MASS_STORAGE,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&partitionDevice);
@@ -55,6 +64,10 @@ PartitionCreateDevice(
partExt->DeviceObject = partitionDevice;
partExt->LowerDevice = FDObject;
+ // NOTE: See comment above.
+ // PFDO_EXTENSION fdoExtension = FDObject->DeviceExtension;
+ // partitionDevice->DeviceType =
/*fdoExtension->LowerDevice*/FDObject->DeviceType;
+
partitionDevice->StackSize = FDObject->StackSize;
partitionDevice->Flags |= DO_DIRECT_IO;
@@ -767,6 +780,27 @@ PartitionHandleDeviceControl(
status = STATUS_SUCCESS;
break;
}
+ case IOCTL_STORAGE_GET_DEVICE_NUMBER:
+ {
+ PSTORAGE_DEVICE_NUMBER deviceNumber = Irp->AssociatedIrp.SystemBuffer;
+ if (!VerifyIrpOutBufferSize(Irp, sizeof(*deviceNumber)))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ PartMgrAcquireLayoutLock(fdoExtension);
+
+ deviceNumber->DeviceType = partExt->DeviceObject->DeviceType;
+ deviceNumber->DeviceNumber = fdoExtension->DiskData.DeviceNumber;
+ deviceNumber->PartitionNumber = partExt->DetectedNumber;
+
+ PartMgrReleaseLayoutLock(fdoExtension);
+
+ status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(*deviceNumber);
+ break;
+ }
case IOCTL_STORAGE_MEDIA_REMOVAL:
{
return ForwardIrpAndForget(DeviceObject, Irp);
diff --git a/drivers/storage/partmgr/partmgr.c b/drivers/storage/partmgr/partmgr.c
index b1c37b5d964..5b79d823898 100644
--- a/drivers/storage/partmgr/partmgr.c
+++ b/drivers/storage/partmgr/partmgr.c
@@ -1182,10 +1182,17 @@ PartMgrAddDevice(
PAGED_CODE();
+ /*
+ * Create the disk FDO. Use FILE_DEVICE_MASS_STORAGE type (or any other
+ * one that is NOT FILE_DEVICE_[DISK|VIRTUAL_DISK|CD_ROM|TAPE]), so that
+ * IoCreateDevice() doesn't automatically create a VPB for this device,
+ * even if we will later want this device to inherit the type of the
+ * underlying PDO which can have any of the types mentioned above.
+ */
NTSTATUS status = IoCreateDevice(DriverObject,
sizeof(FDO_EXTENSION),
NULL,
- FILE_DEVICE_BUS_EXTENDER,
+ FILE_DEVICE_MASS_STORAGE,
FILE_AUTOGENERATED_DEVICE_NAME |
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObject);
@@ -1210,6 +1217,9 @@ PartMgrAddDevice(
deviceExtension->PhysicalDiskDO = PhysicalDeviceObject;
KeInitializeEvent(&deviceExtension->SyncEvent, SynchronizationEvent, TRUE);
+ // Update now the device type with the actual underlying device type
+ deviceObject->DeviceType = deviceExtension->LowerDevice->DeviceType;
+
deviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
// The device is initialized