diff --git a/modules/rostests/kmtests/CMakeLists.txt b/modules/rostests/kmtests/CMakeLists.txt index 8d56d61b2da..c12751eaa0f 100644 --- a/modules/rostests/kmtests/CMakeLists.txt +++ b/modules/rostests/kmtests/CMakeLists.txt @@ -67,6 +67,7 @@ list(APPEND KMTEST_DRV_SOURCE ntos_io/IoInterrupt.c ntos_io/IoIrp.c ntos_io/IoMdl.c + ntos_io/IoVolume.c ntos_ke/KeApc.c ntos_ke/KeDevQueue.c ntos_ke/KeDpc.c diff --git a/modules/rostests/kmtests/kmtest_drv/testlist.c b/modules/rostests/kmtests/kmtest_drv/testlist.c index 11d63bbad2b..3dc3a6d0fc6 100644 --- a/modules/rostests/kmtests/kmtest_drv/testlist.c +++ b/modules/rostests/kmtests/kmtest_drv/testlist.c @@ -33,6 +33,7 @@ KMT_TESTFUNC Test_IoFilesystem; KMT_TESTFUNC Test_IoInterrupt; KMT_TESTFUNC Test_IoIrp; KMT_TESTFUNC Test_IoMdl; +KMT_TESTFUNC Test_IoVolume; KMT_TESTFUNC Test_KeApc; KMT_TESTFUNC Test_KeDeviceQueue; KMT_TESTFUNC Test_KeDpc; @@ -106,6 +107,7 @@ const KMT_TEST TestList[] = { "IoInterrupt", Test_IoInterrupt }, { "IoIrp", Test_IoIrp }, { "IoMdl", Test_IoMdl }, + { "IoVolume", Test_IoVolume }, { "KeApc", Test_KeApc }, { "KeDeviceQueue", Test_KeDeviceQueue }, { "KeDpc", Test_KeDpc }, diff --git a/modules/rostests/kmtests/ntos_io/IoVolume.c b/modules/rostests/kmtests/ntos_io/IoVolume.c new file mode 100644 index 00000000000..ad862f49aad --- /dev/null +++ b/modules/rostests/kmtests/ntos_io/IoVolume.c @@ -0,0 +1,122 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Kernel-Mode Test Suite Volume Device test + * COPYRIGHT: Copyright 2019 Thomas Faber (thomas.faber@reactos.org) + */ + +#include + +static +NTSTATUS +GetNextVolumeDevice( + _Inout_ PUNICODE_STRING VolumeDeviceName, + _Inout_ PULONG VolumeNumber, + _In_ NTSTATUS PreviousStatus) +{ + NTSTATUS Status; + +#ifndef __REACTOS__ + *VolumeNumber++; + Status = RtlStringCbPrintfW(VolumeDeviceName->Buffer, + VolumeDeviceName->MaximumLength, + L"\\Device\\HarddiskVolume%lu", + *VolumeNumber); +#else + /* ROS's storage stack is old an broken, we don't have HarddiskVolumeN */ + ULONG DiskNumber, PartitionNumber; + DiskNumber = *VolumeNumber >> 16; + PartitionNumber = *VolumeNumber & 0xffff; + if (!NT_SUCCESS(PreviousStatus)) + { + if (PartitionNumber == 1) + { + /* Looks like this disk doesn't exist (or has no partitions), + * so we're done */ + return STATUS_NO_MORE_ENTRIES; + } + DiskNumber++; + PartitionNumber = 0; + } + PartitionNumber++; + Status = RtlStringCbPrintfW(VolumeDeviceName->Buffer, + VolumeDeviceName->MaximumLength, + L"\\Device\\Harddisk%lu\\Partition%lu", + DiskNumber, + PartitionNumber); + *VolumeNumber = DiskNumber << 16 | PartitionNumber; +#endif + return Status; +} + +static +void +TestIoVolumeDeviceToDosName(void) +{ + NTSTATUS Status; + ULONG VolumeNumber; + WCHAR VolumeDeviceNameBuffer[32]; + UNICODE_STRING VolumeDeviceName; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DosName; + UNICODE_STRING DosVolumePrefix = RTL_CONSTANT_STRING(L"\\\\?\\Volume"); + + RtlInitEmptyUnicodeString(&VolumeDeviceName, + VolumeDeviceNameBuffer, + sizeof(VolumeDeviceNameBuffer)); + VolumeNumber = 0; + Status = STATUS_SUCCESS; + while (1) + { + Status = GetNextVolumeDevice(&VolumeDeviceName, + &VolumeNumber, + Status); + if (!NT_SUCCESS(Status)) + { + trace("GetNextVolumeDevice(0x%lx) failed with %lx\n", + VolumeNumber, Status); + break; + } + + RtlInitUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer); + Status = IoGetDeviceObjectPointer(&VolumeDeviceName, + READ_CONTROL, + &FileObject, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + trace("IoGetDeviceObjectPointer(%wZ) failed with %lx\n", + &VolumeDeviceName, Status); + continue; + } + + Status = IoVolumeDeviceToDosName(DeviceObject, &DosName); + ok_eq_hex(Status, STATUS_SUCCESS); + if (!skip(NT_SUCCESS(Status), "No DOS name\n")) + { + trace("DOS name for %wZ is %wZ\n", &VolumeDeviceName, &DosName); + if (DosName.Length == 2 * sizeof(WCHAR)) + { + ok(DosName.Buffer[0] >= L'A' && + DosName.Buffer[0] <= L'Z' && + DosName.Buffer[1] == L':', + "Unexpected drive letter: %wZ\n", &DosName); + } + else + { + ok(RtlPrefixUnicodeString(&DosVolumePrefix, &DosName, FALSE), + "Unexpected volume path: %wZ\n", &DosName); + } + RtlFreeUnicodeString(&DosName); + } + ObDereferenceObject(FileObject); + Status = STATUS_SUCCESS; + } + ok(VolumeNumber > 1, "No volumes found\n"); +} + +START_TEST(IoVolume) +{ + TestIoVolumeDeviceToDosName(); +} diff --git a/ntoskrnl/io/iomgr/volume.c b/ntoskrnl/io/iomgr/volume.c index d5ab2ec17d1..6c2e3191e9a 100644 --- a/ntoskrnl/io/iomgr/volume.c +++ b/ntoskrnl/io/iomgr/volume.c @@ -1346,7 +1346,7 @@ IoVolumeDeviceToDosName(IN PVOID VolumeDeviceObject, goto DereferenceFO; } - Status = IoCallDriver(VolumeDeviceObject, Irp); + Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); @@ -1396,7 +1396,7 @@ IoVolumeDeviceToDosName(IN PVOID VolumeDeviceObject, goto ReleaseMemory; } - Status = IoCallDriver(VolumeDeviceObject, Irp); + Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);