Skip to content

Commit

Permalink
small improvements (better document the code, update readme)
Browse files Browse the repository at this point in the history
  • Loading branch information
p0358 committed Jun 24, 2023
1 parent 463ba17 commit 88ec28b
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 20 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions src/loader/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 4 additions & 12 deletions src/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const std::string GetExeName()

void InternalSetup()
{
// Initialize MinHook
MH_Initialize();
MH_SetThreadFreezeMethod(MH_FREEZE_METHOD_FAST_UNDOCUMENTED);

Expand All @@ -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)
{
Expand All @@ -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();
}
9 changes: 7 additions & 2 deletions src/main/origin_client_dll_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<void*(__thiscall*)(void*)>(Qt5Core, "??0QJsonObject@@QAE@XZ");
static auto QJsonObject_QJsonObject_destruct = GetExport<void*(__thiscall*)(void*)>(Qt5Core, "??1QJsonObject@@QAE@XZ");
static auto QJsonObject_toVariantMap = GetExport<void*(__thiscall*)(void*, void*)>(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);
Expand All @@ -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<const char* (*)()>(OriginClient, "OriginClientVersion")();
std::string originClientVersionStr{ originClientVersion };
std::regex versionRegex{ "^10\\.5\\.([0-9]+)\\.[0-9]+$" };
Expand All @@ -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<LPVOID*>(&findUserMigrationTimePeriod_org));
}
2 changes: 1 addition & 1 deletion src/main/origin_client_service_exe_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

void DoOriginClientServiceExePatches()
{

// no patches required in this exe currently
}
8 changes: 8 additions & 0 deletions src/main/origin_exe_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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<LPVOID*>(&LoadLibraryW_org));
}

0 comments on commit 88ec28b

Please sign in to comment.