server: Use create_request_async in ioctl request handler.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-06-26 12:20:10 +02:00 committed by Alexandre Julliard
parent 4e02a3bb13
commit c56c42ff79
8 changed files with 71 additions and 73 deletions

View File

@ -1543,7 +1543,11 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
status = wine_server_call( req ); status = wine_server_call( req );
wait_handle = wine_server_ptr_handle( reply->wait ); wait_handle = wine_server_ptr_handle( reply->wait );
options = reply->options; options = reply->options;
if (status != STATUS_PENDING) io->Information = wine_server_reply_size( reply ); if (wait_handle && status != STATUS_PENDING)
{
io->u.Status = status;
io->Information = wine_server_reply_size( reply );
}
} }
SERVER_END_REQ; SERVER_END_REQ;
@ -1557,10 +1561,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
{ {
NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL ); NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
status = io->u.Status; status = io->u.Status;
NtClose( wait_handle );
} }
if (status != STATUS_PENDING && code != FSCTL_PIPE_LISTEN) io->u.Status = status;
return status; return status;
} }

View File

@ -724,7 +724,7 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
ok( !reserved, "reserved is not 0: %x\n", reserved ); ok( !reserved, "reserved is not 0: %x\n", reserved );
} }
static void test_peek(HANDLE pipe) static void test_peek(HANDLE pipe, BOOL is_msgmode)
{ {
FILE_PIPE_PEEK_BUFFER buf; FILE_PIPE_PEEK_BUFFER buf;
IO_STATUS_BLOCK iosb; IO_STATUS_BLOCK iosb;
@ -743,7 +743,7 @@ static void test_peek(HANDLE pipe)
ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status); ok(!status || status == STATUS_PENDING, "NtFsControlFile failed: %x\n", status);
ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable); ok(buf.ReadDataAvailable == 1, "ReadDataAvailable = %u\n", buf.ReadDataAvailable);
ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status); ok(!iosb.Status, "iosb.Status = %x\n", iosb.Status);
todo_wine todo_wine_if(!is_msgmode)
ok(is_signaled(event), "event is not signaled\n"); ok(is_signaled(event), "event is not signaled\n");
CloseHandle(event); CloseHandle(event);
@ -855,7 +855,7 @@ static void read_pipe_test(ULONG pipe_flags, ULONG pipe_type)
ret = WriteFile( write, buffer, 1, &written, NULL ); ret = WriteFile( write, buffer, 1, &written, NULL );
ok(ret && written == 1, "WriteFile error %d\n", GetLastError()); ok(ret && written == 1, "WriteFile error %d\n", GetLastError());
test_peek(read); test_peek(read, pipe_type & PIPE_TYPE_MESSAGE);
status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL ); status = NtReadFile( read, event, apc, &apc_count, &iosb, buffer, 1, NULL, NULL );
ok( status == STATUS_SUCCESS, "wrong status %x\n", status ); ok( status == STATUS_SUCCESS, "wrong status %x\n", status );

View File

@ -177,7 +177,7 @@ static enum server_fd_type device_file_get_fd_type( struct fd *fd );
static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos ); static int device_file_read( struct fd *fd, struct async *async, file_pos_t pos );
static int device_file_write( struct fd *fd, struct async *async, file_pos_t pos ); static int device_file_write( struct fd *fd, struct async *async, file_pos_t pos );
static obj_handle_t device_file_flush( struct fd *fd, struct async *async ); static obj_handle_t device_file_flush( struct fd *fd, struct async *async );
static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
static const struct object_ops device_file_ops = static const struct object_ops device_file_ops =
{ {
@ -546,7 +546,7 @@ static obj_handle_t device_file_flush( struct fd *fd, struct async *async )
return handle; return handle;
} }
static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct device_file *file = get_fd_user( fd ); struct device_file *file = get_fd_user( fd );
struct irp_call *irp; struct irp_call *irp;
@ -561,7 +561,7 @@ static obj_handle_t device_file_ioctl( struct fd *fd, ioctl_code_t code, struct
irp = create_irp( file, &params, async ); irp = create_irp( file, &params, async );
if (!irp) return 0; if (!irp) return 0;
handle = queue_irp( file, irp, async, 1 ); handle = queue_irp( file, irp, async, 0 );
release_object( irp ); release_object( irp );
return handle; return handle;
} }

View File

@ -2179,20 +2179,20 @@ obj_handle_t no_fd_flush( struct fd *fd, struct async *async )
} }
/* default ioctl() routine */ /* default ioctl() routine */
obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) int no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
set_error( STATUS_OBJECT_TYPE_MISMATCH ); set_error( STATUS_OBJECT_TYPE_MISMATCH );
return 0; return 0;
} }
/* default ioctl() routine */ /* default ioctl() routine */
obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) int default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
switch(code) switch(code)
{ {
case FSCTL_DISMOUNT_VOLUME: case FSCTL_DISMOUNT_VOLUME:
unmount_device( fd ); unmount_device( fd );
return 0; return 1;
default: default:
set_error( STATUS_NOT_SUPPORTED ); set_error( STATUS_NOT_SUPPORTED );
return 0; return 0;
@ -2481,19 +2481,14 @@ DECL_HANDLER(ioctl)
unsigned int access = (req->code >> 14) & (FILE_READ_DATA|FILE_WRITE_DATA); unsigned int access = (req->code >> 14) & (FILE_READ_DATA|FILE_WRITE_DATA);
struct fd *fd = get_handle_fd_obj( current->process, req->async.handle, access ); struct fd *fd = get_handle_fd_obj( current->process, req->async.handle, access );
struct async *async; struct async *async;
struct iosb *iosb;
if (!fd) return; if (!fd) return;
if ((iosb = create_iosb( get_req_data(), get_req_data_size(), get_reply_max_size() ))) if ((async = create_request_async( fd, &req->async )))
{ {
if ((async = create_async( fd, current, &req->async, iosb ))) reply->wait = async_handoff( async, fd->fd_ops->ioctl( fd, req->code, async ), NULL );
{ reply->options = fd->options;
reply->wait = fd->fd_ops->ioctl( fd, req->code, async ); release_object( async );
reply->options = fd->options;
release_object( async );
}
release_object( iosb );
} }
release_object( fd ); release_object( fd );
} }

View File

@ -58,7 +58,7 @@ struct fd_ops
/* flush the object buffers */ /* flush the object buffers */
obj_handle_t (*flush)(struct fd *, struct async *); obj_handle_t (*flush)(struct fd *, struct async *);
/* perform an ioctl on the file */ /* perform an ioctl on the file */
obj_handle_t (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async ); int (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async );
/* queue an async operation */ /* queue an async operation */
void (*queue_async)(struct fd *, struct async *async, int type, int count); void (*queue_async)(struct fd *, struct async *async, int type, int count);
/* selected events for async i/o need an update */ /* selected events for async i/o need an update */
@ -103,8 +103,8 @@ extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos ); extern int no_fd_read( struct fd *fd, struct async *async, file_pos_t pos );
extern int no_fd_write( struct fd *fd, struct async *async, file_pos_t pos ); extern int no_fd_write( struct fd *fd, struct async *async, file_pos_t pos );
extern obj_handle_t no_fd_flush( struct fd *fd, struct async *async ); extern obj_handle_t no_fd_flush( struct fd *fd, struct async *async );
extern obj_handle_t no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); extern int no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); extern int default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
extern void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count );
extern void default_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void default_fd_queue_async( struct fd *fd, struct async *async, int type, int count );
extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue ); extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );

View File

@ -164,7 +164,7 @@ static void pipe_server_dump( struct object *obj, int verbose );
static struct fd *pipe_server_get_fd( struct object *obj ); static struct fd *pipe_server_get_fd( struct object *obj );
static void pipe_server_destroy( struct object *obj); static void pipe_server_destroy( struct object *obj);
static obj_handle_t pipe_server_flush( struct fd *fd, struct async *async ); static obj_handle_t pipe_server_flush( struct fd *fd, struct async *async );
static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
static const struct object_ops pipe_server_ops = static const struct object_ops pipe_server_ops =
{ {
@ -207,7 +207,7 @@ static int pipe_client_signaled( struct object *obj, struct wait_queue_entry *en
static struct fd *pipe_client_get_fd( struct object *obj ); static struct fd *pipe_client_get_fd( struct object *obj );
static void pipe_client_destroy( struct object *obj ); static void pipe_client_destroy( struct object *obj );
static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async ); static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async );
static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
static const struct object_ops pipe_client_ops = static const struct object_ops pipe_client_ops =
{ {
@ -253,8 +253,7 @@ static struct object *named_pipe_device_open_file( struct object *obj, unsigned
unsigned int sharing, unsigned int options ); unsigned int sharing, unsigned int options );
static void named_pipe_device_destroy( struct object *obj ); static void named_pipe_device_destroy( struct object *obj );
static enum server_fd_type named_pipe_device_get_fd_type( struct fd *fd ); static enum server_fd_type named_pipe_device_get_fd_type( struct fd *fd );
static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, static int named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
struct async *async );
static const struct object_ops named_pipe_device_ops = static const struct object_ops named_pipe_device_ops =
{ {
@ -889,7 +888,7 @@ static enum server_fd_type pipe_end_get_fd_type( struct fd *fd )
return FD_TYPE_PIPE; return FD_TYPE_PIPE;
} }
static void pipe_end_peek( struct pipe_end *pipe_end ) static int pipe_end_peek( struct pipe_end *pipe_end )
{ {
unsigned reply_size = get_reply_max_size(); unsigned reply_size = get_reply_max_size();
FILE_PIPE_PEEK_BUFFER *buffer; FILE_PIPE_PEEK_BUFFER *buffer;
@ -900,13 +899,13 @@ static void pipe_end_peek( struct pipe_end *pipe_end )
if (!use_server_io( pipe_end )) if (!use_server_io( pipe_end ))
{ {
set_error( STATUS_NOT_SUPPORTED ); set_error( STATUS_NOT_SUPPORTED );
return; return 0;
} }
if (reply_size < offsetof( FILE_PIPE_PEEK_BUFFER, Data )) if (reply_size < offsetof( FILE_PIPE_PEEK_BUFFER, Data ))
{ {
set_error( STATUS_INFO_LENGTH_MISMATCH ); set_error( STATUS_INFO_LENGTH_MISMATCH );
return; return 0;
} }
reply_size -= offsetof( FILE_PIPE_PEEK_BUFFER, Data ); reply_size -= offsetof( FILE_PIPE_PEEK_BUFFER, Data );
@ -921,18 +920,18 @@ static void pipe_end_peek( struct pipe_end *pipe_end )
} }
else reply_size = 0; else reply_size = 0;
if (!(buffer = set_reply_data_size( offsetof( FILE_PIPE_PEEK_BUFFER, Data[reply_size] )))) return; if (!(buffer = set_reply_data_size( offsetof( FILE_PIPE_PEEK_BUFFER, Data[reply_size] )))) return 0;
buffer->NamedPipeState = 0; /* FIXME */ buffer->NamedPipeState = 0; /* FIXME */
buffer->ReadDataAvailable = avail; buffer->ReadDataAvailable = avail;
buffer->NumberOfMessages = 0; /* FIXME */ buffer->NumberOfMessages = 0; /* FIXME */
buffer->MessageLength = message_length; buffer->MessageLength = message_length;
if (reply_size) memcpy( buffer->Data, (const char *)message->iosb->in_data + message->read_pos, reply_size ); if (reply_size) memcpy( buffer->Data, (const char *)message->iosb->in_data + message->read_pos, reply_size );
return 1;
} }
static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct pipe_server *server = get_fd_user( fd ); struct pipe_server *server = get_fd_user( fd );
obj_handle_t wait_handle = 0;
switch(code) switch(code)
{ {
@ -943,11 +942,10 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct
case ps_wait_connect: case ps_wait_connect:
if (fd_queue_async( server->ioctl_fd, async, ASYNC_TYPE_WAIT )) if (fd_queue_async( server->ioctl_fd, async, ASYNC_TYPE_WAIT ))
{ {
if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
set_server_state( server, ps_wait_open ); set_server_state( server, ps_wait_open );
if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS ); if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return wait_handle; return 1;
} }
break; break;
case ps_connected_server: case ps_connected_server:
@ -987,31 +985,29 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct
case ps_idle_server: case ps_idle_server:
case ps_wait_open: case ps_wait_open:
set_error( STATUS_PIPE_LISTENING ); set_error( STATUS_PIPE_LISTENING );
break; return 0;
case ps_wait_connect: case ps_wait_connect:
set_error( STATUS_PIPE_DISCONNECTED ); set_error( STATUS_PIPE_DISCONNECTED );
break; return 0;
} }
return 0; return 1;
case FSCTL_PIPE_PEEK: case FSCTL_PIPE_PEEK:
pipe_end_peek( &server->pipe_end ); return pipe_end_peek( &server->pipe_end );
return 0;
default: default:
return default_fd_ioctl( fd, code, async ); return default_fd_ioctl( fd, code, async );
} }
} }
static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct pipe_client *client = get_fd_user( fd ); struct pipe_client *client = get_fd_user( fd );
switch(code) switch(code)
{ {
case FSCTL_PIPE_PEEK: case FSCTL_PIPE_PEEK:
pipe_end_peek( &client->pipe_end ); return pipe_end_peek( &client->pipe_end );
return 0;
default: default:
return default_fd_ioctl( fd, code, async ); return default_fd_ioctl( fd, code, async );
@ -1211,7 +1207,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
return &client->pipe_end.obj; return &client->pipe_end.obj;
} }
static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct named_pipe_device *device = get_fd_user( fd ); struct named_pipe_device *device = get_fd_user( fd );
@ -1221,7 +1217,6 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, s
{ {
const FILE_PIPE_WAIT_FOR_BUFFER *buffer = get_req_data(); const FILE_PIPE_WAIT_FOR_BUFFER *buffer = get_req_data();
data_size_t size = get_req_data_size(); data_size_t size = get_req_data_size();
obj_handle_t wait_handle = 0;
struct named_pipe *pipe; struct named_pipe *pipe;
struct pipe_server *server; struct pipe_server *server;
struct unicode_str name; struct unicode_str name;
@ -1244,14 +1239,15 @@ static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, s
queue_async( pipe->waiters, async ); queue_async( pipe->waiters, async );
when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout; when = buffer->TimeoutSpecified ? buffer->Timeout.QuadPart : pipe->timeout;
async_set_timeout( async, when, STATUS_IO_TIMEOUT ); async_set_timeout( async, when, STATUS_IO_TIMEOUT );
if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 ); release_object( pipe );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return 1;
} }
else release_object( server ); else release_object( server );
done: done:
release_object( pipe ); release_object( pipe );
return wait_handle; return 0;
} }
default: default:

View File

@ -63,7 +63,7 @@ static struct fd *serial_get_fd( struct object *obj );
static void serial_destroy(struct object *obj); static void serial_destroy(struct object *obj);
static enum server_fd_type serial_get_fd_type( struct fd *fd ); static enum server_fd_type serial_get_fd_type( struct fd *fd );
static obj_handle_t serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static int serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
static void serial_queue_async( struct fd *fd, struct async *async, int type, int count ); static void serial_queue_async( struct fd *fd, struct async *async, int type, int count );
static void serial_reselect_async( struct fd *fd, struct async_queue *queue ); static void serial_reselect_async( struct fd *fd, struct async_queue *queue );
@ -175,42 +175,49 @@ static enum server_fd_type serial_get_fd_type( struct fd *fd )
return FD_TYPE_SERIAL; return FD_TYPE_SERIAL;
} }
static obj_handle_t serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int serial_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct serial *serial = get_fd_user( fd ); struct serial *serial = get_fd_user( fd );
switch (code) switch (code)
{ {
case IOCTL_SERIAL_GET_TIMEOUTS: case IOCTL_SERIAL_GET_TIMEOUTS:
if (get_reply_max_size() >= sizeof(serial->timeouts)) if (get_reply_max_size() < sizeof(serial->timeouts))
set_reply_data( &serial->timeouts, sizeof(serial->timeouts )); {
else
set_error( STATUS_BUFFER_TOO_SMALL ); set_error( STATUS_BUFFER_TOO_SMALL );
return 0; return 0;
}
set_reply_data( &serial->timeouts, sizeof(serial->timeouts ));
return 1;
case IOCTL_SERIAL_SET_TIMEOUTS: case IOCTL_SERIAL_SET_TIMEOUTS:
if (get_req_data_size() >= sizeof(serial->timeouts)) if (get_req_data_size() < sizeof(serial->timeouts))
memcpy( &serial->timeouts, get_req_data(), sizeof(serial->timeouts) ); {
else
set_error( STATUS_BUFFER_TOO_SMALL ); set_error( STATUS_BUFFER_TOO_SMALL );
return 0; return 0;
}
memcpy( &serial->timeouts, get_req_data(), sizeof(serial->timeouts) );
return 1;
case IOCTL_SERIAL_GET_WAIT_MASK: case IOCTL_SERIAL_GET_WAIT_MASK:
if (get_reply_max_size() >= sizeof(serial->eventmask)) if (get_reply_max_size() < sizeof(serial->eventmask))
set_reply_data( &serial->eventmask, sizeof(serial->eventmask) ); {
else
set_error( STATUS_BUFFER_TOO_SMALL ); set_error( STATUS_BUFFER_TOO_SMALL );
return 0; return 0;
}
set_reply_data( &serial->eventmask, sizeof(serial->eventmask) );
return 1;
case IOCTL_SERIAL_SET_WAIT_MASK: case IOCTL_SERIAL_SET_WAIT_MASK:
if (get_req_data_size() >= sizeof(serial->eventmask)) if (get_req_data_size() < sizeof(serial->eventmask))
{ {
serial->eventmask = *(unsigned int *)get_req_data(); set_error( STATUS_BUFFER_TOO_SMALL );
serial->generation++; return 0;
fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
} }
else set_error( STATUS_BUFFER_TOO_SMALL ); serial->eventmask = *(unsigned int *)get_req_data();
return 0; serial->generation++;
fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
return 1;
default: default:
set_error( STATUS_NOT_SUPPORTED ); set_error( STATUS_NOT_SUPPORTED );

View File

@ -129,7 +129,7 @@ static void sock_destroy_ifchange_q( struct sock *sock );
static int sock_get_poll_events( struct fd *fd ); static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event ); static void sock_poll_event( struct fd *fd, int event );
static enum server_fd_type sock_get_fd_type( struct fd *fd ); static enum server_fd_type sock_get_fd_type( struct fd *fd );
static obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async );
static void sock_queue_async( struct fd *fd, struct async *async, int type, int count ); static void sock_queue_async( struct fd *fd, struct async *async, int type, int count );
static void sock_reselect_async( struct fd *fd, struct async_queue *queue ); static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
@ -534,10 +534,9 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd )
return FD_TYPE_SOCKET; return FD_TYPE_SOCKET;
} }
obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
{ {
struct sock *sock = get_fd_user( fd ); struct sock *sock = get_fd_user( fd );
obj_handle_t wait_handle = 0;
struct async_queue *ifchange_q; struct async_queue *ifchange_q;
assert( sock->obj.ops == &sock_ops ); assert( sock->obj.ops == &sock_ops );
@ -552,9 +551,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
} }
if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0; if (!(ifchange_q = sock_get_ifchange_q( sock ))) return 0;
queue_async( ifchange_q, async ); queue_async( ifchange_q, async );
if (async_is_blocking( async )) wait_handle = alloc_handle( current->process, async, SYNCHRONIZE, 0 );
set_error( STATUS_PENDING ); set_error( STATUS_PENDING );
return wait_handle; return 1;
default: default:
set_error( STATUS_NOT_SUPPORTED ); set_error( STATUS_NOT_SUPPORTED );
return 0; return 0;