iw5-mod/src/main.cpp

135 lines
3.0 KiB
C++
Raw Normal View History

2018-12-01 09:42:29 -05:00
#include <std_include.hpp>
2018-12-23 07:17:08 -05:00
#include "launcher/launcher.hpp"
2018-12-23 16:15:32 -05:00
#include "loader/loader.hpp"
2018-12-24 13:54:44 -05:00
#include "loader/module_loader.hpp"
2018-12-24 17:22:56 -05:00
#include "game/game.hpp"
2018-12-26 10:28:16 -05:00
#include "loader/binary_loader.hpp"
2018-12-27 05:07:15 -05:00
#include "utils/string.hpp"
2019-01-08 18:02:59 -05:00
#include "utils/flags.hpp"
2018-12-26 10:28:16 -05:00
//#define GENERATE_DIFFS
2018-12-24 13:54:44 -05:00
2018-12-27 05:07:15 -05:00
__declspec(thread) char tls_data[TLS_PAYLOAD_SIZE];
2018-12-27 11:11:52 -05:00
DECLSPEC_NORETURN void WINAPI exit_hook(const int code)
2018-12-24 13:54:44 -05:00
{
module_loader::pre_destroy();
exit(code);
}
2018-12-01 09:42:29 -05:00
2018-12-27 05:07:15 -05:00
void verify_tls()
{
utils::nt::module self;
const auto self_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(self.get_ptr() + self
.get_optional_header()
->
DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
const auto ref = DWORD(&tls_data);
const auto tls_index = *reinterpret_cast<DWORD*>(self_tls->AddressOfIndex);
const auto tls_vector = *reinterpret_cast<DWORD*>(__readfsdword(0x2C) + 4 * tls_index);
const auto offset = ref - tls_vector;
if (offset != 0 && offset != 8) // Actually 8 is bad, but I think msvc places custom stuff before
{
throw std::runtime_error(utils::string::va("TLS payload is at offset 0x%X, but should be at 0!",
offset));
}
}
2019-01-08 18:02:59 -05:00
launcher::mode detect_mode_from_arguments()
{
if (utils::flags::has_flag("dedicated"))
{
return launcher::mode::server;
}
if (utils::flags::has_flag("multiplayer"))
{
return launcher::mode::multiplayer;
}
if (utils::flags::has_flag("singleplayer"))
{
return launcher::mode::singleplayer;
}
return launcher::mode::none;
}
2019-01-06 17:24:33 -05:00
FARPROC load_binary(const launcher::mode mode)
2018-12-01 09:42:29 -05:00
{
2019-01-06 17:24:33 -05:00
loader loader(mode);
utils::nt::module self;
2018-12-23 12:25:22 -05:00
2019-01-06 17:24:33 -05:00
loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC
2018-12-23 12:25:22 -05:00
{
2019-01-06 17:24:33 -05:00
if (module == "steam_api.dll")
{
return self.get_proc<FARPROC>(function);
}
else if (function == "ExitProcess")
{
return FARPROC(exit_hook);
}
2018-12-26 10:28:16 -05:00
2019-01-06 17:24:33 -05:00
return nullptr;
});
2019-01-06 17:24:33 -05:00
return loader.load(self);
}
2018-12-23 16:15:32 -05:00
2019-01-06 17:24:33 -05:00
int main()
{
FARPROC entry_point;
2018-12-23 16:15:32 -05:00
2019-01-06 17:24:33 -05:00
{
2019-01-08 18:02:59 -05:00
auto premature_shutdown = true;
const auto _ = gsl::finally([&premature_shutdown]()
2018-12-23 16:15:32 -05:00
{
2019-01-08 18:02:59 -05:00
if (premature_shutdown)
2018-12-23 16:15:32 -05:00
{
2019-01-06 17:24:33 -05:00
module_loader::pre_destroy();
2018-12-23 16:15:32 -05:00
}
2019-01-06 17:24:33 -05:00
});
try
{
#ifdef GENERATE_DIFFS
binary_loader::create();
return 0;
#endif
verify_tls();
if (!module_loader::post_start()) return 0;
2019-01-08 18:02:59 -05:00
auto mode = detect_mode_from_arguments();
if (mode == launcher::mode::none)
{
launcher launcher;
mode = launcher.run();
if (mode == launcher::mode::none) return 0;
}
2019-01-06 17:24:33 -05:00
entry_point = load_binary(mode);
if (!entry_point)
2018-12-23 16:15:32 -05:00
{
2019-01-06 17:24:33 -05:00
throw std::runtime_error("Unable to load binary into memory");
2018-12-23 16:15:32 -05:00
}
2019-01-06 17:24:33 -05:00
game::initialize(mode);
if (!module_loader::post_load()) return 0;
2018-12-23 16:15:32 -05:00
2019-01-06 17:24:33 -05:00
premature_shutdown = false;
}
catch (std::exception& e)
{
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
return 1;
}
2018-12-26 10:28:16 -05:00
}
2018-12-23 12:25:22 -05:00
2018-12-23 16:15:32 -05:00
return entry_point();
2018-12-01 09:42:29 -05:00
}