From 88ec28bfa6d369c4c9ad7ad50e45d71f621ad112 Mon Sep 17 00:00:00 2001 From: p0358 Date: Sat, 24 Jun 2023 04:18:37 +0200 Subject: [PATCH] small improvements (better document the code, update readme) --- README.md | 13 ++++++++++--- src/loader/main.cpp | 4 ++-- src/main/main.cpp | 16 ++++------------ src/main/origin_client_dll_patches.cpp | 9 +++++++-- src/main/origin_client_service_exe_patches.cpp | 2 +- src/main/origin_exe_patches.cpp | 8 ++++++++ 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6f682df..f465022 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # "Fuck off EA App" +[![Github All Releases](https://img.shields.io/github/downloads/p0358/Fuck_off_EA_App/total.svg)](https://github.com/p0358/Fuck_off_EA_App/releases) + A small project to patch the EA Origin app and keep it running, avoiding the nags to upgrade to the new EA App. If you start up Origin app and see a prompt telling you to install EA App, you've come to the right place. @@ -51,20 +53,25 @@ You don't need to either add or remove anything from that file anymore when usin Our custom DLL (named `version.dll`) is loaded by Origin during its startup, after you insert it under its installation directory. It conducts function hooks and patches that prevent the upgrade notice from appearing. You can study the code for more details. -### Is it safe? +### How does the `"Pretend EA App is installed"` option work? -Yeah, the thing is open-sourced, and the actual DLL and installer in Releases section is built by GitHub Actions CI. You can always compile it yourself too if so you wish... +EA games on Steam contain installer script, which instructs the Steam to check whether EA App is already installed by checking the system registry for key `HKEY_LOCAL_MACHINE\SOFTWARE\Electronic Arts\EA Desktop\InstallSuccessful` with string value of `true`, skipping the launch of the installer if it's present. So ticking the checkbox simply creates that key and fulfills that condition. There's no harm done if you have actually installed the EA App already and accidentally checked it either. ### What if EA breaks something again? Will this keep working forever? Given they already broke the older workarounds before a few times, probably not forever. In any case, follow this repository for updates (*star the project ;)*) -- if the workaround stops working, I will probably try to update it to work again in the future -- contributions are also welcome. +### Is it safe? + +Yeah, the thing is open-sourced, and the actual DLL and installer in Releases section is built by GitHub Actions CI. You can always compile it yourself too if so you wish... + ### How do I compile it myself? 1. Clone the repository with git 2. Run `generate.bat` -3. Open the .sln file from `build` folder in Visual Studio +3. Open the .sln file from `build` folder in Visual Studio 2022 4. Compile the solution +5. Copy `version.dll` from `.\build\bin\Win32-Release\` into `C:\Program Files (x86)\Origin` ## Third-party libraries used diff --git a/src/loader/main.cpp b/src/loader/main.cpp index 53b7c47..d1bc6f7 100644 --- a/src/loader/main.cpp +++ b/src/loader/main.cpp @@ -79,8 +79,8 @@ void LoadProxiedLibrary() void Init() { - LoadProxiedLibrary(); - FuckOffEAAppSetup(); + LoadProxiedLibrary(); // loads original `version.dll` to proxy the exported functions back to it + FuckOffEAAppSetup(); // that function is located in the "Main" project } BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) diff --git a/src/main/main.cpp b/src/main/main.cpp index e7f4fe7..ac722dc 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -43,6 +43,7 @@ const std::string GetExeName() void InternalSetup() { + // Initialize MinHook MH_Initialize(); MH_SetThreadFreezeMethod(MH_FREEZE_METHOD_FAST_UNDOCUMENTED); @@ -51,26 +52,16 @@ void InternalSetup() bool isOriginExe = exe_name == "Origin.exe"; bool isOriginClientServiceExe = exe_name == "OriginClientService.exe"; - /*if (isOriginExe) - { - // preload the OriginClient.dll - if (!LoadLibraryW((exe_path / L"OriginClient.dll").wstring().c_str())) - MessageBoxA(nullptr, "Failed preloading OriginClient.dll", ERROR_MSGBOX_CAPTION, MB_ICONERROR); - }*/ - OriginExe = CModule("Origin.exe", uintptr_t(GetModuleHandleA(nullptr))); OriginClientServiceExe = CModule("OriginClientService.exe", uintptr_t(GetModuleHandleA(nullptr))); - //OriginClient = CModule("OriginClient.dll"); OriginExeAdr = CMemory(OriginExe.GetModuleBase()); OriginClientServiceExeAdr = CMemory(OriginClientServiceExe.GetModuleBase()); - //OriginClientAdr = CMemory(OriginClient.GetModuleBase()); if (isOriginExe) { // Main Origin.exe program - DoOriginExePatches(); - //DoOriginClientDllPatches(); + DoOriginExePatches(); // this function will set up a hook to wait for OriginClient.dll to be loaded } else if (isOriginClientServiceExe) { @@ -81,12 +72,13 @@ void InternalSetup() // WARN: loaded into unrecognized program! } + // Enable all queued hooks MH_STATUS result; if ((result = MH_EnableHook(MH_ALL_HOOKS)) != MH_OK) MessageBoxA(nullptr, ("MH_EnableHook(MH_ALL_HOOKS) error: " + std::to_string(result)).c_str(), ERROR_MSGBOX_CAPTION, MB_ICONERROR); } -extern "C" void FuckOffEAAppSetup() +extern "C" void FuckOffEAAppSetup() // called from Loader project { InternalSetup(); } diff --git a/src/main/origin_client_dll_patches.cpp b/src/main/origin_client_dll_patches.cpp index 57d5f20..664e8a2 100644 --- a/src/main/origin_client_dll_patches.cpp +++ b/src/main/origin_client_dll_patches.cpp @@ -8,10 +8,12 @@ void*(__stdcall *findUserMigrationTimePeriod_org)(void*); void* __stdcall findUserMigrationTimePeriod_hook(void* a1) { // just return an empty Qt JSON object - char json[12] = { 0 }; static auto QJsonObject_QJsonObject = GetExport(Qt5Core, "??0QJsonObject@@QAE@XZ"); static auto QJsonObject_QJsonObject_destruct = GetExport(Qt5Core, "??1QJsonObject@@QAE@XZ"); static auto QJsonObject_toVariantMap = GetExport(Qt5Core, "?toVariantMap@QJsonObject@@QBE?AV?$QMap@VQString@@VQVariant@@@@XZ"); + if (!QJsonObject_QJsonObject || !QJsonObject_QJsonObject_destruct || !QJsonObject_toVariantMap) + MessageBoxA(nullptr, "Error in findUserMigrationTimePeriod: one of the functions could not have been resolved, we will crash", ERROR_MSGBOX_CAPTION, MB_ICONERROR); + char json[12] = { 0 }; QJsonObject_QJsonObject(&json); QJsonObject_toVariantMap(&json, a1); QJsonObject_QJsonObject_destruct(&json); @@ -21,7 +23,9 @@ void* __stdcall findUserMigrationTimePeriod_hook(void* a1) void DoOriginClientDllPatches() { { - // Spoof Origin version to '10.5.122.52971' if we're older + // Spoof Origin version to '10.5.122.52971' if we're older, + // this works around the "Please use EA App to continue" message, which appears as a result of user-agent check in JavaScript. + // The `OriginClientVersion` function returns a shared pointer to the version string that is also used while constructing said user agent. auto originClientVersion = GetExport(OriginClient, "OriginClientVersion")(); std::string originClientVersionStr{ originClientVersion }; std::regex versionRegex{ "^10\\.5\\.([0-9]+)\\.[0-9]+$" }; @@ -43,5 +47,6 @@ void DoOriginClientDllPatches() } } + // The function hooked below is used by the primary EA App migration screen, to determine whether said screen should be displayed CreateHookNamed("OriginClient", "?findUserMigrationTimePeriod@ClientSettingsProxy@JsInterface@Client@Origin@@QAE?AV?$QMap@VQString@@VQVariant@@@@XZ", findUserMigrationTimePeriod_hook, reinterpret_cast(&findUserMigrationTimePeriod_org)); } diff --git a/src/main/origin_client_service_exe_patches.cpp b/src/main/origin_client_service_exe_patches.cpp index 22932b4..ddf7983 100644 --- a/src/main/origin_client_service_exe_patches.cpp +++ b/src/main/origin_client_service_exe_patches.cpp @@ -5,5 +5,5 @@ void DoOriginClientServiceExePatches() { - + // no patches required in this exe currently } diff --git a/src/main/origin_exe_patches.cpp b/src/main/origin_exe_patches.cpp index 9a65788..408caac 100644 --- a/src/main/origin_exe_patches.cpp +++ b/src/main/origin_exe_patches.cpp @@ -13,11 +13,16 @@ HMODULE WINAPI LoadLibraryW_Hook(LPCWSTR lpLibFileName) { OriginClient = CModule("OriginClient.dll"); OriginClientAdr = CMemory(OriginClient.GetModuleBase()); + + // statically imported by OriginClient.dll Qt5Core = CModule("Qt5Core.dll"); + DoOriginClientDllPatches(); + MH_STATUS result; if ((result = MH_EnableHook(MH_ALL_HOOKS)) != MH_OK) MessageBoxA(nullptr, ("MH_EnableHook(MH_ALL_HOOKS) error: " + std::to_string(result)).c_str(), ERROR_MSGBOX_CAPTION, MB_ICONERROR); + didDoOriginClientDllPatches = true; } @@ -26,5 +31,8 @@ HMODULE WINAPI LoadLibraryW_Hook(LPCWSTR lpLibFileName) void DoOriginExePatches() { + // We hook LoadLibraryW to monitor for when OriginClient.dll is actually loaded, as it's loaded dynamically. + // It is worth noting that it's not loaded right away, instead Origin.exe itself first starts the updater, which + // then starts Origin.exe again, to then finally actually start up, making this solution necessary. CreateHookNamed("kernel32", "LoadLibraryW", LoadLibraryW_Hook, reinterpret_cast(&LoadLibraryW_org)); }