Alexandre Julliard : server: Queue an IRP_MJ_CREATE request on file creation.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jul 9 09:44:36 CDT 2015


Module: wine
Branch: master
Commit: b1fd5955c9a6de8444ec488db3957aef85c629ed
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b1fd5955c9a6de8444ec488db3957aef85c629ed

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jul  8 17:55:14 2015 +0900

server: Queue an IRP_MJ_CREATE request on file creation.

---

 include/wine/server_protocol.h | 10 +++++-
 server/device.c                | 74 ++++++++++++++++++++++++++++--------------
 server/protocol.def            |  8 +++++
 server/trace.c                 |  9 +++++
 4 files changed, 75 insertions(+), 26 deletions(-)

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 860b66f..8f18035 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -637,6 +637,14 @@ typedef union
     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;
         client_ptr_t     device;
         file_pos_t       pos;
@@ -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 5dd3ae6..021f11b 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 )))
+    if (!(file = alloc_object( &device_file_ops ))) return NULL;
+
+    file->device = (struct device *)grab_object( device );
+    list_init( &file->requests );
+    list_add_tail( &device->files, &file->entry );
+    if (device->unix_path)
     {
-        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 );
+        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 (!file->fd)
+        if ((irp = create_irp( file, &params, 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 ab03f59..5372c52 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -652,6 +652,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 */
         client_ptr_t     device;    /* opaque ptr for the device */
diff --git a/server/trace.c b/server/trace.c
index 8857585..4c728ef 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;




More information about the wine-cvs mailing list