Fix more handles (#126)

This commit is contained in:
Maurice Heumann
2025-02-05 07:36:04 +01:00
committed by GitHub
6 changed files with 92 additions and 66 deletions

View File

@@ -474,7 +474,7 @@ namespace
this->clear_pending_state(); 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); buffer.read_optional(this->creation_data);
this->setup(); this->setup();
@@ -484,7 +484,7 @@ namespace
buffer.read_optional(this->timeout_); 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->creation_data);
buffer.write_optional(this->require_poll_); buffer.write_optional(this->require_poll_);

View File

@@ -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 struct generic_handle_store
{ {
virtual ~generic_handle_store() = default; virtual ~generic_handle_store() = default;
virtual bool erase(handle h) = 0; virtual bool erase(handle h) = 0;
virtual std::optional<handle> duplicate(handle h) = 0;
}; };
template <handle_types::type Type, typename T, uint32_t IndexShift = 0> template <handle_types::type Type, typename T, uint32_t IndexShift = 0>
requires(utils::Serializable<T>) requires(utils::Serializable<T> && std::is_base_of_v<ref_counted_object, T>)
class handle_store : public generic_handle_store class handle_store : public generic_handle_store
{ {
public: public:
@@ -189,6 +219,18 @@ class handle_store : public generic_handle_store
return this->store_.size(); return this->store_.size();
} }
std::optional<handle> duplicate(const handle h) override
{
auto* entry = this->get(h);
if (!entry)
{
return std::nullopt;
}
++static_cast<ref_counted_object*>(entry)->ref_count;
return h;
}
bool erase(const typename value_map::iterator& entry) bool erase(const typename value_map::iterator& entry)
{ {
if (this->block_mutation_) if (this->block_mutation_)

View File

@@ -76,10 +76,10 @@ inline void write_io_status(const emulator_object<IO_STATUS_BLOCK<EmulatorTraits
} }
} }
struct io_device struct io_device : ref_counted_object
{ {
io_device() = default; io_device() = default;
virtual ~io_device() = default; ~io_device() override = default;
io_device(io_device&&) = default; io_device(io_device&&) = default;
io_device& operator=(io_device&&) = default; io_device& operator=(io_device&&) = default;
@@ -100,9 +100,6 @@ struct io_device
(void)win_emu; (void)win_emu;
} }
virtual void serialize(utils::buffer_serializer& buffer) const = 0;
virtual void deserialize(utils::buffer_deserializer& buffer) = 0;
NTSTATUS execute_ioctl(windows_emulator& win_emu, const io_device_context& c) NTSTATUS execute_ioctl(windows_emulator& win_emu, const io_device_context& c)
{ {
if (c.io_status_block) if (c.io_status_block)
@@ -122,11 +119,11 @@ struct stateless_device : io_device
{ {
} }
void serialize(utils::buffer_serializer&) const override void serialize_object(utils::buffer_serializer&) const override
{ {
} }
void deserialize(utils::buffer_deserializer&) override void deserialize_object(utils::buffer_deserializer&) override
{ {
} }
}; };
@@ -157,7 +154,7 @@ class io_device_container : public io_device
return this->device_->work(win_emu); return this->device_->work(win_emu);
} }
void serialize(utils::buffer_serializer& buffer) const override void serialize_object(utils::buffer_serializer& buffer) const override
{ {
this->assert_validity(); this->assert_validity();
@@ -165,7 +162,7 @@ class io_device_container : public io_device
this->device_->serialize(buffer); 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_); buffer.read_string(this->device_name_);
this->setup(); this->setup();

View File

@@ -27,26 +27,6 @@
class windows_emulator; 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 struct event : ref_counted_object
{ {
bool signaled{}; bool signaled{};
@@ -65,22 +45,18 @@ struct event : ref_counted_object
return res; 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->signaled);
buffer.write(this->type); buffer.write(this->type);
buffer.write(this->name); 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->signaled);
buffer.read(this->type); buffer.read(this->type);
buffer.read(this->name); buffer.read(this->name);
ref_counted_object::deserialize(buffer);
} }
}; };
@@ -121,22 +97,18 @@ struct mutant : ref_counted_object
return {old_count, true}; 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->locked_count);
buffer.write(this->owning_thread_id); buffer.write(this->owning_thread_id);
buffer.write(this->name); 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->locked_count);
buffer.read(this->owning_thread_id); buffer.read(this->owning_thread_id);
buffer.read(this->name); 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{}; utils::file_handle handle{};
std::u16string name{}; std::u16string name{};
@@ -189,14 +161,14 @@ struct file
return !this->is_file(); return !this->is_file();
} }
void serialize(utils::buffer_serializer& buffer) const void serialize_object(utils::buffer_serializer& buffer) const override
{ {
// TODO: Serialize handle // TODO: Serialize handle
buffer.write(this->name); buffer.write(this->name);
buffer.write_optional(this->enumeration_state); 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(this->name);
buffer.read_optional(this->enumeration_state); buffer.read_optional(this->enumeration_state);
@@ -204,7 +176,7 @@ struct file
} }
}; };
struct section struct section : ref_counted_object
{ {
std::u16string name{}; std::u16string name{};
std::u16string file_name{}; std::u16string file_name{};
@@ -217,7 +189,7 @@ struct section
return this->allocation_attributes & SEC_IMAGE; 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->name);
buffer.write(this->file_name); buffer.write(this->file_name);
@@ -226,7 +198,7 @@ struct section
buffer.write(this->allocation_attributes); 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->name);
buffer.read(this->file_name); buffer.read(this->file_name);
@@ -267,37 +239,33 @@ struct semaphore : ref_counted_object
return {old_count, true}; 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->name);
buffer.write(this->current_count); buffer.write(this->current_count);
buffer.write(this->max_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->name);
buffer.read(this->current_count); buffer.read(this->current_count);
buffer.read(this->max_count); buffer.read(this->max_count);
ref_counted_object::deserialize(buffer);
} }
}; };
struct port struct port : ref_counted_object
{ {
std::u16string name{}; std::u16string name{};
uint64_t view_base{}; 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->name);
buffer.write(this->view_base); 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->name);
buffer.read(this->view_base); 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()) if (this->marker.was_moved())
{ {
@@ -470,7 +438,7 @@ class emulator_thread : public ref_counted_object
buffer.write_vector(this->last_registers); buffer.write_vector(this->last_registers);
} }
void deserialize(utils::buffer_deserializer& buffer) void deserialize_object(utils::buffer_deserializer& buffer)
{ {
if (this->marker.was_moved()) if (this->marker.was_moved())
{ {

View File

@@ -3,19 +3,20 @@
#include "../std_include.hpp" #include "../std_include.hpp"
#include "hive_parser.hpp" #include "hive_parser.hpp"
#include "serialization_helper.hpp" #include "serialization_helper.hpp"
#include "../handles.hpp"
struct registry_key struct registry_key : ref_counted_object
{ {
utils::path_key hive{}; utils::path_key hive{};
utils::path_key path{}; 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->hive);
buffer.write(this->path); 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->hive);
buffer.read(this->path); buffer.read(this->path);

View File

@@ -1108,8 +1108,20 @@ namespace
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
c.win_emu.log.error("Duplicating non-pseudo object not supported yet!\n"); auto* store = get_handle_store(c.proc, source_handle);
return STATUS_NOT_SUPPORTED; 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, NTSTATUS handle_NtQuerySystemInformationEx(const syscall_context& c, const uint32_t info_class,
@@ -3302,6 +3314,11 @@ namespace
return handle_NtUserGetDCEx(); return handle_NtUserGetDCEx();
} }
NTSTATUS handle_NtUserGetWindowDC()
{
return 1;
}
NTSTATUS handle_NtUserReleaseDC() NTSTATUS handle_NtUserReleaseDC()
{ {
return STATUS_SUCCESS; return STATUS_SUCCESS;
@@ -3734,6 +3751,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtUserModifyUserStartupInfoFlags); add_handler(NtUserModifyUserStartupInfoFlags);
add_handler(NtUserGetDCEx); add_handler(NtUserGetDCEx);
add_handler(NtUserGetDC); add_handler(NtUserGetDC);
add_handler(NtUserGetWindowDC);
add_handler(NtUserGetDpiForCurrentProcess); add_handler(NtUserGetDpiForCurrentProcess);
add_handler(NtReleaseSemaphore); add_handler(NtReleaseSemaphore);
add_handler(NtEnumerateKey); add_handler(NtEnumerateKey);