Use working directory provider

This commit is contained in:
momo5502
2025-02-08 17:05:02 +01:00
parent b5a0f73113
commit 72e88d30d4
3 changed files with 51 additions and 44 deletions

View File

@@ -4,20 +4,26 @@
#include <platform/compiler.hpp>
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<windows_path, std::filesystem::path> mappings_{};
};

View File

@@ -209,7 +209,8 @@ namespace
emu.reg<uint16_t>(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<x64_emulator> 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<x64_emulator> 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<RTL_USER_PROCESS_PARAMETERS64>(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_;
}

View File

@@ -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_context> 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);
};