mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 03:33:56 +00:00
Use working directory provider
This commit is contained in:
@@ -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_{};
|
||||
};
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user