mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Implement NtQueryMultipleValueKey (#684)
This PR implements `NtQueryMultipleValueKey` that is used in calls like `RegQueryMultipleValues`.
This commit is contained in:
@@ -110,4 +110,12 @@ struct KEY_VALUE_FULL_INFORMATION
|
|||||||
char16_t Name[1];
|
char16_t Name[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct KEY_VALUE_ENTRY
|
||||||
|
{
|
||||||
|
EmulatorTraits<Emu64>::PVOID ValueName;
|
||||||
|
ULONG DataLength;
|
||||||
|
ULONG DataOffset;
|
||||||
|
ULONG Type;
|
||||||
|
};
|
||||||
|
|
||||||
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ using NTSTATUS = std::uint32_t;
|
|||||||
#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL)
|
#define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS)0xC000007AL)
|
||||||
#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL)
|
#define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL)
|
||||||
#define STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
|
#define STATUS_FILE_INVALID ((NTSTATUS)0xC0000098L)
|
||||||
|
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
|
||||||
#define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS)0xC000009FL)
|
#define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS)0xC000009FL)
|
||||||
#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0L)
|
#define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS)0xC00000A0L)
|
||||||
#define STATUS_PIPE_BUSY ((NTSTATUS)0xC00000AAL)
|
#define STATUS_PIPE_BUSY ((NTSTATUS)0xC00000AAL)
|
||||||
|
|||||||
@@ -233,6 +233,9 @@ namespace syscalls
|
|||||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> value_name,
|
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> value_name,
|
||||||
KEY_VALUE_INFORMATION_CLASS key_value_information_class, uint64_t key_value_information, ULONG length,
|
KEY_VALUE_INFORMATION_CLASS key_value_information_class, uint64_t key_value_information, ULONG length,
|
||||||
emulator_object<ULONG> result_length);
|
emulator_object<ULONG> result_length);
|
||||||
|
NTSTATUS handle_NtQueryMultipleValueKey(const syscall_context& c, handle key_handle, emulator_object<KEY_VALUE_ENTRY> value_entries,
|
||||||
|
ULONG entry_count, uint64_t value_buffer, emulator_object<ULONG> buffer_length,
|
||||||
|
emulator_object<ULONG> required_buffer_length);
|
||||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, emulator_object<handle> key_handle, ACCESS_MASK desired_access,
|
NTSTATUS handle_NtCreateKey(const syscall_context& c, emulator_object<handle> key_handle, ACCESS_MASK desired_access,
|
||||||
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*title_index*/,
|
emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes, ULONG /*title_index*/,
|
||||||
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/, ULONG /*create_options*/,
|
emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/, ULONG /*create_options*/,
|
||||||
@@ -1159,6 +1162,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
|||||||
add_handler(NtSetInformationFile);
|
add_handler(NtSetInformationFile);
|
||||||
add_handler(NtUserRegisterWindowMessage);
|
add_handler(NtUserRegisterWindowMessage);
|
||||||
add_handler(NtQueryValueKey);
|
add_handler(NtQueryValueKey);
|
||||||
|
add_handler(NtQueryMultipleValueKey);
|
||||||
add_handler(NtQueryKey);
|
add_handler(NtQueryKey);
|
||||||
add_handler(NtGetNlsSectionPtr);
|
add_handler(NtGetNlsSectionPtr);
|
||||||
add_handler(NtAccessCheck);
|
add_handler(NtAccessCheck);
|
||||||
|
|||||||
@@ -261,6 +261,86 @@ namespace syscalls
|
|||||||
return STATUS_NOT_SUPPORTED;
|
return STATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS handle_NtQueryMultipleValueKey(const syscall_context& c, const handle key_handle,
|
||||||
|
const emulator_object<KEY_VALUE_ENTRY> value_entries, const ULONG entry_count,
|
||||||
|
const uint64_t value_buffer, const emulator_object<ULONG> buffer_length,
|
||||||
|
const emulator_object<ULONG> required_buffer_length)
|
||||||
|
{
|
||||||
|
if (entry_count > 0x10000)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* key = c.proc.registry_keys.get(key_handle);
|
||||||
|
if (!key)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
auto remaining_length = buffer_length.read();
|
||||||
|
ULONG required_length = 0;
|
||||||
|
ULONG written_bytes = 0;
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < entry_count; i++)
|
||||||
|
{
|
||||||
|
auto entry = value_entries.read(i);
|
||||||
|
if (!entry.ValueName)
|
||||||
|
{
|
||||||
|
status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto query_name = read_unicode_string(c.emu, entry.ValueName);
|
||||||
|
|
||||||
|
if (c.win_emu.callbacks.on_generic_access)
|
||||||
|
{
|
||||||
|
// TODO: Find a better way to log this
|
||||||
|
c.win_emu.callbacks.on_generic_access("Querying multiple value key ", query_name + u" (" + key->to_string() + u")");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto value = c.win_emu.registry.get_value(*key, u16_to_u8(query_name));
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto data_length = static_cast<ULONG>(value->data.size());
|
||||||
|
|
||||||
|
if (status == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
if (remaining_length >= data_length)
|
||||||
|
{
|
||||||
|
entry.DataOffset = written_bytes;
|
||||||
|
entry.DataLength = data_length;
|
||||||
|
entry.Type = value->type;
|
||||||
|
|
||||||
|
c.emu.write_memory(value_buffer + entry.DataOffset, value->data.data(), entry.DataLength);
|
||||||
|
value_entries.write(entry, i);
|
||||||
|
|
||||||
|
remaining_length -= data_length;
|
||||||
|
written_bytes += data_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = STATUS_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required_length += data_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_length.write(written_bytes);
|
||||||
|
|
||||||
|
if (required_buffer_length.value())
|
||||||
|
{
|
||||||
|
required_buffer_length.write(required_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS handle_NtCreateKey(const syscall_context& c, const emulator_object<handle> key_handle, const ACCESS_MASK desired_access,
|
NTSTATUS handle_NtCreateKey(const syscall_context& c, const emulator_object<handle> key_handle, const ACCESS_MASK desired_access,
|
||||||
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||||
const ULONG /*title_index*/, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
|
const ULONG /*title_index*/, const emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>> /*class*/,
|
||||||
|
|||||||
Reference in New Issue
Block a user