Alexandre Julliard : server: Add support for retrieving results of queued ioctls once they are done.

Alexandre Julliard julliard at wine.codeweavers.com
Wed May 9 07:43:06 CDT 2007


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue May  8 20:45:44 2007 +0200

server: Add support for retrieving results of queued ioctls once they are done.

---

 dlls/ntdll/file.c              |   38 ++++++++++++++++++++++++++++++++++++--
 include/wine/server_protocol.h |   19 ++++++++++++++++++-
 server/device.c                |   40 ++++++++++++++++++++++++++++++++++++++++
 server/protocol.def            |    9 +++++++++
 server/request.h               |    2 ++
 server/trace.c                 |   15 +++++++++++++++
 6 files changed, 120 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 6912350..4936bb2 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -918,10 +918,35 @@ done:
 }
 
 
+struct async_ioctl
+{
+    HANDLE handle;   /* handle to the device */
+    void  *buffer;   /* buffer for output */
+    ULONG  size;     /* size of buffer */
+};
+
 /* callback for ioctl async I/O completion */
 static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status )
 {
-    io->u.Status = status;
+    struct async_ioctl *async = arg;
+
+    if (status == STATUS_ALERTED)
+    {
+        SERVER_START_REQ( get_ioctl_result )
+        {
+            req->handle   = async->handle;
+            req->user_arg = async;
+            wine_server_set_reply( req, async->buffer, async->size );
+            if (!(status = wine_server_call( req )))
+                io->Information = wine_server_reply_size( reply );
+        }
+        SERVER_END_REQ;
+    }
+    if (status != STATUS_PENDING)
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, async );
+        io->u.Status = status;
+    }
     return status;
 }
 
@@ -932,17 +957,24 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
                                    PVOID in_buffer, ULONG in_size,
                                    PVOID out_buffer, ULONG out_size )
 {
+    struct async_ioctl *async;
     NTSTATUS status;
     HANDLE wait_handle;
     ULONG options;
 
+    if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
+        return STATUS_NO_MEMORY;
+    async->handle = handle;
+    async->buffer = out_buffer;
+    async->size   = out_size;
+
     SERVER_START_REQ( ioctl )
     {
         req->handle         = handle;
         req->code           = code;
         req->async.callback = ioctl_completion;
         req->async.iosb     = io;
-        req->async.arg      = NULL;
+        req->async.arg      = async;
         req->async.apc      = apc;
         req->async.apc_arg  = apc_context;
         req->async.event    = event;
@@ -959,6 +991,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
         FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
               code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
 
+    if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, async );
+
     if (wait_handle)
     {
         NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index e9bb098..99f9f82 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2684,6 +2684,20 @@ struct ioctl_reply
 
 
 
+struct get_ioctl_result_request
+{
+    struct request_header __header;
+    obj_handle_t   handle;
+    void*          user_arg;
+};
+struct get_ioctl_result_reply
+{
+    struct reply_header __header;
+    /* VARARG(out_data,bytes); */
+};
+
+
+
 struct create_named_pipe_request
 {
     struct request_header __header;
@@ -4172,6 +4186,7 @@ enum request
     REQ_register_async,
     REQ_cancel_async,
     REQ_ioctl,
+    REQ_get_ioctl_result,
     REQ_create_named_pipe,
     REQ_get_named_pipe_info,
     REQ_create_window,
@@ -4397,6 +4412,7 @@ union generic_request
     struct register_async_request register_async_request;
     struct cancel_async_request cancel_async_request;
     struct ioctl_request ioctl_request;
+    struct get_ioctl_result_request get_ioctl_result_request;
     struct create_named_pipe_request create_named_pipe_request;
     struct get_named_pipe_info_request get_named_pipe_info_request;
     struct create_window_request create_window_request;
@@ -4620,6 +4636,7 @@ union generic_reply
     struct register_async_reply register_async_reply;
     struct cancel_async_reply cancel_async_reply;
     struct ioctl_reply ioctl_reply;
+    struct get_ioctl_result_reply get_ioctl_result_reply;
     struct create_named_pipe_reply create_named_pipe_reply;
     struct get_named_pipe_info_reply get_named_pipe_info_reply;
     struct create_window_reply create_window_reply;
@@ -4705,6 +4722,6 @@ union generic_reply
     struct get_next_device_request_reply get_next_device_request_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 302
+#define SERVER_PROTOCOL_VERSION 303
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/device.c b/server/device.c
index b811ff1..c52cd22 100644
--- a/server/device.c
+++ b/server/device.c
@@ -269,6 +269,18 @@ static enum server_fd_type device_get_fd_type( struct fd *fd )
     return FD_TYPE_DEVICE;
 }
 
+static struct ioctl_call *find_ioctl_call( struct device *device, struct thread *thread,
+                                           void *user_arg )
+{
+    struct ioctl_call *ioctl;
+
+    LIST_FOR_EACH_ENTRY( ioctl, &device->requests, struct ioctl_call, dev_entry )
+        if (ioctl->thread == thread && ioctl->user_arg == user_arg) return ioctl;
+
+    set_error( STATUS_INVALID_PARAMETER );
+    return NULL;
+}
+
 static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
                                   const void *data, data_size_t size )
 {
@@ -488,3 +500,31 @@ DECL_HANDLER(get_next_device_request)
 
     release_object( manager );
 }
+
+
+/* retrieve results of an async ioctl */
+DECL_HANDLER(get_ioctl_result)
+{
+    struct device *device;
+    struct ioctl_call *ioctl;
+
+    if (!(device = (struct device *)get_handle_obj( current->process, req->handle, 0, &device_ops )))
+        return;
+
+    if ((ioctl = find_ioctl_call( device, current, req->user_arg )))
+    {
+        if (ioctl->out_data)
+        {
+            data_size_t size = min( ioctl->out_size, get_reply_max_size() );
+            if (size)
+            {
+                set_reply_data_ptr( ioctl->out_data, size );
+                ioctl->out_data = NULL;
+            }
+        }
+        set_error( ioctl->status );
+        list_remove( &ioctl->dev_entry );
+        release_object( ioctl );  /* no longer on the device queue */
+    }
+    release_object( device );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 55055a4..fb2d8cd 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1979,6 +1979,15 @@ enum message_type
 @END
 
 
+/* Retrieve results of an async ioctl */
+ at REQ(get_ioctl_result)
+    obj_handle_t   handle;        /* handle to the device */
+    void*          user_arg;      /* user arg used to identify the request */
+ at REPLY
+    VARARG(out_data,bytes);       /* ioctl output data */
+ at END
+
+
 /* Create a named pipe */
 @REQ(create_named_pipe)
     unsigned int   access;
diff --git a/server/request.h b/server/request.h
index 4f175a6..90a0c6c 100644
--- a/server/request.h
+++ b/server/request.h
@@ -245,6 +245,7 @@ DECL_HANDLER(set_serial_info);
 DECL_HANDLER(register_async);
 DECL_HANDLER(cancel_async);
 DECL_HANDLER(ioctl);
+DECL_HANDLER(get_ioctl_result);
 DECL_HANDLER(create_named_pipe);
 DECL_HANDLER(get_named_pipe_info);
 DECL_HANDLER(create_window);
@@ -469,6 +470,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_register_async,
     (req_handler)req_cancel_async,
     (req_handler)req_ioctl,
+    (req_handler)req_get_ioctl_result,
     (req_handler)req_create_named_pipe,
     (req_handler)req_get_named_pipe_info,
     (req_handler)req_create_window,
diff --git a/server/trace.c b/server/trace.c
index 7b8b7e4..8ae8d73 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2424,6 +2424,18 @@ static void dump_ioctl_reply( const struct ioctl_reply *req )
     dump_varargs_bytes( cur_size );
 }
 
+static void dump_get_ioctl_result_request( const struct get_ioctl_result_request *req )
+{
+    fprintf( stderr, " handle=%p,", req->handle );
+    fprintf( stderr, " user_arg=%p", req->user_arg );
+}
+
+static void dump_get_ioctl_result_reply( const struct get_ioctl_result_reply *req )
+{
+    fprintf( stderr, " out_data=" );
+    dump_varargs_bytes( cur_size );
+}
+
 static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
@@ -3650,6 +3662,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_register_async_request,
     (dump_func)dump_cancel_async_request,
     (dump_func)dump_ioctl_request,
+    (dump_func)dump_get_ioctl_result_request,
     (dump_func)dump_create_named_pipe_request,
     (dump_func)dump_get_named_pipe_info_request,
     (dump_func)dump_create_window_request,
@@ -3871,6 +3884,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)0,
     (dump_func)0,
     (dump_func)dump_ioctl_reply,
+    (dump_func)dump_get_ioctl_result_reply,
     (dump_func)dump_create_named_pipe_reply,
     (dump_func)dump_get_named_pipe_info_reply,
     (dump_func)dump_create_window_reply,
@@ -4092,6 +4106,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "register_async",
     "cancel_async",
     "ioctl",
+    "get_ioctl_result",
     "create_named_pipe",
     "get_named_pipe_info",
     "create_window",




More information about the wine-cvs mailing list