From af25949a51f8ef8bd6edfd1b078d7760c13c6702 Mon Sep 17 00:00:00 2001 From: Mike Kaplinskiy Date: Sun, 9 Aug 2009 00:11:30 -0400 Subject: [PATCH] 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 3fa6f19782b..561baf02876 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -2603,6 +2603,38 @@ NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes ) return status; } +/****************************************************************** + * 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 03686b28209..6ec1dc0d589 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 f395962ec23..ed7f22c9e61 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 a0e713aeaee..ba3c688d00f 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 6d0b4805d93..1d300bfda53 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);