Support KeyCachedInformation

This commit is contained in:
momo5502
2025-12-23 09:31:10 +01:00
parent b1f7efb8c1
commit db3a89a0da
5 changed files with 93 additions and 1 deletions

View File

@@ -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;

View File

@@ -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_;

View File

@@ -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);

View File

@@ -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_{};

View File

@@ -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);