ntdll: Allow specifying the user APC argument in the system APC callback.

This commit is contained in:
Alexandre Julliard 2015-03-03 16:06:51 +09:00
parent 8843bc144d
commit 0a241b0fcc
4 changed files with 45 additions and 18 deletions

View File

@ -448,7 +448,8 @@ NTSTATUS FILE_GetNtStatus(void)
/*********************************************************************** /***********************************************************************
* FILE_AsyncReadService (INTERNAL) * 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; struct async_fileio_read *fileio = user;
int fd, needs_close, result; 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->u.Status = status;
iosb->Information = fileio->already; iosb->Information = fileio->already;
if (fileio->io.apc) if (fileio->io.apc)
{
*apc = fileio_apc; *apc = fileio_apc;
*arg = &fileio->io;
}
else else
release_fileio( &fileio->io ); release_fileio( &fileio->io );
} }
@ -956,7 +960,8 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
/*********************************************************************** /***********************************************************************
* FILE_AsyncWriteService (INTERNAL) * 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; struct async_fileio_write *fileio = user;
int result, fd, needs_close; 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->u.Status = status;
iosb->Information = fileio->already; iosb->Information = fileio->already;
if (fileio->io.apc) if (fileio->io.apc)
{
*apc = fileio_apc; *apc = fileio_apc;
*arg = &fileio->io;
}
else else
release_fileio( &fileio->io ); release_fileio( &fileio->io );
} }
@ -1370,9 +1378,10 @@ struct async_ioctl
}; };
/* callback for ioctl async I/O completion */ /* 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) if (status == STATUS_ALERTED)
{ {
@ -1390,7 +1399,10 @@ static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS statu
{ {
io->u.Status = status; io->u.Status = status;
if (async->io.apc) if (async->io.apc)
{
*apc = fileio_apc; *apc = fileio_apc;
*arg = &async->io;
}
else else
release_fileio( &async->io ); release_fileio( &async->io );
} }
@ -1709,7 +1721,8 @@ struct read_changes_fileio
char data[1]; 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; struct read_changes_fileio *fileio = user;
NTSTATUS ret; NTSTATUS ret;
@ -1776,7 +1789,10 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st
iosb->u.Status = ret; iosb->u.Status = ret;
iosb->Information = size; iosb->Information = size;
if (fileio->io.apc) if (fileio->io.apc)
{
*apc = fileio_apc; *apc = fileio_apc;
*arg = &fileio->io;
}
else else
release_fileio( &fileio->io ); release_fileio( &fileio->io );
return ret; return ret;

View File

@ -391,17 +391,17 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
} }
case APC_ASYNC_IO: case APC_ASYNC_IO:
{ {
void *apc = NULL; void *apc = NULL, *arg = NULL;
IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb ); 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->type = call->type;
result->async_io.status = func( wine_server_get_ptr( call->async_io.user ), 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) if (result->async_io.status != STATUS_PENDING)
{ {
result->async_io.total = iosb->Information; result->async_io.total = iosb->Information;
result->async_io.apc = wine_server_client_ptr( apc ); 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; break;
} }

View File

@ -2013,7 +2013,8 @@ static int WS2_recv( int fd, struct ws2_async *wsa )
* *
* Handler for overlapped recv() operations. * 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; struct ws2_async *wsa = user;
int result = 0, fd; 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->u.Status = status;
iosb->Information = result; iosb->Information = result;
if (wsa->completion_func) if (wsa->completion_func)
{
*apc = ws2_async_apc; *apc = ws2_async_apc;
*arg = wsa;
}
else else
release_async_io( &wsa->io ); 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 * 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). * 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; 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) if (status == STATUS_PENDING)
return status; 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 * 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; int len;
char *addr; char *addr;
@ -2241,7 +2247,8 @@ static int WS2_send( int fd, struct ws2_async *wsa )
* *
* Handler for overlapped send() operations. * 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; struct ws2_async *wsa = user;
int result = 0, fd; 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; iosb->u.Status = status;
if (wsa->completion_func) if (wsa->completion_func)
{
*apc = ws2_async_apc; *apc = ws2_async_apc;
*arg = wsa;
}
else else
release_async_io( &wsa->io ); 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. * 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; struct ws2_async_shutdown *wsa = user;
int fd, err = 1; int fd, err = 1;

View File

@ -480,7 +480,7 @@ typedef union
{ {
enum apc_type type; /* APC_ASYNC_IO */ enum apc_type type; /* APC_ASYNC_IO */
unsigned int status; /* I/O status */ 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 user; /* user pointer */
client_ptr_t sb; /* status block */ client_ptr_t sb; /* status block */
} async_io; } async_io;