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