diff --git a/src/loader/module.hpp b/src/loader/module.hpp index 10938f5..49c344e 100644 --- a/src/loader/module.hpp +++ b/src/loader/module.hpp @@ -18,4 +18,9 @@ public: virtual void pre_destroy() { } + + virtual void* load_import(const std::string& module, const std::string& function) + { + return nullptr; + } }; diff --git a/src/loader/module_loader.cpp b/src/loader/module_loader.cpp index 615c9e1..bce9176 100644 --- a/src/loader/module_loader.cpp +++ b/src/loader/module_loader.cpp @@ -68,6 +68,22 @@ void module_loader::pre_destroy() } } +void* module_loader::load_import(const std::string& module, const std::string& function) +{ + void* function_ptr = nullptr; + + for (const auto& module_ : *modules_) + { + const auto module_function_ptr = module_->load_import(module, function); + if(module_function_ptr) + { + function_ptr = module_function_ptr; + } + } + + return function_ptr; +} + void module_loader::destroy_modules() { pre_destroy(); diff --git a/src/loader/module_loader.hpp b/src/loader/module_loader.hpp index ae27493..9477f6e 100644 --- a/src/loader/module_loader.hpp +++ b/src/loader/module_loader.hpp @@ -30,6 +30,8 @@ public: static bool post_load(); static void pre_destroy(); + static void* load_import(const std::string& module, const std::string& function); + static void trigger_premature_shutdown(); private: diff --git a/src/main.cpp b/src/main.cpp index 4d582f0..31bd3e8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ FARPROC load_binary(const launcher::mode mode) return FARPROC(exit_hook); } - return nullptr; + return FARPROC(module_loader::load_import(module, function)); }); return loader.load(self); diff --git a/src/module/game_launcher.cpp b/src/module/game_launcher.cpp new file mode 100644 index 0000000..7fe9dd7 --- /dev/null +++ b/src/module/game_launcher.cpp @@ -0,0 +1,59 @@ +#include +#include "loader/module_loader.hpp" +#include "utils/nt.hpp" +#include "utils/string.hpp" +#include "game/game.hpp" + +class game_launcher final : public module +{ +public: + void* load_import(const std::string& module, const std::string& function) override + { + if (utils::string::to_lower(module) == "shell32.dll" && function == "ShellExecuteA") + { + return shell_execute_a; + } + + return nullptr; + } + +private: + static HINSTANCE __stdcall shell_execute_a(const HWND hwnd, const LPCSTR lp_operation, const LPCSTR lp_file, + const LPCSTR lp_parameters, const LPCSTR lp_directory, INT n_show_cmd) + { + static const auto sp_url = "steam://run/42680"s; + static const auto mp_url = "steam://run/42690"s; + + if (lp_file && (sp_url == lp_file || mp_url == lp_file)) + { + launch_game(sp_url == lp_file); + return HINSTANCE(33); + } + + return ShellExecuteA(hwnd, lp_operation, lp_file, lp_parameters, lp_directory, n_show_cmd); + } + + + static void launch_game(const bool singleplayer) + { + utils::nt::module self; + + STARTUPINFOA s_info; + PROCESS_INFORMATION p_info; + + ZeroMemory(&s_info, sizeof(s_info)); + ZeroMemory(&p_info, sizeof(p_info)); + s_info.cb = sizeof(s_info); + + const auto path = self.get_path(); + std::string cmdline = utils::string::va("\"%s\" %s", path.data(), + singleplayer ? "-singleplayer" : "-multiplayer"); + + CreateProcessA(path.data(), cmdline.data(), nullptr, nullptr, false, NULL, nullptr, nullptr, &s_info, &p_info); + + if (p_info.hThread && p_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(p_info.hThread); + if (p_info.hProcess && p_info.hProcess != INVALID_HANDLE_VALUE) CloseHandle(p_info.hProcess); + } +}; + +REGISTER_MODULE(game_launcher)