diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index 84622f5d..46b83939 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -474,7 +474,7 @@ namespace this->clear_pending_state(); } - void deserialize(utils::buffer_deserializer& buffer) override + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read_optional(this->creation_data); this->setup(); @@ -484,7 +484,7 @@ namespace buffer.read_optional(this->timeout_); } - void serialize(utils::buffer_serializer& buffer) const override + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write_optional(this->creation_data); buffer.write_optional(this->require_poll_); diff --git a/src/windows-emulator/handles.hpp b/src/windows-emulator/handles.hpp index 0abf1887..962b1a9f 100644 --- a/src/windows-emulator/handles.hpp +++ b/src/windows-emulator/handles.hpp @@ -111,14 +111,44 @@ namespace handle_detail }; } +class ref_counted_object +{ + public: + virtual ~ref_counted_object() = default; + + uint32_t ref_count{1}; + + void serialize(utils::buffer_serializer& buffer) const + { + buffer.write(this->ref_count); + this->serialize_object(buffer); + } + + void deserialize(utils::buffer_deserializer& buffer) + { + buffer.read(this->ref_count); + this->deserialize_object(buffer); + } + + static bool deleter(ref_counted_object& e) + { + return --e.ref_count == 0; + } + + private: + virtual void serialize_object(utils::buffer_serializer& buffer) const = 0; + virtual void deserialize_object(utils::buffer_deserializer& buffer) = 0; +}; + struct generic_handle_store { virtual ~generic_handle_store() = default; virtual bool erase(handle h) = 0; + virtual std::optional duplicate(handle h) = 0; }; template - requires(utils::Serializable) + requires(utils::Serializable && std::is_base_of_v) class handle_store : public generic_handle_store { public: @@ -189,6 +219,18 @@ class handle_store : public generic_handle_store return this->store_.size(); } + std::optional duplicate(const handle h) override + { + auto* entry = this->get(h); + if (!entry) + { + return std::nullopt; + } + + ++static_cast(entry)->ref_count; + return h; + } + bool erase(const typename value_map::iterator& entry) { if (this->block_mutation_) diff --git a/src/windows-emulator/io_device.hpp b/src/windows-emulator/io_device.hpp index c922decc..43e8b1cf 100644 --- a/src/windows-emulator/io_device.hpp +++ b/src/windows-emulator/io_device.hpp @@ -76,10 +76,10 @@ inline void write_io_status(const emulator_objectdevice_->work(win_emu); } - void serialize(utils::buffer_serializer& buffer) const override + void serialize_object(utils::buffer_serializer& buffer) const override { this->assert_validity(); @@ -165,7 +162,7 @@ class io_device_container : public io_device this->device_->serialize(buffer); } - void deserialize(utils::buffer_deserializer& buffer) override + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read_string(this->device_name_); this->setup(); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 567a9d00..be6b6688 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -27,26 +27,6 @@ class windows_emulator; -struct ref_counted_object -{ - uint32_t ref_count{1}; - - void serialize(utils::buffer_serializer& buffer) const - { - buffer.write(this->ref_count); - } - - void deserialize(utils::buffer_deserializer& buffer) - { - buffer.read(this->ref_count); - } - - static bool deleter(ref_counted_object& e) - { - return --e.ref_count == 0; - } -}; - struct event : ref_counted_object { bool signaled{}; @@ -65,22 +45,18 @@ struct event : ref_counted_object return res; } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->signaled); buffer.write(this->type); buffer.write(this->name); - - ref_counted_object::serialize(buffer); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->signaled); buffer.read(this->type); buffer.read(this->name); - - ref_counted_object::deserialize(buffer); } }; @@ -121,22 +97,18 @@ struct mutant : ref_counted_object return {old_count, true}; } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->locked_count); buffer.write(this->owning_thread_id); buffer.write(this->name); - - ref_counted_object::serialize(buffer); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->locked_count); buffer.read(this->owning_thread_id); buffer.read(this->name); - - ref_counted_object::deserialize(buffer); } }; @@ -173,7 +145,7 @@ struct file_enumeration_state } }; -struct file +struct file : ref_counted_object { utils::file_handle handle{}; std::u16string name{}; @@ -189,14 +161,14 @@ struct file return !this->is_file(); } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { // TODO: Serialize handle buffer.write(this->name); buffer.write_optional(this->enumeration_state); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->name); buffer.read_optional(this->enumeration_state); @@ -204,7 +176,7 @@ struct file } }; -struct section +struct section : ref_counted_object { std::u16string name{}; std::u16string file_name{}; @@ -217,7 +189,7 @@ struct section return this->allocation_attributes & SEC_IMAGE; } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->name); buffer.write(this->file_name); @@ -226,7 +198,7 @@ struct section buffer.write(this->allocation_attributes); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->name); buffer.read(this->file_name); @@ -267,37 +239,33 @@ struct semaphore : ref_counted_object return {old_count, true}; } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->name); buffer.write(this->current_count); buffer.write(this->max_count); - - ref_counted_object::serialize(buffer); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->name); buffer.read(this->current_count); buffer.read(this->max_count); - - ref_counted_object::deserialize(buffer); } }; -struct port +struct port : ref_counted_object { std::u16string name{}; uint64_t view_base{}; - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->name); buffer.write(this->view_base); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->name); buffer.read(this->view_base); @@ -439,7 +407,7 @@ class emulator_thread : public ref_counted_object } } - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const { if (this->marker.was_moved()) { @@ -470,7 +438,7 @@ class emulator_thread : public ref_counted_object buffer.write_vector(this->last_registers); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) { if (this->marker.was_moved()) { diff --git a/src/windows-emulator/registry/registry_manager.hpp b/src/windows-emulator/registry/registry_manager.hpp index 7b6f0c55..c5160d76 100644 --- a/src/windows-emulator/registry/registry_manager.hpp +++ b/src/windows-emulator/registry/registry_manager.hpp @@ -3,19 +3,20 @@ #include "../std_include.hpp" #include "hive_parser.hpp" #include "serialization_helper.hpp" +#include "../handles.hpp" -struct registry_key +struct registry_key : ref_counted_object { utils::path_key hive{}; utils::path_key path{}; - void serialize(utils::buffer_serializer& buffer) const + void serialize_object(utils::buffer_serializer& buffer) const override { buffer.write(this->hive); buffer.write(this->path); } - void deserialize(utils::buffer_deserializer& buffer) + void deserialize_object(utils::buffer_deserializer& buffer) override { buffer.read(this->hive); buffer.read(this->path); diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 7df12fd7..e17d1962 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1108,8 +1108,20 @@ namespace return STATUS_SUCCESS; } - c.win_emu.log.error("Duplicating non-pseudo object not supported yet!\n"); - return STATUS_NOT_SUPPORTED; + auto* store = get_handle_store(c.proc, source_handle); + if (!store) + { + return STATUS_NOT_SUPPORTED; + } + + const auto new_handle = store->duplicate(source_handle); + if (!new_handle) + { + return STATUS_INVALID_HANDLE; + } + + target_handle.write(*new_handle); + return STATUS_SUCCESS; } NTSTATUS handle_NtQuerySystemInformationEx(const syscall_context& c, const uint32_t info_class, @@ -3302,6 +3314,11 @@ namespace return handle_NtUserGetDCEx(); } + NTSTATUS handle_NtUserGetWindowDC() + { + return 1; + } + NTSTATUS handle_NtUserReleaseDC() { return STATUS_SUCCESS; @@ -3734,6 +3751,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtUserModifyUserStartupInfoFlags); add_handler(NtUserGetDCEx); add_handler(NtUserGetDC); + add_handler(NtUserGetWindowDC); add_handler(NtUserGetDpiForCurrentProcess); add_handler(NtReleaseSemaphore); add_handler(NtEnumerateKey);