ntoskrnl.exe: Use completion routine to transfer result of IRP back to server.

Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2016-10-10 17:15:39 +02:00 committed by Alexandre Julliard
parent 28cfa306b4
commit 5400210376
2 changed files with 51 additions and 44 deletions

View file

@ -172,16 +172,40 @@ static HANDLE get_device_manager(void)
return ret;
}
static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp )
/* transfer result of IRP back to wineserver */
static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context )
{
FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
void *out_buff = irp->UserBuffer;
HANDLE handle = context;
SERVER_START_REQ( set_irp_result )
{
req->handle = wine_server_obj_handle( handle );
req->status = irp->IoStatus.u.Status;
req->file_ptr = wine_server_client_ptr( file );
if (irp->IoStatus.u.Status >= 0)
{
req->size = irp->IoStatus.Information;
if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information );
}
wine_server_call( req );
}
SERVER_END_REQ;
HeapFree( GetProcessHeap(), 0, out_buff );
return STATUS_SUCCESS;
}
static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, HANDLE irp_handle )
{
LARGE_INTEGER count;
IoSetCompletionRoutine( irp, dispatch_irp_completion, irp_handle, TRUE, TRUE, TRUE );
KeQueryTickCount( &count ); /* update the global KeTickCount */
device->CurrentIrp = irp;
IoCallDriver( device, irp );
device->CurrentIrp = NULL;
}
@ -211,7 +235,6 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
irpsp = IoGetNextIrpStackLocation( irp );
irpsp->MajorFunction = IRP_MJ_CREATE;
irpsp->DeviceObject = device;
irpsp->CompletionRoutine = NULL;
irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
irpsp->Parameters.Create.Options = params->create.options;
irpsp->Parameters.Create.ShareAccess = params->create.sharing;
@ -222,10 +245,10 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
irp->RequestorMode = UserMode;
irp->AssociatedIrp.SystemBuffer = NULL;
irp->UserBuffer = NULL;
irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
irp->UserIosb = NULL;
irp->UserEvent = NULL;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
return STATUS_SUCCESS;
}
@ -254,16 +277,15 @@ static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp );
irpsp->MajorFunction = IRP_MJ_CLOSE;
irpsp->DeviceObject = device;
irpsp->CompletionRoutine = NULL;
irp->Tail.Overlay.OriginalFileObject = file;
irp->RequestorMode = UserMode;
irp->AssociatedIrp.SystemBuffer = NULL;
irp->UserBuffer = NULL;
irp->UserIosb = irp_handle; /* note: we abuse UserIosb to store the server irp handle */
irp->UserIosb = NULL;
irp->UserEvent = NULL;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
HeapFree( GetProcessHeap(), 0, file ); /* FIXME: async close processing not supported */
return STATUS_SUCCESS;
@ -290,9 +312,8 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
offset.QuadPart = params->read.pos;
/* 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 )))
&offset, NULL, NULL )))
{
HeapFree( GetProcessHeap(), 0, out_buff );
return STATUS_NO_MEMORY;
@ -304,7 +325,7 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp );
irpsp->Parameters.Read.Key = params->read.key;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
return STATUS_SUCCESS;
}
@ -327,9 +348,8 @@ static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG
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 )))
&offset, NULL, NULL )))
return STATUS_NO_MEMORY;
irp->Tail.Overlay.OriginalFileObject = file;
@ -338,7 +358,7 @@ static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp );
irpsp->Parameters.Write.Key = params->write.key;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
return STATUS_SUCCESS;
}
@ -357,15 +377,14 @@ static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG
TRACE( "device %p file %p\n", device, file );
/* note: we abuse UserIosb to store the server irp handle */
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_FLUSH_BUFFERS, device, NULL, 0,
NULL, NULL, irp_handle )))
NULL, NULL, NULL )))
return STATUS_NO_MEMORY;
irp->Tail.Overlay.OriginalFileObject = file;
irp->RequestorMode = UserMode;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
return STATUS_SUCCESS;
}
@ -398,9 +417,8 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG
}
}
/* note: we abuse UserIosb to store the server handle to the ioctl */
irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
FALSE, NULL, irp_handle );
FALSE, NULL, NULL );
if (!irp)
{
HeapFree( GetProcessHeap(), 0, out_buff );
@ -410,7 +428,7 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG
irp->Tail.Overlay.OriginalFileObject = file;
irp->RequestorMode = UserMode;
dispatch_irp( device, irp );
dispatch_irp( device, irp, irp_handle );
return STATUS_SUCCESS;
}
@ -1390,7 +1408,6 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
IO_STACK_LOCATION *irpsp;
PIO_COMPLETION_ROUTINE routine;
NTSTATUS status, stat;
HANDLE handle;
int call_flag = 0;
TRACE( "%p %u\n", irp, priority_boost );
@ -1422,28 +1439,6 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost )
}
}
handle = (HANDLE)irp->UserIosb;
if (handle)
{
void *out_buff = irp->UserBuffer;
FILE_OBJECT *file = irp->Tail.Overlay.OriginalFileObject;
SERVER_START_REQ( set_irp_result )
{
req->handle = wine_server_obj_handle( handle );
req->status = irp->IoStatus.u.Status;
req->file_ptr = wine_server_client_ptr( file );
if (irp->IoStatus.u.Status >= 0)
{
req->size = irp->IoStatus.Information;
if (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 );
}

View file

@ -1189,6 +1189,18 @@ NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
# endif
#endif
static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routine, void *context,
BOOLEAN on_success, BOOLEAN on_error, BOOLEAN on_cancel)
{
IO_STACK_LOCATION *irpsp = IoGetNextIrpStackLocation(irp);
irpsp->CompletionRoutine = routine;
irpsp->Context = context;
irpsp->Control = 0;
if (on_success) irpsp->Control |= SL_INVOKE_ON_SUCCESS;
if (on_error) irpsp->Control |= SL_INVOKE_ON_ERROR;
if (on_cancel) irpsp->Control |= SL_INVOKE_ON_CANCEL;
}
#define KernelMode 0
#define UserMode 1