diff --git a/src/common/platform/threading.hpp b/src/common/platform/threading.hpp index 96e61816..32fa1c75 100644 --- a/src/common/platform/threading.hpp +++ b/src/common/platform/threading.hpp @@ -90,4 +90,23 @@ typedef struct _THREAD_TEB_INFORMATION ULONG BytesToRead; // Number of bytes to read. } THREAD_TEB_INFORMATION, *PTHREAD_TEB_INFORMATION; +typedef enum _KCONTINUE_TYPE +{ + KCONTINUE_UNWIND, + KCONTINUE_RESUME, + KCONTINUE_LONGJUMP, + KCONTINUE_SET, + KCONTINUE_LAST, +} KCONTINUE_TYPE; + +typedef struct _KCONTINUE_ARGUMENT +{ + KCONTINUE_TYPE ContinueType; + ULONG ContinueFlags; + ULONGLONG Reserved[2]; +} KCONTINUE_ARGUMENT, *PKCONTINUE_ARGUMENT; + +#define KCONTINUE_FLAG_TEST_ALERT 0x00000001 +#define KCONTINUE_FLAG_DELIVER_APC 0x00000002 + // NOLINTEND(modernize-use-using) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 2d285295..0ee6e89e 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -270,7 +270,9 @@ namespace syscalls NTSTATUS handle_NtResumeThread(const syscall_context& c, handle thread_handle, emulator_object previous_suspend_count); NTSTATUS handle_NtContinue(const syscall_context& c, emulator_object thread_context, - BOOLEAN /*raise_alert*/); + BOOLEAN raise_alert); + NTSTATUS handle_NtContinueEx(const syscall_context& c, emulator_object thread_context, + uint64_t continue_argument); NTSTATUS handle_NtGetNextThread(const syscall_context& c, handle process_handle, handle thread_handle, ACCESS_MASK /*desired_access*/, ULONG /*handle_attributes*/, ULONG flags, emulator_object new_thread_handle); @@ -664,6 +666,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtQueryLicenseValue); add_handler(NtTestAlert); add_handler(NtContinue); + add_handler(NtContinueEx); add_handler(NtTerminateProcess); add_handler(NtWriteFile); add_handler(NtRaiseHardError); diff --git a/src/windows-emulator/syscalls/thread.cpp b/src/windows-emulator/syscalls/thread.cpp index f9b98484..12446f8a 100644 --- a/src/windows-emulator/syscalls/thread.cpp +++ b/src/windows-emulator/syscalls/thread.cpp @@ -361,22 +361,39 @@ namespace syscalls return STATUS_SUCCESS; } - NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object thread_context, - const BOOLEAN raise_alert) + NTSTATUS handle_NtContinueEx(const syscall_context& c, const emulator_object thread_context, + const uint64_t continue_argument) { c.write_status = false; - if (raise_alert) - { - c.win_emu.current_thread().apc_alertable = false; - } - const auto context = thread_context.read(); cpu_context::restore(c.emu, context); + KCONTINUE_ARGUMENT argument{}; + + if (continue_argument <= 0xFF) + { + argument.ContinueFlags = KCONTINUE_FLAG_TEST_ALERT; + } + else + { + argument = c.emu.read_memory(continue_argument); + } + + if (argument.ContinueFlags & KCONTINUE_FLAG_TEST_ALERT) + { + c.win_emu.yield_thread(true); + } + return STATUS_SUCCESS; } + NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object thread_context, + const BOOLEAN raise_alert) + { + return handle_NtContinueEx(c, thread_context, raise_alert ? 1 : 0); + } + NTSTATUS handle_NtGetNextThread(const syscall_context& c, const handle process_handle, const handle thread_handle, const ACCESS_MASK /*desired_access*/, const ULONG /*handle_attributes*/, const ULONG flags, const emulator_object new_thread_handle)