From c16eb8efd942bfbb0bb7f3da4c740a2e483cce28 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 27 Mar 2007 16:42:27 +0200 Subject: [PATCH] server: Add support for queuing a user APC upon async I/O completion. --- dlls/ntdll/directory.c | 11 +++-------- dlls/ntdll/file.c | 12 ++++++++---- include/wine/server_protocol.h | 4 +++- server/async.c | 10 ++++++++++ server/protocol.def | 2 ++ server/trace.c | 4 ++-- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index e60dad7bf43..697fd1ad705 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2164,8 +2164,6 @@ done: struct read_changes_info { HANDLE FileHandle; - PIO_APC_ROUTINE ApcRoutine; - PVOID ApcContext; PVOID Buffer; ULONG BufferSize; }; @@ -2177,7 +2175,7 @@ static void WINAPI read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, ULONG st NTSTATUS ret = STATUS_SUCCESS; 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! @@ -2266,9 +2264,6 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event, if (CompletionFilter == 0 || (CompletionFilter & ~FILE_NOTIFY_ALL)) return STATUS_INVALID_PARAMETER; - if (ApcRoutine) - FIXME("parameters ignored %p %p\n", ApcRoutine, ApcContext ); - info = RtlAllocateHeap( GetProcessHeap(), 0, sizeof *info ); if (!info) return STATUS_NO_MEMORY; @@ -2276,8 +2271,6 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event, info->FileHandle = FileHandle; info->Buffer = Buffer; info->BufferSize = BufferSize; - info->ApcRoutine = ApcRoutine; - info->ApcContext = ApcContext; SERVER_START_REQ( read_directory_changes ) { @@ -2288,6 +2281,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event, req->async.callback = read_changes_apc; req->async.iosb = IoStatusBlock; req->async.arg = info; + req->async.apc = ApcRoutine; + req->async.apc_arg = ApcContext; req->async.event = Event; status = wine_server_call( req ); } diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 6873e0e77ae..89de3b332a7 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -922,7 +922,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc { HANDLE internal_event = 0; - if(!event) + if(!event && !apc) { io->u.Status = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, NULL, FALSE, FALSE); 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.iosb = io; req->async.arg = NULL; + req->async.apc = apc; + req->async.apc_arg = apc_context; req->async.event = event ? event : internal_event; io->u.Status = wine_server_call(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*/ ; } @@ -951,7 +953,7 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc HANDLE internal_event = 0; 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); 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.iosb = io; req->async.arg = NULL; + req->async.apc = apc; + req->async.apc_arg = apc_context; req->async.event = event ? event : internal_event; wine_server_add_data( req, buff->Name, buff->NameLength ); io->u.Status = wine_server_call( 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*/ ; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 1e215665c2d..a254128a4b5 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -162,6 +162,8 @@ typedef struct void *callback; void *iosb; void *arg; + void *apc; + void *apc_arg; obj_handle_t event; } async_data_t; @@ -4660,6 +4662,6 @@ union generic_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 */ diff --git a/server/async.c b/server/async.c index aa4db4e7a5f..440cb2e27ed 100644 --- a/server/async.c +++ b/server/async.c @@ -150,6 +150,16 @@ void async_set_result( struct object *obj, unsigned int status ) } 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 ); } } diff --git a/server/protocol.def b/server/protocol.def index 5105fd6b98d..ef202350249 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -178,6 +178,8 @@ 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 */ + void *apc_arg; /* argument for user apc */ obj_handle_t event; /* event to signal when done */ } async_data_t; diff --git a/server/trace.c b/server/trace.c index a3328217e5d..898998bcb20 100644 --- a/server/trace.c +++ b/server/trace.c @@ -246,8 +246,8 @@ static void dump_apc_result( const apc_result_t *result ) static void dump_async_data( const async_data_t *data ) { - fprintf( stderr, "{callback=%p,iosb=%p,arg=%p,event=%p}", - data->callback, data->iosb, data->arg, data->event ); + fprintf( stderr, "{callback=%p,iosb=%p,arg=%p,apc=%p,apc_arg=%p,event=%p}", + data->callback, data->iosb, data->arg, data->apc, data->apc_arg, data->event ); } static void dump_luid( const luid_t *luid ) -- 2.11.4.GIT