diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 860b66f2e24..8f18035dd28 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -635,6 +635,14 @@ typedef union { unsigned int major; struct + { + unsigned int major; + unsigned int access; + unsigned int sharing; + unsigned int options; + client_ptr_t device; + } create; + struct { unsigned int major; unsigned int key; @@ -6081,6 +6089,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 477 +#define SERVER_PROTOCOL_VERSION 478 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/device.c b/server/device.c index 5dd3ae6a0c4..021f11bb664 100644 --- a/server/device.c +++ b/server/device.c @@ -335,31 +335,61 @@ static void device_destroy( struct object *obj ) if (device->manager) list_remove( &device->entry ); } +static void add_irp_to_queue( struct device_file *file, struct irp_call *irp ) +{ + struct device_manager *manager = file->device->manager; + + assert( manager ); + + grab_object( irp ); /* grab reference for queued irp */ + irp->thread = (struct thread *)grab_object( current ); + list_add_tail( &file->requests, &irp->dev_entry ); + list_add_tail( &manager->requests, &irp->mgr_entry ); + if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ +} + static struct object *device_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { struct device *device = (struct device *)obj; struct device_file *file; - if ((file = alloc_object( &device_file_ops ))) - { - file->device = (struct device *)grab_object( device ); - list_init( &file->requests ); - list_add_tail( &device->files, &file->entry ); - if (device->unix_path) - { - mode_t mode = 0666; - access = file->obj.ops->map_access( &file->obj, access ); - file->fd = open_fd( NULL, device->unix_path, O_NONBLOCK | O_LARGEFILE, - &mode, access, sharing, options ); - if (file->fd) set_fd_user( file->fd, &device_file_fd_ops, &file->obj ); - } - else file->fd = alloc_pseudo_fd( &device_file_fd_ops, &file->obj, 0 ); + if (!(file = alloc_object( &device_file_ops ))) return NULL; - if (!file->fd) + file->device = (struct device *)grab_object( device ); + list_init( &file->requests ); + list_add_tail( &device->files, &file->entry ); + if (device->unix_path) + { + mode_t mode = 0666; + access = file->obj.ops->map_access( &file->obj, access ); + file->fd = open_fd( NULL, device->unix_path, O_NONBLOCK | O_LARGEFILE, + &mode, access, sharing, options ); + if (file->fd) set_fd_user( file->fd, &device_file_fd_ops, &file->obj ); + } + else file->fd = alloc_pseudo_fd( &device_file_fd_ops, &file->obj, 0 ); + + if (!file->fd) + { + release_object( file ); + return NULL; + } + + if (device->manager) + { + struct irp_call *irp; + irp_params_t params; + + params.create.major = IRP_MJ_CREATE; + params.create.access = access; + params.create.sharing = sharing; + params.create.options = options; + params.create.device = file->device->user_ptr; + + if ((irp = create_irp( file, ¶ms, NULL, 0, 0 ))) { - release_object( file ); - file = NULL; + add_irp_to_queue( file, irp ); + release_object( irp ); } } return &file->obj; @@ -411,9 +441,6 @@ static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, const async_data_t *async_data, int blocking ) { obj_handle_t handle = 0; - struct device_manager *manager = file->device->manager; - - assert( manager ); if (blocking && !(handle = alloc_handle( current->process, irp, SYNCHRONIZE, 0 ))) return 0; @@ -422,13 +449,8 @@ static obj_handle_t queue_irp( struct device_file *file, struct irp_call *irp, if (handle) close_handle( current->process, handle ); return 0; } - irp->thread = (struct thread *)grab_object( current ); irp->user_arg = async_data->arg; - grab_object( irp ); /* grab reference for queued irp */ - - list_add_tail( &file->requests, &irp->dev_entry ); - list_add_tail( &manager->requests, &irp->mgr_entry ); - if (list_head( &manager->requests ) == &irp->mgr_entry) wake_up( &manager->obj, 0 ); /* first one */ + add_irp_to_queue( file, irp ); set_error( STATUS_PENDING ); return handle; } @@ -683,6 +705,8 @@ DECL_HANDLER(get_next_device_request) struct device_manager *manager; struct list *ptr; + 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 ab03f59656e..5372c52361c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -651,6 +651,14 @@ typedef union { unsigned int major; /* irp major function */ struct + { + unsigned int major; /* IRP_MJ_CREATE */ + unsigned int access; /* access rights */ + unsigned int sharing; /* sharing flags */ + unsigned int options; /* file options */ + client_ptr_t device; /* opaque ptr for the device */ + } create; + struct { unsigned int major; /* IRP_MJ_READ */ unsigned int key; /* driver key */ diff --git a/server/trace.c b/server/trace.c index 88575854ddf..4c728efb508 100644 --- a/server/trace.c +++ b/server/trace.c @@ -316,6 +316,12 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) { switch (data->major) { + case IRP_MJ_CREATE: + fprintf( stderr, "%s{major=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_READ: fprintf( stderr, "%s{major=READ,key=%08x", prefix, data->read.key ); dump_uint64( ",pos=", &data->read.pos ); @@ -339,6 +345,9 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) dump_uint64( ",device=", &data->ioctl.device ); fputc( '}', stderr ); break; + case IRP_MJ_MAXIMUM_FUNCTION + 1: /* invalid */ + fprintf( stderr, "%s{}", prefix ); + break; default: fprintf( stderr, "%s{major=%u}", prefix, data->major ); break;