server: Specify the user APC to call only once the system APC has executed.
This commit is contained in:
parent
7ec95c5bee
commit
f507ccbf52
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue