server: Add blocked support for SIO_ADDRESS_LIST_CHANGE ioctl().

This commit is contained in:
Erich E. Hoover 2014-05-06 08:44:59 -06:00 committed by Alexandre Julliard
parent 315de61bb2
commit b121f27b72
4 changed files with 34 additions and 19 deletions

View file

@ -124,6 +124,19 @@ struct event *create_event( struct directory *root, const struct unicode_str *na
return event; 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 ) 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 ); return (struct event *)get_handle_obj( process, handle, access, &event_ops );

View file

@ -590,19 +590,6 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd )
return FD_TYPE_PIPE; 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, 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 ) int blocking, const void *data, data_size_t size )
{ {

View file

@ -161,6 +161,7 @@ extern struct event *create_event( struct directory *root, const struct unicode_
const struct security_descriptor *sd ); const struct security_descriptor *sd );
extern struct keyed_event *create_keyed_event( struct directory *root, const struct unicode_str *name, extern struct keyed_event *create_keyed_event( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct security_descriptor *sd ); 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 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 struct keyed_event *get_keyed_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
extern void pulse_event( struct event *event ); extern void pulse_event( struct event *event );

View file

@ -116,7 +116,7 @@ struct sock
}; };
static void sock_dump( struct object *obj, int verbose ); 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 int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *sock_get_fd( struct object *obj ); static struct fd *sock_get_fd( struct object *obj );
static void sock_destroy( 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 ) int blocking, const void *data, data_size_t size )
{ {
struct sock *sock = get_fd_user( fd ); struct sock *sock = get_fd_user( fd );
obj_handle_t wait_handle = 0;
async_data_t new_data;
assert( sock->obj.ops == &sock_ops ); assert( sock->obj.ops == &sock_ops );
switch(code) switch(code)
{ {
case WS_SIO_ADDRESS_LIST_CHANGE: case WS_SIO_ADDRESS_LIST_CHANGE:
sock_add_ifchange( sock, async_data ); if (blocking)
return 0; {
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: default:
set_error( STATUS_NOT_SUPPORTED ); set_error( STATUS_NOT_SUPPORTED );
return 0; return 0;
@ -944,13 +957,13 @@ static void sock_set_error(void)
} }
/* add interface change notification to a socket */ /* 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_queue *ifchange_q;
struct async *async; struct async *async;
if (!(ifchange_q = sock_get_ifchange_q( sock ))) if (!(ifchange_q = sock_get_ifchange_q( sock )))
return; return 0;
if (!(async = create_async( current, ifchange_q, async_data ))) 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 ); sock_destroy_ifchange_q( sock );
set_error( STATUS_NO_MEMORY ); set_error( STATUS_NO_MEMORY );
return; return 0;
} }
release_object( async ); release_object( async );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return 1;
} }
/* stub ifchange object */ /* stub ifchange object */