From 2cd717a604ace11de820d85211ea1e5143c21fa9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 5 May 2015 14:24:00 +0900 Subject: [PATCH] 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 f8e1f18c459..de999703e10 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: -- 2.11.4.GIT