mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Fixes for section mapping and registry (#635)
This commit is contained in:
@@ -67,6 +67,18 @@ typedef struct _KEY_FULL_INFORMATION
|
||||
char16_t Class[1];
|
||||
} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION;
|
||||
|
||||
typedef struct _KEY_CACHED_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
ULONG TitleIndex;
|
||||
ULONG SubKeys;
|
||||
ULONG MaxNameLen;
|
||||
ULONG Values;
|
||||
ULONG MaxValueNameLen;
|
||||
ULONG MaxValueDataLen;
|
||||
ULONG NameLength;
|
||||
} KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION;
|
||||
|
||||
struct KEY_HANDLE_TAGS_INFORMATION
|
||||
{
|
||||
ULONG HandleTags;
|
||||
|
||||
@@ -62,6 +62,18 @@ class hive_key
|
||||
const hive_value* get_value(std::ifstream& file, std::string_view name);
|
||||
const hive_value* get_value(std::ifstream& file, size_t index);
|
||||
|
||||
size_t get_sub_key_count(std::ifstream& file)
|
||||
{
|
||||
this->parse(file);
|
||||
return this->sub_keys_.size();
|
||||
}
|
||||
|
||||
size_t get_value_count(std::ifstream& file)
|
||||
{
|
||||
this->parse(file);
|
||||
return this->values_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
struct raw_hive_value : hive_value
|
||||
{
|
||||
@@ -138,6 +150,11 @@ class hive_parser
|
||||
return sub_key->get_value(this->file_, index);
|
||||
}
|
||||
|
||||
std::ifstream& get_file()
|
||||
{
|
||||
return this->file_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ifstream file_{};
|
||||
hive_key root_key_;
|
||||
|
||||
@@ -209,6 +209,26 @@ registry_manager::hive_map::iterator registry_manager::find_hive(const utils::pa
|
||||
return this->hives_.end();
|
||||
}
|
||||
|
||||
std::optional<exposed_hive_key> registry_manager::get_hive_key(const registry_key& key)
|
||||
{
|
||||
const auto iterator = this->hives_.find(key.hive);
|
||||
if (iterator == this->hives_.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto* hive_key = iterator->second->get_sub_key(key.path.get());
|
||||
if (!hive_key)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return exposed_hive_key{
|
||||
.key = *hive_key,
|
||||
.file = iterator->second->get_file(),
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<std::string_view> registry_manager::get_sub_key_name(const registry_key& key, const size_t index)
|
||||
{
|
||||
const auto iterator = this->hives_.find(key.hive);
|
||||
|
||||
@@ -54,6 +54,12 @@ struct registry_value
|
||||
std::span<const std::byte> data;
|
||||
};
|
||||
|
||||
struct exposed_hive_key
|
||||
{
|
||||
hive_key& key;
|
||||
std::ifstream& file;
|
||||
};
|
||||
|
||||
class registry_manager
|
||||
{
|
||||
public:
|
||||
@@ -76,6 +82,8 @@ class registry_manager
|
||||
|
||||
std::optional<std::string_view> get_sub_key_name(const registry_key& key, size_t index);
|
||||
|
||||
std::optional<exposed_hive_key> get_hive_key(const registry_key& key);
|
||||
|
||||
private:
|
||||
std::filesystem::path hive_path_{};
|
||||
hive_map hives_{};
|
||||
|
||||
@@ -82,11 +82,46 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (key_information_class == KeyFullInformation || key_information_class == KeyCachedInformation)
|
||||
if (key_information_class == KeyFullInformation)
|
||||
{
|
||||
c.win_emu.log.warn("Unsupported registry class: %X\n", key_information_class);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (key_information_class == KeyCachedInformation)
|
||||
{
|
||||
auto key_name = (key->hive.get() / key->path.get()).u16string();
|
||||
while (key_name.ends_with(u'/') || key_name.ends_with(u'\\'))
|
||||
{
|
||||
key_name.pop_back();
|
||||
}
|
||||
|
||||
const auto hive_key = c.win_emu.registry.get_hive_key(*key);
|
||||
if (!hive_key.has_value())
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
constexpr auto required_size = sizeof(KEY_CACHED_INFORMATION);
|
||||
result_length.write(required_size);
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
KEY_CACHED_INFORMATION info{};
|
||||
info.SubKeys = static_cast<ULONG>(hive_key->key.get_sub_key_count(hive_key->file));
|
||||
info.Values = static_cast<ULONG>(hive_key->key.get_value_count(hive_key->file));
|
||||
info.NameLength = static_cast<ULONG>(key_name.size() * 2);
|
||||
info.MaxValueDataLen = 0x1000;
|
||||
info.MaxValueNameLen = 0x1000;
|
||||
info.MaxNameLen = 0x1000;
|
||||
|
||||
c.emu.write_memory(key_information, info);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (key_information_class == KeyHandleTagsInformation)
|
||||
{
|
||||
constexpr auto required_size = sizeof(KEY_HANDLE_TAGS_INFORMATION);
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace syscalls
|
||||
const emulator_object<uint64_t> base_address,
|
||||
const EMULATOR_CAST(EmulatorTraits<Emu64>::ULONG_PTR, ULONG_PTR) /*zero_bits*/,
|
||||
const EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T) /*commit_size*/,
|
||||
const emulator_object<LARGE_INTEGER> /*section_offset*/,
|
||||
const emulator_object<LARGE_INTEGER> section_offset,
|
||||
const emulator_object<EMULATOR_CAST(EmulatorTraits<Emu64>::SIZE_T, SIZE_T)> view_size,
|
||||
const SECTION_INHERIT /*inherit_disposition*/, const ULONG /*allocation_type*/,
|
||||
const ULONG /*win32_protect*/)
|
||||
@@ -350,9 +350,16 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t size = section_entry->maximum_size;
|
||||
auto size = static_cast<size_t>(section_entry->maximum_size);
|
||||
std::vector<std::byte> file_data{};
|
||||
|
||||
int64_t offset = 0;
|
||||
if (section_offset)
|
||||
{
|
||||
offset = section_offset.read().QuadPart;
|
||||
offset = std::max<int64_t>(offset, 0);
|
||||
}
|
||||
|
||||
if (!section_entry->file_name.empty())
|
||||
{
|
||||
if (!utils::io::read_file(c.win_emu.file_sys.translate(section_entry->file_name), &file_data))
|
||||
@@ -360,21 +367,22 @@ namespace syscalls
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
size = page_align_up(file_data.size());
|
||||
size = static_cast<size_t>(file_data.size() - offset);
|
||||
}
|
||||
|
||||
const auto aligned_size = static_cast<size_t>(page_align_up(size));
|
||||
const auto reserve_only = section_entry->allocation_attributes == SEC_RESERVE;
|
||||
const auto protection = map_nt_to_emulator_protection(section_entry->section_page_protection);
|
||||
const auto address = c.win_emu.memory.allocate_memory(static_cast<size_t>(size), protection, reserve_only);
|
||||
const auto address = c.win_emu.memory.allocate_memory(aligned_size, protection, reserve_only);
|
||||
|
||||
if (!reserve_only && !file_data.empty())
|
||||
{
|
||||
c.emu.write_memory(address, file_data.data(), file_data.size());
|
||||
c.emu.write_memory(address, file_data.data() + offset, size);
|
||||
}
|
||||
|
||||
if (view_size)
|
||||
{
|
||||
view_size.write(size);
|
||||
view_size.write(aligned_size);
|
||||
}
|
||||
|
||||
base_address.write(address);
|
||||
|
||||
Reference in New Issue
Block a user