From: "Erich E. Hoover" Subject: [PATCH 3/5] server: Add delayed processing for socket-specific ioctl() (resend 3). Message-Id: Date: Wed, 20 Aug 2014 23:46:45 -0600 An asynchronous event is necessary for SIO_ADDRESS_LIST_CHANGE, so blocking calls must make such an event available. This patch utilizes alloc_wait_event so that both named pipes and sockets can provide such events for blocking ioctl() calls without duplicating code. From 2150b447c297e02ef272ba64eef9530367fcdc9c Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Tue, 6 May 2014 08:44:59 -0600 Subject: 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 3750d25..7f774c4 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -589,19 +589,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 bb3ff21..bad162f 100644 --- a/server/object.h +++ b/server/object.h @@ -159,6 +159,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 dc0e8d0..f9d0a52 100644 --- a/server/sock.c +++ b/server/sock.c @@ -117,7 +117,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; @@ -940,13 +953,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 = NULL; struct async *async; if (!(ifchange_q = sock_get_ifchange_q( sock ))) - return; + return FALSE; if (!(async = create_async( current, ifchange_q, async_data ))) { @@ -954,11 +967,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 FALSE; } release_object( async ); set_error( STATUS_PENDING ); + return TRUE; } /* stub ifchange object */ -- 1.7.9.5