Erich E. Hoover : server: Add blocked support for SIO_ADDRESS_LIST_CHANGE ioctl().

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 10 10:46:04 CST 2015


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

Author: Erich E. Hoover <erich.e.hoover at wine-staging.com>
Date:   Tue May  6 08:44:59 2014 -0600

server: Add blocked support for SIO_ADDRESS_LIST_CHANGE ioctl().

---

 server/event.c      | 13 +++++++++++++
 server/named_pipe.c | 13 -------------
 server/object.h     |  1 +
 server/sock.c       | 26 ++++++++++++++++++++------
 4 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/server/event.c b/server/event.c
index 4d3c562..0daa5b2 100644
--- a/server/event.c
+++ b/server/event.c
@@ -124,6 +124,19 @@ struct event *create_event( struct directory *root, const struct unicode_str *na
     return event;
 }
 
+obj_handle_t alloc_wait_event( struct process *process )
+{
+    obj_handle_t handle = 0;
+    struct event *event = create_event( NULL, NULL, 0, 1, 0, NULL );
+
+    if (event)
+    {
+        handle = alloc_handle( process, event, EVENT_ALL_ACCESS, 0 );
+        release_object( event );
+    }
+    return handle;
+}
+
 struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access )
 {
     return (struct event *)get_handle_obj( process, handle, access, &event_ops );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 047b62c..706cce8 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -590,19 +590,6 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd )
     return FD_TYPE_PIPE;
 }
 
-static obj_handle_t alloc_wait_event( struct process *process )
-{
-    obj_handle_t handle = 0;
-    struct event *event = create_event( NULL, NULL, 0, 1, 0, NULL );
-
-    if (event)
-    {
-        handle = alloc_handle( process, event, EVENT_ALL_ACCESS, 0 );
-        release_object( event );
-    }
-    return handle;
-}
-
 static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
                                        int blocking, const void *data, data_size_t size )
 {
diff --git a/server/object.h b/server/object.h
index dd93b76e..3817c75 100644
--- a/server/object.h
+++ b/server/object.h
@@ -161,6 +161,7 @@ extern struct event *create_event( struct directory *root, const struct unicode_
                                    const struct security_descriptor *sd );
 extern struct keyed_event *create_keyed_event( struct directory *root, const struct unicode_str *name,
                                                unsigned int attr, const struct security_descriptor *sd );
+extern obj_handle_t alloc_wait_event( struct process *process );
 extern struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern struct keyed_event *get_keyed_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern void pulse_event( struct event *event );
diff --git a/server/sock.c b/server/sock.c
index 8c8db87..748159f 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -116,7 +116,7 @@ struct sock
 };
 
 static void sock_dump( struct object *obj, int verbose );
-static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
 static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
 static struct fd *sock_get_fd( struct object *obj );
 static void sock_destroy( struct object *obj );
@@ -534,14 +534,27 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
                          int blocking, const void *data, data_size_t size )
 {
     struct sock *sock = get_fd_user( fd );
+    obj_handle_t wait_handle = 0;
+    async_data_t new_data;
 
     assert( sock->obj.ops == &sock_ops );
 
     switch(code)
     {
     case WS_SIO_ADDRESS_LIST_CHANGE:
-        sock_add_ifchange( sock, async_data );
-        return 0;
+        if (blocking)
+        {
+            if (!(wait_handle = alloc_wait_event( current->process ))) return 0;
+            new_data = *async_data;
+            new_data.event = wait_handle;
+            async_data = &new_data;
+        }
+        if (!sock_add_ifchange( sock, async_data ) && wait_handle)
+        {
+            close_handle( current->process, wait_handle );
+            return 0;
+        }
+        return wait_handle;
     default:
         set_error( STATUS_NOT_SUPPORTED );
         return 0;
@@ -944,13 +957,13 @@ static void sock_set_error(void)
 }
 
 /* add interface change notification to a socket */
-static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
 {
     struct async_queue *ifchange_q;
     struct async *async;
 
     if (!(ifchange_q = sock_get_ifchange_q( sock )))
-        return;
+        return 0;
 
     if (!(async = create_async( current, ifchange_q, async_data )))
     {
@@ -958,11 +971,12 @@ static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data
             sock_destroy_ifchange_q( sock );
 
         set_error( STATUS_NO_MEMORY );
-        return;
+        return 0;
     }
 
     release_object( async );
     set_error( STATUS_PENDING );
+    return 1;
 }
 
 /* stub ifchange object */




More information about the wine-cvs mailing list