#include "rem/version_guard.h" #include #include #include #include "rem/log.h" #include "rem/runtime.h" namespace { constexpr std::uint16_t FreelancerV10Build = 1223; bool ReadProductBuild(const char* moduleName, std::uint16_t& build) { HMODULE module = GetModuleHandleA(moduleName); if (!module) module = LoadLibraryA(moduleName); if (!module) { rem::log::ModuleMissing("version_guard", moduleName); return false; } char path[MAX_PATH]{}; if (GetModuleFileNameA(module, path, MAX_PATH) == 0) return false; DWORD ignored = 0; const DWORD infoSize = GetFileVersionInfoSizeA(path, &ignored); if (infoSize == 0) return false; std::vector info(infoSize); if (!GetFileVersionInfoA(path, 0, infoSize, info.data())) return false; VS_FIXEDFILEINFO* fixedInfo = nullptr; UINT fixedInfoSize = 0; if (!VerQueryValueA(info.data(), "\\", reinterpret_cast(&fixedInfo), &fixedInfoSize) || !fixedInfo || fixedInfoSize < sizeof(VS_FIXEDFILEINFO) || fixedInfo->dwSignature != 0xFEEF04BD) { return false; } build = HIWORD(fixedInfo->dwProductVersionLS); return true; } bool CheckModule(const char* moduleName) { std::uint16_t build = 0; if (!ReadProductBuild(moduleName, build)) { char message[256]{}; sprintf_s(message, "could not verify the product version of %s", moduleName); rem::log::Error(message); return false; } if (build <= FreelancerV10Build) { char message[256]{}; sprintf_s(message, "%s build %u is unsupported; Freelancer 1.1 is required", moduleName, build); rem::log::Error(message); return false; } return true; } } namespace rem { bool IsSupportedGameVersion() { const bool commonSupported = CheckModule("common.dll"); const bool serverSupported = CheckModule("server.dll"); if (commonSupported && serverSupported) return true; log::Error("initialization stopped because the Freelancer 1.1 module check failed"); if (IsClient()) { MessageBoxA( nullptr, "rem-essentials requires the official Freelancer 1.1 modules.\n" "No memory patches were applied.", "REM Essentials", MB_OK | MB_ICONERROR); } return false; } }