Zebediah Figura : ntoskrnl.exe: Dispatch user IRPs to the top of the device stack.

Alexandre Julliard julliard at winehq.org
Thu Jun 6 17:05:19 CDT 2019


Module: wine
Branch: master
Commit: 4820d9d76ca2dba20c264354f776ed6633df0817
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4820d9d76ca2dba20c264354f776ed6633df0817

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Thu Jun  6 11:12:51 2019 -0400

ntoskrnl.exe: Dispatch user IRPs to the top of the device stack.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/ntoskrnl.c       | 12 ++++++-----
 dlls/ntoskrnl.exe/tests/driver.c   | 44 ++++++++++++++++++++++++++++++--------
 dlls/ntoskrnl.exe/tests/driver.h   |  1 +
 dlls/ntoskrnl.exe/tests/ntoskrnl.c | 11 ++++++++--
 include/ddk/ntifs.h                |  1 +
 5 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index cf4d8cb..ec24e08 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -516,6 +516,8 @@ static NTSTATUS dispatch_create( struct dispatch_context *context )
     file->Size = sizeof(*file);
     file->DeviceObject = device;
 
+    device = IoGetAttachedDevice( device );
+
     if (!(irp = IoAllocateIrp( device->StackSize, FALSE ))) return STATUS_NO_MEMORY;
 
     irpsp = IoGetNextIrpStackLocation( irp );
@@ -550,7 +552,7 @@ static NTSTATUS dispatch_close( struct dispatch_context *context )
 
     if (!file) return STATUS_INVALID_HANDLE;
 
-    device = file->DeviceObject;
+    device = IoGetAttachedDevice( file->DeviceObject );
 
     TRACE( "device %p file %p\n", device, file );
 
@@ -590,7 +592,7 @@ static NTSTATUS dispatch_read( struct dispatch_context *context )
 
     if (!file) return STATUS_INVALID_HANDLE;
 
-    device = file->DeviceObject;
+    device = IoGetAttachedDevice( file->DeviceObject );
 
     TRACE( "device %p file %p size %u\n", device, file, out_size );
 
@@ -630,7 +632,7 @@ static NTSTATUS dispatch_write( struct dispatch_context *context )
 
     if (!file) return STATUS_INVALID_HANDLE;
 
-    device = file->DeviceObject;
+    device = IoGetAttachedDevice( file->DeviceObject );
 
     TRACE( "device %p file %p size %u\n", device, file, context->in_size );
 
@@ -665,7 +667,7 @@ static NTSTATUS dispatch_flush( struct dispatch_context *context )
 
     if (!file) return STATUS_INVALID_HANDLE;
 
-    device = file->DeviceObject;
+    device = IoGetAttachedDevice( file->DeviceObject );
 
     TRACE( "device %p file %p\n", device, file );
 
@@ -697,7 +699,7 @@ static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
 
     if (!file) return STATUS_INVALID_HANDLE;
 
-    device = file->DeviceObject;
+    device = IoGetAttachedDevice( file->DeviceObject );
 
     TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
            context->params.ioctl.code, device, file, context->in_size, out_size );
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c
index 468b183..f5801a5 100644
--- a/dlls/ntoskrnl.exe/tests/driver.c
+++ b/dlls/ntoskrnl.exe/tests/driver.c
@@ -34,12 +34,15 @@
 
 #include "driver.h"
 
-static const WCHAR driver_device[] = {'\\','D','e','v','i','c','e',
-                                      '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
+static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
+                                    '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
+static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
+                                   '\\','W','i','n','e','T','e','s','t','U','p','p','e','r',0};
 static const WCHAR driver_link[] = {'\\','D','o','s','D','e','v','i','c','e','s',
                                     '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
 
 static DRIVER_OBJECT *driver_obj;
+static DEVICE_OBJECT *lower_device, *upper_device;
 
 static HANDLE okfile;
 static LONG successes;
@@ -234,10 +237,11 @@ static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device)
 {
     IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
 
+    ok(device == upper_device, "Expected device %p, got %p.\n", upper_device, device);
     ok(last_created_file != NULL, "last_created_file = NULL\n");
     ok(irpsp->FileObject == last_created_file, "FileObject != last_created_file\n");
-    ok(irpsp->DeviceObject == device, "unexpected DeviceObject\n");
-    ok(irpsp->FileObject->DeviceObject == device, "unexpected FileObject->DeviceObject\n");
+    ok(irpsp->DeviceObject == upper_device, "unexpected DeviceObject\n");
+    ok(irpsp->FileObject->DeviceObject == lower_device, "unexpected FileObject->DeviceObject\n");
     ok(!irp->UserEvent, "UserEvent = %p\n", irp->UserEvent);
     ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
        "IRP thread is not the current thread\n");
@@ -1591,7 +1595,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st
 
     if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
 
-    main_test_work_item = IoAllocateWorkItem(device);
+    main_test_work_item = IoAllocateWorkItem(lower_device);
     ok(main_test_work_item != NULL, "main_test_work_item = NULL\n");
 
     IoQueueWorkItem(main_test_work_item, main_test_task, DelayedWorkQueue, irp);
@@ -1687,6 +1691,10 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
         case IOCTL_WINETEST_GET_CANCEL_COUNT:
             status = get_cancel_count(irp, stack, &irp->IoStatus.Information);
             break;
+        case IOCTL_WINETEST_DETACH:
+            IoDetachDevice(lower_device);
+            status = STATUS_SUCCESS;
+            break;
         default:
             break;
     }
@@ -1703,6 +1711,7 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp)
 static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
 {
     IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
+    ok(device == lower_device, "Expected device %p, got %p.\n", lower_device, device);
     ok(irpsp->DeviceObject == device, "device != DeviceObject\n");
     ok(irp->Tail.Overlay.Thread == (PETHREAD)KeGetCurrentThread(),
        "IRP thread is not the current thread\n");
@@ -1726,13 +1735,13 @@ static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
     RtlInitUnicodeString(&linkW, driver_link);
     IoDeleteSymbolicLink(&linkW);
 
-    IoDeleteDevice(driver->DeviceObject);
+    IoDeleteDevice(upper_device);
+    IoDeleteDevice(lower_device);
 }
 
 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
 {
     UNICODE_STRING nameW, linkW;
-    DEVICE_OBJECT *device;
     NTSTATUS status;
 
     DbgPrint("loading driver\n");
@@ -1748,12 +1757,29 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
     driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS]     = driver_FlushBuffers;
     driver->MajorFunction[IRP_MJ_CLOSE]             = driver_Close;
 
-    RtlInitUnicodeString(&nameW, driver_device);
+    RtlInitUnicodeString(&nameW, device_name);
     RtlInitUnicodeString(&linkW, driver_link);
 
     if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
-                                  FILE_DEVICE_SECURE_OPEN, FALSE, &device)))
+                                  FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device)))
+    {
         status = IoCreateSymbolicLink(&linkW, &nameW);
+        lower_device->Flags &= ~DO_DEVICE_INITIALIZING;
+    }
+
+    if (!status)
+    {
+        RtlInitUnicodeString(&nameW, upper_name);
+
+        status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN,
+                                FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device);
+    }
+
+    if (!status)
+    {
+        IoAttachDeviceToDeviceStack(upper_device, lower_device);
+        upper_device->Flags &= ~DO_DEVICE_INITIALIZING;
+    }
 
     return status;
 }
diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h
index 1e75529..d5ff09a 100644
--- a/dlls/ntoskrnl.exe/tests/driver.h
+++ b/dlls/ntoskrnl.exe/tests/driver.h
@@ -28,6 +28,7 @@
 #define IOCTL_WINETEST_RESET_CANCEL     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_WINETEST_TEST_CANCEL      CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_WINETEST_GET_CANCEL_COUNT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_DETACH           CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 static const char teststr[] = "Wine is not an emulator";
 
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index 43418f3..19eeca2 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -63,8 +63,6 @@ static void unload_driver(SC_HANDLE service)
 {
     SERVICE_STATUS status;
 
-    CloseHandle(device);
-
     ControlService(service, SERVICE_CONTROL_STOP, &status);
     while (status.dwCurrentState == SERVICE_STOP_PENDING)
     {
@@ -343,6 +341,8 @@ START_TEST(ntoskrnl)
 {
     char filename[MAX_PATH], filename2[MAX_PATH];
     SC_HANDLE service, service2;
+    DWORD written;
+    BOOL ret;
 
     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
     pRtlDosPathNameToNtPathName_U = (void *)GetProcAddress(hntdll, "RtlDosPathNameToNtPathName_U");
@@ -368,6 +368,13 @@ START_TEST(ntoskrnl)
     test_overlapped();
     test_load_driver(service2);
 
+    /* We need a separate ioctl to call IoDetachDevice(); calling it in the
+     * driver unload routine causes a live-lock. */
+    ret = DeviceIoControl(device, IOCTL_WINETEST_DETACH, NULL, 0, NULL, 0, &written, NULL);
+    ok(ret, "DeviceIoControl failed: %u\n", GetLastError());
+
+    CloseHandle(device);
+
     unload_driver(service2);
     unload_driver(service);
     ok(DeleteFileA(filename), "DeleteFile failed: %u\n", GetLastError());
diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h
index acdd232..b287b06 100644
--- a/include/ddk/ntifs.h
+++ b/include/ddk/ntifs.h
@@ -130,6 +130,7 @@ typedef struct _FS_FILTER_CALLBACKS
 } FS_FILTER_CALLBACKS, *PFS_FILTER_CALLBACKS;
 
 BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING, PUNICODE_STRING, BOOLEAN, PWCH);
+DEVICE_OBJECT * WINAPI IoGetAttachedDevice(DEVICE_OBJECT*);
 NTSTATUS WINAPI ObOpenObjectByPointer(void*,ULONG,PACCESS_STATE,ACCESS_MASK,POBJECT_TYPE,KPROCESSOR_MODE,HANDLE*);
 NTSTATUS WINAPI ObQueryNameString(PVOID,POBJECT_NAME_INFORMATION,ULONG,PULONG);
 BOOLEAN WINAPI PsIsSystemThread(PETHREAD);




More information about the wine-cvs mailing list