Lisiano
May 15th, 2012, 07:29 AM
diff --git a/server/async.c b/server/async.c
index dd28dff..38b3b4f 100644
--- a/server/async.c
+++ b/server/async.c
@@ -43,7 +43,8 @@ struct async
unsigned int timeout_status; /* status to report upon timeout */
struct event *event;
struct completion *completion;
- apc_param_t comp_key;
+ apc_param_t comp_key; /* completion key (multi-use) */
+ obj_handle_t comp_handle; /* completion handle to return to APC callbacks */
async_data_t data; /* data for async I/O call */
};
@@ -155,6 +156,8 @@ void async_terminate( struct async *async, unsigned int status )
data.async_io.user = async->data.arg;
data.async_io.sb = async->data.iosb;
data.async_io.status = status;
+ data.async_io.ckey = async->comp_key;
+ data.async_io.chandle= async->comp_handle;
thread_queue_apc( async->thread, &async->obj, &data );
async->status = status;
async_reselect( async );
@@ -214,7 +217,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
async->timeout = NULL;
async->queue = (struct async_queue *)grab_object( queue );
async->completion = NULL;
- if (queue->fd) async->completion = fd_get_completion( queue->fd, &async->comp_key );
+ if (queue->fd) async->completion = fd_get_completion( queue->fd, &async->comp_key, &async->comp_handle );
list_add_tail( &queue->queue, &async->queue_entry );
grab_object( async );
diff --git a/server/fd.c b/server/fd.c
index a8b3a5f..6666431 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -188,6 +188,7 @@ struct fd
struct async_queue *wait_q; /* other async waiters of this fd */
struct completion *completion; /* completion object attached to this fd */
apc_param_t comp_key; /* completion key to set in completion events */
+ obj_handle_t comp_handle; /* completion handle to give APC callbacks */
};
static void fd_dump( struct object *obj, int verbose );
@@ -1585,6 +1586,8 @@ static struct fd *alloc_fd_object(void)
fd->write_q = NULL;
fd->wait_q = NULL;
fd->completion = NULL;
+ fd->comp_key = 0;
+ fd->comp_handle= 0;
list_init( &fd->inode_entry );
list_init( &fd->locks );
@@ -1620,6 +1623,8 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
fd->write_q = NULL;
fd->wait_q = NULL;
fd->completion = NULL;
+ fd->comp_key = 0;
+ fd->comp_handle= 0;
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
list_init( &fd->inode_entry );
list_init( &fd->locks );
@@ -2193,16 +2198,17 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
return fd;
}
-struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key )
+struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key, obj_handle_t *p_handle )
{
*p_key = fd->comp_key;
+ *p_handle = fd->comp_handle;
return fd->completion ? (struct completion *)grab_object( fd->completion ) : NULL;
}
void fd_copy_completion( struct fd *src, struct fd *dst )
{
assert( !dst->completion );
- dst->completion = fd_get_completion( src, &dst->comp_key );
+ dst->completion = fd_get_completion( src, &dst->comp_key, &dst->comp_handle );
}
/* flush a file buffers */
@@ -2349,6 +2355,7 @@ DECL_HANDLER(set_completion_info)
if (!(fd->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) && !fd->completion)
{
fd->completion = get_completion_obj( current->process, req->chandle, IO_COMPLETION_MODIFY_STATE );
+ fd->comp_handle = req->chandle;
fd->comp_key = req->ckey;
}
else set_error( STATUS_INVALID_PARAMETER );
diff --git a/server/file.h b/server/file.h
index ead356d..faf9b15 100644
--- a/server/file.h
+++ b/server/file.h
@@ -164,7 +164,7 @@ 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 struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key, obj_handle_t *p_handle );
extern void fd_copy_completion( struct fd *src, struct fd *dst );
/* access rights that require Unix read permission */
diff --git a/server/protocol.def b/server/protocol.def
index 31a3b0d..73fc48e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -442,9 +442,11 @@ typedef union
{
enum apc_type type; /* APC_ASYNC_IO */
unsigned int status; /* I/O status */
- client_ptr_t func; /* unsigned int (*func)(void*, void*, unsigned int, void **); */
+ client_ptr_t func; /* unsigned int (*func)(void*, void*, unsigned int, void **, FILE_COMPLETION_INFORMATION* ); */
client_ptr_t user; /* user pointer */
client_ptr_t sb; /* status block */
+ obj_handle_t chandle; /* completion handle */
+ apc_param_t ckey; /* completion key */
} async_io;
struct
{
diff --git a/tools/make_requests b/tools/make_requests
index 445ad06..163a954 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -45,7 +45,7 @@ my %formats =
"timeout_t" => [ 8, 8, "&dump_timeout" ],
"rectangle_t" => [ 16, 4, "&dump_rectangle" ],
"char_info_t" => [ 4, 2, "&dump_char_info" ],
- "apc_call_t" => [ 40, 8, "&dump_apc_call" ],
+ "apc_call_t" => [ 44, 8, "&dump_apc_call" ],
"apc_result_t" => [ 40, 8, "&dump_apc_result" ],
"async_data_t" => [ 40, 8, "&dump_async_data" ],
"luid_t" => [ 8, 4, "&dump_luid" ],
diff --git a/server/async.c b/server/async.c
index 38b3b4f..74e758b 100644
--- a/server/async.c
+++ b/server/async.c
@@ -217,11 +217,12 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
async->timeout = NULL;
async->queue = (struct async_queue *)grab_object( queue );
async->completion = NULL;
- if (queue->fd) async->completion = fd_get_completion( queue->fd, &async->comp_key, &async->comp_handle );
list_add_tail( &queue->queue, &async->queue_entry );
grab_object( async );
+ async_update( async->queue );
+
if (queue->fd) set_fd_signaled( queue->fd, 0 );
if (event) reset_event( event );
return async;
@@ -333,3 +334,20 @@ void async_wake_up( struct async_queue *queue, unsigned int status )
if (status == STATUS_ALERTED) break; /* only wake up the first one */
}
}
+
+/* update an async to correspond to new file object information */
+void async_update( struct async_queue *queue )
+{
+ struct list *ptr, *next;
+
+ if (!queue) return;
+
+ LIST_FOR_EACH_SAFE( ptr, next, &queue->queue )
+ {
+ struct async *async = LIST_ENTRY( ptr, struct async, queue_entry );
+
+ if (async->queue->fd)
+ async->completion = fd_get_completion( async->queue->fd, &async->comp_key, &async->comp_handle );
+ }
+}
+
diff --git a/server/fd.c b/server/fd.c
index 6666431..a99c671 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2108,6 +2108,14 @@ void default_fd_cancel_async( struct fd *fd, struct process *process, struct thr
set_error( STATUS_NOT_FOUND );
}
+/* default update_async() fd routine */
+void default_fd_update_async( struct fd *fd )
+{
+ async_update( fd->read_q );
+ async_update( fd->write_q );
+ async_update( fd->wait_q );
+}
+
/* default flush() routine */
void no_flush( struct fd *fd, struct event **event )
{
@@ -2357,6 +2365,7 @@ DECL_HANDLER(set_completion_info)
fd->completion = get_completion_obj( current->process, req->chandle, IO_COMPLETION_MODIFY_STATE );
fd->comp_handle = req->chandle;
fd->comp_key = req->ckey;
+ fd->fd_ops->update_async( fd );
}
else set_error( STATUS_INVALID_PARAMETER );
release_object( fd );
diff --git a/server/file.c b/server/file.c
index 02a1e37..83634c5 100644
--- a/server/file.c
+++ b/server/file.c
@@ -102,7 +102,8 @@ static const struct fd_ops file_fd_ops =
default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
static inline int is_overlapped( const struct file *file )
diff --git a/server/file.h b/server/file.h
index faf9b15..cacef8d 100644
--- a/server/file.h
+++ b/server/file.h
@@ -48,6 +48,8 @@ struct fd_ops
void (*reselect_async)( struct fd *, struct async_queue *queue );
/* cancel an async operation */
void (*cancel_async)(struct fd *, struct process *process, struct thread *thread, client_ptr_t iosb);
+ /* update an async operation to correspond to changes in the file object */
+ void (*update_async)(struct fd *);
};
/* file descriptor functions */
@@ -92,6 +94,7 @@ extern void no_fd_queue_async( struct fd *fd, const async_data_t *data, int type
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, struct process *process, struct thread *thread, client_ptr_t iosb );
+extern void default_fd_update_async( struct fd *fd );
extern void no_flush( struct fd *fd, struct event **event );
extern void main_loop(void);
extern void remove_process_locks( struct process *process );
@@ -164,6 +167,7 @@ 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 void async_update( struct async_queue *queue );
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key, obj_handle_t *p_handle );
extern void fd_copy_completion( struct fd *src, struct fd *dst );
diff --git a/server/mailslot.c b/server/mailslot.c
index 051f0ad..b29c168 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -102,7 +102,8 @@ static const struct fd_ops mailslot_fd_ops =
default_fd_ioctl, /* ioctl */
mailslot_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
@@ -152,7 +153,8 @@ static const struct fd_ops mail_writer_fd_ops =
default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
@@ -202,7 +204,8 @@ static const struct fd_ops mailslot_device_fd_ops =
default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
static void mailslot_destroy( struct object *obj)
diff --git a/server/mapping.c b/server/mapping.c
index 90956e9..60e9c5f 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -103,7 +103,8 @@ static const struct fd_ops mapping_fd_ops =
no_fd_ioctl, /* ioctl */
no_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
static struct list shared_list = LIST_INIT(shared_list);
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 590adca..2bd3827 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -173,6 +173,7 @@ static const struct fd_ops pipe_server_fd_ops =
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
/* client end functions */
@@ -212,7 +213,8 @@ static const struct fd_ops pipe_client_fd_ops =
default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
static void named_pipe_device_dump( struct object *obj, int verbose );
@@ -256,7 +258,8 @@ static const struct fd_ops named_pipe_device_fd_ops =
named_pipe_device_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
static void named_pipe_dump( struct object *obj, int verbose )
diff --git a/server/serial.c b/server/serial.c
index 587fee1..57ba51c 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -112,7 +112,8 @@ static const struct fd_ops serial_fd_ops =
default_fd_ioctl, /* ioctl */
serial_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
- default_fd_cancel_async /* cancel_async */
+ default_fd_cancel_async, /* cancel_async */
+ default_fd_update_async /* update_async */
};
/* check if the given fd is a serial port */
diff --git a/server/signal.c b/server/signal.c
index 5e4fe33..79dee43 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -90,7 +90,8 @@ static const struct fd_ops handler_fd_ops =
NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
- NULL /* cancel_async */
+ NULL, /* cancel_async */
+ NULL /* update_async */
};
static struct handler *handler_sighup;
diff --git a/server/sock.c b/server/sock.c
index 7e4acd8..7d21a1e 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -119,6 +119,7 @@ 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, struct process *process, struct thread *thread, client_ptr_t iosb );
+static void sock_update_async( struct fd *fd );
static int sock_get_ntstatus( int err );
static int sock_get_error( int err );
@@ -153,7 +154,8 @@ static const struct fd_ops sock_fd_ops =
default_fd_ioctl, /* ioctl */
sock_queue_async, /* queue_async */
sock_reselect_async, /* reselect_async */
- sock_cancel_async /* cancel_async */
+ sock_cancel_async, /* cancel_async */
+ sock_update_async /* update_async */
};
@@ -573,6 +575,15 @@ static void sock_cancel_async( struct fd *fd, struct process *process, struct th
set_error( STATUS_NOT_FOUND );
}
+static void sock_update_async( struct fd *fd )
+{
+ struct sock *sock = get_fd_user( fd );
+ assert( sock->obj.ops == &sock_ops );
+
+ async_update( sock->read_q );
+ async_update( sock->write_q );
+}
+
static struct fd *sock_get_fd( struct object *obj )
{
struct sock *sock = (struct sock *)obj;
diff --git a/server/thread.c b/server/thread.c
index f9a575e..3ee9486 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -157,7 +157,8 @@ static const struct fd_ops thread_fd_ops =
NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
- NULL /* cancel_async */
+ NULL, /* cancel_async */
+ NULL /* update_async */
};
static struct list thread_list = LIST_INIT(thread_list);
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 8e48602..33ca49a 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -358,7 +358,8 @@ NTSTATUS FILE_GetNtStatus(void)
/************************************************** *********************
* FILE_AsyncReadService (INTERNAL)
*/
-static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc)
+static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp)
{
async_fileio_read *fileio = user;
int fd, needs_close, result;
@@ -847,7 +848,8 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
/************************************************** *********************
* FILE_AsyncWriteService (INTERNAL)
*/
-static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc)
+static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp)
{
async_fileio_write *fileio = user;
int result, fd, needs_close;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index f759ce6..2cf0e7e 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -864,11 +864,16 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
case APC_ASYNC_IO:
{
void *apc = NULL;
+ FILE_COMPLETION_INFORMATION comp;
IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb );
- NTSTATUS (*func)(void *, IO_STATUS_BLOCK *, NTSTATUS, void **) = wine_server_get_ptr( call->async_io.func );
+ NTSTATUS (*func)(void *, IO_STATUS_BLOCK *, NTSTATUS, void **, FILE_COMPLETION_INFORMATION *);
+
+ comp.CompletionPort = wine_server_ptr_handle( call->async_io.chandle );
+ comp.CompletionKey = call->async_io.ckey;
+ func = wine_server_get_ptr( call->async_io.func );
result->type = call->type;
result->async_io.status = func( wine_server_get_ptr( call->async_io.user ),
- iosb, call->async_io.status, &apc );
+ iosb, call->async_io.status, &apc, &comp );
if (result->async_io.status != STATUS_PENDING)
{
result->async_io.total = iosb->Information;
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 21e084b..471ff63 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1563,7 +1563,8 @@ static int WS2_recv( int fd, struct ws2_async *wsa )
*
* Handler for overlapped recv() operations.
*/
-static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
+static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp )
{
ws2_async* wsa = user;
int result = 0, fd;
@@ -1620,12 +1621,13 @@ static void WINAPI ws2_async_accept_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG
* This function is used to finish the read part of an accept request. It is
* needed to place the completion on the correct socket (listener).
*/
-static NTSTATUS WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc )
+static NTSTATUS WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp )
{
void *junk;
struct ws2_accept_async *wsa = arg;
- status = WS2_async_recv( wsa->read, iosb, status, &junk );
+ status = WS2_async_recv( wsa->read, iosb, status, &junk, comp );
if (status == STATUS_PENDING)
return status;
@@ -1643,7 +1645,8 @@ static NTSTATUS WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATU
*
* This is the function called to satisfy the AcceptEx callback
*/
-static NTSTATUS WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc )
+static NTSTATUS WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp )
{
struct ws2_accept_async *wsa = arg;
int len;
@@ -1794,7 +1797,8 @@ static int WS2_send( int fd, struct ws2_async *wsa )
*
* Handler for overlapped send() operations.
*/
-static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
+static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp)
{
ws2_async* wsa = user;
int result = 0, fd;
@@ -1847,7 +1851,8 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu
*
* Handler for shutdown() operations on overlapped sockets.
*/
-static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc )
+static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc,
+ FILE_COMPLETION_INFORMATION *comp )
{
ws2_async* wsa = user;
int fd, err = 1;
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 471ff63..12d09b9 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -273,15 +273,16 @@ typedef struct ws2_async
typedef struct ws2_accept_async
{
- HANDLE listen_socket;
- HANDLE accept_socket;
- LPOVERLAPPED user_overlapped;
- ULONG_PTR cvalue;
- PVOID buf; /* buffer to write data to */
- int data_len;
- int local_len;
- int remote_len;
- struct ws2_async *read;
+ HANDLE listen_socket;
+ HANDLE accept_socket;
+ LPOVERLAPPED user_overlapped;
+ ULONG_PTR cvalue;
+ FILE_COMPLETION_INFORMATION comp_info; /* information for sending file completions */
+ PVOID buf; /* buffer to write data to */
+ int data_len;
+ int local_len;
+ int remote_len;
+ struct ws2_async *read;
} ws2_accept_async;
/************************************************** **************/
@@ -1634,7 +1635,8 @@ static NTSTATUS WS2_async_accept_recv( void *arg, IO_STATUS_BLOCK *iosb, NTSTATU
if (wsa->user_overlapped->hEvent)
SetEvent(wsa->user_overlapped->hEvent);
if (wsa->cvalue)
- WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information );
+ NtSetIoCompletion( wsa->comp_info.CompletionPort, wsa->comp_info.CompletionKey, wsa->cvalue,
+ iosb->u.Status, iosb->Information );
*apc = ws2_async_accept_apc;
return status;
@@ -1695,6 +1697,7 @@ static NTSTATUS WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS sta
if (!wsa->read)
goto finish;
+ wsa->comp_info = *comp;
SERVER_START_REQ( register_async )
{
req->type = ASYNC_TYPE_READ;
@@ -1718,7 +1721,7 @@ finish:
if (wsa->user_overlapped->hEvent)
SetEvent(wsa->user_overlapped->hEvent);
if (wsa->cvalue)
- WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information );
+ NtSetIoCompletion( comp->CompletionPort, comp->CompletionKey, wsa->cvalue, iosb->u.Status, iosb->Information );
*apc = ws2_async_accept_apc;
return status;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index e9814e3..29616b2 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -5494,11 +5494,11 @@ static void test_completion_port(void)
bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
ok(bret == FALSE, "failed to get completion status %u\n", bret);
- todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
- todo_wine ok(key == 125, "Key is %lu\n", key);
- todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
- todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
- todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+ ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+ ok(key == 125, "Key is %lu\n", key);
+ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+ ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+ ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
SetLastError(0xdeadbeef);
key = 0xdeadbeef;
@@ -5537,11 +5537,11 @@ static void test_completion_port(void)
bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
ok(bret == FALSE, "failed to get completion status %u\n", bret);
- todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
- todo_wine ok(key == 125, "Key is %lu\n", key);
- todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
- todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
- todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+ ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+ ok(key == 125, "Key is %lu\n", key);
+ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+ ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+ ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
SetLastError(0xdeadbeef);
key = 0xdeadbeef;
@@ -5596,11 +5596,11 @@ static void test_completion_port(void)
olp = (WSAOVERLAPPED *)0xdeadbeef;
bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
ok(bret == FALSE, "failed to get completion status %u\n", bret);
- todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
- todo_wine ok(key == 125, "Key is %lu\n", key);
- todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
- todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
- todo_wine ok(olp && olp->Internal == (ULONG)STATUS_CANCELLED, "Internal status is %lx\n", olp ? olp->Internal : 0);
+ ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+ ok(key == 125, "Key is %lu\n", key);
+ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+ ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+ ok(olp && olp->Internal == (ULONG)STATUS_CANCELLED, "Internal status is %lx\n", olp ? olp->Internal : 0);
SetLastError(0xdeadbeef);
key = 0xdeadbeef;
@@ -5663,11 +5663,11 @@ static void test_completion_port(void)
bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
ok(bret == FALSE, "failed to get completion status %u\n", bret);
- todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
- todo_wine ok(key == 125, "Key is %lu\n", key);
- todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
- todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
- todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+ ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+ ok(key == 125, "Key is %lu\n", key);
+ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+ ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+ ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
SetLastError(0xdeadbeef);
key = 0xdeadbeef;
@@ -5719,11 +5719,11 @@ static void test_completion_port(void)
bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
ok(bret == FALSE, "failed to get completion status %u\n", bret);
- todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
- todo_wine ok(key == 125, "Key is %lu\n", key);
- todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
- todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
- todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+ ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+ ok(key == 125, "Key is %lu\n", key);
+ ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+ ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+ ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
SetLastError(0xdeadbeef);
key = 0xdeadbeef; Yea...
vBulletin® v3.8.7, Copyright ©2000-2012, vBulletin Solutions, Inc.