ntoskrnl.exe: Use completion routine to transfer result of IRP back to server.

Sebastian Lackner sebastian at fds-team.de
Mon Oct 10 10:15:39 CDT 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---

No longer abuses UserIosb to store the IRP handle. Other parts of Wine
pass an IO_STATUS_BLOCK pointer, and there would be no good way to
distinguish both. When using a completion, we can store the handle in
the Context parameter.

 dlls/ntoskrnl.exe/ntoskrnl.c |   83 ++++++++++++++++++++-----------------------
 include/ddk/wdm.h            |   12 ++++++
 2 files changed, 51 insertions(+), 44 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index cf87f7a..909bf6f 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -172,16 +172,40 @@ static HANDLE get_device_manager(void)
     return ret;
 }
 
-static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
+/* transfer result of IRP back to wineserver */
+static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context )
+{
+    FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
+    void *out_buff = irp->UserBuffer;
+    HANDLE handle = context;
+
+    SERVER_START_REQ( set_irp_result )
+    {
+        req->handle   = wine_server_obj_handle( handle );
+        req->status   = irp->IoStatus.u.Status;
+        req->file_ptr = wine_server_client_ptr( file );
+        if (irp->IoStatus.u.Status >= 0)
+        {
+            req->size = irp->IoStatus.Information;
+            if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
+        }
+        wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    HeapFree( GetProcessHeap(), 0, out_buff );
+    return STATUS_SUCCESS;
+}
+
+static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, HANDLE irp_handle )
 {
     LARGE_INTEGER count;
 
+    IoSetCompletionRoutine( irp, dispatch_irp_completion, irp_handle, TRUE, TRUE, TRUE );
     KeQueryTickCount( &count );  /* update the global KeTickCount */
 
     device->CurrentIrp = irp;
-
     IoCallDriver( device, irp );
-
     device->CurrentIrp = NULL;
 }
 
@@ -211,7 +235,6 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
     irpsp = IoGetNextIrpStackLocation( irp );
     irpsp->MajorFunction = IRP_MJ_CREATE;
     irpsp->DeviceObject = device;
-    irpsp->CompletionRoutine = NULL;
     irpsp->Parameters.Create.SecurityContext = NULL;  /* FIXME */
     irpsp->Parameters.Create.Options = params->create.options;
     irpsp->Parameters.Create.ShareAccess = params->create.sharing;
@@ -222,10 +245,10 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
     irp->RequestorMode = UserMode;
     irp->AssociatedIrp.SystemBuffer = NULL;
     irp->UserBuffer = NULL;
-    irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
+    irp->UserIosb = NULL;
     irp->UserEvent = NULL;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     return STATUS_SUCCESS;
 }
@@ -254,16 +277,15 @@ static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG
     irpsp = IoGetNextIrpStackLocation( irp );
     irpsp->MajorFunction = IRP_MJ_CLOSE;
     irpsp->DeviceObject = device;
-    irpsp->CompletionRoutine = NULL;
 
     irp->Tail.Overlay.OriginalFileObject = file;
     irp->RequestorMode = UserMode;
     irp->AssociatedIrp.SystemBuffer = NULL;
     irp->UserBuffer = NULL;
-    irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
+    irp->UserIosb = NULL;
     irp->UserEvent = NULL;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     HeapFree( GetProcessHeap(), 0, file );  /* FIXME: async close processing not supported */
     return STATUS_SUCCESS;
@@ -290,9 +312,8 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
 
     offset.QuadPart = params->read.pos;
 
-    /* note: we abuse UserIosb to store the server irp handle */
     if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
-                                              &offset, NULL, irp_handle )))
+                                              &offset, NULL, NULL )))
     {
         HeapFree( GetProcessHeap(), 0, out_buff );
         return STATUS_NO_MEMORY;
@@ -304,7 +325,7 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
     irpsp = IoGetNextIrpStackLocation( irp );
     irpsp->Parameters.Read.Key = params->read.key;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     return STATUS_SUCCESS;
 }
@@ -327,9 +348,8 @@ static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG
 
     offset.QuadPart = params->write.pos;
 
-    /* note: we abuse UserIosb to store the server irp handle */
     if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size,
-                                              &offset, NULL, irp_handle )))
+                                              &offset, NULL, NULL )))
         return STATUS_NO_MEMORY;
 
     irp->Tail.Overlay.OriginalFileObject = file;
@@ -338,7 +358,7 @@ static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG
     irpsp = IoGetNextIrpStackLocation( irp );
     irpsp->Parameters.Write.Key = params->write.key;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     return STATUS_SUCCESS;
 }
@@ -357,15 +377,14 @@ static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG
 
     TRACE( "device %p file %p\n", device, file );
 
-    /* note: we abuse UserIosb to store the server irp handle */
     if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, NULL, 0,
-                                              NULL, NULL, irp_handle )))
+                                              NULL, NULL, NULL )))
         return STATUS_NO_MEMORY;
 
     irp->Tail.Overlay.OriginalFileObject = file;
     irp->RequestorMode = UserMode;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     return STATUS_SUCCESS;
 }
@@ -398,9 +417,8 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG
         }
     }
 
-    /* note: we abuse UserIosb to store the server handle to the ioctl */
     irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
-                                         FALSE, NULL, irp_handle );
+                                         FALSE, NULL, NULL );
     if (!irp)
     {
         HeapFree( GetProcessHeap(), 0, out_buff );
@@ -410,7 +428,7 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG
     irp->Tail.Overlay.OriginalFileObject = file;
     irp->RequestorMode = UserMode;
 
-    dispatch_irp( device, irp );
+    dispatch_irp( device, irp, irp_handle );
 
     return STATUS_SUCCESS;
 }
@@ -1390,7 +1408,6 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
     IO_STACK_LOCATION *irpsp;
     PIO_COMPLETION_ROUTINE routine;
     NTSTATUS status, stat;
-    HANDLE handle;
     int call_flag = 0;
 
     TRACE( "%p %u\n", irp, priority_boost );
@@ -1422,28 +1439,6 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
         }
     }
 
-    handle = (HANDLE)irp->UserIosb;
-    if (handle)
-    {
-        void *out_buff = irp->UserBuffer;
-        FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
-
-        SERVER_START_REQ( set_irp_result )
-        {
-            req->handle   = wine_server_obj_handle( handle );
-            req->status   = irp->IoStatus.u.Status;
-            req->file_ptr = wine_server_client_ptr( file );
-            if (irp->IoStatus.u.Status >= 0)
-            {
-                req->size = irp->IoStatus.Information;
-                if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
-            }
-            wine_server_call( req );
-        }
-        SERVER_END_REQ;
-        HeapFree( GetProcessHeap(), 0, out_buff );
-    }
-
     IoFreeIrp( irp );
 }
 
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 918797e..5602f7d 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1189,6 +1189,18 @@ NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
 # endif
 #endif
 
+static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routine, void *context,
+                                          BOOLEAN on_success, BOOLEAN on_error, BOOLEAN on_cancel)
+{
+    IO_STACK_LOCATION *irpsp = IoGetNextIrpStackLocation(irp);
+    irpsp->CompletionRoutine = routine;
+    irpsp->Context = context;
+    irpsp->Control = 0;
+    if (on_success) irpsp->Control |= SL_INVOKE_ON_SUCCESS;
+    if (on_error)   irpsp->Control |= SL_INVOKE_ON_ERROR;
+    if (on_cancel)  irpsp->Control |= SL_INVOKE_ON_CANCEL;
+}
+
 #define KernelMode 0
 #define UserMode   1
 
-- 
2.9.0



More information about the wine-patches mailing list