[NTOS:IO] Send IRPs to the correct device in IoVolumeDeviceToDosName. CORE-15415
authorThomas Faber <thomas.faber@reactos.org>
Fri, 29 Mar 2019 08:08:36 +0000 (09:08 +0100)
committerThomas Faber <thomas.faber@reactos.org>
Sat, 30 Mar 2019 09:13:27 +0000 (10:13 +0100)
modules/rostests/kmtests/CMakeLists.txt
modules/rostests/kmtests/kmtest_drv/testlist.c
modules/rostests/kmtests/ntos_io/IoVolume.c [new file with mode: 0644]
ntoskrnl/io/iomgr/volume.c

index 8d56d61..c12751e 100644 (file)
@@ -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
index 11d63bb..3dc3a6d 100644 (file)
@@ -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 (file)
index 0000000..ad862f4
--- /dev/null
@@ -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 <kmt_test.h>
+
+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();
+}
index d5ab2ec..6c2e319 100644 (file)
@@ -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);