diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 7fbde5095d6..cefc1ddd444 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1561,6 +1561,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, req->async.event = wine_server_obj_handle( event ); req->async.cvalue = cvalue; wine_server_add_data( req, in_buffer, in_size ); + if ((code & 3) != METHOD_BUFFERED) + wine_server_add_data( req, out_buffer, out_size ); wine_server_set_reply( req, out_buffer, out_size ); status = wine_server_call( req ); wait_handle = wine_server_ptr_handle( reply->wait ); diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 3c18ee654a5..912d0840318 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -428,17 +428,27 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n", params->ioctl.code, device, file, 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 ((params->ioctl.code & 3) == METHOD_BUFFERED) + if ((params->ioctl.code & 3) != METHOD_BUFFERED) { + if (in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST; + in_size -= out_size; + if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY; + memcpy( out_buff, (char *)in_buff + in_size, out_size ); + } + else if (out_size > in_size) + { + if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY; memcpy( out_buff, in_buff, in_size ); to_free = in_buff; in_buff = out_buff; } + else + { + out_buff = in_buff; + out_size = in_size; + } } irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size, @@ -449,6 +459,9 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG return STATUS_NO_MEMORY; } + if (out_size && (params->ioctl.code & 3) != METHOD_BUFFERED) + HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, in_buff, in_size ); + irp->Tail.Overlay.OriginalFileObject = file; irp->RequestorMode = UserMode; irp->AssociatedIrp.SystemBuffer = in_buff;