Commit 4c1da455 authored by Alexandre Julliard's avatar Alexandre Julliard

ntoskrnl: Allow IoCompleteRequest to report completion asynchronously.

parent ecf7ed66
...@@ -129,55 +129,54 @@ static HANDLE get_device_manager(void) ...@@ -129,55 +129,54 @@ static HANDLE get_device_manager(void)
} }
/* process an ioctl request for a given device */ /* process an ioctl request for a given device */
static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size, static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
void *out_buff, ULONG *out_size ) ULONG in_size, ULONG out_size, HANDLE ioctl )
{ {
IRP *irp; IRP *irp;
void *sys_buff = NULL; void *out_buff = NULL;
FILE_OBJECT file; FILE_OBJECT file;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER count; LARGE_INTEGER count;
TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, *out_size ); TRACE( "ioctl %x device %p in_size %u out_size %u\n", code, device, in_size, out_size );
/* so we can spot things that we should initialize */ /* so we can spot things that we should initialize */
memset( &file, 0x88, sizeof(file) ); memset( &file, 0x88, sizeof(file) );
if ((code & 3) == METHOD_BUFFERED) if ((code & 3) == METHOD_BUFFERED) out_size = max( in_size, out_size );
if (out_size)
{ {
if (!(sys_buff = HeapAlloc( GetProcessHeap(), 0, max( in_size, *out_size ) ))) if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
return STATUS_NO_MEMORY; if ((code & 3) == METHOD_BUFFERED)
memcpy( sys_buff, in_buff, in_size ); {
memcpy( out_buff, in_buff, in_size );
in_buff = out_buff;
}
} }
irp = IoBuildDeviceIoControlRequest( code, device, in_buff, in_size, out_buff, *out_size, /* note: we abuse UserIosb to store the server handle to the ioctl */
FALSE, NULL, &iosb ); irp = IoBuildDeviceIoControlRequest( code, device, in_buff, in_size, out_buff, out_size,
FALSE, NULL, (IO_STATUS_BLOCK *)ioctl );
if (!irp) if (!irp)
{ {
HeapFree( GetProcessHeap(), 0, sys_buff ); HeapFree( GetProcessHeap(), 0, out_buff );
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
irp->RequestorMode = UserMode; irp->RequestorMode = UserMode;
irp->AssociatedIrp.SystemBuffer = ((code & 3) == METHOD_BUFFERED) ? sys_buff : in_buff;
irp->UserBuffer = out_buff;
irp->Tail.Overlay.OriginalFileObject = &file; irp->Tail.Overlay.OriginalFileObject = &file;
file.FsContext = NULL; file.FsContext = NULL;
file.FsContext2 = NULL; file.FsContext2 = NULL;
IoAllocateMdl( out_buff, *out_size, FALSE, FALSE, irp ); KeQueryTickCount( &count ); /* update the global KeTickCount */
device->CurrentIrp = irp; device->CurrentIrp = irp;
KeQueryTickCount( &count ); /* update the global KeTickCount */
IoCallDriver( device, irp ); IoCallDriver( device, irp );
*out_size = (iosb.u.Status >= 0) ? iosb.Information : 0; device->CurrentIrp = NULL;
if (out_buff && (code & 3) == METHOD_BUFFERED) memcpy( out_buff, sys_buff, *out_size );
HeapFree( GetProcessHeap(), 0, sys_buff ); return STATUS_SUCCESS;
return iosb.u.Status;
} }
...@@ -187,10 +186,10 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ...@@ -187,10 +186,10 @@ static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff,
NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
{ {
HANDLE manager = get_device_manager(); HANDLE manager = get_device_manager();
obj_handle_t ioctl = 0; HANDLE ioctl = 0;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
ULONG code = 0; ULONG code = 0;
void *in_buff, *out_buff = NULL; void *in_buff;
DEVICE_OBJECT *device = NULL; DEVICE_OBJECT *device = NULL;
ULONG in_size = 4096, out_size = 0; ULONG in_size = 4096, out_size = 0;
HANDLE handles[2]; HANDLE handles[2];
...@@ -211,14 +210,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) ...@@ -211,14 +210,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
SERVER_START_REQ( get_next_device_request ) SERVER_START_REQ( get_next_device_request )
{ {
req->manager = wine_server_obj_handle( manager ); req->manager = wine_server_obj_handle( manager );
req->prev = ioctl; req->prev = wine_server_obj_handle( ioctl );
req->status = status; req->status = status;
wine_server_add_data( req, out_buff, out_size );
wine_server_set_reply( req, in_buff, in_size ); wine_server_set_reply( req, in_buff, in_size );
if (!(status = wine_server_call( req ))) if (!(status = wine_server_call( req )))
{ {
code = reply->code; code = reply->code;
ioctl = reply->next; ioctl = wine_server_ptr_handle( reply->next );
device = wine_server_get_ptr( reply->user_ptr ); device = wine_server_get_ptr( reply->user_ptr );
client_tid = reply->client_tid; client_tid = reply->client_tid;
client_pid = reply->client_pid; client_pid = reply->client_pid;
...@@ -237,10 +235,8 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) ...@@ -237,10 +235,8 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
switch(status) switch(status)
{ {
case STATUS_SUCCESS: case STATUS_SUCCESS:
HeapFree( GetProcessHeap(), 0, out_buff ); status = process_ioctl( device, code, in_buff, in_size, out_size, ioctl );
if (out_size) out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ); if (status == STATUS_SUCCESS) ioctl = 0; /* status reported by IoCompleteRequest */
else out_buff = NULL;
status = process_ioctl( device, code, in_buff, in_size, out_buff, &out_size );
break; break;
case STATUS_BUFFER_OVERFLOW: case STATUS_BUFFER_OVERFLOW:
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, in_buff );
...@@ -251,7 +247,6 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) ...@@ -251,7 +247,6 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
if (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) == WAIT_OBJECT_0) if (WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) == WAIT_OBJECT_0)
{ {
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, in_buff );
HeapFree( GetProcessHeap(), 0, out_buff );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
break; break;
...@@ -504,10 +499,26 @@ PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device, ...@@ -504,10 +499,26 @@ PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT device,
irpsp->Parameters.DeviceIoControl.IoControlCode = code; irpsp->Parameters.DeviceIoControl.IoControlCode = code;
irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len; irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len; irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
irpsp->DeviceObject = device; irpsp->DeviceObject = device;
irpsp->CompletionRoutine = NULL; irpsp->CompletionRoutine = NULL;
switch (code & 3)
{
case METHOD_BUFFERED:
irp->AssociatedIrp.SystemBuffer = in_buff;
break;
case METHOD_IN_DIRECT:
case METHOD_OUT_DIRECT:
irp->AssociatedIrp.SystemBuffer = in_buff;
IoAllocateMdl( out_buff, out_len, FALSE, FALSE, irp );
break;
case METHOD_NEITHER:
irpsp->Parameters.DeviceIoControl.Type3InputBuffer = in_buff;
break;
}
irp->RequestorMode = KernelMode;
irp->UserBuffer = out_buff;
irp->UserIosb = iosb; irp->UserIosb = iosb;
irp->UserEvent = event; irp->UserEvent = event;
return irp; return irp;
...@@ -958,13 +969,12 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost ) ...@@ -958,13 +969,12 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
{ {
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
PIO_COMPLETION_ROUTINE routine; PIO_COMPLETION_ROUTINE routine;
IO_STATUS_BLOCK *iosb;
NTSTATUS status, stat; NTSTATUS status, stat;
HANDLE ioctl;
int call_flag = 0; int call_flag = 0;
TRACE( "%p %u\n", irp, priority_boost ); TRACE( "%p %u\n", irp, priority_boost );
iosb = irp->UserIosb;
status = irp->IoStatus.u.Status; status = irp->IoStatus.u.Status;
while (irp->CurrentLocation <= irp->StackCount) while (irp->CurrentLocation <= irp->StackCount)
{ {
...@@ -991,11 +1001,26 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost ) ...@@ -991,11 +1001,26 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
return; return;
} }
} }
if (iosb)
ioctl = (HANDLE)irp->UserIosb;
if (ioctl)
{ {
iosb->u.Status = irp->IoStatus.u.Status; HANDLE manager = get_device_manager();
if (iosb->u.Status >= 0) iosb->Information = irp->IoStatus.Information; void *out_buff = irp->UserBuffer;
SERVER_START_REQ( set_ioctl_result )
{
req->manager = wine_server_obj_handle( manager );
req->handle = wine_server_obj_handle( ioctl );
req->status = irp->IoStatus.u.Status;
if (irp->IoStatus.u.Status >= 0 && out_buff)
wine_server_add_data( req, out_buff, irp->IoStatus.Information );
wine_server_call( req );
}
SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, out_buff );
} }
IoFreeIrp( irp ); IoFreeIrp( irp );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment