Module: wine Branch: master Commit: af25949a51f8ef8bd6edfd1b078d7760c13c6702 URL: http://source.winehq.org/git/wine.git/?a=commit;h=af25949a51f8ef8bd6edfd1b07...
Author: Mike Kaplinskiy mike.kaplinskiy@gmail.com Date: Sun Aug 9 00:11:30 2009 -0400
ntdll: Implement NtCancelIoFileEx and fix NtCancelIoFile.
---
dlls/ntdll/file.c | 44 +++++++++++++++++++++++++++++++++++++++++--- dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/tests/change.c | 5 ++--- dlls/ntdll/tests/file.c | 2 +- include/winternl.h | 1 + 5 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 3fa6f19..561baf0 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -2604,6 +2604,38 @@ NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes ) }
/****************************************************************** + * NtCancelIoFileEx (NTDLL.@) + * + * + */ +NTSTATUS WINAPI NtCancelIoFileEx( HANDLE hFile, PIO_STATUS_BLOCK iosb, PIO_STATUS_BLOCK io_status ) +{ + LARGE_INTEGER timeout; + + TRACE("%p %p %p\n", hFile, iosb, io_status ); + + SERVER_START_REQ( cancel_async ) + { + req->handle = wine_server_obj_handle( hFile ); + req->iosb = wine_server_client_ptr( iosb ); + req->only_thread = FALSE; + io_status->u.Status = wine_server_call( req ); + } + SERVER_END_REQ; + if (io_status->u.Status) + return io_status->u.Status; + + /* Let some APC be run, so that we can run the remaining APCs on hFile + * either the cancelation of the pending one, but also the execution + * of the queued APC, but not yet run. This is needed to ensure proper + * clean-up of allocated data. + */ + timeout.u.LowPart = timeout.u.HighPart = 0; + NtDelayExecution( TRUE, &timeout ); + return io_status->u.Status; +} + +/****************************************************************** * NtCancelIoFile (NTDLL.@) * * @@ -2616,17 +2648,23 @@ NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
SERVER_START_REQ( cancel_async ) { - req->handle = wine_server_obj_handle( hFile ); - wine_server_call( req ); + req->handle = wine_server_obj_handle( hFile ); + req->iosb = 0; + req->only_thread = TRUE; + io_status->u.Status = wine_server_call( req ); } SERVER_END_REQ; + if (io_status->u.Status) + return io_status->u.Status; + /* Let some APC be run, so that we can run the remaining APCs on hFile * either the cancelation of the pending one, but also the execution * of the queued APC, but not yet run. This is needed to ensure proper * clean-up of allocated data. */ timeout.u.LowPart = timeout.u.HighPart = 0; - return io_status->u.Status = NtDelayExecution( TRUE, &timeout ); + NtDelayExecution( TRUE, &timeout ); + return io_status->u.Status; }
/****************************************************************************** diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 03686b2..6ec1dc0 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -109,6 +109,7 @@ @ stub NtCallbackReturn # @ stub NtCancelDeviceWakeupRequest @ stdcall NtCancelIoFile(long ptr) +@ stdcall NtCancelIoFileEx(long ptr ptr) @ stdcall NtCancelTimer(long ptr) @ stdcall NtClearEvent(long) @ stdcall NtClose(long) @@ -959,6 +960,7 @@ @ stub ZwCallbackReturn # @ stub ZwCancelDeviceWakeupRequest @ stdcall ZwCancelIoFile(long ptr) NtCancelIoFile +@ stdcall ZwCancelIoFileEx(long ptr ptr) NtCancelIoFileEx @ stdcall ZwCancelTimer(long ptr) NtCancelTimer @ stdcall ZwClearEvent(long) NtClearEvent @ stdcall ZwClose(long) NtClose diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c index f395962..ed7f22c 100644 --- a/dlls/ntdll/tests/change.c +++ b/dlls/ntdll/tests/change.c @@ -295,15 +295,14 @@ static void test_ntncdf_async(void) ok(U(iosb).Status == 0x01234567, "status set too soon\n"); ok(iosb.Information == 0x12345678, "info set too soon\n");
- todo_wine { r = pNtCancelIoFile(hdir, &iosb); ok( r == STATUS_SUCCESS, "cancel failed\n");
CloseHandle(hdir);
ok(U(iosb).Status == STATUS_SUCCESS, "status wrong\n"); - ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong\n"); - } + todo_wine ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong\n"); + ok(iosb.Information == 0, "info wrong\n"); ok(iosb2.Information == 0, "info wrong\n");
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index a0e713a..ba3c688 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -376,7 +376,7 @@ static void read_file_test(void) ok( U(iosb).Status == STATUS_CANCELLED, "wrong status %x\n", U(iosb).Status ); ok( iosb.Information == 0, "wrong info %lu\n", iosb.Information ); ok( is_signaled( event ), "event is signaled\n" ); - ok( !apc_count, "apc was called\n" ); + todo_wine ok( !apc_count, "apc was called\n" ); SleepEx( 1, TRUE ); /* alertable sleep */ ok( apc_count == 1, "apc was not called\n" ); CloseHandle( read ); diff --git a/include/winternl.h b/include/winternl.h index 6d0b480..1d300bf 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2013,6 +2013,7 @@ NTSYSAPI NTSTATUS WINAPI NtAreMappedFilesTheSame(PVOID,PVOID); NTSYSAPI NTSTATUS WINAPI NtAssignProcessToJobObject(HANDLE,HANDLE); NTSYSAPI NTSTATUS WINAPI NtCallbackReturn(PVOID,ULONG,NTSTATUS); NTSYSAPI NTSTATUS WINAPI NtCancelIoFile(HANDLE,PIO_STATUS_BLOCK); +NTSYSAPI NTSTATUS WINAPI NtCancelIoFileEx(HANDLE,PIO_STATUS_BLOCK,PIO_STATUS_BLOCK); NTSYSAPI NTSTATUS WINAPI NtCancelTimer(HANDLE, BOOLEAN*); NTSYSAPI NTSTATUS WINAPI NtClearEvent(HANDLE); NTSYSAPI NTSTATUS WINAPI NtClose(HANDLE);