Module: wine Branch: master Commit: 0a241b0fcc550cc60d8a59dfec0bdcd99bd0f1b6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0a241b0fcc550cc60d8a59dfec...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Mar 3 16:06:51 2015 +0900
ntdll: Allow specifying the user APC argument in the system APC callback.
---
dlls/ntdll/file.c | 26 +++++++++++++++++++++----- dlls/ntdll/server.c | 8 ++++---- dlls/ws2_32/socket.c | 27 +++++++++++++++++++-------- server/protocol.def | 2 +- 4 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 43b6097..1cd6546 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -448,7 +448,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, IO_STATUS_BLOCK *iosb, + NTSTATUS status, void **apc, void **arg ) { struct async_fileio_read *fileio = user; int fd, needs_close, result; @@ -501,7 +502,10 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU iosb->u.Status = status; iosb->Information = fileio->already; if (fileio->io.apc) + { *apc = fileio_apc; + *arg = &fileio->io; + } else release_fileio( &fileio->io ); } @@ -956,7 +960,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, void **arg ) { struct async_fileio_write *fileio = user; int result, fd, needs_close; @@ -999,7 +1004,10 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT iosb->u.Status = status; iosb->Information = fileio->already; if (fileio->io.apc) + { *apc = fileio_apc; + *arg = &fileio->io; + } else release_fileio( &fileio->io ); } @@ -1370,9 +1378,10 @@ struct async_ioctl };
/* callback for ioctl async I/O completion */ -static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status, void **apc ) +static NTSTATUS ioctl_completion( void *user, IO_STATUS_BLOCK *io, + NTSTATUS status, void **apc, void **arg ) { - struct async_ioctl *async = arg; + struct async_ioctl *async = user;
if (status == STATUS_ALERTED) { @@ -1390,7 +1399,10 @@ static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS statu { io->u.Status = status; if (async->io.apc) + { *apc = fileio_apc; + *arg = &async->io; + } else release_fileio( &async->io ); } @@ -1709,7 +1721,8 @@ struct read_changes_fileio char data[1]; };
-static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc ) +static NTSTATUS read_changes_apc( void *user, IO_STATUS_BLOCK *iosb, + NTSTATUS status, void **apc, void **arg ) { struct read_changes_fileio *fileio = user; NTSTATUS ret; @@ -1776,7 +1789,10 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st iosb->u.Status = ret; iosb->Information = size; if (fileio->io.apc) + { *apc = fileio_apc; + *arg = &fileio->io; + } else release_fileio( &fileio->io ); return ret; diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index e3f1694..2c99cbe 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -391,17 +391,17 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result ) } case APC_ASYNC_IO: { - void *apc = NULL; + void *apc = NULL, *arg = NULL; 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 **, void **) = 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, &arg ); if (result->async_io.status != STATUS_PENDING) { result->async_io.total = iosb->Information; result->async_io.apc = wine_server_client_ptr( apc ); - result->async_io.arg = call->async_io.user; + result->async_io.arg = wine_server_client_ptr( arg ); } break; } diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index f1f00eb..5bfdecf 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2013,7 +2013,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, void **arg ) { struct ws2_async *wsa = user; int result = 0, fd; @@ -2051,7 +2052,10 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat iosb->u.Status = status; iosb->Information = result; if (wsa->completion_func) + { *apc = ws2_async_apc; + *arg = wsa; + } else release_async_io( &wsa->io ); } @@ -2064,12 +2068,13 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat * 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 *user, IO_STATUS_BLOCK *iosb, + NTSTATUS status, void **apc, void **arg ) { void *junk; - struct ws2_accept_async *wsa = arg; + struct ws2_accept_async *wsa = user;
- status = WS2_async_recv( wsa->read, iosb, status, &junk ); + status = WS2_async_recv( wsa->read, iosb, status, &junk, &junk ); if (status == STATUS_PENDING) return status;
@@ -2087,9 +2092,10 @@ 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 *user, IO_STATUS_BLOCK *iosb, + NTSTATUS status, void **apc, void **arg ) { - struct ws2_accept_async *wsa = arg; + struct ws2_accept_async *wsa = user; int len; char *addr;
@@ -2241,7 +2247,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, void **arg ) { struct ws2_async *wsa = user; int result = 0, fd; @@ -2285,7 +2292,10 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu { iosb->u.Status = status; if (wsa->completion_func) + { *apc = ws2_async_apc; + *arg = wsa; + } else release_async_io( &wsa->io ); } @@ -2297,7 +2307,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, IO_STATUS_BLOCK *iosb, + NTSTATUS status, void **apc, void **arg ) { struct ws2_async_shutdown *wsa = user; int fd, err = 1; diff --git a/server/protocol.def b/server/protocol.def index f2a5a9a..7ec380b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -480,7 +480,7 @@ 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**, void**); */ client_ptr_t user; /* user pointer */ client_ptr_t sb; /* status block */ } async_io;