diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 8d6b7dace8a..016245d07ac 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -25,6 +25,7 @@ #include "wine/port.h" #include +#include #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -860,13 +861,10 @@ static NTSTATUS dispatch_ioctl( const irp_params_t *params, void *in_buff, ULONG return STATUS_SUCCESS; } -/* This is not a real IRP_MJ_CLEANUP dispatcher. We use it to notify client that server - * object associated with kernel object is freed so that we may free it on client side - * as well. */ -static NTSTATUS dispatch_cleanup( const irp_params_t *params, void *in_buff, ULONG in_size, - HANDLE irp_handle ) +static NTSTATUS dispatch_free( const irp_params_t *params, void *in_buff, ULONG in_size, + HANDLE irp_handle ) { - void *obj = wine_server_get_ptr( params->cleanup.obj ); + void *obj = wine_server_get_ptr( params->free.obj ); TRACE( "freeing %p object\n", obj ); free_kernel_object( obj ); return STATUS_SUCCESS; @@ -875,36 +873,16 @@ static NTSTATUS dispatch_cleanup( const irp_params_t *params, void *in_buff, ULO typedef NTSTATUS (*dispatch_func)( const irp_params_t *params, void *in_buff, ULONG in_size, HANDLE irp_handle ); -static const dispatch_func dispatch_funcs[IRP_MJ_MAXIMUM_FUNCTION + 1] = +static const dispatch_func dispatch_funcs[] = { - dispatch_create, /* IRP_MJ_CREATE */ - NULL, /* IRP_MJ_CREATE_NAMED_PIPE */ - dispatch_close, /* IRP_MJ_CLOSE */ - dispatch_read, /* IRP_MJ_READ */ - dispatch_write, /* IRP_MJ_WRITE */ - NULL, /* IRP_MJ_QUERY_INFORMATION */ - NULL, /* IRP_MJ_SET_INFORMATION */ - NULL, /* IRP_MJ_QUERY_EA */ - NULL, /* IRP_MJ_SET_EA */ - dispatch_flush, /* IRP_MJ_FLUSH_BUFFERS */ - NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */ - NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */ - NULL, /* IRP_MJ_DIRECTORY_CONTROL */ - NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */ - dispatch_ioctl, /* IRP_MJ_DEVICE_CONTROL */ - NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */ - NULL, /* IRP_MJ_SHUTDOWN */ - NULL, /* IRP_MJ_LOCK_CONTROL */ - dispatch_cleanup, /* IRP_MJ_CLEANUP */ - NULL, /* IRP_MJ_CREATE_MAILSLOT */ - NULL, /* IRP_MJ_QUERY_SECURITY */ - NULL, /* IRP_MJ_SET_SECURITY */ - NULL, /* IRP_MJ_POWER */ - NULL, /* IRP_MJ_SYSTEM_CONTROL */ - NULL, /* IRP_MJ_DEVICE_CHANGE */ - NULL, /* IRP_MJ_QUERY_QUOTA */ - NULL, /* IRP_MJ_SET_QUOTA */ - NULL, /* IRP_MJ_PNP */ + NULL, /* IRP_CALL_NONE */ + dispatch_create, /* IRP_CALL_CREATE */ + dispatch_close, /* IRP_CALL_CLOSE */ + dispatch_read, /* IRP_CALL_READ */ + dispatch_write, /* IRP_CALL_WRITE */ + dispatch_flush, /* IRP_CALL_FLUSH */ + dispatch_ioctl, /* IRP_CALL_IOCTL */ + dispatch_free /* IRP_CALL_FREE */ }; /* helper function to update service status */ @@ -1012,13 +990,8 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) switch (status) { case STATUS_SUCCESS: - if (irp_params.major > IRP_MJ_MAXIMUM_FUNCTION || !dispatch_funcs[irp_params.major]) - { - WARN( "unsupported request %u\n", irp_params.major ); - status = STATUS_NOT_SUPPORTED; - break; - } - status = dispatch_funcs[irp_params.major]( &irp_params, in_buff, in_size, irp ); + 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 ); if (status == STATUS_SUCCESS) { irp = 0; /* status reported by IoCompleteRequest */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 4236c12ae52..9c5c1968c7a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -640,12 +640,24 @@ typedef union } create_thread; } apc_result_t; +enum irp_type +{ + IRP_CALL_NONE, + IRP_CALL_CREATE, + IRP_CALL_CLOSE, + IRP_CALL_READ, + IRP_CALL_WRITE, + IRP_CALL_FLUSH, + IRP_CALL_IOCTL, + IRP_CALL_FREE +}; + typedef union { - unsigned int major; + enum irp_type type; struct { - unsigned int major; + enum irp_type type; unsigned int access; unsigned int sharing; unsigned int options; @@ -653,13 +665,13 @@ typedef union } create; struct { - unsigned int major; + enum irp_type type; int __pad; client_ptr_t file; } close; struct { - unsigned int major; + enum irp_type type; unsigned int key; data_size_t out_size; int __pad; @@ -668,20 +680,20 @@ typedef union } read; struct { - unsigned int major; + enum irp_type type; unsigned int key; client_ptr_t file; file_pos_t pos; } write; struct { - unsigned int major; + enum irp_type type; int __pad; client_ptr_t file; } flush; struct { - unsigned int major; + enum irp_type type; ioctl_code_t code; data_size_t out_size; int __pad; @@ -689,10 +701,10 @@ typedef union } ioctl; struct { - unsigned int major; + enum irp_type type; int __pad; client_ptr_t obj; - } cleanup; + } free; } irp_params_t; @@ -6682,6 +6694,6 @@ union generic_reply struct resume_process_reply resume_process_reply; }; -#define SERVER_PROTOCOL_VERSION 580 +#define SERVER_PROTOCOL_VERSION 581 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/device.c b/server/device.c index 97d316e152e..0fa23cae2ef 100644 --- a/server/device.c +++ b/server/device.c @@ -460,7 +460,7 @@ static struct object *device_open_file( struct object *obj, unsigned int access, irp_params_t params; memset( ¶ms, 0, sizeof(params) ); - params.create.major = IRP_MJ_CREATE; + params.create.type = IRP_CALL_CREATE; params.create.access = access; params.create.sharing = sharing; params.create.options = options; @@ -512,7 +512,7 @@ static int device_file_close_handle( struct object *obj, struct process *process file->closed = 1; memset( ¶ms, 0, sizeof(params) ); - params.close.major = IRP_MJ_CLOSE; + params.close.type = IRP_CALL_CLOSE; if ((irp = create_irp( file, ¶ms, NULL ))) { @@ -542,22 +542,26 @@ static void fill_irp_params( struct device_manager *manager, struct irp_call *ir { *params = irp->params; - switch (params->major) + switch (params->type) { - case IRP_MJ_CLOSE: + case IRP_CALL_NONE: + case IRP_CALL_CREATE: + case IRP_CALL_FREE: + break; + case IRP_CALL_CLOSE: params->close.file = get_kernel_object_ptr( manager, &irp->file->obj ); break; - case IRP_MJ_READ: + case IRP_CALL_READ: params->read.file = get_kernel_object_ptr( manager, &irp->file->obj ); params->read.out_size = irp->iosb->out_size; break; - case IRP_MJ_WRITE: + case IRP_CALL_WRITE: params->write.file = get_kernel_object_ptr( manager, &irp->file->obj ); break; - case IRP_MJ_FLUSH_BUFFERS: + case IRP_CALL_FLUSH: params->flush.file = get_kernel_object_ptr( manager, &irp->file->obj ); break; - case IRP_MJ_DEVICE_CONTROL: + case IRP_CALL_IOCTL: params->ioctl.file = get_kernel_object_ptr( manager, &irp->file->obj ); params->ioctl.out_size = irp->iosb->out_size; break; @@ -589,9 +593,9 @@ static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos irp_params_t params; memset( ¶ms, 0, sizeof(params) ); - params.read.major = IRP_MJ_READ; - params.read.key = 0; - params.read.pos = pos; + params.read.type = IRP_CALL_READ; + params.read.key = 0; + params.read.pos = pos; return queue_irp( file, ¶ms, async ); } @@ -601,9 +605,9 @@ static int device_file_write( struct fd *fd, struct async *async, file_pos_t pos irp_params_t params; memset( ¶ms, 0, sizeof(params) ); - params.write.major = IRP_MJ_WRITE; - params.write.key = 0; - params.write.pos = pos; + params.write.type = IRP_CALL_WRITE; + params.write.key = 0; + params.write.pos = pos; return queue_irp( file, ¶ms, async ); } @@ -613,7 +617,7 @@ static int device_file_flush( struct fd *fd, struct async *async ) irp_params_t params; memset( ¶ms, 0, sizeof(params) ); - params.flush.major = IRP_MJ_FLUSH_BUFFERS; + params.flush.type = IRP_CALL_FLUSH; return queue_irp( file, ¶ms, async ); } @@ -623,8 +627,8 @@ static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *as irp_params_t params; memset( ¶ms, 0, sizeof(params) ); - params.ioctl.major = IRP_MJ_DEVICE_CONTROL; - params.ioctl.code = code; + params.ioctl.type = IRP_CALL_IOCTL; + params.ioctl.code = code; return queue_irp( file, ¶ms, async ); } @@ -757,9 +761,9 @@ void free_kernel_objects( struct object *obj ) assert( !kernel_object->owned ); - /* abuse IRP_MJ_CLEANUP to request client to free no longer valid kernel object */ memset( ¶ms, 0, sizeof(params) ); - params.cleanup.major = IRP_MJ_CLEANUP; + params.free.type = IRP_CALL_FREE; + params.free.obj = kernel_object->user_ptr; if ((irp = create_irp( NULL, ¶ms, NULL ))) { @@ -851,8 +855,6 @@ DECL_HANDLER(get_next_device_request) struct list *ptr; struct iosb *iosb; - reply->params.major = IRP_MJ_MAXIMUM_FUNCTION + 1; - if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager, 0, &device_manager_ops ))) return; diff --git a/server/protocol.def b/server/protocol.def index 9a261eb6f0d..15ee31d88ae 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -656,12 +656,24 @@ typedef union } create_thread; } apc_result_t; +enum irp_type +{ + IRP_CALL_NONE, + IRP_CALL_CREATE, + IRP_CALL_CLOSE, + IRP_CALL_READ, + IRP_CALL_WRITE, + IRP_CALL_FLUSH, + IRP_CALL_IOCTL, + IRP_CALL_FREE +}; + typedef union { - unsigned int major; /* irp major function */ + enum irp_type type; /* irp call type */ struct { - unsigned int major; /* IRP_MJ_CREATE */ + enum irp_type type; /* IRP_CALL_CREATE */ unsigned int access; /* access rights */ unsigned int sharing; /* sharing flags */ unsigned int options; /* file options */ @@ -669,13 +681,13 @@ typedef union } create; struct { - unsigned int major; /* IRP_MJ_CLOSE */ + enum irp_type type; /* IRP_CALL_CLOSE */ int __pad; client_ptr_t file; /* opaque ptr for the file object */ } close; struct { - unsigned int major; /* IRP_MJ_READ */ + enum irp_type type; /* IRP_CALL_READ */ unsigned int key; /* driver key */ data_size_t out_size; /* needed output size */ int __pad; @@ -684,20 +696,20 @@ typedef union } read; struct { - unsigned int major; /* IRP_MJ_WRITE */ + enum irp_type type; /* IRP_CALL_WRITE */ unsigned int key; /* driver key */ client_ptr_t file; /* opaque ptr for the file object */ file_pos_t pos; /* file position */ } write; struct { - unsigned int major; /* IRP_MJ_FLUSH_BUFFERS */ + enum irp_type type; /* IRP_CALL_FLUSH */ int __pad; client_ptr_t file; /* opaque ptr for the file object */ } flush; struct { - unsigned int major; /* IRP_MJ_DEVICE_CONTROL */ + enum irp_type type; /* IRP_CALL_IOCTL */ ioctl_code_t code; /* ioctl code */ data_size_t out_size; /* needed output size */ int __pad; @@ -705,10 +717,10 @@ typedef union } ioctl; struct { - unsigned int major; /* IRP_MJ_DEVICE_CLEANUP */ + enum irp_type type; /* IRP_CALL_FREE */ int __pad; client_ptr_t obj; /* opaque ptr for the freed object */ - } cleanup; + } free; } irp_params_t; /* information about a PE image mapping, roughly equivalent to SECTION_IMAGE_INFORMATION */ diff --git a/server/trace.c b/server/trace.c index cb5b9c01e07..b5f3008f64c 100644 --- a/server/trace.c +++ b/server/trace.c @@ -317,49 +317,51 @@ static void dump_async_data( const char *prefix, const async_data_t *data ) static void dump_irp_params( const char *prefix, const irp_params_t *data ) { - switch (data->major) + switch (data->type) { - case IRP_MJ_CREATE: - fprintf( stderr, "%s{major=CREATE,access=%08x,sharing=%08x,options=%08x", + case IRP_CALL_NONE: + fprintf( stderr, "%s{NONE}", prefix ); + break; + case IRP_CALL_CREATE: + fprintf( stderr, "%s{CREATE,access=%08x,sharing=%08x,options=%08x", prefix, data->create.access, data->create.sharing, data->create.options ); dump_uint64( ",device=", &data->create.device ); fputc( '}', stderr ); break; - case IRP_MJ_CLOSE: - fprintf( stderr, "%s{major=CLOSE", prefix ); + case IRP_CALL_CLOSE: + fprintf( stderr, "%s{CLOSE", prefix ); dump_uint64( ",file=", &data->close.file ); fputc( '}', stderr ); break; - case IRP_MJ_READ: - fprintf( stderr, "%s{major=READ,key=%08x,out_size=%u", prefix, data->read.key, + case IRP_CALL_READ: + fprintf( stderr, "%s{READ,key=%08x,out_size=%u", prefix, data->read.key, data->read.out_size ); dump_uint64( ",pos=", &data->read.pos ); dump_uint64( ",file=", &data->read.file ); fputc( '}', stderr ); break; - case IRP_MJ_WRITE: - fprintf( stderr, "%s{major=WRITE,key=%08x", prefix, data->write.key ); + case IRP_CALL_WRITE: + fprintf( stderr, "%s{WRITE,key=%08x", prefix, data->write.key ); dump_uint64( ",pos=", &data->write.pos ); dump_uint64( ",file=", &data->write.file ); fputc( '}', stderr ); break; - case IRP_MJ_FLUSH_BUFFERS: - fprintf( stderr, "%s{major=FLUSH_BUFFERS", prefix ); + case IRP_CALL_FLUSH: + fprintf( stderr, "%s{FLUSH", prefix ); dump_uint64( ",file=", &data->flush.file ); fputc( '}', stderr ); break; - case IRP_MJ_DEVICE_CONTROL: - fprintf( stderr, "%s{major=DEVICE_CONTROL", prefix ); + case IRP_CALL_IOCTL: + fprintf( stderr, "%s{IOCTL", prefix ); dump_ioctl_code( ",code=", &data->ioctl.code ); fprintf( stderr, ",out_size=%u", data->ioctl.out_size ); dump_uint64( ",file=", &data->ioctl.file ); fputc( '}', stderr ); break; - case IRP_MJ_MAXIMUM_FUNCTION + 1: /* invalid */ - fprintf( stderr, "%s{}", prefix ); - break; - default: - fprintf( stderr, "%s{major=%u}", prefix, data->major ); + case IRP_CALL_FREE: + fprintf( stderr, "%s{FREE", prefix ); + dump_uint64( ",obj=", &data->free.obj ); + fputc( '}', stderr ); break; } }