diff --git a/src/common/utils/string.hpp b/src/common/utils/string.hpp new file mode 100644 index 00000000..a03d7b45 --- /dev/null +++ b/src/common/utils/string.hpp @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include +#include + +namespace utils::string +{ + inline char char_to_lower(const char val) + { + return static_cast(std::tolower(static_cast(val))); + } + + inline wchar_t char_to_lower(const wchar_t val) + { + return std::towlower(val); + } + + template + void to_lower_inplace(std::basic_string& str) + { + std::ranges::transform(str, str.begin(), [](const Elem e) + { + return char_to_lower(e); + }); + } + + template + std::basic_string to_lower(std::basic_string str) + { + to_lower_inplace(str); + return str; + } + + template + std::basic_string to_lower_consume(std::basic_string& str) + { + return to_lower(std::move(str)); + } +} diff --git a/src/windows-emulator/module/module_manager.cpp b/src/windows-emulator/module/module_manager.cpp index ca5f4412..42e367f8 100644 --- a/src/windows-emulator/module/module_manager.cpp +++ b/src/windows-emulator/module/module_manager.cpp @@ -3,6 +3,22 @@ #include "module_mapping.hpp" #include "windows-emulator/logger.hpp" +namespace +{ + std::filesystem::path canonicalize_module_path(const std::filesystem::path& file) + { + constexpr std::u16string_view nt_prefix = u"\\??\\"; + const auto wide_file = file.u16string(); + + if (!wide_file.starts_with(nt_prefix)) + { + return canonical(absolute(file)); + } + + return canonicalize_module_path(wide_file.substr(nt_prefix.size())); + } +} + static void serialize(utils::buffer_serializer& buffer, const exported_symbol& sym) { buffer.write(sym.name); @@ -52,7 +68,7 @@ module_manager::module_manager(emulator& emu) mapped_module* module_manager::map_module(const std::filesystem::path& file, logger& logger) { - const auto canonical_file = canonical(absolute(file)); + const auto canonical_file = canonicalize_module_path(file); for (auto& mod : this->modules_) { diff --git a/src/windows-emulator/registry/hive_parser.cpp b/src/windows-emulator/registry/hive_parser.cpp index e9825f3e..a71f7b2f 100644 --- a/src/windows-emulator/registry/hive_parser.cpp +++ b/src/windows-emulator/registry/hive_parser.cpp @@ -1,4 +1,5 @@ #include "hive_parser.hpp" +#include // Based on this implementation: https://github.com/reahly/windows-hive-parser @@ -130,11 +131,6 @@ namespace throw std::runtime_error("Bad hive file '" + file_path.string() + "': " + e.what()); } } - - char char_to_lower(const char val) - { - return static_cast(std::tolower(static_cast(val))); - } } const hive_value* hive_key::get_value(std::ifstream& file, const std::string_view name) @@ -188,7 +184,7 @@ void hive_key::parse(std::ifstream& file) raw_value.data_offset = offset + static_cast(offsetof(value_block_t, offset)); } - std::ranges::transform(value_name, value_name.begin(), char_to_lower); + utils::string::to_lower_inplace(value_name); this->values_[std::move(value_name)] = std::move(raw_value); } @@ -211,7 +207,7 @@ void hive_key::parse(std::ifstream& file) const auto subkey = read_file_object(file, subkey_block_offset); std::string subkey_name(subkey.name, std::min(subkey.len, static_cast(sizeof(subkey.name)))); - std::ranges::transform(subkey_name, subkey_name.begin(), char_to_lower); + utils::string::to_lower_inplace(subkey_name); this->sub_keys_.emplace(std::move(subkey_name), hive_key{subkey.subkeys, subkey.value_count, subkey.offsets}); } diff --git a/src/windows-emulator/registry/registry_manager.cpp b/src/windows-emulator/registry/registry_manager.cpp index 193bf65a..9947035e 100644 --- a/src/windows-emulator/registry/registry_manager.cpp +++ b/src/windows-emulator/registry/registry_manager.cpp @@ -1,25 +1,16 @@ #include "registry_manager.hpp" -#include #include #include "hive_parser.hpp" +#include namespace { - void string_to_lower(std::string& str) - { - std::ranges::transform(str, str.begin(), [](const char val) - { - return static_cast(std::tolower(static_cast(val))); - }); - } - std::filesystem::path canonicalize_path(const std::filesystem::path& key) { auto path = key.lexically_normal().wstring(); - std::ranges::transform(path, path.begin(), std::towlower); - return {std::move(path)}; + return utils::string::to_lower_consume(path); } bool is_subpath(const std::filesystem::path& root, const std::filesystem::path& p) @@ -144,7 +135,7 @@ std::optional registry_manager::get_key(const std::filesystem::pat std::optional registry_manager::get_value(const registry_key& key, std::string name) { - string_to_lower(name); + utils::string::to_lower_inplace(name); const auto iterator = this->hives_.find(key.hive); if (iterator == this->hives_.end())