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

This commit is contained in:
Andrey Turkin 2007-11-10 01:12:07 +03:00 committed by Alexandre Julliard
parent 27cb7c7274
commit 793453f768
5 changed files with 50 additions and 19 deletions

View File

@ -2324,6 +2324,7 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
{ {
struct read_changes_info *info; struct read_changes_info *info;
NTSTATUS status; NTSTATUS status;
ULONG_PTR cvalue = ApcRoutine ? 0 : (ULONG_PTR)ApcContext;
TRACE("%p %p %p %p %p %p %u %u %d\n", TRACE("%p %p %p %p %p %p %u %u %d\n",
FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock,
@ -2356,7 +2357,7 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
req->async.arg = info; req->async.arg = info;
req->async.apc = read_changes_user_apc; req->async.apc = read_changes_user_apc;
req->async.event = Event; req->async.event = Event;
req->async.cvalue = 0; req->async.cvalue = cvalue;
status = wine_server_call( req ); status = wine_server_call( req );
} }
SERVER_END_REQ; SERVER_END_REQ;

View File

@ -560,6 +560,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
NTSTATUS status; NTSTATUS status;
ULONG total = 0; ULONG total = 0;
enum server_fd_type type; 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", 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); 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; BOOL avail_mode;
if ((status = get_io_avail_mode( hFile, type, &avail_mode ))) if ((status = get_io_avail_mode( hFile, type, &avail_mode )))
goto done; goto err;
if (total && avail_mode) if (total && avail_mode)
{ {
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
@ -630,7 +631,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio)))) if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto err;
} }
fileio->io.handle = hFile; fileio->io.handle = hFile;
fileio->io.apc = apc; fileio->io.apc = apc;
@ -650,13 +651,13 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
req->async.arg = fileio; req->async.arg = fileio;
req->async.apc = fileio_apc; req->async.apc = fileio_apc;
req->async.event = hEvent; req->async.event = hEvent;
req->async.cvalue = 0; req->async.cvalue = cvalue;
status = wine_server_call( req ); status = wine_server_call( req );
} }
SERVER_END_REQ; SERVER_END_REQ;
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio ); if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
goto done; goto err;
} }
else /* synchronous read, wait for the fd to become ready */ 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; timeout_init_done = 1;
if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts ))) if ((status = get_io_timeouts( hFile, type, length, TRUE, &timeouts )))
goto done; goto err;
if (hEvent) NtResetEvent( hEvent, NULL ); if (hEvent) NtResetEvent( hEvent, NULL );
} }
timeout = get_next_io_timeout( &timeouts, total ); timeout = get_next_io_timeout( &timeouts, total );
@ -693,6 +694,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
} }
done: done:
if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
err:
if (needs_close) close( unix_handle ); if (needs_close) close( unix_handle );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
@ -794,6 +798,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
NTSTATUS status; NTSTATUS status;
ULONG total = 0; ULONG total = 0;
enum server_fd_type type; 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", TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n",
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key); 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 == EINTR) continue;
if (errno != EAGAIN) if (errno != EAGAIN)
{ {
if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER; if (errno == EFAULT)
else status = FILE_GetNtStatus(); {
status = STATUS_INVALID_USER_BUFFER;
goto err;
}
status = FILE_GetNtStatus();
goto done; goto done;
} }
} }
@ -861,7 +870,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio)))) if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*fileio))))
{ {
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto done; goto err;
} }
fileio->io.handle = hFile; fileio->io.handle = hFile;
fileio->io.apc = apc; fileio->io.apc = apc;
@ -880,13 +889,13 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
req->async.arg = fileio; req->async.arg = fileio;
req->async.apc = fileio_apc; req->async.apc = fileio_apc;
req->async.event = hEvent; req->async.event = hEvent;
req->async.cvalue = 0; req->async.cvalue = cvalue;
status = wine_server_call( req ); status = wine_server_call( req );
} }
SERVER_END_REQ; SERVER_END_REQ;
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio ); if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, fileio );
goto done; goto err;
} }
else /* synchronous write, wait for the fd to become ready */ 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; timeout_init_done = 1;
if ((status = get_io_timeouts( hFile, type, length, FALSE, &timeouts ))) if ((status = get_io_timeouts( hFile, type, length, FALSE, &timeouts )))
goto done; goto err;
if (hEvent) NtResetEvent( hEvent, NULL ); if (hEvent) NtResetEvent( hEvent, NULL );
} }
timeout = get_next_io_timeout( &timeouts, total ); timeout = get_next_io_timeout( &timeouts, total );
@ -921,6 +930,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
} }
done: done:
if (cvalue) NTDLL_AddCompletion( hFile, cvalue, status, total );
err:
if (needs_close) close( unix_handle ); if (needs_close) close( unix_handle );
if (status == STATUS_SUCCESS) if (status == STATUS_SUCCESS)
{ {
@ -989,6 +1001,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
NTSTATUS status; NTSTATUS status;
HANDLE wait_handle; HANDLE wait_handle;
ULONG options; ULONG options;
ULONG_PTR cvalue = apc ? 0 : (ULONG_PTR)apc_context;
if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) ))) if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
@ -1007,7 +1020,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
req->async.arg = async; req->async.arg = async;
req->async.apc = (apc || event) ? ioctl_apc : NULL; req->async.apc = (apc || event) ? ioctl_apc : NULL;
req->async.event = event; req->async.event = event;
req->async.cvalue = 0; req->async.cvalue = cvalue;
wine_server_add_data( req, in_buffer, in_size ); wine_server_add_data( req, in_buffer, in_size );
wine_server_set_reply( req, out_buffer, out_size ); wine_server_set_reply( req, out_buffer, out_size );
if (!(status = wine_server_call( req ))) if (!(status = wine_server_call( req )))
@ -2127,6 +2140,8 @@ NTSTATUS WINAPI NtLockFile( HANDLE hFile, HANDLE lock_granted_event,
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
if (apc_user) FIXME("I/O completion on lock not implemented yet\n");
for (;;) for (;;)
{ {
SERVER_START_REQ( lock_file ) SERVER_START_REQ( lock_file )

View File

@ -198,4 +198,7 @@ static inline struct ntdll_thread_regs *ntdll_get_thread_regs(void)
return (struct ntdll_thread_regs *)NtCurrentTeb()->SpareBytes1; return (struct ntdll_thread_regs *)NtCurrentTeb()->SpareBytes1;
} }
/* Completion */
extern NTSTATUS NTDLL_AddCompletion( HANDLE hFile, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG_PTR Information );
#endif #endif

View File

@ -1310,3 +1310,19 @@ NTSTATUS WINAPI NtQueryIoCompletion( HANDLE CompletionPort, IO_COMPLETION_INFORM
} }
return status; 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;
}

View File

@ -521,15 +521,15 @@ static void test_iocp_fileio(HANDLE h)
ok( !count, "Unexpected msg count: %ld\n", count ); ok( !count, "Unexpected msg count: %ld\n", count );
WriteFile( hPipeClt, buf, 3, &read, NULL ); WriteFile( hPipeClt, buf, 3, &read, NULL );
todo_wine {
if (get_msg(h)) if (get_msg(h))
{ {
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
todo_wine {
ok( ioSb.Information == 3, "Invalid ioSb.Information: %ld\n", ioSb.Information ); 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( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
} }
}
count = get_pending_msgs(h); count = get_pending_msgs(h);
ok( !count, "Unexpected msg count: %ld\n", count ); 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 ); ok( !count, "Unexpected msg count: %ld\n", count );
ReadFile( hPipeSrv, buf, 2, &read, &o); ReadFile( hPipeSrv, buf, 2, &read, &o);
count = get_pending_msgs(h); count = get_pending_msgs(h);
todo_wine {
ok( count == 1, "Unexpected msg count: %ld\n", count ); ok( count == 1, "Unexpected msg count: %ld\n", count );
}
todo_wine {
if (get_msg(h)) if (get_msg(h))
{ {
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); 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( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
} }
}
} }
CloseHandle( hPipeSrv ); CloseHandle( hPipeSrv );