mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-21 04:33:56 +00:00
Improvements to registry syscalls
This commit is contained in:
@@ -242,8 +242,195 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtEnumerateKey()
|
||||
NTSTATUS handle_NtEnumerateKey(const syscall_context& c, const handle key_handle, const ULONG index,
|
||||
const KEY_INFORMATION_CLASS key_information_class, const uint64_t key_information,
|
||||
const ULONG length, const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
const auto subkey_name = c.win_emu.registry.get_sub_key_name(*key, index);
|
||||
if (!subkey_name)
|
||||
{
|
||||
return STATUS_NO_MORE_ENTRIES;
|
||||
}
|
||||
|
||||
const std::u16string subkey_name_u16(subkey_name->begin(), subkey_name->end());
|
||||
|
||||
if (key_information_class == KeyBasicInformation)
|
||||
{
|
||||
constexpr auto base_size = offsetof(KEY_BASIC_INFORMATION, Name);
|
||||
const auto name_size = subkey_name_u16.size() * 2;
|
||||
const auto required_size = base_size + name_size;
|
||||
result_length.write(static_cast<ULONG>(required_size));
|
||||
|
||||
KEY_BASIC_INFORMATION info{};
|
||||
info.LastWriteTime.QuadPart = 0;
|
||||
info.TitleIndex = 0;
|
||||
info.NameLength = static_cast<ULONG>(name_size);
|
||||
|
||||
if (base_size <= length)
|
||||
{
|
||||
c.emu.write_memory(key_information, &info, base_size);
|
||||
}
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
c.emu.write_memory(key_information + base_size, subkey_name_u16.data(), name_size);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (key_information_class == KeyNodeInformation)
|
||||
{
|
||||
constexpr auto base_size = offsetof(KEY_NODE_INFORMATION, Name);
|
||||
const auto name_size = subkey_name_u16.size() * 2;
|
||||
constexpr auto class_size = 0; // TODO: Class Name
|
||||
const auto required_size = base_size + name_size + class_size;
|
||||
result_length.write(static_cast<ULONG>(required_size));
|
||||
|
||||
KEY_NODE_INFORMATION info{};
|
||||
info.LastWriteTime.QuadPart = 0;
|
||||
info.TitleIndex = 0;
|
||||
info.ClassOffset = static_cast<ULONG>(base_size + name_size);
|
||||
info.ClassLength = static_cast<ULONG>(class_size);
|
||||
info.NameLength = static_cast<ULONG>(name_size);
|
||||
|
||||
if (base_size <= length)
|
||||
{
|
||||
c.emu.write_memory(key_information, &info, base_size);
|
||||
}
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
c.emu.write_memory(key_information + base_size, subkey_name_u16.data(), name_size);
|
||||
// TODO: Write Class Name
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
c.win_emu.log.print(color::gray, "Unsupported registry enumeration class: %X\n", key_information_class);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtEnumerateValueKey(const syscall_context& c, const handle key_handle, const ULONG index,
|
||||
const KEY_VALUE_INFORMATION_CLASS key_value_information_class,
|
||||
const uint64_t key_value_information, const ULONG length,
|
||||
const emulator_object<ULONG> result_length)
|
||||
{
|
||||
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||
if (!key)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
const auto value = c.win_emu.registry.get_value(*key, index);
|
||||
if (!value)
|
||||
{
|
||||
return STATUS_NO_MORE_ENTRIES;
|
||||
}
|
||||
|
||||
const std::u16string value_name_u16(value->name.begin(), value->name.end());
|
||||
|
||||
if (key_value_information_class == KeyValueBasicInformation)
|
||||
{
|
||||
constexpr auto base_size = offsetof(KEY_VALUE_BASIC_INFORMATION, Name);
|
||||
const auto name_size = value_name_u16.size() * 2;
|
||||
const auto required_size = base_size + name_size;
|
||||
result_length.write(static_cast<ULONG>(required_size));
|
||||
|
||||
KEY_VALUE_BASIC_INFORMATION info{};
|
||||
info.TitleIndex = 0;
|
||||
info.Type = value->type;
|
||||
info.NameLength = static_cast<ULONG>(name_size);
|
||||
|
||||
if (base_size <= length)
|
||||
{
|
||||
c.emu.write_memory(key_value_information, &info, base_size);
|
||||
}
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
c.emu.write_memory(key_value_information + base_size, value_name_u16.data(), name_size);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (key_value_information_class == KeyValuePartialInformation)
|
||||
{
|
||||
constexpr auto base_size = offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data);
|
||||
const auto data_size = value->data.size();
|
||||
const auto required_size = base_size + data_size;
|
||||
result_length.write(static_cast<ULONG>(required_size));
|
||||
|
||||
KEY_VALUE_PARTIAL_INFORMATION info{};
|
||||
info.TitleIndex = 0;
|
||||
info.Type = value->type;
|
||||
info.DataLength = static_cast<ULONG>(data_size);
|
||||
|
||||
if (base_size <= length)
|
||||
{
|
||||
c.emu.write_memory(key_value_information, &info, base_size);
|
||||
}
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
c.emu.write_memory(key_value_information + base_size, value->data.data(), data_size);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (key_value_information_class == KeyValueFullInformation)
|
||||
{
|
||||
constexpr auto base_size = offsetof(KEY_VALUE_FULL_INFORMATION, Name);
|
||||
const auto name_size = value_name_u16.size() * 2;
|
||||
const auto data_size = value->data.size();
|
||||
const ULONG data_offset = static_cast<ULONG>(base_size + name_size);
|
||||
const auto required_size = data_offset + data_size;
|
||||
|
||||
result_length.write(static_cast<ULONG>(required_size));
|
||||
|
||||
KEY_VALUE_FULL_INFORMATION info{};
|
||||
info.TitleIndex = 0;
|
||||
info.Type = value->type;
|
||||
info.DataOffset = data_offset;
|
||||
info.DataLength = static_cast<ULONG>(data_size);
|
||||
info.NameLength = static_cast<ULONG>(name_size);
|
||||
|
||||
if (base_size <= length)
|
||||
{
|
||||
c.emu.write_memory(key_value_information, &info, base_size);
|
||||
}
|
||||
|
||||
if (required_size > length)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
c.emu.write_memory(key_value_information + base_size, value_name_u16.data(), name_size);
|
||||
|
||||
c.emu.write_memory(key_value_information + data_offset, value->data.data(), data_size);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
c.win_emu.log.print(color::gray, "Unsupported registry value enumeration class: %X\n",
|
||||
key_value_information_class);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user