From 9d0de32cde149a492c771dd7db8d523f0c82a4ab Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 18:21:29 -0300 Subject: [PATCH 1/6] Add new tests --- src/samples/test-sample/test.cpp | 180 ++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 3 deletions(-) diff --git a/src/samples/test-sample/test.cpp b/src/samples/test-sample/test.cpp index a3b03a34..7923e6d1 100644 --- a/src/samples/test-sample/test.cpp +++ b/src/samples/test-sample/test.cpp @@ -273,16 +273,189 @@ namespace return {std::string(data, std::min(static_cast(length - 1), sizeof(data)))}; } + std::optional> get_all_registry_keys(const HKEY root, const char* path) + { + HKEY key{}; + if (RegOpenKeyExA(root, path, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) + { + return std::nullopt; + } + + std::vector keys; + std::vector name_buffer(MAX_PATH + 1); + + for (DWORD i = 0;; ++i) + { + auto name_buffer_len = static_cast(name_buffer.size()); + const LSTATUS status = + RegEnumKeyExA(key, i, name_buffer.data(), &name_buffer_len, nullptr, nullptr, nullptr, nullptr); + if (status == ERROR_SUCCESS) + { + keys.emplace_back(name_buffer.data(), name_buffer_len); + } + else if (status == ERROR_NO_MORE_ITEMS) + { + break; + } + else + { + keys.clear(); + break; + } + } + + if (keys.empty()) + { + RegCloseKey(key); + return std::nullopt; + } + + if (RegCloseKey(key) != ERROR_SUCCESS) + { + return std::nullopt; + } + + return keys; + } + + std::optional> get_all_registry_values(const HKEY root, const char* path) + { + HKEY key{}; + if (RegOpenKeyExA(root, path, 0, KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) + { + return std::nullopt; + } + + std::vector values; + std::vector name_buffer(MAX_PATH + 1); + + for (DWORD i = 0;; ++i) + { + auto name_buffer_len = static_cast(name_buffer.size()); + const auto status = + RegEnumValueA(key, i, name_buffer.data(), &name_buffer_len, nullptr, nullptr, nullptr, nullptr); + if (status == ERROR_SUCCESS) + { + values.emplace_back(name_buffer.data(), name_buffer_len); + } + else if (status == ERROR_NO_MORE_ITEMS) + { + break; + } + else + { + values.clear(); + break; + } + } + + if (values.empty()) + { + RegCloseKey(key); + return std::nullopt; + } + + if (RegCloseKey(key) != ERROR_SUCCESS) + { + return std::nullopt; + } + + return values; + } + bool test_registry() { - const auto val = + // Basic Reading Test + const auto prog_files_dir = read_registry_string(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows\CurrentVersion)", "ProgramFilesDir"); - if (!val) + if (!prog_files_dir || *prog_files_dir != "C:\\Program Files") { return false; } - return *val == "C:\\Program Files"; + // WOW64 Redirection Test + const auto pst_display = read_registry_string( + HKEY_LOCAL_MACHINE, + R"(SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\Time Zones\Pacific Standard Time)", "Display"); + if (!pst_display || pst_display->empty()) + { + return false; + } + + // Key Sub-keys Enumeration Test + const auto subkeys_opt = + get_all_registry_keys(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"); + if (!subkeys_opt) + { + return false; + } + + bool found_fonts = false; + for (const auto& key_name : *subkeys_opt) + { + if (key_name == "Fonts") + { + found_fonts = true; + break; + } + } + if (!found_fonts) + { + return false; + } + + // Key Values Enumeration Test + const auto values_opt = + get_all_registry_values(HKEY_LOCAL_MACHINE, R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"); + if (!values_opt) + { + return false; + } + + bool found_product_name = false; + for (const auto& val_name : *values_opt) + { + if (val_name == "ProductName") + { + found_product_name = true; + break; + } + } + if (!found_product_name) + { + return false; + } + + return true; + } + + bool test_system_info() + { + char sys_dir[MAX_PATH]; + if (GetSystemDirectoryA(sys_dir, sizeof(sys_dir)) == 0) + { + return false; + } + if (strlen(sys_dir) != 19) + { + return false; + } + + // TODO: This currently doesn't work. + /* + char username[256]; + DWORD username_len = sizeof(username); + if (!GetUserNameA(username, &username_len)) + { + return false; + } + if (username_len <= 1) + { + return false; + } + */ + + return true; } void throw_exception() @@ -477,6 +650,7 @@ int main(const int argc, const char* argv[]) RUN_TEST(test_dir_io, "Dir I/O") RUN_TEST(test_working_directory, "Working Directory") RUN_TEST(test_registry, "Registry") + RUN_TEST(test_system_info, "System Info") RUN_TEST(test_threads, "Threads") RUN_TEST(test_env, "Environment") RUN_TEST(test_exceptions, "Exceptions") From 7fef4ebc24f6fc831fe86f785d7130ea7346c3d2 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 18:22:06 -0300 Subject: [PATCH 2/6] Handle TokenGroups in NtQueryInformationToken --- src/common/platform/process.hpp | 6 ++++++ src/windows-emulator/syscalls/token.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/common/platform/process.hpp b/src/common/platform/process.hpp index e02d8f99..0fc6adbb 100644 --- a/src/common/platform/process.hpp +++ b/src/common/platform/process.hpp @@ -770,6 +770,12 @@ struct TOKEN_USER64 SID_AND_ATTRIBUTES64 User; }; +struct TOKEN_GROUPS64 +{ + ULONG GroupCount; + SID_AND_ATTRIBUTES64 Groups[1]; +}; + struct TOKEN_OWNER64 { EMULATOR_CAST(EmulatorTraits::PVOID, PSID) Owner; diff --git a/src/windows-emulator/syscalls/token.cpp b/src/windows-emulator/syscalls/token.cpp index 52857c72..7580f334 100644 --- a/src/windows-emulator/syscalls/token.cpp +++ b/src/windows-emulator/syscalls/token.cpp @@ -75,6 +75,26 @@ namespace syscalls return STATUS_SUCCESS; } + if (token_information_class == TokenGroups) + { + constexpr auto required_size = sizeof(TOKEN_GROUPS64) + sizeof(sid); + return_length.write(required_size); + + if (required_size > token_information_length) + { + return STATUS_BUFFER_TOO_SMALL; + } + + TOKEN_GROUPS64 groups{}; + groups.GroupCount = 1; + groups.Groups[0].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY; + groups.Groups[0].Sid = token_information + sizeof(TOKEN_GROUPS64); + + emulator_object{c.emu, token_information}.write(groups); + c.emu.write_memory(token_information + sizeof(TOKEN_GROUPS64), sid, sizeof(sid)); + return STATUS_SUCCESS; + } + if (token_information_class == TokenOwner) { constexpr auto required_size = sizeof(sid) + sizeof(TOKEN_OWNER64); From 3b918f2d5cd867d05b7dd1bc9633ed4b88efe84b Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 18:24:12 -0300 Subject: [PATCH 3/6] Stub SystemFirmwareTableInformation in NtQuerySystemInformation --- src/windows-emulator/syscalls/system.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/windows-emulator/syscalls/system.cpp b/src/windows-emulator/syscalls/system.cpp index 991f1aa9..2cee38e8 100644 --- a/src/windows-emulator/syscalls/system.cpp +++ b/src/windows-emulator/syscalls/system.cpp @@ -105,6 +105,7 @@ namespace syscalls case SystemFeatureConfigurationInformation: case SystemSupportedProcessorArchitectures2: case SystemFeatureConfigurationSectionInformation: + case SystemFirmwareTableInformation: return STATUS_NOT_SUPPORTED; case SystemControlFlowTransition: From 21af0de2c8272e353c3ee81ee4e9cf3aa7b0893f Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 18:24:36 -0300 Subject: [PATCH 4/6] Add c_437.nls to create-root.bat --- src/tools/create-root.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/create-root.bat b/src/tools/create-root.bat index c93361c2..07936796 100644 --- a/src/tools/create-root.bat +++ b/src/tools/create-root.bat @@ -130,6 +130,7 @@ CALL :collect msacm32.dll CALL :collect locale.nls CALL :collect c_1252.nls CALL :collect c_850.nls +CALL :collect c_437.nls EXIT /B 0 From a3a786c6ec6b55b5a399f75b16f1729b11be6ff3 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 18:41:56 -0300 Subject: [PATCH 5/6] Fix failing check --- src/windows-emulator/syscalls/token.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows-emulator/syscalls/token.cpp b/src/windows-emulator/syscalls/token.cpp index 7580f334..b917bf14 100644 --- a/src/windows-emulator/syscalls/token.cpp +++ b/src/windows-emulator/syscalls/token.cpp @@ -87,7 +87,7 @@ namespace syscalls TOKEN_GROUPS64 groups{}; groups.GroupCount = 1; - groups.Groups[0].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY; + groups.Groups[0].Attributes = 0; groups.Groups[0].Sid = token_information + sizeof(TOKEN_GROUPS64); emulator_object{c.emu, token_information}.write(groups); From 0474eef3737455e00dd890c41c88dc55bca80569 Mon Sep 17 00:00:00 2001 From: Igor Pissolati Date: Wed, 23 Apr 2025 19:11:25 -0300 Subject: [PATCH 6/6] Fix failing test --- src/windows-emulator/registry/registry_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/registry/registry_manager.cpp b/src/windows-emulator/registry/registry_manager.cpp index 3309f1e5..b6d7c860 100644 --- a/src/windows-emulator/registry/registry_manager.cpp +++ b/src/windows-emulator/registry/registry_manager.cpp @@ -110,12 +110,12 @@ std::optional registry_manager::get_key(const utils::path_key& key if (!entry) { - constexpr std::wstring_view wowPrefix = L"wow6432node\\"; + constexpr std::wstring_view wowPrefix = L"wow6432node"; const auto pathStr = path.wstring(); if (pathStr.starts_with(wowPrefix)) { - path = pathStr.substr(wowPrefix.size()); + path = pathStr.substr(wowPrefix.size() + 1); reg_key.path = path; entry = iterator->second->get_sub_key(path); }