Commit f507ccbf authored by Alexandre Julliard's avatar Alexandre Julliard

server: Specify the user APC to call only once the system APC has executed.

parent 7ec95c5b
......@@ -2302,7 +2302,7 @@ static void WINAPI read_changes_user_apc( void *arg, IO_STATUS_BLOCK *io, ULONG
RtlFreeHeap( GetProcessHeap(), 0, info );
}
static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, ULONG *total )
static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc )
{
struct read_changes_info *info = user;
char path[PATH_MAX];
......@@ -2347,7 +2347,8 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st
}
iosb->u.Status = ret;
iosb->Information = *total = len;
iosb->Information = len;
*apc = read_changes_user_apc;
return ret;
}
......@@ -2403,7 +2404,6 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
req->async.callback = read_changes_apc;
req->async.iosb = IoStatusBlock;
req->async.arg = info;
req->async.apc = read_changes_user_apc;
req->async.event = wine_server_obj_handle( Event );
req->async.cvalue = cvalue;
status = wine_server_call( req );
......
......@@ -334,7 +334,7 @@ NTSTATUS FILE_GetNtStatus(void)
/***********************************************************************
* FILE_AsyncReadService (INTERNAL)
*/
static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, ULONG *total)
static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc)
{
async_fileio_read *fileio = user;
int fd, needs_close, result;
......@@ -385,7 +385,8 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = *total = fileio->already;
iosb->Information = fileio->already;
*apc = fileio_apc;
}
return status;
}
......@@ -659,7 +660,6 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
req->async.callback = FILE_AsyncReadService;
req->async.iosb = io_status;
req->async.arg = fileio;
req->async.apc = fileio_apc;
req->async.cvalue = cvalue;
status = wine_server_call( req );
}
......@@ -812,7 +812,7 @@ 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, ULONG *total)
static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc)
{
async_fileio_write *fileio = user;
int result, fd, needs_close;
......@@ -853,7 +853,8 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = *total = fileio->already;
iosb->Information = fileio->already;
*apc = fileio_apc;
}
return status;
}
......@@ -983,7 +984,6 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
req->async.callback = FILE_AsyncWriteService;
req->async.iosb = io_status;
req->async.arg = fileio;
req->async.apc = fileio_apc;
req->async.cvalue = cvalue;
status = wine_server_call( req );
}
......@@ -1139,14 +1139,23 @@ NTSTATUS WINAPI NtWriteFileGather( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
struct async_ioctl
{
HANDLE handle; /* handle to the device */
HANDLE event; /* async event */
void *buffer; /* buffer for output */
ULONG size; /* size of buffer */
PIO_APC_ROUTINE apc; /* user apc params */
void *apc_arg;
};
/* callback for ioctl user APC */
static void WINAPI ioctl_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
{
struct async_ioctl *async = arg;
if (async->apc) async->apc( async->apc_arg, io, reserved );
RtlFreeHeap( GetProcessHeap(), 0, async );
}
/* callback for ioctl async I/O completion */
static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status, ULONG *total )
static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status, void **apc )
{
struct async_ioctl *async = arg;
......@@ -1158,22 +1167,18 @@ static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS statu
req->user_arg = async;
wine_server_set_reply( req, async->buffer, async->size );
if (!(status = wine_server_call( req )))
io->Information = *total = wine_server_reply_size( reply );
io->Information = wine_server_reply_size( reply );
}
SERVER_END_REQ;
}
if (status != STATUS_PENDING) io->u.Status = status;
if (status != STATUS_PENDING)
{
io->u.Status = status;
if (async->apc || async->event) *apc = ioctl_apc;
}
return status;
}
/* callback for ioctl user APC */
static void WINAPI ioctl_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
{
struct async_ioctl *async = arg;
if (async->apc) async->apc( async->apc_arg, io, reserved );
RtlFreeHeap( GetProcessHeap(), 0, async );
}
/* do a ioctl call through the server */
static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
PIO_APC_ROUTINE apc, PVOID apc_context,
......@@ -1190,6 +1195,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
return STATUS_NO_MEMORY;
async->handle = handle;
async->event = event;
async->buffer = out_buffer;
async->size = out_size;
async->apc = apc;
......@@ -1203,7 +1209,6 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
req->async.callback = ioctl_completion;
req->async.iosb = io;
req->async.arg = async;
req->async.apc = (apc || event) ? ioctl_apc : NULL;
req->async.event = wine_server_obj_handle( event );
req->async.cvalue = cvalue;
wine_server_add_data( req, in_buffer, in_size );
......
......@@ -865,12 +865,19 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
break;
}
case APC_ASYNC_IO:
{
void *apc = NULL;
IO_STATUS_BLOCK *iosb = call->async_io.sb;
result->type = call->type;
result->async_io.status = call->async_io.func( call->async_io.user,
call->async_io.sb,
call->async_io.status,
&result->async_io.total );
result->async_io.status = call->async_io.func( call->async_io.user, iosb,
call->async_io.status, &apc );
if (result->async_io.status != STATUS_PENDING)
{
result->async_io.total = iosb->Information;
result->async_io.apc = apc;
}
break;
}
case APC_VIRTUAL_ALLOC:
result->type = call->type;
addr = wine_server_get_ptr( call->virtual_alloc.addr );
......
......@@ -1127,7 +1127,7 @@ 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, ULONG *total )
static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
{
ws2_async* wsa = user;
int result = 0, fd;
......@@ -1163,7 +1163,8 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat
if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = *total = result;
iosb->Information = result;
*apc = ws2_async_apc;
}
return status;
}
......@@ -1228,7 +1229,7 @@ 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, ULONG *total )
static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS status, void **apc)
{
ws2_async* wsa = user;
int result = 0, fd;
......@@ -1273,7 +1274,8 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu
if (status != STATUS_PENDING)
{
iosb->u.Status = status;
iosb->Information = *total = result;
iosb->Information = result;
*apc = ws2_async_apc;
}
return status;
}
......@@ -1283,7 +1285,7 @@ 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, ULONG *total )
static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc )
{
ws2_async* wsa = user;
int fd, err = 1;
......@@ -1303,8 +1305,8 @@ static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS
status = err ? wsaErrno() : STATUS_SUCCESS;
break;
}
*total = 0;
iosb->u.Status = status;
*apc = ws2_async_apc;
return status;
}
......@@ -1335,7 +1337,6 @@ static int WS2_register_async_shutdown( SOCKET s, int type )
req->async.callback = WS2_async_shutdown;
req->async.iosb = &wsa->local_iosb;
req->async.arg = wsa;
req->async.apc = ws2_async_apc;
req->async.cvalue = 0;
status = wine_server_call( req );
}
......@@ -2788,7 +2789,6 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
req->async.callback = WS2_async_send;
req->async.iosb = iosb;
req->async.arg = wsa;
req->async.apc = ws2_async_apc;
req->async.event = wine_server_obj_handle( lpCompletionRoutine ? 0 : lpOverlapped->hEvent );
req->async.cvalue = cvalue;
err = wine_server_call( req );
......@@ -4314,7 +4314,6 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
req->async.callback = WS2_async_recv;
req->async.iosb = iosb;
req->async.arg = wsa;
req->async.apc = ws2_async_apc;
req->async.event = wine_server_obj_handle( lpCompletionRoutine ? 0 : lpOverlapped->hEvent );
req->async.cvalue = cvalue;
err = wine_server_call( req );
......
......@@ -169,7 +169,6 @@ typedef struct
void *callback;
void *iosb;
void *arg;
void *apc;
apc_param_t cvalue;
} async_data_t;
......@@ -287,7 +286,7 @@ typedef union
struct
{
enum apc_type type;
unsigned int (*func)(void*, void*, unsigned int, unsigned int *);
unsigned int (*func)(void*, void*, unsigned int, void **);
void *user;
void *sb;
unsigned int status;
......@@ -377,6 +376,7 @@ typedef union
{
enum apc_type type;
unsigned int status;
void *apc;
unsigned int total;
} async_io;
struct
......@@ -5060,6 +5060,6 @@ union generic_reply
struct set_window_layered_info_reply set_window_layered_info_reply;
};
#define SERVER_PROTOCOL_VERSION 371
#define SERVER_PROTOCOL_VERSION 372
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -234,7 +234,7 @@ void async_set_timeout( struct async *async, timeout_t timeout, unsigned int sta
}
/* store the result of the client-side async callback */
void async_set_result( struct object *obj, unsigned int status, unsigned int total )
void async_set_result( struct object *obj, unsigned int status, unsigned int total, void *apc )
{
struct async *async = (struct async *)obj;
......@@ -260,12 +260,12 @@ void async_set_result( struct object *obj, unsigned int status, unsigned int tot
async->status = status;
if (async->completion && async->data.cvalue)
add_completion( async->completion, async->comp_key, async->data.cvalue, status, total );
if (async->data.apc)
if (apc)
{
apc_call_t data;
memset( &data, 0, sizeof(data) );
data.type = APC_USER;
data.user.func = async->data.apc;
data.user.func = apc;
data.user.args[0] = (apc_param_t)(unsigned long)async->data.arg;
data.user.args[1] = (apc_param_t)(unsigned long)async->data.iosb;
data.user.args[2] = 0;
......
......@@ -138,7 +138,7 @@ extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct thread *thread, struct async_queue *queue,
const async_data_t *data );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
extern void async_set_result( struct object *obj, unsigned int status, unsigned int total );
extern void async_set_result( struct object *obj, unsigned int status, unsigned int total, void *apc );
extern int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status );
extern void async_wake_up( struct async_queue *queue, unsigned int status );
......
......@@ -185,7 +185,6 @@ typedef struct
void *callback; /* client-side callback to call upon end of async */
void *iosb; /* I/O status block in client addr space */
void *arg; /* opaque user data to pass to callback */
void *apc; /* user apc to call */
apc_param_t cvalue; /* completion value to use for completion events */
} async_data_t;
......@@ -303,7 +302,7 @@ typedef union
struct
{
enum apc_type type; /* APC_ASYNC_IO */
unsigned int (*func)(void*, void*, unsigned int, unsigned int *);
unsigned int (*func)(void*, void*, unsigned int, void **);
void *user; /* user pointer */
void *sb; /* status block */
unsigned int status; /* I/O status */
......@@ -393,6 +392,7 @@ typedef union
{
enum apc_type type; /* APC_ASYNC_IO */
unsigned int status; /* new status of async operation */
void *apc; /* user APC to call */
unsigned int total; /* bytes transferred */
} async_io;
struct
......
......@@ -1196,7 +1196,9 @@ DECL_HANDLER(select)
}
else if (apc->result.type == APC_ASYNC_IO)
{
if (apc->owner) async_set_result( apc->owner, apc->result.async_io.status, apc->result.async_io.total );
if (apc->owner)
async_set_result( apc->owner, apc->result.async_io.status,
apc->result.async_io.total, apc->result.async_io.apc );
}
wake_up( &apc->obj, 0 );
close_handle( current->process, req->prev_apc );
......
......@@ -218,8 +218,8 @@ static void dump_apc_result( const apc_result_t *result )
case APC_NONE:
break;
case APC_ASYNC_IO:
fprintf( stderr, "APC_ASYNC_IO,status=%s",
get_status_name( result->async_io.status ) );
fprintf( stderr, "APC_ASYNC_IO,status=%s,total=%u,apc=%p",
get_status_name( result->async_io.status ), result->async_io.total, result->async_io.apc );
break;
case APC_VIRTUAL_ALLOC:
fprintf( stderr, "APC_VIRTUAL_ALLOC,status=%s,addr=",
......@@ -301,9 +301,10 @@ static void dump_apc_result( const apc_result_t *result )
static void dump_async_data( const async_data_t *data )
{
fprintf( stderr, "{handle=%04x,event=%04x,callback=%p,iosb=%p,arg=%p,apc=%p,cvalue=}",
data->handle, data->event, data->callback, data->iosb, data->arg, data->apc );
fprintf( stderr, "{handle=%04x,event=%04x,callback=%p,iosb=%p,arg=%p,cvalue=",
data->handle, data->event, data->callback, data->iosb, data->arg );
dump_uint64( &data->cvalue );
fputc( '}', stderr );
}
static void dump_luid( const luid_t *luid )
......
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