From bb4b159850c595b0118ba68ad0355f9d28e8ed37 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 13 Apr 2025 10:56:28 +0200 Subject: [PATCH] Implement NtQueueApcThreadEx2 --- src/windows-emulator/emulator_thread.hpp | 43 +++++++++++++++++++++--- src/windows-emulator/syscalls/thread.cpp | 21 ++++++++++-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/windows-emulator/emulator_thread.hpp b/src/windows-emulator/emulator_thread.hpp index d3e34c3a..0a646092 100644 --- a/src/windows-emulator/emulator_thread.hpp +++ b/src/windows-emulator/emulator_thread.hpp @@ -8,6 +8,33 @@ struct process_context; +struct pending_apc +{ + ULONG flags{}; + uint64_t apc_routine{}; + uint64_t apc_argument1{}; + uint64_t apc_argument2{}; + uint64_t apc_argument3{}; + + void serialize(utils::buffer_serializer& buffer) const + { + buffer.write(this->flags); + buffer.write(this->apc_routine); + buffer.write(this->apc_argument1); + buffer.write(this->apc_argument2); + buffer.write(this->apc_argument3); + } + + void deserialize(utils::buffer_deserializer& buffer) + { + buffer.read(this->flags); + buffer.read(this->apc_routine); + buffer.read(this->apc_argument1); + buffer.read(this->apc_argument2); + buffer.read(this->apc_argument3); + } +}; + class emulator_thread : public ref_counted_object { public: @@ -54,10 +81,12 @@ class emulator_thread : public ref_counted_object bool await_any{false}; bool waiting_for_alert{false}; bool alerted{false}; - bool apc_alertable{false}; uint32_t suspended{0}; std::optional await_time{}; + bool apc_alertable{false}; + std::vector pending_apcs{}; + std::optional pending_status{}; std::optional gs_segment; @@ -124,11 +153,13 @@ class emulator_thread : public ref_counted_object buffer.write(this->waiting_for_alert); buffer.write(this->alerted); - buffer.write(this->apc_alertable); buffer.write(this->suspended); - buffer.write_optional(this->await_time); + + buffer.write(this->apc_alertable); + buffer.write_vector(this->pending_apcs); + buffer.write_optional(this->pending_status); buffer.write_optional(this->gs_segment); buffer.write_optional(this->teb); @@ -160,11 +191,13 @@ class emulator_thread : public ref_counted_object buffer.read(this->waiting_for_alert); buffer.read(this->alerted); - buffer.read(this->apc_alertable); buffer.read(this->suspended); - buffer.read_optional(this->await_time); + + buffer.read(this->apc_alertable); + buffer.read_vector(this->pending_apcs); + buffer.read_optional(this->pending_status); buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->memory_ptr); }); buffer.read_optional(this->teb, [this] { return emulator_object(*this->memory_ptr); }); diff --git a/src/windows-emulator/syscalls/thread.cpp b/src/windows-emulator/syscalls/thread.cpp index db30c708..25ebd1ba 100644 --- a/src/windows-emulator/syscalls/thread.cpp +++ b/src/windows-emulator/syscalls/thread.cpp @@ -565,10 +565,25 @@ namespace syscalls } NTSTATUS handle_NtQueueApcThreadEx2(const syscall_context& c, const handle thread_handle, - const handle reserve_handle, const ULONG apc_flags, const uint64_t apc_routine, - const uint64_t apc_argument1, const uint64_t apc_argument2, - const uint64_t apc_argument3) + const handle /*reserve_handle*/, const ULONG apc_flags, + const uint64_t apc_routine, const uint64_t apc_argument1, + const uint64_t apc_argument2, const uint64_t apc_argument3) { + auto* thread = thread_handle == CURRENT_THREAD ? c.proc.active_thread : c.proc.threads.get(thread_handle); + + if (!thread) + { + return STATUS_INVALID_HANDLE; + } + + thread->pending_apcs.push_back({ + .flags = apc_flags, + .apc_routine = apc_routine, + .apc_argument1 = apc_argument1, + .apc_argument2 = apc_argument2, + .apc_argument3 = apc_argument3, + }); + return STATUS_NOT_SUPPORTED; } } \ No newline at end of file