Alexandre Julliard : server: Add support for queuing a user APC upon async I/O completion.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Mar 28 06:41:42 CDT 2007


Module: wine
Branch: master
Commit: c16eb8efd942bfbb0bb7f3da4c740a2e483cce28
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c16eb8efd942bfbb0bb7f3da4c740a2e483cce28

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Mar 27 16:42:27 2007 +0200

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 e60dad7..697fd1a 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 6873e0e..89de3b3 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 1e21566..a254128 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 aa4db4e..440cb2e 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 5105fd6..ef20235 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 a332821..898998b 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 )




More information about the wine-cvs mailing list