ntoskrnl.exe: Pass context as a structure to IRP dispatchers.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-05-27 13:38:27 +02:00 committed by Alexandre Julliard
parent e1d932a9e1
commit 6870bb74d4
1 changed files with 82 additions and 82 deletions

View File

@ -574,11 +574,19 @@ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, HANDLE irp_handle ) struct dispatch_context
{
irp_params_t params;
HANDLE handle;
ULONG in_size;
void *in_buff;
};
static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, struct dispatch_context *context )
{ {
LARGE_INTEGER count; LARGE_INTEGER count;
IoSetCompletionRoutine( irp, dispatch_irp_completion, irp_handle, TRUE, TRUE, TRUE ); IoSetCompletionRoutine( irp, dispatch_irp_completion, context->handle, TRUE, TRUE, TRUE );
KeQueryTickCount( &count ); /* update the global KeTickCount */ KeQueryTickCount( &count ); /* update the global KeTickCount */
device->CurrentIrp = irp; device->CurrentIrp = irp;
@ -587,14 +595,13 @@ static void dispatch_irp( DEVICE_OBJECT *device, IRP *irp, HANDLE irp_handle )
} }
/* process a create request for a given file */ /* process a create request for a given file */
static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_create( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IRP *irp; IRP *irp;
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
FILE_OBJECT *file; FILE_OBJECT *file;
DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device ); DEVICE_OBJECT *device = wine_server_get_ptr( context->params.create.device );
HANDLE handle = wine_server_ptr_handle( params->create.file ); HANDLE handle = wine_server_ptr_handle( context->params.create.file );
if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 ))) if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
@ -611,8 +618,8 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
irpsp->MajorFunction = IRP_MJ_CREATE; irpsp->MajorFunction = IRP_MJ_CREATE;
irpsp->FileObject = file; irpsp->FileObject = file;
irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */ irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
irpsp->Parameters.Create.Options = params->create.options; irpsp->Parameters.Create.Options = context->params.create.options;
irpsp->Parameters.Create.ShareAccess = params->create.sharing; irpsp->Parameters.Create.ShareAccess = context->params.create.sharing;
irpsp->Parameters.Create.FileAttributes = 0; irpsp->Parameters.Create.FileAttributes = 0;
irpsp->Parameters.Create.EaLength = 0; irpsp->Parameters.Create.EaLength = 0;
@ -624,20 +631,19 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
irp->UserEvent = NULL; irp->UserEvent = NULL;
irp->Flags |= IRP_CREATE_OPERATION; irp->Flags |= IRP_CREATE_OPERATION;
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context->in_buff );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* process a close request for a given file */ /* process a close request for a given file */
static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_close( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IRP *irp; IRP *irp;
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
DEVICE_OBJECT *device; DEVICE_OBJECT *device;
FILE_OBJECT *file = wine_server_get_ptr( params->close.file ); FILE_OBJECT *file = wine_server_get_ptr( context->params.close.file );
if (!file) return STATUS_INVALID_HANDLE; if (!file) return STATUS_INVALID_HANDLE;
@ -663,23 +669,22 @@ static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG
irp->UserEvent = NULL; irp->UserEvent = NULL;
irp->Flags |= IRP_CLOSE_OPERATION; irp->Flags |= IRP_CLOSE_OPERATION;
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context->in_buff );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* process a read request for a given device */ /* process a read request for a given device */
static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_read( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IRP *irp; IRP *irp;
void *out_buff; void *out_buff;
LARGE_INTEGER offset; LARGE_INTEGER offset;
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
DEVICE_OBJECT *device; DEVICE_OBJECT *device;
FILE_OBJECT *file = wine_server_get_ptr( params->read.file ); FILE_OBJECT *file = wine_server_get_ptr( context->params.read.file );
ULONG out_size = params->read.out_size; ULONG out_size = context->params.read.out_size;
if (!file) return STATUS_INVALID_HANDLE; if (!file) return STATUS_INVALID_HANDLE;
@ -689,7 +694,7 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY; if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
offset.QuadPart = params->read.pos; offset.QuadPart = context->params.read.pos;
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size, if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
&offset, NULL, NULL ))) &offset, NULL, NULL )))
@ -703,35 +708,34 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp ); irpsp = IoGetNextIrpStackLocation( irp );
irpsp->FileObject = file; irpsp->FileObject = file;
irpsp->Parameters.Read.Key = params->read.key; irpsp->Parameters.Read.Key = context->params.read.key;
irp->Flags |= IRP_READ_OPERATION; irp->Flags |= IRP_READ_OPERATION;
irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate out_buff */ irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate out_buff */
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context->in_buff );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* process a write request for a given device */ /* process a write request for a given device */
static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_write( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IRP *irp; IRP *irp;
LARGE_INTEGER offset; LARGE_INTEGER offset;
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
DEVICE_OBJECT *device; DEVICE_OBJECT *device;
FILE_OBJECT *file = wine_server_get_ptr( params->write.file ); FILE_OBJECT *file = wine_server_get_ptr( context->params.write.file );
if (!file) return STATUS_INVALID_HANDLE; if (!file) return STATUS_INVALID_HANDLE;
device = file->DeviceObject; device = file->DeviceObject;
TRACE( "device %p file %p size %u\n", device, file, in_size ); TRACE( "device %p file %p size %u\n", device, file, context->in_size );
offset.QuadPart = params->write.pos; offset.QuadPart = context->params.write.pos;
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, in_buff, in_size, if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, device, context->in_buff, context->in_size,
&offset, NULL, NULL ))) &offset, NULL, NULL )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
@ -740,23 +744,22 @@ static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp ); irpsp = IoGetNextIrpStackLocation( irp );
irpsp->FileObject = file; irpsp->FileObject = file;
irpsp->Parameters.Write.Key = params->write.key; irpsp->Parameters.Write.Key = context->params.write.key;
irp->Flags |= IRP_WRITE_OPERATION; irp->Flags |= IRP_WRITE_OPERATION;
irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */ irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* process a flush request for a given device */ /* process a flush request for a given device */
static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_flush( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IRP *irp; IRP *irp;
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
DEVICE_OBJECT *device; DEVICE_OBJECT *device;
FILE_OBJECT *file = wine_server_get_ptr( params->flush.file ); FILE_OBJECT *file = wine_server_get_ptr( context->params.flush.file );
if (!file) return STATUS_INVALID_HANDLE; if (!file) return STATUS_INVALID_HANDLE;
@ -774,90 +777,87 @@ static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG
irpsp = IoGetNextIrpStackLocation( irp ); irpsp = IoGetNextIrpStackLocation( irp );
irpsp->FileObject = file; irpsp->FileObject = file;
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context->in_buff );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* process an ioctl request for a given device */ /* process an ioctl request for a given device */
static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
HANDLE irp_handle )
{ {
IO_STACK_LOCATION *irpsp; IO_STACK_LOCATION *irpsp;
IRP *irp; IRP *irp;
void *out_buff = NULL; void *out_buff = NULL;
void *to_free = NULL; void *to_free = NULL;
DEVICE_OBJECT *device; DEVICE_OBJECT *device;
FILE_OBJECT *file = wine_server_get_ptr( params->ioctl.file ); FILE_OBJECT *file = wine_server_get_ptr( context->params.ioctl.file );
ULONG out_size = params->ioctl.out_size; ULONG out_size = context->params.ioctl.out_size;
if (!file) return STATUS_INVALID_HANDLE; if (!file) return STATUS_INVALID_HANDLE;
device = file->DeviceObject; device = file->DeviceObject;
TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n", TRACE( "ioctl %x device %p file %p in_size %u out_size %u\n",
params->ioctl.code, device, file, in_size, out_size ); context->params.ioctl.code, device, file, context->in_size, out_size );
if (out_size) if (out_size)
{ {
if ((params->ioctl.code & 3) != METHOD_BUFFERED) if ((context->params.ioctl.code & 3) != METHOD_BUFFERED)
{ {
if (in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST; if (context->in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST;
in_size -= out_size; context->in_size -= out_size;
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY; if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
memcpy( out_buff, (char *)in_buff + in_size, out_size ); memcpy( out_buff, (char *)context->in_buff + context->in_size, out_size );
} }
else if (out_size > in_size) else if (out_size > context->in_size)
{ {
if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY; if (!(out_buff = HeapAlloc( GetProcessHeap(), 0, out_size ))) return STATUS_NO_MEMORY;
memcpy( out_buff, in_buff, in_size ); memcpy( out_buff, context->in_buff, context->in_size );
to_free = in_buff; to_free = context->in_buff;
in_buff = out_buff; context->in_buff = out_buff;
} }
else else
{ {
out_buff = in_buff; out_buff = context->in_buff;
out_size = in_size; out_size = context->in_size;
} }
} }
irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size, irp = IoBuildDeviceIoControlRequest( context->params.ioctl.code, device, context->in_buff,
FALSE, NULL, NULL ); context->in_size, out_buff, out_size, FALSE, NULL, NULL );
if (!irp) if (!irp)
{ {
HeapFree( GetProcessHeap(), 0, out_buff ); HeapFree( GetProcessHeap(), 0, out_buff );
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
if (out_size && (params->ioctl.code & 3) != METHOD_BUFFERED) if (out_size && (context->params.ioctl.code & 3) != METHOD_BUFFERED)
HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, in_buff, in_size ); HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, context->in_buff, context->in_size );
irpsp = IoGetNextIrpStackLocation( irp ); irpsp = IoGetNextIrpStackLocation( irp );
irpsp->FileObject = file; irpsp->FileObject = file;
irp->Tail.Overlay.OriginalFileObject = file; irp->Tail.Overlay.OriginalFileObject = file;
irp->RequestorMode = UserMode; irp->RequestorMode = UserMode;
irp->AssociatedIrp.SystemBuffer = in_buff; irp->AssociatedIrp.SystemBuffer = context->in_buff;
irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */ irp->Flags |= IRP_DEALLOCATE_BUFFER; /* deallocate in_buff */
dispatch_irp( device, irp, irp_handle ); dispatch_irp( device, irp, context );
HeapFree( GetProcessHeap(), 0, to_free ); HeapFree( GetProcessHeap(), 0, to_free );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS dispatch_free( const irp_params_t *params, void *in_buff, ULONG in_size, static NTSTATUS dispatch_free( struct dispatch_context *context )
HANDLE irp_handle )
{ {
void *obj = wine_server_get_ptr( params->free.obj ); void *obj = wine_server_get_ptr( context->params.free.obj );
TRACE( "freeing %p object\n", obj ); TRACE( "freeing %p object\n", obj );
free_kernel_object( obj ); free_kernel_object( obj );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size, typedef NTSTATUS (*dispatch_func)( struct dispatch_context *context );
HANDLE irp_handle );
static const dispatch_func dispatch_funcs[] = static const dispatch_func dispatch_funcs[] =
{ {
@ -926,13 +926,13 @@ PEPROCESS PsInitialSystemProcess = NULL;
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();
HANDLE irp = 0; struct dispatch_context context;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
irp_params_t irp_params;
ULONG in_size = 4096;
void *in_buff = NULL;
HANDLE handles[2]; HANDLE handles[2];
context.in_size = 4096;
context.in_buff = NULL;
/* Set the system process global before setting up the request thread trickery */ /* Set the system process global before setting up the request thread trickery */
PsInitialSystemProcess = IoGetCurrentProcess(); PsInitialSystemProcess = IoGetCurrentProcess();
request_thread = GetCurrentThreadId(); request_thread = GetCurrentThreadId();
@ -943,7 +943,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
for (;;) for (;;)
{ {
NtCurrentTeb()->Reserved5[1] = NULL; NtCurrentTeb()->Reserved5[1] = NULL;
if (!in_buff && !(in_buff = HeapAlloc( GetProcessHeap(), 0, in_size ))) if (!context.in_buff && !(context.in_buff = HeapAlloc( GetProcessHeap(), 0, context.in_size )))
{ {
ERR( "failed to allocate buffer\n" ); ERR( "failed to allocate buffer\n" );
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
@ -953,22 +953,22 @@ 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 = wine_server_obj_handle( irp ); req->prev = wine_server_obj_handle( context.handle );
req->status = status; req->status = status;
wine_server_set_reply( req, in_buff, in_size ); wine_server_set_reply( req, context.in_buff, context.in_size );
if (!(status = wine_server_call( req ))) if (!(status = wine_server_call( req )))
{ {
irp = wine_server_ptr_handle( reply->next ); context.handle = wine_server_ptr_handle( reply->next );
irp_params = reply->params; context.params = reply->params;
context.in_size = reply->in_size;
client_tid = reply->client_tid; client_tid = reply->client_tid;
in_size = reply->in_size;
NtCurrentTeb()->Reserved5[1] = wine_server_get_ptr( reply->client_thread ); NtCurrentTeb()->Reserved5[1] = wine_server_get_ptr( reply->client_thread );
} }
else else
{ {
irp = 0; /* no previous irp */ context.handle = 0; /* no previous irp */
if (status == STATUS_BUFFER_OVERFLOW) if (status == STATUS_BUFFER_OVERFLOW)
in_size = reply->in_size; context.in_size = reply->in_size;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
@ -976,18 +976,18 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
switch (status) switch (status)
{ {
case STATUS_SUCCESS: case STATUS_SUCCESS:
assert( irp_params.type != IRP_CALL_NONE && irp_params.type < ARRAY_SIZE(dispatch_funcs) ); assert( context.params.type != IRP_CALL_NONE && context.params.type < ARRAY_SIZE(dispatch_funcs) );
status = dispatch_funcs[irp_params.type]( &irp_params, in_buff, in_size, irp ); status = dispatch_funcs[context.params.type]( &context );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
irp = 0; /* status reported by IoCompleteRequest */ context.handle = 0; /* status reported by IoCompleteRequest */
in_size = 4096; context.in_size = 4096;
in_buff = NULL; context.in_buff = NULL;
} }
break; break;
case STATUS_BUFFER_OVERFLOW: case STATUS_BUFFER_OVERFLOW:
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context.in_buff );
in_buff = NULL; context.in_buff = NULL;
/* restart with larger buffer */ /* restart with larger buffer */
break; break;
case STATUS_PENDING: case STATUS_PENDING:
@ -996,7 +996,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE ); DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
if (ret == WAIT_OBJECT_0) if (ret == WAIT_OBJECT_0)
{ {
HeapFree( GetProcessHeap(), 0, in_buff ); HeapFree( GetProcessHeap(), 0, context.in_buff );
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
goto done; goto done;
} }