Fix stuff
This commit is contained in:
@ -1,121 +1,121 @@
|
||||
#include <std_include.hpp>
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/compression.hpp"
|
||||
|
||||
#define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
std::string load_resource(const int id)
|
||||
{
|
||||
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||
if (!res) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, res);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
|
||||
}
|
||||
|
||||
std::string load_delta(const launcher::mode mode)
|
||||
{
|
||||
if (mode == launcher::mode::singleplayer)
|
||||
{
|
||||
return load_resource(BINARY_SP);
|
||||
}
|
||||
|
||||
if (mode == launcher::mode::multiplayer)
|
||||
{
|
||||
return load_resource(BINARY_MP);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string load_base(const bool verify = true)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file("iw5mp_server.exe", &data))
|
||||
{
|
||||
throw std::runtime_error("Unable to load iw5mp_server.exe");
|
||||
}
|
||||
|
||||
if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH)
|
||||
{
|
||||
throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void create_for_file(const std::string& file, const std::string& base)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(file, &data))
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load file %s!", file.data()));
|
||||
}
|
||||
|
||||
const auto new_data = reinterpret_cast<const unsigned char*>(data.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
|
||||
std::vector<unsigned char> diff;
|
||||
create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff);
|
||||
|
||||
const unsigned long long size = data.size();
|
||||
|
||||
std::string result(reinterpret_cast<char*>(diff.data()), diff.size());
|
||||
result.append(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
result = utils::compression::zlib::compress(result);
|
||||
|
||||
utils::io::write_file(file + ".diff", result);
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
const auto base = load_base(false);
|
||||
|
||||
utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true));
|
||||
|
||||
create_for_file("iw5sp.exe", base);
|
||||
create_for_file("iw5mp.exe", base);
|
||||
}
|
||||
|
||||
std::string build_binary(const std::string& base, const std::string& diff)
|
||||
{
|
||||
const auto* size = reinterpret_cast<const unsigned long long*>(diff.data() + diff.size() - sizeof(unsigned long
|
||||
long));
|
||||
|
||||
std::string binary;
|
||||
binary.resize(size_t(*size));
|
||||
|
||||
const auto new_data = reinterpret_cast<unsigned char*>(binary.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
const auto diff_data = reinterpret_cast<const unsigned char*>(diff.data());
|
||||
|
||||
if (patch(new_data, new_data + binary.size(), old_data, old_data + base.size(), diff_data,
|
||||
diff_data + diff.size() - sizeof(*size)) == hpatch_FALSE || binary.empty())
|
||||
{
|
||||
throw std::runtime_error("Unable to create binary from patch!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
std::string load(const launcher::mode mode)
|
||||
{
|
||||
auto base = load_base();
|
||||
if (mode == launcher::mode::server)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
auto delta = load_delta(mode);
|
||||
delta = utils::compression::zlib::decompress(delta);
|
||||
return build_binary(base, delta);
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/io.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/compression.hpp"
|
||||
|
||||
#define DEDI_HASH "F271C305117B79242E254E9F64BD5AA2993CAC8E57975243EBD44CD576418D20"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
std::string load_resource(const int id)
|
||||
{
|
||||
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||
if (!res) return {};
|
||||
|
||||
const auto handle = LoadResource(nullptr, res);
|
||||
if (!handle) return {};
|
||||
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
|
||||
}
|
||||
|
||||
std::string load_delta(const launcher::mode mode)
|
||||
{
|
||||
if (mode == launcher::mode::singleplayer)
|
||||
{
|
||||
return load_resource(BINARY_SP);
|
||||
}
|
||||
|
||||
if (mode == launcher::mode::multiplayer)
|
||||
{
|
||||
return load_resource(BINARY_MP);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string load_base(const bool verify = true)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file("iw5mp_server.exe", &data))
|
||||
{
|
||||
throw std::runtime_error("Unable to load iw5mp_server.exe");
|
||||
}
|
||||
|
||||
if (verify && utils::cryptography::sha256::compute(data, true) != DEDI_HASH)
|
||||
{
|
||||
throw std::runtime_error("Your iw5mp_server.exe is incompatible with this client.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void create_for_file(const std::string& file, const std::string& base)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(file, &data))
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load file %s!", file.data()));
|
||||
}
|
||||
|
||||
const auto new_data = reinterpret_cast<const unsigned char*>(data.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
|
||||
std::vector<unsigned char> diff;
|
||||
create_diff(new_data, new_data + data.size(), old_data, old_data + base.size(), diff);
|
||||
|
||||
const unsigned long long size = data.size();
|
||||
|
||||
std::string result(reinterpret_cast<char*>(diff.data()), diff.size());
|
||||
result.append(reinterpret_cast<const char*>(&size), sizeof(size));
|
||||
result = utils::compression::zlib::compress(result);
|
||||
|
||||
utils::io::write_file(file + ".diff", result);
|
||||
}
|
||||
|
||||
void create()
|
||||
{
|
||||
const auto base = load_base(false);
|
||||
|
||||
utils::io::write_file("hash.txt", utils::cryptography::sha256::compute(base, true));
|
||||
|
||||
create_for_file("iw5sp.exe", base);
|
||||
create_for_file("iw5mp.exe", base);
|
||||
}
|
||||
|
||||
std::string build_binary(const std::string& base, const std::string& diff)
|
||||
{
|
||||
const auto* size = reinterpret_cast<const unsigned long long*>(diff.data() + diff.size() - sizeof(unsigned long
|
||||
long));
|
||||
|
||||
std::string binary;
|
||||
binary.resize(size_t(*size));
|
||||
|
||||
const auto new_data = reinterpret_cast<unsigned char*>(binary.data());
|
||||
const auto old_data = reinterpret_cast<const unsigned char*>(base.data());
|
||||
const auto diff_data = reinterpret_cast<const unsigned char*>(diff.data());
|
||||
|
||||
if (patch(new_data, new_data + binary.size(), old_data, old_data + base.size(), diff_data,
|
||||
diff_data + diff.size() - sizeof(*size)) == hpatch_FALSE || binary.empty())
|
||||
{
|
||||
throw std::runtime_error("Unable to create binary from patch!");
|
||||
}
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
std::string load(const launcher::mode mode)
|
||||
{
|
||||
auto base = load_base();
|
||||
if (mode == launcher::mode::server)
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
auto delta = load_delta(mode);
|
||||
delta = utils::compression::zlib::decompress(delta);
|
||||
return build_binary(base, delta);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
void create();
|
||||
std::string load(launcher::mode mode);
|
||||
}
|
||||
#pragma once
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
namespace binary_loader
|
||||
{
|
||||
void create();
|
||||
std::string load(launcher::mode mode);
|
||||
}
|
||||
|
@ -1,165 +1,165 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader.hpp"
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
loader::loader(const launcher::mode mode) : mode_(mode)
|
||||
{
|
||||
}
|
||||
|
||||
FARPROC loader::load(const utils::nt::module& module) const
|
||||
{
|
||||
const auto buffer = binary_loader::load(this->mode_);
|
||||
if (buffer.empty()) return nullptr;
|
||||
|
||||
utils::nt::module source(HMODULE(buffer.data()));
|
||||
if (!source) return nullptr;
|
||||
|
||||
this->load_sections(module, source);
|
||||
this->load_imports(module, source);
|
||||
|
||||
if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||
{
|
||||
const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||
*reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index;
|
||||
|
||||
if (tls_size > TLS_PAYLOAD_SIZE)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va(
|
||||
"TLS data is of size 0x%X, but we have only reserved 0x%X bytes!", tls_size, TLS_PAYLOAD_SIZE));
|
||||
}
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||
&old_protect);
|
||||
|
||||
const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
}
|
||||
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
|
||||
module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source
|
||||
.get_optional_header()->DataDirectory[
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
std::memmove(module.get_nt_headers(), source.get_nt_headers(),
|
||||
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof(
|
||||
IMAGE_SECTION_HEADER))));
|
||||
|
||||
return FARPROC(module.get_ptr() + source.get_relative_entry_point());
|
||||
}
|
||||
|
||||
void loader::set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver)
|
||||
{
|
||||
this->import_resolver_ = resolver;
|
||||
}
|
||||
|
||||
void loader::load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section)
|
||||
{
|
||||
void* target_ptr = target.get_ptr() + section->VirtualAddress;
|
||||
const void* source_ptr = source.get_ptr() + section->PointerToRawData;
|
||||
|
||||
if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE))
|
||||
{
|
||||
throw std::runtime_error("Section exceeds the binary payload size, please increase it!");
|
||||
}
|
||||
|
||||
if (section->SizeOfRawData > 0)
|
||||
{
|
||||
const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize);
|
||||
std::memmove(target_ptr, source_ptr, size_of_data);
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(target_ptr, size_of_data, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_sections(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
for (auto& section : source.get_section_headers())
|
||||
{
|
||||
this->load_section(target, source, section);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_imports(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
const auto import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||
|
||||
while (descriptor->Name)
|
||||
{
|
||||
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||
|
||||
auto name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->OriginalFirstThunk);
|
||||
auto address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
|
||||
if (!descriptor->OriginalFirstThunk)
|
||||
{
|
||||
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
}
|
||||
|
||||
while (*name_table_entry)
|
||||
{
|
||||
FARPROC function = nullptr;
|
||||
std::string function_name;
|
||||
|
||||
// is this an ordinal-only import?
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)));
|
||||
}
|
||||
|
||||
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
|
||||
if (this->import_resolver_) function = this->import_resolver_(name, function_name);
|
||||
if (!function)
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, function_name.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'",
|
||||
function_name.data(), name.data()));
|
||||
}
|
||||
|
||||
*address_table_entry = reinterpret_cast<uintptr_t>(function);
|
||||
|
||||
name_table_entry++;
|
||||
address_table_entry++;
|
||||
}
|
||||
|
||||
descriptor++;
|
||||
}
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "loader.hpp"
|
||||
#include "binary_loader.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
loader::loader(const launcher::mode mode) : mode_(mode)
|
||||
{
|
||||
}
|
||||
|
||||
FARPROC loader::load(const utils::nt::module& module) const
|
||||
{
|
||||
const auto buffer = binary_loader::load(this->mode_);
|
||||
if (buffer.empty()) return nullptr;
|
||||
|
||||
utils::nt::module source(HMODULE(buffer.data()));
|
||||
if (!source) return nullptr;
|
||||
|
||||
this->load_sections(module, source);
|
||||
this->load_imports(module, source);
|
||||
|
||||
if (source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
|
||||
{
|
||||
const auto target_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + module
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
const auto source_tls = reinterpret_cast<PIMAGE_TLS_DIRECTORY>(module.get_ptr() + source
|
||||
.get_optional_header()
|
||||
->
|
||||
DataDirectory
|
||||
[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
|
||||
|
||||
const auto tls_size = source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData;
|
||||
const auto tls_index = *reinterpret_cast<DWORD*>(target_tls->AddressOfIndex);
|
||||
*reinterpret_cast<DWORD*>(source_tls->AddressOfIndex) = tls_index;
|
||||
|
||||
if (tls_size > TLS_PAYLOAD_SIZE)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va(
|
||||
"TLS data is of size 0x%X, but we have only reserved 0x%X bytes!", tls_size, TLS_PAYLOAD_SIZE));
|
||||
}
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(PVOID(target_tls->StartAddressOfRawData),
|
||||
source_tls->EndAddressOfRawData - source_tls->StartAddressOfRawData, PAGE_READWRITE,
|
||||
&old_protect);
|
||||
|
||||
const auto tls_base = *reinterpret_cast<LPVOID*>(__readfsdword(0x2C) + 4 * tls_index);
|
||||
std::memmove(tls_base, PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
std::memmove(PVOID(target_tls->StartAddressOfRawData), PVOID(source_tls->StartAddressOfRawData), tls_size);
|
||||
}
|
||||
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(module.get_nt_headers(), 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
|
||||
module.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] = source
|
||||
.get_optional_header()->DataDirectory[
|
||||
IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
std::memmove(module.get_nt_headers(), source.get_nt_headers(),
|
||||
sizeof(IMAGE_NT_HEADERS) + (source.get_nt_headers()->FileHeader.NumberOfSections * (sizeof(
|
||||
IMAGE_SECTION_HEADER))));
|
||||
|
||||
return FARPROC(module.get_ptr() + source.get_relative_entry_point());
|
||||
}
|
||||
|
||||
void loader::set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver)
|
||||
{
|
||||
this->import_resolver_ = resolver;
|
||||
}
|
||||
|
||||
void loader::load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section)
|
||||
{
|
||||
void* target_ptr = target.get_ptr() + section->VirtualAddress;
|
||||
const void* source_ptr = source.get_ptr() + section->PointerToRawData;
|
||||
|
||||
if (PBYTE(target_ptr) >= (target.get_ptr() + BINARY_PAYLOAD_SIZE))
|
||||
{
|
||||
throw std::runtime_error("Section exceeds the binary payload size, please increase it!");
|
||||
}
|
||||
|
||||
if (section->SizeOfRawData > 0)
|
||||
{
|
||||
const auto size_of_data = std::min(section->SizeOfRawData, section->Misc.VirtualSize);
|
||||
std::memmove(target_ptr, source_ptr, size_of_data);
|
||||
|
||||
DWORD old_protect;
|
||||
VirtualProtect(target_ptr, size_of_data, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_sections(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
for (auto& section : source.get_section_headers())
|
||||
{
|
||||
this->load_section(target, source, section);
|
||||
}
|
||||
}
|
||||
|
||||
void loader::load_imports(const utils::nt::module& target, const utils::nt::module& source) const
|
||||
{
|
||||
const auto import_directory = &source.get_optional_header()->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
auto descriptor = PIMAGE_IMPORT_DESCRIPTOR(target.get_ptr() + import_directory->VirtualAddress);
|
||||
|
||||
while (descriptor->Name)
|
||||
{
|
||||
std::string name = LPSTR(target.get_ptr() + descriptor->Name);
|
||||
|
||||
auto name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->OriginalFirstThunk);
|
||||
auto address_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
|
||||
if (!descriptor->OriginalFirstThunk)
|
||||
{
|
||||
name_table_entry = reinterpret_cast<uintptr_t*>(target.get_ptr() + descriptor->FirstThunk);
|
||||
}
|
||||
|
||||
while (*name_table_entry)
|
||||
{
|
||||
FARPROC function = nullptr;
|
||||
std::string function_name;
|
||||
|
||||
// is this an ordinal-only import?
|
||||
if (IMAGE_SNAP_BY_ORDINAL(*name_table_entry))
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, MAKEINTRESOURCEA(IMAGE_ORDINAL(*name_table_entry)));
|
||||
}
|
||||
|
||||
function_name = "#" + std::to_string(IMAGE_ORDINAL(*name_table_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto import = PIMAGE_IMPORT_BY_NAME(target.get_ptr() + *name_table_entry);
|
||||
function_name = import->Name;
|
||||
|
||||
if (this->import_resolver_) function = this->import_resolver_(name, function_name);
|
||||
if (!function)
|
||||
{
|
||||
auto module = utils::nt::module::load(name);
|
||||
if (module)
|
||||
{
|
||||
function = GetProcAddress(module, function_name.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("Unable to load import '%s' from module '%s'",
|
||||
function_name.data(), name.data()));
|
||||
}
|
||||
|
||||
*address_table_entry = reinterpret_cast<uintptr_t>(function);
|
||||
|
||||
name_table_entry++;
|
||||
address_table_entry++;
|
||||
}
|
||||
|
||||
descriptor++;
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
#pragma once
|
||||
#include "utils/nt.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
class loader final
|
||||
{
|
||||
public:
|
||||
explicit loader(launcher::mode mode);
|
||||
|
||||
FARPROC load(const utils::nt::module& module) const;
|
||||
|
||||
void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver);
|
||||
|
||||
private:
|
||||
launcher::mode mode_;
|
||||
std::function<FARPROC(const std::string&, const std::string&)> import_resolver_;
|
||||
|
||||
static void load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section);
|
||||
void load_sections(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
void load_imports(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
};
|
||||
#pragma once
|
||||
#include "utils/nt.hpp"
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
class loader final
|
||||
{
|
||||
public:
|
||||
explicit loader(launcher::mode mode);
|
||||
|
||||
FARPROC load(const utils::nt::module& module) const;
|
||||
|
||||
void set_import_resolver(const std::function<FARPROC(const std::string&, const std::string&)>& resolver);
|
||||
|
||||
private:
|
||||
launcher::mode mode_;
|
||||
std::function<FARPROC(const std::string&, const std::string&)> import_resolver_;
|
||||
|
||||
static void load_section(const utils::nt::module& target, const utils::nt::module& source,
|
||||
IMAGE_SECTION_HEADER* section);
|
||||
void load_sections(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
void load_imports(const utils::nt::module& target, const utils::nt::module& source) const;
|
||||
};
|
||||
|
@ -1,100 +1,100 @@
|
||||
#include <std_include.hpp>
|
||||
#include "module_loader.hpp"
|
||||
|
||||
std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr;
|
||||
|
||||
void module_loader::register_module(std::unique_ptr<module>&& module_)
|
||||
{
|
||||
if (!modules_)
|
||||
{
|
||||
modules_ = new std::vector<std::unique_ptr<module>>();
|
||||
atexit(destroy_modules);
|
||||
}
|
||||
|
||||
modules_->push_back(std::move(module_));
|
||||
}
|
||||
|
||||
bool module_loader::post_start()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_start();
|
||||
}
|
||||
}
|
||||
catch(premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool module_loader::post_load()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_load();
|
||||
}
|
||||
}
|
||||
catch (premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void module_loader::pre_destroy()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return;
|
||||
handled = true;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->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();
|
||||
|
||||
if (!modules_) return;
|
||||
|
||||
delete modules_;
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
void module_loader::trigger_premature_shutdown()
|
||||
{
|
||||
throw premature_shutdown_trigger();
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "module_loader.hpp"
|
||||
|
||||
std::vector<std::unique_ptr<module>>* module_loader::modules_ = nullptr;
|
||||
|
||||
void module_loader::register_module(std::unique_ptr<module>&& module_)
|
||||
{
|
||||
if (!modules_)
|
||||
{
|
||||
modules_ = new std::vector<std::unique_ptr<module>>();
|
||||
atexit(destroy_modules);
|
||||
}
|
||||
|
||||
modules_->push_back(std::move(module_));
|
||||
}
|
||||
|
||||
bool module_loader::post_start()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_start();
|
||||
}
|
||||
}
|
||||
catch(premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool module_loader::post_load()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return true;
|
||||
handled = true;
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->post_load();
|
||||
}
|
||||
}
|
||||
catch (premature_shutdown_trigger&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void module_loader::pre_destroy()
|
||||
{
|
||||
static auto handled = false;
|
||||
if (handled || !modules_) return;
|
||||
handled = true;
|
||||
|
||||
for (const auto& module_ : *modules_)
|
||||
{
|
||||
module_->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();
|
||||
|
||||
if (!modules_) return;
|
||||
|
||||
delete modules_;
|
||||
modules_ = nullptr;
|
||||
}
|
||||
|
||||
void module_loader::trigger_premature_shutdown()
|
||||
{
|
||||
throw premature_shutdown_trigger();
|
||||
}
|
||||
|
Reference in New Issue
Block a user