server: Add support for queuing a user APC upon async I/O completion.
This commit is contained in:
parent
9eaea34e04
commit
c16eb8efd9
@ -2164,8 +2164,6 @@ done:
|
|||||||
struct read_changes_info
|
struct read_changes_info
|
||||||
{
|
{
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
PIO_APC_ROUTINE ApcRoutine;
|
|
||||||
PVOID ApcContext;
|
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
ULONG BufferSize;
|
ULONG BufferSize;
|
||||||
};
|
};
|
||||||
@ -2177,7 +2175,7 @@ static void WINAPI read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, ULONG st
|
|||||||
NTSTATUS ret = STATUS_SUCCESS;
|
NTSTATUS ret = STATUS_SUCCESS;
|
||||||
int len, action, i;
|
int len, action, i;
|
||||||
|
|
||||||
TRACE("%p %p %p %08x\n", info, info->ApcContext, iosb, status);
|
TRACE("%p %p %08x\n", info, iosb, status);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: race me!
|
* FIXME: race me!
|
||||||
@ -2266,9 +2264,6 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
|
|||||||
if (CompletionFilter == 0 || (CompletionFilter & ~FILE_NOTIFY_ALL))
|
if (CompletionFilter == 0 || (CompletionFilter & ~FILE_NOTIFY_ALL))
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (ApcRoutine)
|
|
||||||
FIXME("parameters ignored %p %p\n", ApcRoutine, ApcContext );
|
|
||||||
|
|
||||||
info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof *info );
|
info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof *info );
|
||||||
if (!info)
|
if (!info)
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
@ -2276,8 +2271,6 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
|
|||||||
info->FileHandle = FileHandle;
|
info->FileHandle = FileHandle;
|
||||||
info->Buffer = Buffer;
|
info->Buffer = Buffer;
|
||||||
info->BufferSize = BufferSize;
|
info->BufferSize = BufferSize;
|
||||||
info->ApcRoutine = ApcRoutine;
|
|
||||||
info->ApcContext = ApcContext;
|
|
||||||
|
|
||||||
SERVER_START_REQ( read_directory_changes )
|
SERVER_START_REQ( read_directory_changes )
|
||||||
{
|
{
|
||||||
@ -2288,6 +2281,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
|
|||||||
req->async.callback = read_changes_apc;
|
req->async.callback = read_changes_apc;
|
||||||
req->async.iosb = IoStatusBlock;
|
req->async.iosb = IoStatusBlock;
|
||||||
req->async.arg = info;
|
req->async.arg = info;
|
||||||
|
req->async.apc = ApcRoutine;
|
||||||
|
req->async.apc_arg = ApcContext;
|
||||||
req->async.event = Event;
|
req->async.event = Event;
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
}
|
}
|
||||||
|
@ -922,7 +922,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
|||||||
{
|
{
|
||||||
HANDLE internal_event = 0;
|
HANDLE internal_event = 0;
|
||||||
|
|
||||||
if(!event)
|
if(!event && !apc)
|
||||||
{
|
{
|
||||||
io->u.Status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE);
|
io->u.Status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE);
|
||||||
if (io->u.Status != STATUS_SUCCESS) return io->u.Status;
|
if (io->u.Status != STATUS_SUCCESS) return io->u.Status;
|
||||||
@ -933,12 +933,14 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
|||||||
req->async.callback = pipe_completion_wait;
|
req->async.callback = pipe_completion_wait;
|
||||||
req->async.iosb = io;
|
req->async.iosb = io;
|
||||||
req->async.arg = NULL;
|
req->async.arg = NULL;
|
||||||
|
req->async.apc = apc;
|
||||||
|
req->async.apc_arg = apc_context;
|
||||||
req->async.event = event ? event : internal_event;
|
req->async.event = event ? event : internal_event;
|
||||||
io->u.Status = wine_server_call(req);
|
io->u.Status = wine_server_call(req);
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (!event && io->u.Status == STATUS_PENDING)
|
if (internal_event && io->u.Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
while (NtWaitForSingleObject(internal_event, TRUE, NULL) == STATUS_USER_APC) /*nothing*/ ;
|
while (NtWaitForSingleObject(internal_event, TRUE, NULL) == STATUS_USER_APC) /*nothing*/ ;
|
||||||
}
|
}
|
||||||
@ -951,7 +953,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
|||||||
HANDLE internal_event = 0;
|
HANDLE internal_event = 0;
|
||||||
FILE_PIPE_WAIT_FOR_BUFFER *buff = in_buffer;
|
FILE_PIPE_WAIT_FOR_BUFFER *buff = in_buffer;
|
||||||
|
|
||||||
if(!event)
|
if(!event && !apc)
|
||||||
{
|
{
|
||||||
io->u.Status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE);
|
io->u.Status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE);
|
||||||
if (io->u.Status != STATUS_SUCCESS) return io->u.Status;
|
if (io->u.Status != STATUS_SUCCESS) return io->u.Status;
|
||||||
@ -964,13 +966,15 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
|||||||
req->async.callback = pipe_completion_wait;
|
req->async.callback = pipe_completion_wait;
|
||||||
req->async.iosb = io;
|
req->async.iosb = io;
|
||||||
req->async.arg = NULL;
|
req->async.arg = NULL;
|
||||||
|
req->async.apc = apc;
|
||||||
|
req->async.apc_arg = apc_context;
|
||||||
req->async.event = event ? event : internal_event;
|
req->async.event = event ? event : internal_event;
|
||||||
wine_server_add_data( req, buff->Name, buff->NameLength );
|
wine_server_add_data( req, buff->Name, buff->NameLength );
|
||||||
io->u.Status = wine_server_call( req );
|
io->u.Status = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if (!event && io->u.Status == STATUS_PENDING)
|
if (internal_event && io->u.Status == STATUS_PENDING)
|
||||||
{
|
{
|
||||||
while (NtWaitForSingleObject(internal_event, TRUE, NULL) == STATUS_USER_APC) /*nothing*/ ;
|
while (NtWaitForSingleObject(internal_event, TRUE, NULL) == STATUS_USER_APC) /*nothing*/ ;
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,8 @@ typedef struct
|
|||||||
void *callback;
|
void *callback;
|
||||||
void *iosb;
|
void *iosb;
|
||||||
void *arg;
|
void *arg;
|
||||||
|
void *apc;
|
||||||
|
void *apc_arg;
|
||||||
obj_handle_t event;
|
obj_handle_t event;
|
||||||
} async_data_t;
|
} async_data_t;
|
||||||
|
|
||||||
@ -4660,6 +4662,6 @@ union generic_reply
|
|||||||
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
|
struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 288
|
#define SERVER_PROTOCOL_VERSION 289
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
@ -150,6 +150,16 @@ void async_set_result( struct object *obj, unsigned int status )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (async->data.apc)
|
||||||
|
{
|
||||||
|
apc_call_t data;
|
||||||
|
data.type = APC_USER;
|
||||||
|
data.user.func = async->data.apc;
|
||||||
|
data.user.args[0] = (unsigned long)async->data.apc_arg;
|
||||||
|
data.user.args[1] = (unsigned long)async->data.iosb;
|
||||||
|
data.user.args[2] = 0;
|
||||||
|
thread_queue_apc( async->thread, NULL, &data );
|
||||||
|
}
|
||||||
if (async->event) set_event( async->event );
|
if (async->event) set_event( async->event );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,8 @@ typedef struct
|
|||||||
void *callback; /* client-side callback to call upon end of async */
|
void *callback; /* client-side callback to call upon end of async */
|
||||||
void *iosb; /* I/O status block in client addr space */
|
void *iosb; /* I/O status block in client addr space */
|
||||||
void *arg; /* opaque user data to pass to callback */
|
void *arg; /* opaque user data to pass to callback */
|
||||||
|
void *apc; /* user apc to call */
|
||||||
|
void *apc_arg; /* argument for user apc */
|
||||||
obj_handle_t event; /* event to signal when done */
|
obj_handle_t event; /* event to signal when done */
|
||||||
} async_data_t;
|
} async_data_t;
|
||||||
|
|
||||||
|
@ -246,8 +246,8 @@ static void dump_apc_result( const apc_result_t *result )
|
|||||||
|
|
||||||
static void dump_async_data( const async_data_t *data )
|
static void dump_async_data( const async_data_t *data )
|
||||||
{
|
{
|
||||||
fprintf( stderr, "{callback=%p,iosb=%p,arg=%p,event=%p}",
|
fprintf( stderr, "{callback=%p,iosb=%p,arg=%p,apc=%p,apc_arg=%p,event=%p}",
|
||||||
data->callback, data->iosb, data->arg, data->event );
|
data->callback, data->iosb, data->arg, data->apc, data->apc_arg, data->event );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_luid( const luid_t *luid )
|
static void dump_luid( const luid_t *luid )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user