Commit b05774ee authored by Mike Kaplinskiy's avatar Mike Kaplinskiy Committed by Alexandre Julliard

server: Change cancel_async to take an optional iosb and only_thread.

parent e49918b5
......@@ -2859,6 +2859,9 @@ struct cancel_async_request
{
struct request_header __header;
obj_handle_t handle;
client_ptr_t iosb;
int only_thread;
char __pad_28[4];
};
struct cancel_async_reply
{
......@@ -5312,6 +5315,6 @@ union generic_reply
struct set_window_layered_info_reply set_window_layered_info_reply;
};
#define SERVER_PROTOCOL_VERSION 387
#define SERVER_PROTOCOL_VERSION 388
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -288,6 +288,28 @@ int async_waiting( struct async_queue *queue )
return async->status == STATUS_PENDING;
}
int async_wake_up_by( struct async_queue *queue, struct process *process,
struct thread *thread, client_ptr_t iosb, unsigned int status )
{
struct list *ptr, *next;
int woken = 0;
if (!queue || (!process && !thread && !iosb)) return 0;
LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
{
struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
if ( (!process || async->thread->process == process) &&
(!thread || async->thread == thread) &&
(!iosb || async->data.iosb == iosb) )
{
async_terminate( async, status );
woken++;
}
}
return woken;
}
/* wake up async operations on the queue */
void async_wake_up( struct async_queue *queue, unsigned int status )
{
......
......@@ -1856,11 +1856,15 @@ void default_fd_reselect_async( struct fd *fd, struct async_queue *queue )
}
/* default cancel_async() fd routine */
void default_fd_cancel_async( struct fd *fd )
void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
{
async_wake_up( fd->read_q, STATUS_CANCELLED );
async_wake_up( fd->write_q, STATUS_CANCELLED );
async_wake_up( fd->wait_q, STATUS_CANCELLED );
int n = 0;
n += async_wake_up_by( fd->read_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( fd->write_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( fd->wait_q, process, thread, iosb, STATUS_CANCELLED );
if (!n && iosb)
set_error( STATUS_NOT_FOUND );
}
/* default flush() routine */
......@@ -2064,10 +2068,11 @@ DECL_HANDLER(register_async)
DECL_HANDLER(cancel_async)
{
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
struct thread *thread = req->only_thread ? current : NULL;
if (fd)
{
if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd );
if (get_unix_fd( fd ) != -1) fd->fd_ops->cancel_async( fd, current->process, thread, req->iosb );
release_object( fd );
}
}
......
......@@ -46,7 +46,7 @@ struct fd_ops
/* selected events for async i/o need an update */
void (*reselect_async)( struct fd *, struct async_queue *queue );
/* cancel an async operation */
void (*cancel_async)(struct fd *);
void (*cancel_async)(struct fd *, struct process *process, struct thread *thread, client_ptr_t iosb);
};
/* file descriptor functions */
......@@ -83,7 +83,7 @@ extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const as
int blocking, const void *data, data_size_t size );
extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );
extern void default_fd_cancel_async( struct fd *fd );
extern void default_fd_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
extern void no_flush( struct fd *fd, struct event **event );
extern void main_loop(void);
extern void remove_process_locks( struct process *process );
......@@ -143,6 +143,8 @@ extern void async_set_result( struct object *obj, unsigned int status,
unsigned int total, client_ptr_t apc );
extern int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status );
extern int async_wake_up_by( struct async_queue *queue, struct process *process,
struct thread *thread, client_ptr_t iosb, unsigned int status );
extern void async_wake_up( struct async_queue *queue, unsigned int status );
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
extern void fd_copy_completion( struct fd *src, struct fd *dst );
......
......@@ -2072,6 +2072,8 @@ enum message_type
/* Cancel all async op on a fd */
@REQ(cancel_async)
obj_handle_t handle; /* handle to comm port, socket or file */
client_ptr_t iosb; /* I/O status block (NULL=all) */
int only_thread; /* cancel matching this thread */
@END
......
......@@ -1351,7 +1351,9 @@ C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 );
C_ASSERT( sizeof(struct register_async_request) == 64 );
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, handle) == 12 );
C_ASSERT( sizeof(struct cancel_async_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, iosb) == 16 );
C_ASSERT( FIELD_OFFSET(struct cancel_async_request, only_thread) == 24 );
C_ASSERT( sizeof(struct cancel_async_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct ioctl_request, code) == 12 );
C_ASSERT( FIELD_OFFSET(struct ioctl_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct ioctl_request, blocking) == 56 );
......
......@@ -97,7 +97,7 @@ static void sock_poll_event( struct fd *fd, int event );
static enum server_fd_type sock_get_fd_type( struct fd *fd );
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
static void sock_cancel_async( struct fd *fd );
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
static int sock_get_error( int err );
static void sock_set_error(void);
......@@ -538,13 +538,16 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue )
if (events) sock_try_event( sock, events );
}
static void sock_cancel_async( struct fd *fd )
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb )
{
struct sock *sock = get_fd_user( fd );
int n = 0;
assert( sock->obj.ops == &sock_ops );
async_wake_up( sock->read_q, STATUS_CANCELLED );
async_wake_up( sock->write_q, STATUS_CANCELLED );
n += async_wake_up_by( sock->read_q, process, thread, iosb, STATUS_CANCELLED );
n += async_wake_up_by( sock->write_q, process, thread, iosb, STATUS_CANCELLED );
if (!n && iosb)
set_error( STATUS_NOT_FOUND );
}
static struct fd *sock_get_fd( struct object *obj )
......
......@@ -2568,6 +2568,8 @@ static void dump_register_async_request( const struct register_async_request *re
static void dump_cancel_async_request( const struct cancel_async_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
dump_uint64( ", iosb=", &req->iosb );
fprintf( stderr, ", only_thread=%d", req->only_thread );
}
static void dump_ioctl_request( const struct ioctl_request *req )
......@@ -4583,12 +4585,12 @@ static const struct
{ "IO_TIMEOUT", STATUS_IO_TIMEOUT },
{ "KEY_DELETED", STATUS_KEY_DELETED },
{ "MAPPED_FILE_SIZE_ZERO", STATUS_MAPPED_FILE_SIZE_ZERO },
{ "MEDIA_WRITE_PROTECTED", STATUS_MEDIA_WRITE_PROTECTED },
{ "MUTANT_NOT_OWNED", STATUS_MUTANT_NOT_OWNED },
{ "NAME_TOO_LONG", STATUS_NAME_TOO_LONG },
{ "NOTIFY_ENUM_DIR", STATUS_NOTIFY_ENUM_DIR },
{ "NOT_ALL_ASSIGNED", STATUS_NOT_ALL_ASSIGNED },
{ "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY },
{ "NOT_FOUND", STATUS_NOT_FOUND },
{ "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED },
{ "NOT_REGISTRY_FILE", STATUS_NOT_REGISTRY_FILE },
{ "NOT_SUPPORTED", STATUS_NOT_SUPPORTED },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment