Alexandre Julliard : ntoskrnl: Add support for read and write requests.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 6 09:29:04 CDT 2015


Module: wine
Branch: master
Commit: 2cd717a604ace11de820d85211ea1e5143c21fa9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2cd717a604ace11de820d85211ea1e5143c21fa9

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue May  5 14:24:00 2015 +0900

ntoskrnl: Add support for read and write requests.

---

 dlls/ntoskrnl.exe/ntoskrnl.c | 159 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 125 insertions(+), 34 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index f8e1f18..de99970 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -128,26 +128,96 @@ static HANDLE get_device_manager(void)
     return ret;
 }
 
-/* process an ioctl request for a given device */
-static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
-                               ULONG in_size, ULONG out_size, HANDLE ioctl )
+static NTSTATUS dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
 {
-    IRP *irp;
-    void *out_buff = NULL;
-    FILE_OBJECT file;
     LARGE_INTEGER count;
+    FILE_OBJECT file;
 
-    TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, out_size );
+    irp->RequestorMode = UserMode;
+    irp->Tail.Overlay.OriginalFileObject = &file;
 
-    /* so we can spot things that we should initialize */
     memset( &file, 0x88, sizeof(file) );
+    file.FsContext = NULL;
+    file.FsContext2 = NULL;
+
+    KeQueryTickCount( &count );  /* update the global KeTickCount */
+
+    device->CurrentIrp = irp;
+
+    IoCallDriver( device, irp );
+
+    device->CurrentIrp = NULL;
+
+    return STATUS_SUCCESS;
+}
+
+/* process a read request for a given device */
+static NTSTATUS dispatch_read( DEVICE_OBJECT *device, const irp_params_t *params,
+                               void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
+{
+    IRP *irp;
+    void *out_buff;
+    LARGE_INTEGER offset;
+    IO_STACK_LOCATION *irpsp;
+
+    TRACE( "device %p size %u\n", device, out_size );
+
+    if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
+
+    offset.QuadPart = params->read.pos;
 
-    if ((code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
+    /* 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 )))
+    {
+        HeapFree( GetProcessHeap(), 0, out_buff );
+        return STATUS_NO_MEMORY;
+    }
+
+    irpsp = IoGetNextIrpStackLocation( irp );
+    irpsp->Parameters.Read.Key = params->read.key;
+
+    return dispatch_irp( device, irp );
+}
+
+/* process a write request for a given device */
+static NTSTATUS dispatch_write( DEVICE_OBJECT *device, const irp_params_t *params,
+                                void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
+{
+    IRP *irp;
+    LARGE_INTEGER offset;
+    IO_STACK_LOCATION *irpsp;
+
+    TRACE( "device %p size %u\n", device, in_size );
+
+    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 )))
+        return STATUS_NO_MEMORY;
+
+    irpsp = IoGetNextIrpStackLocation( irp );
+    irpsp->Parameters.Write.Key = params->write.key;
+
+    return dispatch_irp( device, irp );
+}
+
+/* process an ioctl request for a given device */
+static NTSTATUS dispatch_ioctl( DEVICE_OBJECT *device, const irp_params_t *params,
+                                void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle )
+{
+    IRP *irp;
+    void *out_buff = NULL;
+
+    TRACE( "ioctl %x device %p in_size %u out_size %u\n", params->ioctl.code, device, in_size, out_size );
+
+    if ((params->ioctl.code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
 
     if (out_size)
     {
         if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
-        if ((code & 3) == METHOD_BUFFERED)
+        if ((params->ioctl.code & 3) == METHOD_BUFFERED)
         {
             memcpy( out_buff, in_buff, in_size );
             in_buff = out_buff;
@@ -155,29 +225,50 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
     }
 
     /* note: we abuse UserIosb to store the server handle to the ioctl */
-    irp = IoBuildDeviceIoControlRequest( code, device, in_buff, in_size, out_buff, out_size,
-                                         FALSE, NULL, (IO_STATUS_BLOCK *)ioctl );
+    irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
+                                         FALSE, NULL, irp_handle );
     if (!irp)
     {
         HeapFree( GetProcessHeap(), 0, out_buff );
         return STATUS_NO_MEMORY;
     }
-    irp->RequestorMode = UserMode;
-    irp->Tail.Overlay.OriginalFileObject = &file;
-
-    file.FsContext = NULL;
-    file.FsContext2 = NULL;
-
-    KeQueryTickCount( &count );  /* update the global KeTickCount */
-
-    device->CurrentIrp = irp;
-
-    IoCallDriver( device, irp );
-
-    device->CurrentIrp = NULL;
-
-    return STATUS_SUCCESS;
-}
+    return dispatch_irp( device, irp );
+}
+
+typedef NTSTATUS (*dispatch_func)( DEVICE_OBJECT *device, const irp_params_t *params,
+                                   void *in_buff, ULONG in_size, ULONG out_size, HANDLE irp_handle );
+
+static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] =
+{
+    NULL,              /* IRP_MJ_CREATE */
+    NULL,              /* IRP_MJ_CREATE_NAMED_PIPE */
+    NULL,              /* IRP_MJ_CLOSE */
+    dispatch_read,     /* IRP_MJ_READ */
+    dispatch_write,    /* IRP_MJ_WRITE */
+    NULL,              /* IRP_MJ_QUERY_INFORMATION */
+    NULL,              /* IRP_MJ_SET_INFORMATION */
+    NULL,              /* IRP_MJ_QUERY_EA */
+    NULL,              /* IRP_MJ_SET_EA */
+    NULL,              /* IRP_MJ_FLUSH_BUFFERS */
+    NULL,              /* IRP_MJ_QUERY_VOLUME_INFORMATION */
+    NULL,              /* IRP_MJ_SET_VOLUME_INFORMATION */
+    NULL,              /* IRP_MJ_DIRECTORY_CONTROL */
+    NULL,              /* IRP_MJ_FILE_SYSTEM_CONTROL */
+    dispatch_ioctl,    /* IRP_MJ_DEVICE_CONTROL */
+    NULL,              /* IRP_MJ_INTERNAL_DEVICE_CONTROL */
+    NULL,              /* IRP_MJ_SHUTDOWN */
+    NULL,              /* IRP_MJ_LOCK_CONTROL */
+    NULL,              /* IRP_MJ_CLEANUP */
+    NULL,              /* IRP_MJ_CREATE_MAILSLOT */
+    NULL,              /* IRP_MJ_QUERY_SECURITY */
+    NULL,              /* IRP_MJ_SET_SECURITY */
+    NULL,              /* IRP_MJ_POWER */
+    NULL,              /* IRP_MJ_SYSTEM_CONTROL */
+    NULL,              /* IRP_MJ_DEVICE_CHANGE */
+    NULL,              /* IRP_MJ_QUERY_QUOTA */
+    NULL,              /* IRP_MJ_SET_QUOTA */
+    NULL,              /* IRP_MJ_PNP */
+};
 
 
 /***********************************************************************
@@ -235,16 +326,16 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
         switch(status)
         {
         case STATUS_SUCCESS:
-            switch (irp_params.major)
+            if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION ||
+                !dispatch_funcs[irp_params.major] ||
+                !device->DriverObject->MajorFunction[irp_params.major])
             {
-            case IRP_MJ_DEVICE_CONTROL:
-                status = process_ioctl( device, irp_params.ioctl.code, in_buff, in_size, out_size, irp );
-                break;
-            default:
-                FIXME( "unsupported request %u\n", irp_params.major );
+                WARN( "unsupported request %u\n", irp_params.major );
                 status = STATUS_NOT_SUPPORTED;
                 break;
             }
+            status = dispatch_funcs[irp_params.major]( device, &irp_params,
+                                                       in_buff, in_size, out_size, irp );
             if (status == STATUS_SUCCESS) irp = 0;  /* status reported by IoCompleteRequest */
             break;
         case STATUS_BUFFER_OVERFLOW:




More information about the wine-cvs mailing list