From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/signal_arm64ec.c | 1 + dlls/ntdll/tests/file.c | 1 - dlls/ntdll/unix/sync.c | 20 ++++++++++++ dlls/wow64/sync.c | 12 +++++++ include/winternl.h | 1 + server/completion.c | 62 +++++++++++++++++++++++++++++++++++++ server/protocol.def | 7 +++++ 8 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 2085be4aaf7..8132ff23cea 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -159,6 +159,7 @@ @ stdcall -syscall NtCancelIoFileEx(long ptr ptr) @ stdcall -syscall NtCancelSynchronousIoFile(long ptr ptr) @ stdcall -syscall NtCancelTimer(long ptr) +@ stdcall -syscall NtCancelWaitCompletionPacket(ptr long) @ stdcall -syscall NtClearEvent(long) @ stdcall -syscall NtClose(long) # @ stub NtCloseObjectAuditAlarm diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index c33757b7ec0..0662bc300a6 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -263,6 +263,7 @@ DEFINE_SYSCALL(NtCancelIoFile, (HANDLE handle, IO_STATUS_BLOCK *io_status)) DEFINE_SYSCALL(NtCancelIoFileEx, (HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_BLOCK *io_status)) DEFINE_SYSCALL(NtCancelSynchronousIoFile, (HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_BLOCK *io_status)) DEFINE_SYSCALL(NtCancelTimer, (HANDLE handle, BOOLEAN *state)) +DEFINE_SYSCALL(NtCancelWaitCompletionPacket, (HANDLE packet, BOOLEAN remove_signaled)) DEFINE_SYSCALL(NtClearEvent, (HANDLE handle)) DEFINE_SYSCALL(NtClose, (HANDLE handle)) DEFINE_SYSCALL(NtCommitTransaction, (HANDLE transaction, BOOLEAN wait)) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 056167b7309..2cb0c02a83d 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -6570,7 +6570,6 @@ static void test_cancel_wait_completion_packet(void)
if (!pNtCancelWaitCompletionPacket) { - todo_wine win_skip("NtCancelWaitCompletionPacket is unavailable.\n"); return; } diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 16337a64daa..6fa28225cb9 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2822,6 +2822,26 @@ NTSTATUS WINAPI NtAssociateWaitCompletionPacket( HANDLE packet, HANDLE completio return ret; }
+/*********************************************************************** + * NtCancelWaitCompletionPacket (NTDLL.@) + */ +NTSTATUS WINAPI NtCancelWaitCompletionPacket( HANDLE packet, BOOLEAN remove_signaled ) +{ + NTSTATUS status; + + TRACE("packet %p, remove_signaled %d.\n", packet, remove_signaled); + + SERVER_START_REQ( cancel_wait_completion_packet ) + { + req->packet = wine_server_obj_handle( packet ); + req->remove_signaled = remove_signaled; + status = wine_server_call( req ); + } + SERVER_END_REQ; + return status; +} + + /*********************************************************************** * NtCreateWaitCompletionPacket (NTDLL.@) */ diff --git a/dlls/wow64/sync.c b/dlls/wow64/sync.c index d9bea95fd5e..7362adde7a4 100644 --- a/dlls/wow64/sync.c +++ b/dlls/wow64/sync.c @@ -1801,6 +1801,18 @@ NTSTATUS WINAPI wow64_NtAssociateWaitCompletionPacket( UINT *args ) }
+/********************************************************************** + * wow64_NtCancelWaitCompletionPacket + */ +NTSTATUS WINAPI wow64_NtCancelWaitCompletionPacket( UINT *args ) +{ + HANDLE packet = get_handle( &args ); + BOOLEAN remove_signaled = get_ulong( &args ); + + return NtCancelWaitCompletionPacket( packet, remove_signaled ); +} + + /********************************************************************** * wow64_NtCreateWaitCompletionPacket */ diff --git a/include/winternl.h b/include/winternl.h index 6105cef9528..3f74a18c4aa 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4493,6 +4493,7 @@ NTSYSAPI NTSTATUS WINAPI NtCancelIoFile(HANDLE,PIO_STATUS_BLOCK); NTSYSAPI NTSTATUS WINAPI NtCancelIoFileEx(HANDLE,PIO_STATUS_BLOCK,PIO_STATUS_BLOCK); NTSYSAPI NTSTATUS WINAPI NtCancelSynchronousIoFile(HANDLE,PIO_STATUS_BLOCK,PIO_STATUS_BLOCK); NTSYSAPI NTSTATUS WINAPI NtCancelTimer(HANDLE, BOOLEAN*); +NTSYSAPI NTSTATUS WINAPI NtCancelWaitCompletionPacket(HANDLE, BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtClearEvent(HANDLE); NTSYSAPI NTSTATUS WINAPI NtClose(HANDLE); NTSYSAPI NTSTATUS WINAPI NtCloseObjectAuditAlarm(PUNICODE_STRING,HANDLE,BOOLEAN); diff --git a/server/completion.c b/server/completion.c index 0c5b98851a9..8de1d8f6d72 100644 --- a/server/completion.c +++ b/server/completion.c @@ -495,6 +495,68 @@ DECL_HANDLER(associate_wait_completion_packet) release_object( completion ); }
+/* cancel a wait completion packet */ +DECL_HANDLER(cancel_wait_completion_packet) +{ + struct wait_completion_packet *packet; + + packet = get_wait_completion_packet_obj( current->process, req->packet, WAIT_COMPLETION_PACKET_QUERY_STATE ); + if (!packet) + return; + + if (!packet->in_object_packet_queue && !packet->in_completion_queue) + { + set_error( STATUS_CANCELLED ); + release_object( packet ); + return; + } + + if (packet->in_completion_queue && !req->remove_signaled) + { + set_error( STATUS_PENDING ); + release_object( packet ); + return; + } + + if (packet->in_object_packet_queue) + { + list_remove( &packet->entry ); + packet->in_object_packet_queue = 0; + } + + if (packet->in_completion_queue) + { + struct comp_msg *comp_msg; + + LIST_FOR_EACH_ENTRY( comp_msg, &packet->completion->queue, struct comp_msg, queue_entry ) + { + if (comp_msg->packet == packet) + { + list_remove( &comp_msg->queue_entry ); + free( comp_msg ); + packet->completion->depth--; + break; + } + } + + packet->in_completion_queue = 0; + } + + if (packet->target) + { + release_object( packet->target ); + packet->target = NULL; + } + + if (packet->completion) + { + release_object( packet->completion ); + packet->completion = NULL; + } + + release_object( packet ); +} + /* create a completion */ DECL_HANDLER(create_completion) { diff --git a/server/protocol.def b/server/protocol.def index 1c5ac39cce9..cca69edef17 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3872,6 +3872,13 @@ struct handle_info @END
+/* Cancel a wait completion packet */ +@REQ(cancel_wait_completion_packet) + obj_handle_t packet; /* wait completion packet handle */ + int remove_signaled;/* whether to remove signaled packet */ +@END + + /* check for associated completion and push msg */ @REQ(add_fd_completion) obj_handle_t handle; /* async' object */