From 73bb6721cbf72756409321a2d1c005b522de0241 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Fri, 29 May 2009 17:35:45 +0400 Subject: [PATCH] Add implementation of IRP_MJ_WRITE handling. --- dlls/ntdll/file.c | 7 ++++- dlls/ntoskrnl.exe/ntoskrnl.c | 60 +++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 732f02947e..6323479fd0 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -523,7 +523,9 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL } -#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \ +#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \ + METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINE_DRIVER_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x101, \ METHOD_BUFFERED, FILE_ANY_ACCESS) static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, @@ -917,6 +919,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle, &needs_close, &type, &options ); + if (status == STATUS_BAD_DEVICE_TYPE) + return server_ioctl_file( hFile, hEvent, apc, apc_user, io_status, + IOCTL_WINE_DRIVER_WRITE, buffer, length, buffer, length ); if (status) return status; if (!virtual_check_buffer_for_read( buffer, length )) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 7c659c8ee3..54d3826216 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -134,7 +134,9 @@ struct HandleInstance ULONG refs; }; -#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \ +#define IOCTL_WINE_DRIVER_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x100, \ + METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINE_DRIVER_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x101, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #ifdef __i386__ @@ -612,6 +614,49 @@ static NTSTATUS process_read( DEVICE_OBJECT *device, void *buff, ULONG *size ) return status; } +/* process IRP_MJ_WRITE request for a given device */ +static NTSTATUS process_write( DEVICE_OBJECT *device, void *buff, ULONG *size ) +{ + PIRP irp; + PIO_STACK_LOCATION irpsp; + NTSTATUS status; + LARGE_INTEGER count; + MDL mdl; + + irp = IoAllocateIrp( device->StackSize, FALSE ); + if (irp == NULL) + return STATUS_NO_MEMORY; + irp->RequestorMode = UserMode; + irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1; + irpsp->DeviceObject = device; + irpsp->MajorFunction = IRP_MJ_WRITE; + irpsp->Parameters.Write.Length = *size; + device->CurrentIrp = irp; + + if (device->Flags & DO_DIRECT_IO) + { + mdl.Next = NULL; + mdl.Size = sizeof(mdl); + mdl.MdlFlags = MDL_PAGES_LOCKED; + mdl.StartVa = buff; + mdl.MappedSystemVa = buff; + mdl.ByteCount = *size; + mdl.ByteOffset = 0; + irp->MdlAddress = &mdl; + } + else if (device->Flags & DO_BUFFERED_IO) + irp->AssociatedIrp.SystemBuffer = buff; + else irp->UserBuffer = buff; + + KeQueryTickCount( &count ); /* update the global KeTickCount */ + status = IoCallDriver( device, irp ); + irp->IoStatus.Information = *size; + if (irp->MdlAddress == NULL) /* for UPKey.sys */ + *size = (status == STATUS_SUCCESS) ? irp->IoStatus.Information : 0; + IoFreeIrp( irp ); + return status; +} + /*********************************************************************** * wine_ntoskrnl_main_loop (Not a Windows API) @@ -674,14 +719,19 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) else out_buff = NULL; while (device->AttachedDevice) device = device->AttachedDevice; - if (code != IOCTL_WINE_DRIVER_READ) + if (code == IOCTL_WINE_DRIVER_READ) { - status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size ); + memcpy( out_buff, in_buff, min( in_size, out_size ) ); + status = process_read( device, out_buff, &out_size ); } - else + else if (code == IOCTL_WINE_DRIVER_WRITE) { memcpy( out_buff, in_buff, min( in_size, out_size ) ); - status = process_read( device, out_buff, &out_size ); + status = process_write( device, out_buff, &out_size ); + } + else + { + status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size ); } break; case STATUS_BUFFER_OVERFLOW: -- 2.33.8