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