Files
windows-user-space-emulator/src/windows-emulator/windows_objects.hpp
2026-01-07 07:34:34 +02:00

331 lines
8.4 KiB
C++

#pragma once
#include "handles.hpp"
#include <serialization_helper.hpp>
#include <utils/file_handle.hpp>
#include <platform/synchronisation.hpp>
#include <platform/win_pefile.hpp>
struct timer : ref_counted_object
{
std::u16string name{};
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->name);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->name);
}
};
struct event : ref_counted_object
{
bool signaled{};
EVENT_TYPE type{};
std::u16string name{};
bool is_signaled()
{
const auto res = this->signaled;
if (this->type == SynchronizationEvent)
{
this->signaled = false;
}
return res;
}
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->signaled);
buffer.write(this->type);
buffer.write(this->name);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->signaled);
buffer.read(this->type);
buffer.read(this->name);
}
};
struct window : ref_counted_object
{
uint32_t thread_id{};
std::u16string name{};
std::u16string class_name{};
int32_t width;
int32_t height;
int32_t x;
int32_t y;
std::unordered_map<std::u16string, uint64_t> props;
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->thread_id);
buffer.write(this->name);
buffer.write(this->class_name);
buffer.write(this->width);
buffer.write(this->height);
buffer.write(this->x);
buffer.write(this->y);
buffer.write_map(this->props);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->thread_id);
buffer.read(this->name);
buffer.read(this->class_name);
buffer.read(this->width);
buffer.read(this->height);
buffer.read(this->x);
buffer.read(this->y);
buffer.read_map(this->props);
}
};
struct mutant : ref_counted_object
{
uint32_t locked_count{0};
uint32_t owning_thread_id{};
std::u16string name{};
bool try_lock(const uint32_t thread_id)
{
if (this->locked_count == 0)
{
++this->locked_count;
this->owning_thread_id = thread_id;
return true;
}
if (this->owning_thread_id != thread_id)
{
return false;
}
++this->locked_count;
return true;
}
std::pair<uint32_t, bool> release(const uint32_t thread_id)
{
const auto old_count = this->locked_count;
if (this->locked_count <= 0 || this->owning_thread_id != thread_id)
{
return {old_count, false};
}
--this->locked_count;
return {old_count, true};
}
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->locked_count);
buffer.write(this->owning_thread_id);
buffer.write(this->name);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->locked_count);
buffer.read(this->owning_thread_id);
buffer.read(this->name);
}
};
struct file_entry
{
std::filesystem::path file_path{};
uint64_t file_size{};
bool is_directory{};
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->file_path);
buffer.write(this->file_size);
buffer.write(this->is_directory);
}
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->file_path);
buffer.read(this->file_size);
buffer.read(this->is_directory);
}
};
struct file_enumeration_state
{
size_t current_index{0};
std::vector<file_entry> files{};
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->current_index);
buffer.write_vector(this->files);
}
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->current_index);
buffer.read_vector(this->files);
}
};
struct file : ref_counted_object
{
utils::file_handle handle{};
std::u16string name{};
std::optional<file_enumeration_state> enumeration_state{};
std::optional<std::u16string> deferred_rename;
bool is_file() const
{
return this->handle;
}
bool is_directory() const
{
return !this->is_file();
}
void serialize_object(utils::buffer_serializer& buffer) const override
{
// TODO: Serialize handle
buffer.write(this->name);
buffer.write_optional(this->enumeration_state);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->name);
buffer.read_optional(this->enumeration_state);
this->handle = {};
}
};
struct section : ref_counted_object
{
std::u16string name{};
std::u16string file_name{};
uint64_t maximum_size{};
uint32_t section_page_protection{};
uint32_t allocation_attributes{};
std::optional<winpe::pe_image_basic_info> cached_image_info{};
bool is_image() const
{
return this->allocation_attributes & SEC_IMAGE;
}
void cache_image_info_from_filedata(const std::vector<std::byte>& file_data)
{
winpe::pe_image_basic_info info{};
// Read the PE magic to determine if it's 32-bit or 64-bit
bool parsed = false;
if (file_data.size() >= sizeof(PEDosHeader_t))
{
const auto* dos_header = reinterpret_cast<const PEDosHeader_t*>(file_data.data());
if (dos_header->e_magic == PEDosHeader_t::k_Magic &&
file_data.size() >= dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t) + sizeof(uint16_t))
{
const auto* magic_ptr =
reinterpret_cast<const uint16_t*>(file_data.data() + dos_header->e_lfanew + sizeof(uint32_t) + sizeof(PEFileHeader_t));
const uint16_t magic = *magic_ptr;
// Parse based on the actual PE type
if (magic == PEOptionalHeader_t<std::uint32_t>::k_Magic)
{
parsed = winpe::parse_pe_headers<uint32_t>(file_data, info);
}
else if (magic == PEOptionalHeader_t<std::uint64_t>::k_Magic)
{
parsed = winpe::parse_pe_headers<uint64_t>(file_data, info);
}
}
}
if (parsed)
{
this->cached_image_info = info;
}
}
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->name);
buffer.write(this->file_name);
buffer.write(this->maximum_size);
buffer.write(this->section_page_protection);
buffer.write(this->allocation_attributes);
buffer.write_optional<winpe::pe_image_basic_info>(this->cached_image_info);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->name);
buffer.read(this->file_name);
buffer.read(this->maximum_size);
buffer.read(this->section_page_protection);
buffer.read(this->allocation_attributes);
buffer.read_optional(this->cached_image_info);
}
};
struct semaphore : ref_counted_object
{
std::u16string name{};
uint32_t current_count{};
uint32_t max_count{};
bool try_lock()
{
if (this->current_count > 0)
{
--this->current_count;
return true;
}
return false;
}
std::pair<uint32_t, bool> release(const uint32_t release_count)
{
const auto old_count = this->current_count;
if (this->current_count + release_count > this->max_count)
{
return {old_count, false};
}
this->current_count += release_count;
return {old_count, true};
}
void serialize_object(utils::buffer_serializer& buffer) const override
{
buffer.write(this->name);
buffer.write(this->current_count);
buffer.write(this->max_count);
}
void deserialize_object(utils::buffer_deserializer& buffer) override
{
buffer.read(this->name);
buffer.read(this->current_count);
buffer.read(this->max_count);
}
};