From 72e88d30d47d33e8c5f7c2d808d5d85b22d8115d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 8 Feb 2025 17:05:02 +0100 Subject: [PATCH] Use working directory provider --- src/windows-emulator/file_system.hpp | 40 +++++++------------ src/windows-emulator/windows_emulator.cpp | 47 ++++++++++++++++------- src/windows-emulator/windows_emulator.hpp | 8 ++-- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/src/windows-emulator/file_system.hpp b/src/windows-emulator/file_system.hpp index 4161bf3e..159cf311 100644 --- a/src/windows-emulator/file_system.hpp +++ b/src/windows-emulator/file_system.hpp @@ -4,20 +4,26 @@ #include +struct working_directory_provider +{ + virtual windows_path get_working_directory() = 0; +}; + class file_system { public: - file_system(std::filesystem::path root, windows_path working_dir = "C:\\") - : root_(std::move(root)) + file_system(std::filesystem::path root, working_directory_provider& working_dir_provider) + : root_(std::move(root)), + working_dir_provider_(&working_dir_provider) { - this->set_working_directory(std::move(working_dir)); } std::filesystem::path translate(const windows_path& win_path) const { + assert(win_path.is_absolute() && "Path should always be absolute"); const auto& full_path = win_path.is_absolute() // ? win_path - : (this->working_dir_ / win_path); + : (this->working_dir_provider_->get_working_directory() / win_path); const auto mapping = this->mappings_.find(full_path); if (mapping != this->mappings_.end()) @@ -36,20 +42,10 @@ class file_system return this->root_ / full_path.to_portable_path(); } - void set_working_directory(windows_path working_dir) - { - if (!working_dir.is_absolute()) - { - throw std::runtime_error("Working directory is not an absolute path: " + working_dir.string()); - } - - this->working_dir_ = std::move(working_dir); - } - - const windows_path& get_working_directory() const + /*const windows_path& get_working_directory() const { return this->working_dir_; - } + }*/ windows_path local_to_windows_path(const std::filesystem::path& local_path) const { @@ -81,16 +77,6 @@ class file_system return windows_path{drive, std::move(folders)}; } - void serialize(utils::buffer_serializer& buffer) const - { - buffer.write(this->working_dir_); - } - - void deserialize(utils::buffer_deserializer& buffer) - { - buffer.read(this->working_dir_); - } - void map(windows_path src, std::filesystem::path dest) { this->mappings_[std::move(src)] = std::move(dest); @@ -98,6 +84,6 @@ class file_system private: std::filesystem::path root_{}; - windows_path working_dir_{}; + working_directory_provider* working_dir_provider_{}; std::unordered_map mappings_{}; }; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index a5e11bb2..b41e0cf6 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -209,7 +209,8 @@ namespace emu.reg(x64_register::ss, 0x2B); } - void setup_context(windows_emulator& win_emu, const emulator_settings& settings) + void setup_context(windows_emulator& win_emu, const emulator_settings& settings, + const windows_path& working_directory) { auto& emu = win_emu.emu(); auto& context = win_emu.process(); @@ -269,8 +270,7 @@ namespace } allocator.make_unicode_string(proc_params.CommandLine, command_line); - allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, - win_emu.file_sys().get_working_directory().u16string()); + allocator.make_unicode_string(proc_params.CurrentDirectory.DosPath, working_directory.u16string() + u"\\"); allocator.make_unicode_string(proc_params.ImagePathName, application_str); const auto total_length = allocator.get_next_address() - context.process_params.value(); @@ -829,19 +829,21 @@ windows_emulator::windows_emulator(const emulator_settings& settings, emulator_c std::unique_ptr emu) : windows_emulator(settings.emulation_root, std::move(emu)) { + windows_path working_dir{}; + if (!settings.working_directory.empty()) { - this->file_sys().set_working_directory(settings.working_directory); + working_dir = settings.working_directory; } #ifdef OS_WINDOWS else if (settings.application.is_relative()) { - this->file_sys().set_working_directory(std::filesystem::current_path()); + working_dir = std::filesystem::current_path(); } #endif else { - this->file_sys().set_working_directory(settings.application.parent()); + working_dir = settings.application.parent(); } for (const auto& mapping : settings.path_mappings) @@ -859,12 +861,12 @@ windows_emulator::windows_emulator(const emulator_settings& settings, emulator_c this->use_relative_time_ = settings.use_relative_time; this->log.disable_output(settings.disable_logging || this->silent_until_main_); this->callbacks_ = std::move(callbacks); - this->setup_process(settings); + this->setup_process(settings, working_dir); } windows_emulator::windows_emulator(const std::filesystem::path& emulation_root, std::unique_ptr emu) : emulation_root_{emulation_root.empty() ? emulation_root : absolute(emulation_root)}, - file_sys_(emulation_root_.empty() ? emulation_root_ : emulation_root_ / "filesys"), + file_sys_(emulation_root_.empty() ? emulation_root_ : emulation_root_ / "filesys", *this), emu_(std::move(emu)), process_(*emu_, file_sys_) { @@ -878,14 +880,16 @@ windows_emulator::windows_emulator(const std::filesystem::path& emulation_root, this->setup_hooks(); } -void windows_emulator::setup_process(const emulator_settings& settings) +windows_emulator::~windows_emulator() = default; + +void windows_emulator::setup_process(const emulator_settings& settings, const windows_path& working_directory) { auto& emu = this->emu(); auto& context = this->process(); context.mod_manager = module_manager(emu, this->file_sys()); // TODO: Cleanup module manager - setup_context(*this, settings); + setup_context(*this, settings, working_directory); context.executable = context.mod_manager.map_module(settings.application, this->log, true); @@ -938,6 +942,25 @@ bool windows_emulator::activate_thread(const uint32_t id) return switch_to_thread(*this, *thread, true); } +windows_path windows_emulator::get_working_directory() +{ + if (!this->process_.peb) + { + return {}; + } + + const auto peb = this->process_.peb.read(); + if (!peb.ProcessParameters) + { + return {}; + } + + const auto& emu = this->emu(); + + const auto process_params = emu.read_memory(peb.ProcessParameters); + return read_unicode_string(emu, process_params.CurrentDirectory.DosPath); +} + void windows_emulator::on_instruction_execution(const uint64_t address) { auto& process = this->process(); @@ -1154,7 +1177,6 @@ void windows_emulator::serialize(utils::buffer_serializer& buffer) const { buffer.write(this->switch_thread_); buffer.write(this->use_relative_time_); - this->file_sys().serialize(buffer); this->emu().serialize(buffer); this->process_.serialize(buffer); this->dispatcher_.serialize(buffer); @@ -1172,7 +1194,6 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer) buffer.read(this->switch_thread_); buffer.read(this->use_relative_time_); - this->file_sys().deserialize(buffer); this->emu().deserialize(buffer); this->process_.deserialize(buffer); @@ -1184,7 +1205,6 @@ void windows_emulator::save_snapshot() this->emu().save_snapshot(); utils::buffer_serializer serializer{}; - this->file_sys().serialize(serializer); this->process_.serialize(serializer); this->process_snapshot_ = serializer.move_buffer(); @@ -1204,7 +1224,6 @@ void windows_emulator::restore_snapshot() this->emu().restore_snapshot(); utils::buffer_deserializer deserializer{this->process_snapshot_}; - this->file_sys().deserialize(deserializer); this->process_.deserialize(deserializer); // this->process_ = *this->process_snapshot_; } diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 29b3f5ca..fe95dc71 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -48,7 +48,7 @@ enum class apiset_location : uint8_t default_windows_11 }; -class windows_emulator +class windows_emulator : working_directory_provider { public: windows_emulator(const std::filesystem::path& emulation_root, @@ -61,7 +61,7 @@ class windows_emulator windows_emulator& operator=(windows_emulator&&) = delete; windows_emulator& operator=(const windows_emulator&) = delete; - ~windows_emulator() = default; + ~windows_emulator(); x64_emulator& emu() { @@ -190,6 +190,8 @@ class windows_emulator return this->emulation_root_; } + windows_path get_working_directory() override; + private: std::filesystem::path emulation_root_{}; file_system file_sys_; @@ -211,6 +213,6 @@ class windows_emulator // std::optional process_snapshot_{}; void setup_hooks(); - void setup_process(const emulator_settings& settings); + void setup_process(const emulator_settings& settings, const windows_path& working_directory); void on_instruction_execution(uint64_t address); };