diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index a965db91179..3148e7e7b47 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -709,6 +709,12 @@ IopDereferenceDeviceObject( IN BOOLEAN ForceUnload ); +NTSTATUS +NTAPI +IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, + OUT PDEVICE_OBJECT *DeviceObject +); + // // IRP Routines // diff --git a/reactos/ntoskrnl/io/iomgr/device.c b/reactos/ntoskrnl/io/iomgr/device.c index 0df8da8aec4..051bf648aad 100644 --- a/reactos/ntoskrnl/io/iomgr/device.c +++ b/reactos/ntoskrnl/io/iomgr/device.c @@ -552,6 +552,51 @@ IopStartNextPacketByKeyEx(IN PDEVICE_OBJECT DeviceObject, } } +NTSTATUS +NTAPI +IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, + OUT PDEVICE_NODE *DeviceNode) +{ + NTSTATUS Status; + IO_STACK_LOCATION Stack = {0}; + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_RELATIONS DeviceRelations; + PDEVICE_OBJECT DeviceObject = NULL; + + ASSERT(FileObject); + + /* Get DeviceObject related to given FileObject */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + if (!DeviceObject) return STATUS_NO_SUCH_DEVICE; + + /* Define input parameters */ + Stack.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation; + Stack.FileObject = FileObject; + + /* Call the driver to query all relations (IRP_MJ_PNP) */ + Status = IopInitiatePnpIrp(DeviceObject, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_RELATIONS, + &Stack); + if (!NT_SUCCESS(Status)) return Status; + + /* Get returned pointer to DEVICE_RELATIONS */ + DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information; + + /* Make sure it's not NULL and contains only one object */ + ASSERT(DeviceRelations); + ASSERT(DeviceRelations->Count == 1); + + /* Finally get the device node */ + *DeviceNode = IopGetDeviceNode(DeviceRelations->Objects[0]); + if (!*DeviceNode) Status = STATUS_NO_SUCH_DEVICE; + + /* Free the DEVICE_RELATIONS structure, it's not needed anymore */ + ExFreePool(DeviceRelations); + + return Status; +} + /* PUBLIC FUNCTIONS ***********************************************************/ /* @@ -1207,6 +1252,26 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject) return DeviceObject; } +/* + * @implemented + */ +NTSTATUS +NTAPI +IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject, + OUT PDEVICE_OBJECT *DeviceObject) +{ + NTSTATUS Status; + PDEVICE_NODE DeviceNode = NULL; + + /* Call the internal helper function */ + Status = IopGetRelatedTargetDevice(FileObject, &DeviceNode); + if (NT_SUCCESS(Status) && DeviceNode) + { + *DeviceObject = DeviceNode->PhysicalDeviceObject; + } + return Status; +} + /* * @implemented */ diff --git a/reactos/ntoskrnl/io/iomgr/iofunc.c b/reactos/ntoskrnl/io/iomgr/iofunc.c index 4f253de9438..35049b4abfe 100644 --- a/reactos/ntoskrnl/io/iomgr/iofunc.c +++ b/reactos/ntoskrnl/io/iomgr/iofunc.c @@ -3307,7 +3307,8 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle, } /* Get the device object */ - DeviceObject = IoGetRelatedDeviceObject(FileObject); + Status = IoGetRelatedTargetDevice(FileObject, &DeviceObject); + if (!NT_SUCCESS(Status)) return Status; /* Clear File Object event */ KeClearEvent(&FileObject->Event);