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:
parent
e1d932a9e1
commit
6870bb74d4
|
@ -574,11 +574,19 @@ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp,
|
|||
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;
|
||||
|
||||
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 */
|
||||
|
||||
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 */
|
||||
static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_create( struct dispatch_context *context )
|
||||
{
|
||||
IRP *irp;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
FILE_OBJECT *file;
|
||||
DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
|
||||
HANDLE handle = wine_server_ptr_handle( params->create.file );
|
||||
DEVICE_OBJECT *device = wine_server_get_ptr( context->params.create.device );
|
||||
HANDLE handle = wine_server_ptr_handle( context->params.create.file );
|
||||
|
||||
if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 )))
|
||||
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->FileObject = file;
|
||||
irpsp->Parameters.Create.SecurityContext = NULL; /* FIXME */
|
||||
irpsp->Parameters.Create.Options = params->create.options;
|
||||
irpsp->Parameters.Create.ShareAccess = params->create.sharing;
|
||||
irpsp->Parameters.Create.Options = context->params.create.options;
|
||||
irpsp->Parameters.Create.ShareAccess = context->params.create.sharing;
|
||||
irpsp->Parameters.Create.FileAttributes = 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->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;
|
||||
}
|
||||
|
||||
/* process a close request for a given file */
|
||||
static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_close( struct dispatch_context *context )
|
||||
{
|
||||
IRP *irp;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
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;
|
||||
|
||||
|
@ -663,23 +669,22 @@ static NTSTATUS dispatch_close( const irp_params_t *params, void *in_buff, ULONG
|
|||
irp->UserEvent = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* process a read request for a given device */
|
||||
static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_read( struct dispatch_context *context )
|
||||
{
|
||||
IRP *irp;
|
||||
void *out_buff;
|
||||
LARGE_INTEGER offset;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
DEVICE_OBJECT *device;
|
||||
FILE_OBJECT *file = wine_server_get_ptr( params->read.file );
|
||||
ULONG out_size = params->read.out_size;
|
||||
FILE_OBJECT *file = wine_server_get_ptr( context->params.read.file );
|
||||
ULONG out_size = context->params.read.out_size;
|
||||
|
||||
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;
|
||||
|
||||
offset.QuadPart = params->read.pos;
|
||||
offset.QuadPart = context->params.read.pos;
|
||||
|
||||
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, device, out_buff, out_size,
|
||||
&offset, NULL, NULL )))
|
||||
|
@ -703,35 +708,34 @@ static NTSTATUS dispatch_read( const irp_params_t *params, void *in_buff, ULONG
|
|||
|
||||
irpsp = IoGetNextIrpStackLocation( irp );
|
||||
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_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;
|
||||
}
|
||||
|
||||
/* process a write request for a given device */
|
||||
static NTSTATUS dispatch_write( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_write( struct dispatch_context *context )
|
||||
{
|
||||
IRP *irp;
|
||||
LARGE_INTEGER offset;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
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;
|
||||
|
||||
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 )))
|
||||
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->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_DEALLOCATE_BUFFER; /* deallocate in_buff */
|
||||
dispatch_irp( device, irp, irp_handle );
|
||||
dispatch_irp( device, irp, context );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* process a flush request for a given device */
|
||||
static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_flush( struct dispatch_context *context )
|
||||
{
|
||||
IRP *irp;
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
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;
|
||||
|
||||
|
@ -774,90 +777,87 @@ static NTSTATUS dispatch_flush( const irp_params_t *params, void *in_buff, ULONG
|
|||
irpsp = IoGetNextIrpStackLocation( irp );
|
||||
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;
|
||||
}
|
||||
|
||||
/* process an ioctl request for a given device */
|
||||
static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_ioctl( struct dispatch_context *context )
|
||||
{
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
IRP *irp;
|
||||
void *out_buff = NULL;
|
||||
void *to_free = NULL;
|
||||
DEVICE_OBJECT *device;
|
||||
FILE_OBJECT *file = wine_server_get_ptr( params->ioctl.file );
|
||||
ULONG out_size = params->ioctl.out_size;
|
||||
FILE_OBJECT *file = wine_server_get_ptr( context->params.ioctl.file );
|
||||
ULONG out_size = context->params.ioctl.out_size;
|
||||
|
||||
if (!file) return STATUS_INVALID_HANDLE;
|
||||
|
||||
device = file->DeviceObject;
|
||||
|
||||
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 ((params->ioctl.code & 3) != METHOD_BUFFERED)
|
||||
if ((context->params.ioctl.code & 3) != METHOD_BUFFERED)
|
||||
{
|
||||
if (in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST;
|
||||
in_size -= out_size;
|
||||
if (context->in_size < out_size) return STATUS_INVALID_DEVICE_REQUEST;
|
||||
context->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 );
|
||||
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;
|
||||
memcpy( out_buff, in_buff, in_size );
|
||||
to_free = in_buff;
|
||||
in_buff = out_buff;
|
||||
memcpy( out_buff, context->in_buff, context->in_size );
|
||||
to_free = context->in_buff;
|
||||
context->in_buff = out_buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_buff = in_buff;
|
||||
out_size = in_size;
|
||||
out_buff = context->in_buff;
|
||||
out_size = context->in_size;
|
||||
}
|
||||
}
|
||||
|
||||
irp = IoBuildDeviceIoControlRequest( params->ioctl.code, device, in_buff, in_size, out_buff, out_size,
|
||||
FALSE, NULL, NULL );
|
||||
irp = IoBuildDeviceIoControlRequest( context->params.ioctl.code, device, context->in_buff,
|
||||
context->in_size, out_buff, out_size, FALSE, NULL, NULL );
|
||||
if (!irp)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, out_buff );
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (out_size && (params->ioctl.code & 3) != METHOD_BUFFERED)
|
||||
HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, in_buff, in_size );
|
||||
if (out_size && (context->params.ioctl.code & 3) != METHOD_BUFFERED)
|
||||
HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, context->in_buff, context->in_size );
|
||||
|
||||
irpsp = IoGetNextIrpStackLocation( irp );
|
||||
irpsp->FileObject = file;
|
||||
|
||||
irp->Tail.Overlay.OriginalFileObject = file;
|
||||
irp->RequestorMode = UserMode;
|
||||
irp->AssociatedIrp.SystemBuffer = in_buff;
|
||||
irp->AssociatedIrp.SystemBuffer = context->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 );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS dispatch_free( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle )
|
||||
static NTSTATUS dispatch_free( struct dispatch_context *context )
|
||||
{
|
||||
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 );
|
||||
free_kernel_object( obj );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size,
|
||||
HANDLE irp_handle );
|
||||
typedef NTSTATUS (*dispatch_func)( struct dispatch_context *context );
|
||||
|
||||
static const dispatch_func dispatch_funcs[] =
|
||||
{
|
||||
|
@ -926,13 +926,13 @@ PEPROCESS PsInitialSystemProcess = NULL;
|
|||
NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
||||
{
|
||||
HANDLE manager = get_device_manager();
|
||||
HANDLE irp = 0;
|
||||
struct dispatch_context context;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
irp_params_t irp_params;
|
||||
ULONG in_size = 4096;
|
||||
void *in_buff = NULL;
|
||||
HANDLE handles[2];
|
||||
|
||||
context.in_size = 4096;
|
||||
context.in_buff = NULL;
|
||||
|
||||
/* Set the system process global before setting up the request thread trickery */
|
||||
PsInitialSystemProcess = IoGetCurrentProcess();
|
||||
request_thread = GetCurrentThreadId();
|
||||
|
@ -943,7 +943,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
for (;;)
|
||||
{
|
||||
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" );
|
||||
status = STATUS_NO_MEMORY;
|
||||
|
@ -953,22 +953,22 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
SERVER_START_REQ( get_next_device_request )
|
||||
{
|
||||
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;
|
||||
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 )))
|
||||
{
|
||||
irp = wine_server_ptr_handle( reply->next );
|
||||
irp_params = reply->params;
|
||||
context.handle = wine_server_ptr_handle( reply->next );
|
||||
context.params = reply->params;
|
||||
context.in_size = reply->in_size;
|
||||
client_tid = reply->client_tid;
|
||||
in_size = reply->in_size;
|
||||
NtCurrentTeb()->Reserved5[1] = wine_server_get_ptr( reply->client_thread );
|
||||
}
|
||||
else
|
||||
{
|
||||
irp = 0; /* no previous irp */
|
||||
context.handle = 0; /* no previous irp */
|
||||
if (status == STATUS_BUFFER_OVERFLOW)
|
||||
in_size = reply->in_size;
|
||||
context.in_size = reply->in_size;
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -976,18 +976,18 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
switch (status)
|
||||
{
|
||||
case STATUS_SUCCESS:
|
||||
assert( irp_params.type != IRP_CALL_NONE && irp_params.type < ARRAY_SIZE(dispatch_funcs) );
|
||||
status = dispatch_funcs[irp_params.type]( &irp_params, in_buff, in_size, irp );
|
||||
assert( context.params.type != IRP_CALL_NONE && context.params.type < ARRAY_SIZE(dispatch_funcs) );
|
||||
status = dispatch_funcs[context.params.type]( &context );
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
irp = 0; /* status reported by IoCompleteRequest */
|
||||
in_size = 4096;
|
||||
in_buff = NULL;
|
||||
context.handle = 0; /* status reported by IoCompleteRequest */
|
||||
context.in_size = 4096;
|
||||
context.in_buff = NULL;
|
||||
}
|
||||
break;
|
||||
case STATUS_BUFFER_OVERFLOW:
|
||||
HeapFree( GetProcessHeap(), 0, in_buff );
|
||||
in_buff = NULL;
|
||||
HeapFree( GetProcessHeap(), 0, context.in_buff );
|
||||
context.in_buff = NULL;
|
||||
/* restart with larger buffer */
|
||||
break;
|
||||
case STATUS_PENDING:
|
||||
|
@ -996,7 +996,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
DWORD ret = WaitForMultipleObjectsEx( 2, handles, FALSE, INFINITE, TRUE );
|
||||
if (ret == WAIT_OBJECT_0)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, in_buff );
|
||||
HeapFree( GetProcessHeap(), 0, context.in_buff );
|
||||
status = STATUS_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue