Skip to content
This repository was archived by the owner on Jun 27, 2025. It is now read-only.

Commit cc4d68e

Browse files
committed
finally proper solution to the startup issue!
1 parent 10db676 commit cc4d68e

File tree

2 files changed

+91
-136
lines changed

2 files changed

+91
-136
lines changed

src/main/origin_client_dll_patches.cpp

Lines changed: 88 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -56,29 +56,113 @@ void*(__cdecl* readSetting_org)(void*, void*, int, void*);
5656
void* __cdecl readSetting_hook(void* out_qv, void* setting, int a3, void* a4)
5757
{
5858
static auto QVariant_QVariant_from_bool = GetExport<void*(__thiscall*)(void*, bool)>(Qt5Core, "??0QVariant@@QAE@_N@Z");
59+
static auto QVariant_QVariant_from_cchar = GetExport<void*(__thiscall*)(void*, const char*)>(Qt5Core, "??0QVariant@@QAE@PBD@Z");
60+
static auto QVariant_destroy = GetExport<void*(__thiscall*)(void*)>(Qt5Core, "??1QVariant@@QAE@XZ");
61+
5962
static auto SETTING_MigrationDisabled = GetExport<void*>(OriginClient, "?SETTING_MigrationDisabled@Services@Origin@@3VSetting@12@A"); // non-const symbol
6063
if (!SETTING_MigrationDisabled)
6164
SETTING_MigrationDisabled = GetExport<void*>(OriginClient, "?SETTING_MigrationDisabled@Services@Origin@@3VSetting@12@B"); // const symbol
65+
static auto SETTING_REMEMBER_ME_PROD = GetExport<void*>(OriginClient, "?SETTING_REMEMBER_ME_PROD@Services@Origin@@3VSetting@12@A"); // non-const symbol
66+
if (!SETTING_REMEMBER_ME_PROD)
67+
SETTING_REMEMBER_ME_PROD = GetExport<void*>(OriginClient, "?SETTING_REMEMBER_ME_PROD@Services@Origin@@3VSetting@12@B"); // const symbol
68+
69+
static auto Origin_Services_Variant_operator_QString = GetExport<void* (__thiscall*)(void*, void*)>(OriginClient, "??BVariant@Services@Origin@@QBE?AVQString@@XZ");
70+
static auto QString_destroy = GetExport<void(__thiscall*)(void*)>(Qt5Core, "??1QString@@QAE@XZ");
71+
static auto QString_toStdString = GetExport<void* (__thiscall*)(void*, std::string*)>(Qt5Core, "?toStdString@QString@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ");
6272

6373
static bool didWarnAboutMissingAlready = false;
64-
if (!didWarnAboutMissingAlready && (!QVariant_QVariant_from_bool || !SETTING_MigrationDisabled)) [[unlikely]]
74+
if (!didWarnAboutMissingAlready && (!QVariant_QVariant_from_bool || !QVariant_QVariant_from_cchar || !QVariant_destroy
75+
|| !SETTING_MigrationDisabled || !SETTING_REMEMBER_ME_PROD || !Origin_Services_Variant_operator_QString || !QString_destroy
76+
|| !QString_toStdString)) [[unlikely]]
6577
{
6678
didWarnAboutMissingAlready = true;
6779
MessageBoxA(nullptr, ("Error in Origin::Services::readSetting: one of the exports could not have been resolved, we may crash\n"
68-
"\nQVariant_QVariant_from_bool: " + std::to_string(uintptr_t(QVariant_QVariant_from_bool))
69-
+ "\nSETTING_MigrationDisabled: " + std::to_string(uintptr_t(SETTING_MigrationDisabled))
80+
"\nQVariant_QVariant_from_bool: " + std::format("{:#010x}", uintptr_t(QVariant_QVariant_from_bool))
81+
+ "\nQVariant_QVariant_from_cchar: " + std::format("{:#010x}", uintptr_t(QVariant_QVariant_from_cchar))
82+
+ "\nQVariant_destroy: " + std::format("{:#010x}", uintptr_t(QVariant_destroy))
83+
+ "\nSETTING_MigrationDisabled: " + std::format("{:#010x}", uintptr_t(SETTING_MigrationDisabled))
84+
+ "\nSETTING_REMEMBER_ME_PROD: " + std::format("{:#010x}", uintptr_t(SETTING_REMEMBER_ME_PROD))
85+
+ "\nOrigin_Services_Variant_operator_QString: " + std::format("{:#010x}", uintptr_t(Origin_Services_Variant_operator_QString))
86+
+ "\nQString_destroy: " + std::format("{:#010x}", uintptr_t(QString_destroy))
87+
+ "\nQString_toStdString: " + std::format("{:#010x}", uintptr_t(QString_toStdString))
7088
).c_str(),
7189
ERROR_MSGBOX_CAPTION, MB_ICONERROR);
7290
}
91+
92+
void* ret = readSetting_org(out_qv, setting, a3, a4);
93+
94+
if (IsDebuggerPresent())
95+
{
96+
97+
if (Origin_Services_Variant_operator_QString && QString_destroy && QString_toStdString)
98+
{
99+
char qs[4] = { 0 };
100+
Origin_Services_Variant_operator_QString(ret, qs);
101+
102+
std::string qss;
103+
QString_toStdString(qs, &qss);
104+
105+
std::string setting_name;
106+
QString_toStdString((void*)(uintptr_t(setting) + 8), &setting_name);
107+
OutputDebugStringA(("readSetting: " + setting_name + "=" + qss).c_str());
108+
109+
/*if (setting_name == "RememberMeProd")
110+
{
111+
QVariant_destroy(ret);
112+
static auto QVariant_QVariant_from_cchar = GetExport<void* (__thiscall*)(void*, const char*)>(Qt5Core, "??0QVariant@@QAE@PBD@Z");
113+
QVariant_QVariant_from_cchar(out_qv, "TUU...||accounts.ea.com||2025-03-11T21:21:02Z||/connect");
114+
OutputDebugStringA("overriding!");
115+
}*/
116+
117+
QString_destroy(qs);
118+
}
119+
}
73120

74121
if (setting == SETTING_MigrationDisabled)
75122
{
76123
// override to true
124+
QVariant_destroy(ret);
77125
QVariant_QVariant_from_bool(out_qv, true); // caller will destruct this
78126
return out_qv;
79127
}
128+
129+
if (setting == SETTING_REMEMBER_ME_PROD)
130+
{
131+
OutputDebugStringA("[Origin::Services::readSetting] SETTING_REMEMBER_ME_PROD");
132+
char qs[4] = { 0 };
133+
Origin_Services_Variant_operator_QString(ret, qs);
134+
135+
std::string qss;
136+
QString_toStdString(qs, &qss);
137+
QString_destroy(qs);
138+
//OutputDebugStringA(("[Origin::Services::readSetting] qss: " + qss).c_str());
139+
140+
std::vector<std::string> parts;
141+
for (const auto word : std::views::split(qss, "||"sv))
142+
parts.push_back(std::string{ word.begin(), word.end() });
143+
144+
if (parts.size() >= 2)
145+
{
146+
//OutputDebugStringA(("[Origin::Services::readSetting] parts[1]: " + parts[1]).c_str());
147+
if (parts[1] == ".ea.com")
148+
{
149+
OutputDebugStringA("[Origin::Services::readSetting] Fixing domain name to accounts.ea.com for cookie remid");
150+
parts[1] = "accounts.ea.com";
151+
152+
qss.clear();
153+
for (auto word : parts)
154+
qss += "||" + word;
155+
qss.erase(0, 2);
156+
157+
QVariant_destroy(ret);
158+
QVariant_QVariant_from_cchar(out_qv, qss.c_str()); // caller will destruct this
159+
//OutputDebugStringA(("[Origin::Services::readSetting] final value: " + qss).c_str());
160+
return out_qv;
161+
}
162+
}
163+
}
80164

81-
return readSetting_org(out_qv, setting, a3, a4);
165+
return ret;
82166
}
83167

84168
// Origin::Engine::Content::LocalContent::treatUpdatesAsMandatory
@@ -97,129 +181,6 @@ void __fastcall checkForUpdate_hook(void* thisptr /*ecx*/)
97181
// downloaded upon next Origin launch by thin setup.
98182
}
99183

100-
#if 0
101-
// NOTE: This hook is completely broken, but also not needed...
102-
// QString::compare
103-
bool(__thiscall* qstring_compare_org)(void*, void*, int);
104-
bool __fastcall qstring_compare_hook(void* thisptr /*ecx*/, void* /*edx*/, void* comparee, int a3)
105-
{
106-
if (a3 == 1)
107-
{
108-
static auto QString_startsWith = GetExport<void* (__thiscall*)(void*, void*, int)>(Qt5Core, "?startsWith@QString@@QBE_NABV1@W4CaseSensitivity@Qt@@@Z");
109-
static auto QString_QString = GetExport<void* (__thiscall*)(void*, const char*)>(Qt5Core, "??0QString@@QAE@PBD@Z");
110-
static int ten = 0;
111-
static int twelve = 0;
112-
if (ten == 0) QString_QString(&twelve, "10.5.");
113-
if (twelve == 0) QString_QString(&twelve, "12.");
114-
if (QString_startsWith(comparee, &twelve, 0) && QString_startsWith(thisptr, &ten, 0))
115-
return 0;
116-
}
117-
return qstring_compare_org(thisptr, comparee, a3);
118-
}
119-
#endif
120-
121-
#if 0
122-
// Origin::Client::LoginViewController::init
123-
void(__thiscall* loginViewController_init_org)(void*, DWORD*, /* Origin::Client::AuthenticationJsHelper* */ void*, int);
124-
void __fastcall loginViewController_init_hook(void* thisptr /*ecx*/, void* /*edx*/, DWORD* a2, void* a3, int a4)
125-
{
126-
loginViewController_init_org(thisptr, a2, a3, a4);
127-
////*(bool*)((uintptr_t)thisptr + 166) = true; // make it think we've loaded all cookies already
128-
//*(bool*)((uintptr_t)thisptr + 167) = true; // make it think Trusted Clock is already initialized
129-
loginViewController_init_org(thisptr, a2, a3, a4);
130-
131-
// this does NOT seem to work here!
132-
// Origin::Client::LoginViewController::killSplashScreenAndShowLoginWindow
133-
//static auto killSplashScreenAndShowLoginWindow = GetExport<void(__thiscall*)(void*)>(OriginClient, "?killSplashScreenAndShowLoginWindow@LoginViewController@Client@Origin@@AAEXXZ");
134-
//killSplashScreenAndShowLoginWindow(thisptr);
135-
}
136-
137-
// Origin::Services::TrustedClock::isInitialized
138-
bool(__thiscall* trustedClock_isInitialized_org)(void*);
139-
bool __fastcall trustedClock_isInitialized_hook(void* thisptr /*ecx*/)
140-
{
141-
return true;
142-
}
143-
144-
// Origin::Client::LoginViewController::loadLoginPage
145-
void(__thiscall* loginViewController_loadLoginPage_org)(void*, int);
146-
void __fastcall loginViewController_loadLoginPage_hook(void* thisptr /*ecx*/, void* /*edx*/, int a2)
147-
{
148-
loginViewController_loadLoginPage_org(thisptr, a2);
149-
150-
static auto killSplashScreenAndShowLoginWindow = GetExport<void(__thiscall*)(void*)>(OriginClient, "?killSplashScreenAndShowLoginWindow@LoginViewController@Client@Origin@@AAEXXZ");
151-
152-
static bool didWarnAboutMissingAlready = false;
153-
if (!didWarnAboutMissingAlready && (!killSplashScreenAndShowLoginWindow)) [[unlikely]]
154-
{
155-
didWarnAboutMissingAlready = true;
156-
MessageBoxA(nullptr, "Error in Origin::Client::LoginViewController::loadLoginPage: killSplashScreenAndShowLoginWindow was not found, your Origin client will probably be stuck on splash screen\n"
157-
"\nRight-click Origin icon in your tray and click Open Origin as a workaround.",
158-
ERROR_MSGBOX_CAPTION, MB_ICONERROR);
159-
}
160-
161-
// well it seems someone forgot to call this func in a reasonable place like here
162-
if (killSplashScreenAndShowLoginWindow)
163-
killSplashScreenAndShowLoginWindow(thisptr);
164-
}
165-
#endif
166-
167-
// QWebEngineCookieStore::setCookie
168-
void(__thiscall* QWebEngineCookieStore_setCookie_org)(void*, /* QNetworkCookie */ void*, /* QUrl */ void*);
169-
void __fastcall QWebEngineCookieStore_setCookie_hook(void* thisptr /*ecx*/, void* /*edx*/, void* cookie, void* url)
170-
{
171-
static auto QString_destroy = GetExport<void(__thiscall*)(void*)>(Qt5Core, "??1QString@@QAE@XZ");
172-
static auto QString_QString_from_cchar = GetExport<void* (__thiscall*)(void*, const char*)>(Qt5Core, "??0QString@@QAE@PBD@Z");
173-
static auto QString_toStdString = GetExport<void* (__thiscall*)(void*, std::string*)>(Qt5Core, "?toStdString@QString@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ");
174-
static auto QByteArray_toStdString = GetExport<void* (__thiscall*)(void*, std::string*)>(Qt5Core, "?toStdString@QByteArray@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ");
175-
static auto QByteArray_destroy = GetExport<void* (__thiscall*)(void*)>(Qt5Core, "??1QByteArray@@QAE@XZ");
176-
static auto QNetworkCookie_setDomain = GetExport<void(__thiscall*)(void*, void*)>(Qt5Network, "?setDomain@QNetworkCookie@@QAEXABVQString@@@Z");
177-
static auto QNetworkCookie_domain = GetExport<void(__thiscall*)(void*, void*)>(Qt5Network, "?domain@QNetworkCookie@@QBE?AVQString@@XZ");
178-
static auto QNetworkCookie_name = GetExport<void(__thiscall*)(void*, void*)>(Qt5Network, "?name@QNetworkCookie@@QBE?AVQByteArray@@XZ");
179-
180-
OutputDebugStringA("[QWebEngineCookieStore::setCookie] Howdy");
181-
182-
if (QString_destroy && QString_QString_from_cchar && QString_toStdString && QByteArray_toStdString && QByteArray_destroy && QNetworkCookie_setDomain && QNetworkCookie_domain)
183-
{
184-
char qs_cookie_domain[4] = { 0 };
185-
char qba_cookie_name[4] = { 0 };
186-
std::string cookie_domain;
187-
std::string cookie_name;
188-
189-
QNetworkCookie_domain(cookie, qs_cookie_domain);
190-
QString_toStdString(qs_cookie_domain, &cookie_domain);
191-
192-
QNetworkCookie_name(cookie, qba_cookie_name);
193-
QByteArray_toStdString(qba_cookie_name, &cookie_name);
194-
195-
OutputDebugStringA(("[QWebEngineCookieStore::setCookie] name=" + cookie_name + " domain=" + cookie_domain).c_str());
196-
//__debugbreak();
197-
198-
if (cookie_name == "remid" && cookie_domain == "")
199-
{
200-
OutputDebugStringA("[QWebEngineCookieStore::setCookie] Fixing domain name to accounts.ea.com for cookie remid");
201-
char qs_cookie_domain_new[4] = { 0 };
202-
QString_QString_from_cchar(qs_cookie_domain_new, "accounts.ea.com");
203-
QNetworkCookie_setDomain(cookie, qs_cookie_domain_new);
204-
QString_destroy(qs_cookie_domain_new);
205-
}
206-
207-
QString_destroy(qs_cookie_domain);
208-
QByteArray_destroy(qba_cookie_name);
209-
}
210-
else
211-
{
212-
static bool didWarnAboutMissingAlready = false;
213-
if (!didWarnAboutMissingAlready) [[unlikely]]
214-
{
215-
didWarnAboutMissingAlready = true;
216-
MessageBoxA(nullptr, "Error in QWebEngineCookieStore::setCookie: one of the exports could not have been resolved!", ERROR_MSGBOX_CAPTION, MB_ICONERROR);
217-
}
218-
}
219-
220-
QWebEngineCookieStore_setCookie_org(thisptr, cookie, url);
221-
}
222-
223184
void DoOriginClientDllPatches()
224185
{
225186
{
@@ -259,13 +220,4 @@ void DoOriginClientDllPatches()
259220

260221
// This checks for update to nag the user in the UI and auto-download the update zip, we don't ever need that
261222
CreateHookNamed("OriginClient", "?checkForUpdate@SelfUpdateService@Services@Origin@@QAEXXZ", checkForUpdate_hook, reinterpret_cast<LPVOID*>(&checkForUpdate_org));
262-
//CreateHookNamed("Qt5Core", "?compare@QString@@QBEHABV1@W4CaseSensitivity@Qt@@@Z", qstring_compare_hook, reinterpret_cast<LPVOID*>(&qstring_compare_org));
263-
264-
// Patches around broken login screen due to missing cookie (hopefully it's a temporary thing?)
265-
///CreateHookNamed("OriginClient", "?init@LoginViewController@Client@Origin@@QAEXABW4StartupState@@W4IconType@OriginBanner@UIToolkit@3@ABVQString@@@Z", loginViewController_init_hook, reinterpret_cast<LPVOID*>(&loginViewController_init_org));
266-
//CreateHookNamed("OriginClient", "?isInitialized@TrustedClock@Services@Origin@@QBE_NXZ", trustedClock_isInitialized_hook, reinterpret_cast<LPVOID*>(&trustedClock_isInitialized_org));
267-
///CreateHookNamed("OriginClient", "?loadLoginPage@LoginViewController@Client@Origin@@IAEX_N@Z", loginViewController_loadLoginPage_hook, reinterpret_cast<LPVOID*>(&loginViewController_loadLoginPage_org));
268-
269-
//
270-
//CreateHookNamed("Qt5WebEngineCore", "?setCookie@QWebEngineCookieStore@@QAEXABVQNetworkCookie@@ABVQUrl@@@Z", QWebEngineCookieStore_setCookie_hook, reinterpret_cast<LPVOID*>(&QWebEngineCookieStore_setCookie_org));
271223
}

src/main/pch.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
#include <string>
1111
#include <vector>
1212
#include <iterator>
13+
#include <ranges>
1314
#include <regex>
1415
#include <filesystem>
1516
namespace fs = std::filesystem;
1617

18+
using std::operator""sv;
19+
1720
#include <MinHook.h>
1821

1922
#include <silver-bun/memaddr.h>

0 commit comments

Comments
 (0)