Andrey Turkin : ntdll: Make async i/ o functions generate completion messages.

Alexandre Julliard julliard at winehq.org
Thu Nov 15 07:45:06 CST 2007


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

Author: Andrey Turkin <andrey.turkin at gmail.com>
Date:   Sat Nov 10 01:12:07 2007 +0300

ntdll: Make async i/o functions generate completion messages.

---

 dlls/ntdll/directory.c  |    3 ++-
 dlls/ntdll/file.c       |   39 +++++++++++++++++++++++++++------------
 dlls/ntdll/ntdll_misc.h |    3 +++
 dlls/ntdll/sync.c       |   16 ++++++++++++++++
 dlls/ntdll/tests/file.c |    8 ++------
 5 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 6891949..981d2a1 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -2324,6 +2324,7 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
 {
     struct read_changes_info *info;
     NTSTATUS status;
+    ULONG_PTR cvalue = ApcRoutine ? 0 : (ULONG_PTR)ApcContext;
 
     TRACE("%p %p %p %p %p %p %u %u %d\n",
           FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock,
@@ -2356,7 +2357,7 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
         req->async.arg      = info;
         req->async.apc      = read_changes_user_apc;
         req->async.event    = Event;
-        req->async.cvalue   = 0;
+        req->async.cvalue   = cvalue;
         status = wine_server_call( req );
     }
     SERVER_END_REQ;
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index a3a4af1..e84bc3d 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -560,6 +560,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
     NTSTATUS status;
     ULONG total = 0;
     enum server_fd_type type;
+    ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
 
     TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
           hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
@@ -620,7 +621,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
             BOOL avail_mode;
 
             if ((status = get_io_avail_mode( hFile, type, &avail_mode )))
-                goto done;
+                goto err;
             if (total && avail_mode)
             {
                 status = STATUS_SUCCESS;
@@ -630,7 +631,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
             if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
             {
                 status = STATUS_NO_MEMORY;
-                goto done;
+                goto err;
             }
             fileio->io.handle  = hFile;
             fileio->io.apc     = apc;
@@ -650,13 +651,13 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
                 req->async.arg      = fileio;
                 req->async.apc      = fileio_apc;
                 req->async.event    = hEvent;
-                req->async.cvalue   = 0;
+                req->async.cvalue   = cvalue;
                 status = wine_server_call( req );
             }
             SERVER_END_REQ;
 
             if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
-            goto done;
+            goto err;
         }
         else  /* synchronous read, wait for the fd to become ready */
         {
@@ -667,7 +668,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
             {
                 timeout_init_done = 1;
                 if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts )))
-                    goto done;
+                    goto err;
                 if (hEvent) NtResetEvent( hEvent, NULL );
             }
             timeout = get_next_io_timeout( &timeouts, total );
@@ -693,6 +694,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
     }
 
 done:
+    if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
+
+err:
     if (needs_close) close( unix_handle );
     if (status == STATUS_SUCCESS)
     {
@@ -794,6 +798,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
     NTSTATUS status;
     ULONG total = 0;
     enum server_fd_type type;
+    ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_user;
 
     TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n",
           hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
@@ -848,8 +853,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
             if (errno == EINTR) continue;
             if (errno != EAGAIN)
             {
-                if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
-                else status = FILE_GetNtStatus();
+                if (errno == EFAULT)
+                {
+                    status = STATUS_INVALID_USER_BUFFER;
+                    goto err;
+                }
+                status = FILE_GetNtStatus();
                 goto done;
             }
         }
@@ -861,7 +870,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
             if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
             {
                 status = STATUS_NO_MEMORY;
-                goto done;
+                goto err;
             }
             fileio->io.handle  = hFile;
             fileio->io.apc     = apc;
@@ -880,13 +889,13 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
                 req->async.arg      = fileio;
                 req->async.apc      = fileio_apc;
                 req->async.event    = hEvent;
-                req->async.cvalue   = 0;
+                req->async.cvalue   = cvalue;
                 status = wine_server_call( req );
             }
             SERVER_END_REQ;
 
             if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
-            goto done;
+            goto err;
         }
         else  /* synchronous write, wait for the fd to become ready */
         {
@@ -897,7 +906,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
             {
                 timeout_init_done = 1;
                 if ((status = get_io_timeouts( hFile, type, length, FALSE, &timeouts )))
-                    goto done;
+                    goto err;
                 if (hEvent) NtResetEvent( hEvent, NULL );
             }
             timeout = get_next_io_timeout( &timeouts, total );
@@ -921,6 +930,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
     }
 
 done:
+    if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
+
+err:
     if (needs_close) close( unix_handle );
     if (status == STATUS_SUCCESS)
     {
@@ -989,6 +1001,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
     NTSTATUS status;
     HANDLE wait_handle;
     ULONG options;
+    ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_context;
 
     if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
         return STATUS_NO_MEMORY;
@@ -1007,7 +1020,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
         req->async.arg      = async;
         req->async.apc      = (apc || event) ? ioctl_apc : NULL;
         req->async.event    = event;
-        req->async.cvalue   = 0;
+        req->async.cvalue   = cvalue;
         wine_server_add_data( req, in_buffer, in_size );
         wine_server_set_reply( req, out_buffer, out_size );
         if (!(status = wine_server_call( req )))
@@ -2127,6 +2140,8 @@ NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
         return STATUS_NOT_IMPLEMENTED;
     }
 
+    if (apc_user) FIXME("I/O completion on lock not implemented yet\n");
+
     for (;;)
     {
         SERVER_START_REQ( lock_file )
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 405f348..c283e1e 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -198,4 +198,7 @@ static inline struct ntdll_thread_regs *ntdll_get_thread_regs(void)
     return (struct ntdll_thread_regs *)NtCurrentTeb()->SpareBytes1;
 }
 
+/* Completion */
+extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG_PTR Information );
+
 #endif
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 47c8461..ec8aa59 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1310,3 +1310,19 @@ NTSTATUS WINAPI NtQueryIoCompletion( HANDLE CompletionPort, IO_COMPLETION_INFORM
     }
     return status;
 }
+
+NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG_PTR Information )
+{
+    NTSTATUS status;
+
+    SERVER_START_REQ( add_fd_completion )
+    {
+        req->handle      = hFile;
+        req->cvalue      = CompletionValue;
+        req->status      = CompletionStatus;
+        req->information = Information;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+    return status;
+}
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index eb3bc8c..5592711 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -521,15 +521,15 @@ static void test_iocp_fileio(HANDLE h)
         ok( !count, "Unexpected msg count: %ld\n", count );
         WriteFile( hPipeClt, buf, 3, &read, NULL );
 
-        todo_wine {
         if (get_msg(h))
         {
             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
+            todo_wine {
             ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information );
+            }
             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
         }
-        }
         count = get_pending_msgs(h);
         ok( !count, "Unexpected msg count: %ld\n", count );
 
@@ -538,10 +538,7 @@ static void test_iocp_fileio(HANDLE h)
         ok( !count, "Unexpected msg count: %ld\n", count );
         ReadFile( hPipeSrv, buf, 2, &read, &o);
         count = get_pending_msgs(h);
-        todo_wine {
         ok( count == 1, "Unexpected msg count: %ld\n", count );
-        }
-        todo_wine {
         if (get_msg(h))
         {
             ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
@@ -549,7 +546,6 @@ static void test_iocp_fileio(HANDLE h)
             ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
             ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
         }
-        }
     }
 
     CloseHandle( hPipeSrv );




More information about the wine-cvs mailing list