diff --git a/src/common/platform/threading.hpp b/src/common/platform/threading.hpp index 256a6ef7..de430220 100644 --- a/src/common/platform/threading.hpp +++ b/src/common/platform/threading.hpp @@ -109,4 +109,13 @@ typedef struct _KCONTINUE_ARGUMENT #define KCONTINUE_FLAG_TEST_ALERT 0x00000001 #define KCONTINUE_FLAG_DELIVER_APC 0x00000002 +#ifndef OS_WINDOWS +typedef enum _QUEUE_USER_APC_FLAGS +{ + QUEUE_USER_APC_FLAGS_NONE, + QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC, + QUEUE_USER_APC_CALLBACK_DATA_CONTEXT +} QUEUE_USER_APC_FLAGS; +#endif + // NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) diff --git a/src/windows-emulator/syscalls/thread.cpp b/src/windows-emulator/syscalls/thread.cpp index d11511ce..6c72d506 100644 --- a/src/windows-emulator/syscalls/thread.cpp +++ b/src/windows-emulator/syscalls/thread.cpp @@ -600,7 +600,16 @@ namespace syscalls const uint64_t apc_argument1, const uint64_t apc_argument2, const uint64_t apc_argument3) { - return handle_NtQueueApcThreadEx2(c, thread_handle, reserve_handle, 0, apc_routine, apc_argument1, + uint32_t flags{0}; + auto real_reserve_handle = reserve_handle; + if (reserve_handle.bits == QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC) + { + real_reserve_handle.bits = 0; + flags = QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC; + static_assert(QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC == 1); + } + + return handle_NtQueueApcThreadEx2(c, thread_handle, real_reserve_handle, flags, apc_routine, apc_argument1, apc_argument2, apc_argument3); } @@ -611,4 +620,4 @@ namespace syscalls return handle_NtQueueApcThreadEx(c, thread_handle, make_handle(0), apc_routine, apc_argument1, apc_argument2, apc_argument3); } -} \ No newline at end of file +}