diff options
-rw-r--r-- | LauncherInjector/main.cpp | 228 | ||||
-rw-r--r-- | LauncherInjector/memalloc.cpp | 11 | ||||
-rw-r--r-- | NorthstarDedicatedTest/dllmain.cpp | 7 | ||||
-rw-r--r-- | NorthstarDedicatedTest/gameutils.cpp | 19 | ||||
-rw-r--r-- | NorthstarDedicatedTest/hooks.cpp | 82 | ||||
-rw-r--r-- | NorthstarDedicatedTest/memalloc.cpp | 30 | ||||
-rw-r--r-- | loader_launcher_proxy/Memory.cpp | 22 | ||||
-rw-r--r-- | loader_launcher_proxy/dllmain.cpp | 76 | ||||
-rw-r--r-- | loader_launcher_proxy/loader_launcher_proxy.vcxproj | 2 |
9 files changed, 313 insertions, 164 deletions
diff --git a/LauncherInjector/main.cpp b/LauncherInjector/main.cpp index 0fd41daf..4f21b200 100644 --- a/LauncherInjector/main.cpp +++ b/LauncherInjector/main.cpp @@ -16,6 +16,7 @@ extern "C" { HMODULE hLauncherModule; HMODULE hHookModule; +HMODULE hTier0Module; wchar_t exePath[4096]; wchar_t buffer[8196]; @@ -68,144 +69,147 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* char text[2048]; std::string message = std::system_category().message(dwMessageId); sprintf_s(text, "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs\n\nMake sure you followed the Northstar installation instructions carefully.", libName, location, dwMessageId, message.c_str()); - MessageBoxA(GetForegroundWindow(), text, "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Error", 0); } -int main(int argc, char* argv[]) { - - // checked to avoid starting origin, Northstar.dll will check for -dedicated as well on its own - bool isDedicated = false; - for (int i = 0; i < argc; i++) - if (!strcmp(argv[i], "-dedicated")) - isDedicated = true; +void EnsureOriginStarted() +{ + if (GetProcessByName(L"Origin.exe") || GetProcessByName(L"EADesktop.exe")) + return; // already started - bool noOriginStartup = false; - for (int i = 0; i < argc; i++) - if (!strcmp(argv[i], "-noOriginStartup")) - noOriginStartup = true; + // unpacked exe will crash if origin isn't open on launch, so launch it + // get origin path from registry, code here is reversed from OriginSDK.dll + HKEY key; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Origin", 0, KEY_READ, &key) != ERROR_SUCCESS) + { + MessageBoxA(0, "Error: failed reading origin path!", "", MB_OK); + return; + } - if (!isDedicated && !GetProcessByName(L"Origin.exe") && !GetProcessByName(L"EADesktop.exe") && !noOriginStartup) + char originPath[520]; + DWORD originPathLength = 520; + if (RegQueryValueExA(key, "ClientPath", 0, 0, (LPBYTE)&originPath, &originPathLength) != ERROR_SUCCESS) { - // unpacked exe will crash if origin isn't open on launch, so launch it - // get origin path from registry, code here is reversed from OriginSDK.dll - HKEY key; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Origin", 0, KEY_READ, &key) != ERROR_SUCCESS) - { - MessageBoxA(0, "Error: failed reading origin path!", "", MB_OK); - return 1; - } + MessageBoxA(0, "Error: failed reading origin path!", "", MB_OK); + return; + } - char originPath[520]; - DWORD originPathLength = 520; - if (RegQueryValueExA(key, "ClientPath", 0, 0, (LPBYTE)&originPath, &originPathLength) != ERROR_SUCCESS) - { - MessageBoxA(0, "Error: failed reading origin path!", "", MB_OK); - return 1; - } + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + CreateProcessA(originPath, (char*)"", NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, (LPSTARTUPINFOA)&si, &pi); - PROCESS_INFORMATION pi; - memset(&pi, 0, sizeof(pi)); - STARTUPINFO si; - memset(&si, 0, sizeof(si)); - CreateProcessA(originPath, (char*)"", NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP, NULL, NULL, (LPSTARTUPINFOA)&si, &pi); + printf("[*] Waiting for Origin...\n"); - // wait for origin to be ready, this process is created when origin is ready enough to launch game without any errors - while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe")) - Sleep(200); + // wait for origin to be ready, this process is created when origin is ready enough to launch game without any errors + while (!GetProcessByName(L"OriginClientService.exe") && !GetProcessByName(L"EADesktop.exe")) + Sleep(200); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +} -#if 0 - // TODO: MOVE TO Northstar.dll itself and inject in some place - // for example hook GetCommandLineA() before real LauncherMain gets called (ie. during InitialiseNorthstar) - // GetCommandLineA() is always used, the parameters passed to LauncherMain are basically ignored - // get cmdline args from file - std::wstring args; - std::ifstream cmdlineArgFile; +void PrependPath() +{ + wchar_t* pPath; + size_t len; + errno_t err = _wdupenv_s(&pPath, &len, L"PATH"); + if (!err) + { + swprintf_s(buffer, L"PATH=%s\\bin\\x64_retail\\;%s", exePath, pPath); + auto result = _wputenv(buffer); + if (result == -1) + { + MessageBoxW(GetForegroundWindow(), L"Warning: could not prepend the current directory to app's PATH environment variable. Something may break because of that.", L"Northstar Launcher Warning", 0); + } + //free(pPath); + } + else + { + MessageBoxW(GetForegroundWindow(), L"Warning: could not get current PATH environment variable in order to prepend the current directory to it. Something may break because of that.", L"Northstar Launcher Warning", 0); + } +} - args.append(L" "); +bool ShouldLoadNorthstar(int argc, char* argv[]) +{ + bool loadNorthstar = true; for (int i = 0; i < argc; i++) - { - std::string str = argv[i]; + if (!strcmp(argv[i], "-vanilla")) + loadNorthstar = false; - args.append(std::wstring(str.begin(), str.end())); - args.append(L" "); - } + if (!loadNorthstar) + return loadNorthstar; - if (!isDedi) - cmdlineArgFile = std::ifstream("ns_startup_args.txt"); - else - cmdlineArgFile = std::ifstream("ns_startup_args_dedi.txt"); + auto runNorthstarFile = std::ifstream("run_northstar.txt"); + if (runNorthstarFile) + { + std::stringstream runNorthstarFileBuffer; + runNorthstarFileBuffer << runNorthstarFile.rdbuf(); + runNorthstarFile.close(); + if (runNorthstarFileBuffer.str()._Starts_with("0")) + loadNorthstar = false; + } + return loadNorthstar; +} - if (cmdlineArgFile) +bool LoadNorthstar() +{ + FARPROC Hook_Init = nullptr; { - std::stringstream argBuffer; - argBuffer << cmdlineArgFile.rdbuf(); - cmdlineArgFile.close(); - - std::string str = argBuffer.str(); - args.append(std::wstring(str.begin(), str.end())); + swprintf_s(buffer, L"%s\\Northstar.dll", exePath); + hHookModule = LoadLibraryExW(buffer, 0i64, 8u); + if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar"); + if (!hHookModule || Hook_Init == nullptr) + { + LibraryLoadError(GetLastError(), L"Northstar.dll", buffer); + return false; + } } - //if (isDedicated) - // // copy -dedicated into args if we have it in commandline args - // args.append(L" -dedicated"); -#endif + ((bool (*)()) Hook_Init)(); + return true; +} - // +int main(int argc, char* argv[]) { - bool loadNorthstar = true; + // checked to avoid starting origin, Northstar.dll will check for -dedicated as well on its own + bool isDedicated = false; for (int i = 0; i < argc; i++) - if (!strcmp(argv[i], "-vanilla")) - loadNorthstar = false; + if (!strcmp(argv[i], "-dedicated")) + isDedicated = true; + + bool noOriginStartup = false; + for (int i = 0; i < argc; i++) + if (!strcmp(argv[i], "-noOriginStartup")) + noOriginStartup = true; + + if (!isDedicated && !noOriginStartup) + { + EnsureOriginStarted(); + } { if (!GetExePathWide(exePath, 4096)) { - MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Northstar Launcher Error", 0); return 1; } - { - wchar_t* pPath; - size_t len; - errno_t err = _wdupenv_s(&pPath, &len, L"PATH"); - if (!err) - { - swprintf_s(buffer, L"PATH=%s\\bin\\x64_retail\\;%s", exePath, pPath); - auto result = _wputenv(buffer); - if (result == -1) - { - MessageBoxW(GetForegroundWindow(), L"Warning: could not prepend the current directory to app's PATH environment variable. Something may break because of that.", L"Launcher Warning", 0); - } - free(pPath); - } - else - { - MessageBoxW(GetForegroundWindow(), L"Warning: could not get current PATH environment variable in order to prepend the current directory to it. Something may break because of that.", L"Launcher Warning", 0); - } - } + PrependPath(); + bool loadNorthstar = ShouldLoadNorthstar(argc, argv); if (loadNorthstar) { - FARPROC Hook_Init = nullptr; - { - swprintf_s(buffer, L"%s\\Northstar.dll", exePath); - hHookModule = LoadLibraryExW(buffer, 0i64, 8u); - if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar"); - if (!hHookModule || Hook_Init == nullptr) - { - LibraryLoadError(GetLastError(), L"Northstar.dll", buffer); - return 1; - } - } - - ((bool (*)()) Hook_Init)(); + printf("[*] Loading Northstar\n"); + if (!LoadNorthstar()) + return 1; } + else + printf("[*] Going to load the vanilla game\n"); + printf("[*] Loading launcher.dll\n"); swprintf_s(buffer, L"%s\\bin\\x64_retail\\launcher.dll", exePath); hLauncherModule = LoadLibraryExW(buffer, 0i64, 8u); if (!hLauncherModule) @@ -213,12 +217,24 @@ int main(int argc, char* argv[]) { LibraryLoadError(GetLastError(), L"launcher.dll", buffer); return 1; } + + printf("[*] Loading tier0.dll\n"); + // this makes zero sense given tier0.dll is already loaded via imports on launcher.dll, but we do it for full consistency with original launcher exe + // and to also let load callbacks in Northstar work for tier0.dll + swprintf_s(buffer, L"%s\\bin\\x64_retail\\tier0.dll", exePath); + hTier0Module = LoadLibraryW(buffer); + if (!hTier0Module) + { + LibraryLoadError(GetLastError(), L"tier0.dll", buffer); + return 1; + } } + printf("[*] Launching the game...\n"); auto LauncherMain = GetLauncherMain(); if (!LauncherMain) - MessageBoxA(GetForegroundWindow(), "Failed loading launcher.dll.\nThe game cannot continue and has to exit.", "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), "Failed loading launcher.dll.\nThe game cannot continue and has to exit.", "Northstar Launcher Error", 0); //auto result = ((__int64(__fastcall*)())LauncherMain)(); //auto result = ((signed __int64(__fastcall*)(__int64))LauncherMain)(0i64); - return ((int(__fastcall*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(NULL, NULL, NULL, 0); // the parameters aren't really used anyways + return ((int(/*__fastcall*/*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(NULL, NULL, NULL, 0); // the parameters aren't really used anyways }
\ No newline at end of file diff --git a/LauncherInjector/memalloc.cpp b/LauncherInjector/memalloc.cpp index 64bc7b76..1d0f13e6 100644 --- a/LauncherInjector/memalloc.cpp +++ b/LauncherInjector/memalloc.cpp @@ -1,13 +1,14 @@ #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include "memalloc.h" +#include <stdio.h> -HMODULE hTier0Module; +extern HMODULE hTier0Module; IMemAlloc** g_ppMemAllocSingleton; void LoadTier0Handle() { - hTier0Module = GetModuleHandleA("tier0.dll"); + if (!hTier0Module) hTier0Module = GetModuleHandleA("tier0.dll"); if (!hTier0Module) return; g_ppMemAllocSingleton = (IMemAlloc**)GetProcAddress(hTier0Module, "g_pMemAllocSingleton"); @@ -18,10 +19,11 @@ const int STATIC_ALLOC_SIZE = 16384; size_t g_iStaticAllocated = 0; char pStaticAllocBuf[STATIC_ALLOC_SIZE]; -// they should never be used here, except in LibraryLoadError +// they should never be used here, except in LibraryLoadError // haha not true void* malloc(size_t n) { + //printf("NorthstarLauncher malloc: %llu\n", n); // allocate into static buffer if (g_iStaticAllocated + n <= STATIC_ALLOC_SIZE) { @@ -32,7 +34,7 @@ void* malloc(size_t n) else { // try to fallback to g_pMemAllocSingleton - if (!hTier0Module) LoadTier0Handle(); + if (!hTier0Module || !g_ppMemAllocSingleton) LoadTier0Handle(); if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton) return (*g_ppMemAllocSingleton)->m_vtable->Alloc(*g_ppMemAllocSingleton, n); else @@ -42,6 +44,7 @@ void* malloc(size_t n) void free(void* p) { + //printf("NorthstarLauncher free: %p\n", p); // if it was allocated into the static buffer, just do nothing, safest way to deal with it if (p >= pStaticAllocBuf && p <= pStaticAllocBuf + STATIC_ALLOC_SIZE) return; diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index 1aa4bd3b..dfc3afe1 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -70,7 +70,7 @@ bool InitialiseNorthstar() { if (initialised) { - fprintf(stderr, "[WARN] Called InitialiseNorthstar more than once!\n"); + fprintf(stderr, "[info] Called InitialiseNorthstar more than once!\n"); return false; } initialised = true; @@ -81,8 +81,7 @@ bool InitialiseNorthstar() InstallInitialHooks(); InitialiseInterfaceCreationHooks(); - // adding a callback to tier0 won't work for some reason - AddDllLoadCallback("launcher.org.dll", InitialiseTier0GameUtilFunctions); + AddDllLoadCallback("tier0.dll", InitialiseTier0GameUtilFunctions); AddDllLoadCallback("engine.dll", WaitForDebugger); AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions); AddDllLoadCallback("server.dll", InitialiseServerGameUtilFunctions); @@ -91,7 +90,7 @@ bool InitialiseNorthstar() // dedi patches { AddDllLoadCallback("engine.dll", InitialiseDedicated); - AddDllLoadCallback("launcher.org.dll", InitialiseDedicatedOrigin); + AddDllLoadCallback("tier0.dll", InitialiseDedicatedOrigin); AddDllLoadCallback("server.dll", InitialiseDedicatedServerGameDLL); AddDllLoadCallback("materialsystem_dx11.dll", InitialiseDedicatedMaterialSystem); // this fucking sucks, but seemingly we somehow load after rtech_game???? unsure how, but because of this we have to apply patches here, not on rtech_game load diff --git a/NorthstarDedicatedTest/gameutils.cpp b/NorthstarDedicatedTest/gameutils.cpp index 97011059..3e62037c 100644 --- a/NorthstarDedicatedTest/gameutils.cpp +++ b/NorthstarDedicatedTest/gameutils.cpp @@ -78,16 +78,25 @@ void InitialiseServerGameUtilFunctions(HMODULE baseAddress) void InitialiseTier0GameUtilFunctions(HMODULE baseAddress) { - baseAddress = GetModuleHandleA("tier0.dll"); - if (!baseAddress) - throw "tier0.dll is not loaded"; - CreateGlobalMemAlloc = reinterpret_cast<CreateGlobalMemAllocType>(GetProcAddress(baseAddress, "CreateGlobalMemAlloc")); IMemAlloc** ppMemAllocSingleton = reinterpret_cast<IMemAlloc**>(GetProcAddress(baseAddress, "g_pMemAllocSingleton")); - if (!ppMemAllocSingleton || !*ppMemAllocSingleton) + if (!ppMemAllocSingleton) + { + spdlog::critical("Address of g_pMemAllocSingleton is a null pointer, this should never happen"); + throw "Address of g_pMemAllocSingleton is a null pointer, this should never happen"; + } + if (!*ppMemAllocSingleton) + { g_pMemAllocSingleton = CreateGlobalMemAlloc(); + *ppMemAllocSingleton = g_pMemAllocSingleton; + spdlog::warn("Created new g_pMemAllocSingleton"); + } else + { g_pMemAllocSingleton = *ppMemAllocSingleton; + extern size_t g_iStaticAllocated; + spdlog::info("Using existing g_pMemAllocSingleton for memory allocations, preallocated {} bytes beforehand", g_iStaticAllocated); + } Error = reinterpret_cast<ErrorType>(GetProcAddress(baseAddress, "Error")); CommandLine = reinterpret_cast<CommandLineType>(GetProcAddress(baseAddress, "CommandLine")); diff --git a/NorthstarDedicatedTest/hooks.cpp b/NorthstarDedicatedTest/hooks.cpp index 3de8d483..9d2be61c 100644 --- a/NorthstarDedicatedTest/hooks.cpp +++ b/NorthstarDedicatedTest/hooks.cpp @@ -6,14 +6,24 @@ #include <iostream> #include <vector> +// note that these load library callbacks only support explicitly loaded dynamic libraries + typedef HMODULE(*LoadLibraryExAType)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +typedef HMODULE(*LoadLibraryAType)(LPCSTR lpLibFileName); +HMODULE LoadLibraryAHook(LPCSTR lpLibFileName); + typedef HMODULE(*LoadLibraryExWType)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); +typedef HMODULE(*LoadLibraryWType)(LPCWSTR lpLibFileName); +HMODULE LoadLibraryWHook(LPCWSTR lpLibFileName); + LoadLibraryExAType LoadLibraryExAOriginal; +LoadLibraryAType LoadLibraryAOriginal; LoadLibraryExWType LoadLibraryExWOriginal; +LoadLibraryWType LoadLibraryWOriginal; void InstallInitialHooks() { @@ -22,7 +32,9 @@ void InstallInitialHooks() HookEnabler hook; ENABLER_CREATEHOOK(hook, &LoadLibraryExA, &LoadLibraryExAHook, reinterpret_cast<LPVOID*>(&LoadLibraryExAOriginal)); + ENABLER_CREATEHOOK(hook, &LoadLibraryA, &LoadLibraryAHook, reinterpret_cast<LPVOID*>(&LoadLibraryAOriginal)); ENABLER_CREATEHOOK(hook, &LoadLibraryExW, &LoadLibraryExWHook, reinterpret_cast<LPVOID*>(&LoadLibraryExWOriginal)); + ENABLER_CREATEHOOK(hook, &LoadLibraryW, &LoadLibraryWHook, reinterpret_cast<LPVOID*>(&LoadLibraryWOriginal)); } // dll load callback stuff @@ -46,20 +58,51 @@ void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback) dllLoadCallbacks.push_back(callbackStruct); } +void CallLoadLibraryACallbacks(LPCSTR lpLibFileName, HMODULE moduleAddress) +{ + for (auto& callbackStruct : dllLoadCallbacks) + { + if (!callbackStruct->called && strstr(lpLibFileName + (strlen(lpLibFileName) - strlen(callbackStruct->dll.c_str())), callbackStruct->dll.c_str()) != nullptr) + { + callbackStruct->callback(moduleAddress); + callbackStruct->called = true; + } + } +} + +void CallLoadLibraryWCallbacks(LPCWSTR lpLibFileName, HMODULE moduleAddress) +{ + for (auto& callbackStruct : dllLoadCallbacks) + { + std::wstring wcharStrDll = std::wstring(callbackStruct->dll.begin(), callbackStruct->dll.end()); + const wchar_t* callbackDll = wcharStrDll.c_str(); + if (!callbackStruct->called && wcsstr(lpLibFileName + (wcslen(lpLibFileName) - wcslen(callbackDll)), callbackDll) != nullptr) + { + callbackStruct->callback(moduleAddress); + callbackStruct->called = true; + } + } +} + HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { HMODULE moduleAddress = LoadLibraryExAOriginal(lpLibFileName, hFile, dwFlags); if (moduleAddress) { - for (auto& callbackStruct : dllLoadCallbacks) - { - if (!callbackStruct->called && strstr(lpLibFileName + (strlen(lpLibFileName) - strlen(callbackStruct->dll.c_str())), callbackStruct->dll.c_str()) != nullptr) - { - callbackStruct->callback(moduleAddress); - callbackStruct->called = true; - } - } + CallLoadLibraryACallbacks(lpLibFileName, moduleAddress); + } + + return moduleAddress; +} + +HMODULE LoadLibraryAHook(LPCSTR lpLibFileName) +{ + HMODULE moduleAddress = LoadLibraryAOriginal(lpLibFileName); + + if (moduleAddress) + { + CallLoadLibraryACallbacks(lpLibFileName, moduleAddress); } return moduleAddress; @@ -71,16 +114,19 @@ HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) if (moduleAddress) { - for (auto& callbackStruct : dllLoadCallbacks) - { - std::wstring wcharStrDll = std::wstring(callbackStruct->dll.begin(), callbackStruct->dll.end()); - const wchar_t* callbackDll = wcharStrDll.c_str(); - if (!callbackStruct->called && wcsstr(lpLibFileName + (wcslen(lpLibFileName) - wcslen(callbackDll)), callbackDll) != nullptr) - { - callbackStruct->callback(moduleAddress); - callbackStruct->called = true; - } - } + CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress); + } + + return moduleAddress; +} + +HMODULE LoadLibraryWHook(LPCWSTR lpLibFileName) +{ + HMODULE moduleAddress = LoadLibraryWOriginal(lpLibFileName); + + if (moduleAddress) + { + CallLoadLibraryWCallbacks(lpLibFileName, moduleAddress); } return moduleAddress; diff --git a/NorthstarDedicatedTest/memalloc.cpp b/NorthstarDedicatedTest/memalloc.cpp index 113f56b9..cff0ecac 100644 --- a/NorthstarDedicatedTest/memalloc.cpp +++ b/NorthstarDedicatedTest/memalloc.cpp @@ -17,24 +17,48 @@ const int STATIC_ALLOC_SIZE = 100000; // alot more than we need, could reduce to size_t g_iStaticAllocated = 0; char pStaticAllocBuf[STATIC_ALLOC_SIZE]; -void* operator new(size_t n) +// TODO: rename to malloc and free after removing statically compiled .libs + +void* malloc_(size_t n) { // allocate into static buffer if g_pMemAllocSingleton isn't initialised if (g_pMemAllocSingleton) + { + //printf("Northstar malloc (g_pMemAllocSingleton): %llu\n", n); return g_pMemAllocSingleton->m_vtable->Alloc(g_pMemAllocSingleton, n); + } else { + if (g_iStaticAllocated + n > STATIC_ALLOC_SIZE) + { + throw "Ran out of prealloc space"; // we could log, but spdlog probably does use allocations as well... + } + //printf("Northstar malloc (prealloc): %llu\n", n); void* ret = pStaticAllocBuf + g_iStaticAllocated; g_iStaticAllocated += n; return ret; - } + } } -void operator delete(void* p) +void free_(void* p) { // if it was allocated into the static buffer, just do nothing, safest way to deal with it if (p >= pStaticAllocBuf && p <= pStaticAllocBuf + STATIC_ALLOC_SIZE) + { + //printf("Northstar free (prealloc): %p\n", p); return; + } + //printf("Northstar free (g_pMemAllocSingleton): %p\n", p); g_pMemAllocSingleton->m_vtable->Free(g_pMemAllocSingleton, p); +} + +void* operator new(size_t n) +{ + return malloc_(n); +} + +void operator delete(void* p) +{ + free_(p); }
\ No newline at end of file diff --git a/loader_launcher_proxy/Memory.cpp b/loader_launcher_proxy/Memory.cpp index d5642ca5..6c69d80f 100644 --- a/loader_launcher_proxy/Memory.cpp +++ b/loader_launcher_proxy/Memory.cpp @@ -1,11 +1,11 @@ #include "pch.h" -HMODULE hTier0Module; +extern HMODULE hTier0Module; IMemAlloc** g_ppMemAllocSingleton; void LoadTier0Handle() { - hTier0Module = GetModuleHandleA("tier0.dll"); + if (!hTier0Module) hTier0Module = GetModuleHandleA("tier0.dll"); if (!hTier0Module) return; g_ppMemAllocSingleton = (IMemAlloc**)GetProcAddress(hTier0Module, "g_pMemAllocSingleton"); @@ -16,9 +16,9 @@ const int STATIC_ALLOC_SIZE = 4096; size_t g_iStaticAllocated = 0; char pStaticAllocBuf[STATIC_ALLOC_SIZE]; -// they should never be used here, except in LibraryLoadError +// they should never be used here, except in LibraryLoadError? -void* operator new(size_t n) +void* malloc(size_t n) { // allocate into static buffer if (g_iStaticAllocated + n <= STATIC_ALLOC_SIZE) @@ -30,7 +30,7 @@ void* operator new(size_t n) else { // try to fallback to g_pMemAllocSingleton - if (!hTier0Module) LoadTier0Handle(); + if (!hTier0Module || !g_ppMemAllocSingleton) LoadTier0Handle(); if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton) return (*g_ppMemAllocSingleton)->m_vtable->Alloc(*g_ppMemAllocSingleton, n); else @@ -38,7 +38,7 @@ void* operator new(size_t n) } } -void operator delete(void* p) +void free(void* p) { // if it was allocated into the static buffer, just do nothing, safest way to deal with it if (p >= pStaticAllocBuf && p <= pStaticAllocBuf + STATIC_ALLOC_SIZE) @@ -47,3 +47,13 @@ void operator delete(void* p) if (g_ppMemAllocSingleton && *g_ppMemAllocSingleton) (*g_ppMemAllocSingleton)->m_vtable->Free(*g_ppMemAllocSingleton, p); } + +void* operator new(size_t n) +{ + return malloc(n); +} + +void operator delete(void* p) +{ + return free(p); +} diff --git a/loader_launcher_proxy/dllmain.cpp b/loader_launcher_proxy/dllmain.cpp index 31360a8e..6db50986 100644 --- a/loader_launcher_proxy/dllmain.cpp +++ b/loader_launcher_proxy/dllmain.cpp @@ -3,9 +3,12 @@ #include <string> #include <system_error> #include <Shlwapi.h> +#include <sstream> +#include <fstream> HMODULE hLauncherModule; HMODULE hHookModule; +HMODULE hTier0Module; using CreateInterfaceFn = void* (*)(const char* pName, int* pReturnCode); @@ -44,7 +47,7 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* char text[2048]; std::string message = std::system_category().message(dwMessageId); sprintf_s(text, "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs", libName, location, dwMessageId, message.c_str()); - MessageBoxA(GetForegroundWindow(), text, "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Proxy Error", 0); } BOOL APIENTRY DllMain( HMODULE hModule, @@ -66,32 +69,61 @@ BOOL APIENTRY DllMain( HMODULE hModule, wchar_t exePath[4096]; wchar_t dllPath[4096]; +bool ShouldLoadNorthstar() +{ + bool loadNorthstar = !strstr(GetCommandLineA(), "-vanilla"); + + if (!loadNorthstar) + return loadNorthstar; + + auto runNorthstarFile = std::ifstream("run_northstar.txt"); + if (runNorthstarFile) + { + std::stringstream runNorthstarFileBuffer; + runNorthstarFileBuffer << runNorthstarFile.rdbuf(); + runNorthstarFile.close(); + if (runNorthstarFileBuffer.str()._Starts_with("0")) + loadNorthstar = false; + } + return loadNorthstar; +} + +bool LoadNorthstar() +{ + FARPROC Hook_Init = nullptr; + { + swprintf_s(dllPath, L"%s\\Northstar.dll", exePath); + hHookModule = LoadLibraryExW(dllPath, 0i64, 8u); + if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar"); + if (!hHookModule || Hook_Init == nullptr) + { + LibraryLoadError(GetLastError(), L"Northstar.dll", dllPath); + return false; + } + } + + printf("WILL CALL HOOK INIT\n"); + ((bool (*)()) Hook_Init)(); + return true; +} + extern "C" __declspec(dllexport) int LauncherMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { { if (!GetExePathWide(exePath, 4096)) { - MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Northstar Launcher Proxy Error", 0); return 1; } - bool loadNorthstar = !strstr(GetCommandLineA(), "-vanilla"); + bool loadNorthstar = ShouldLoadNorthstar(); + if (loadNorthstar) { - FARPROC Hook_Init = nullptr; - { - swprintf_s(dllPath, L"%s\\Northstar.dll", exePath); - hHookModule = LoadLibraryExW(dllPath, 0i64, 8u); - if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar"); - if (!hHookModule || Hook_Init == nullptr) - { - LibraryLoadError(GetLastError(), L"Northstar.dll", dllPath); - return 1; - } - } - - ((bool (*)()) Hook_Init)(); + if (!LoadNorthstar()) + return 1; } + //else printf("\n\n WILL !!!NOT!!! LOAD NORTHSTAR\n\n"); swprintf_s(dllPath, L"%s\\bin\\x64_retail\\launcher.org.dll", exePath); hLauncherModule = LoadLibraryExW(dllPath, 0i64, 8u); @@ -100,11 +132,21 @@ extern "C" __declspec(dllexport) int LauncherMain(HINSTANCE hInstance, HINSTANCE LibraryLoadError(GetLastError(), L"launcher.org.dll", dllPath); return 1; } + + // this makes zero sense given tier0.dll is already loaded via imports on launcher.dll, but we do it for full consistency with original launcher exe + // and to also let load callbacks in Northstar work for tier0.dll + swprintf_s(dllPath, L"%s\\bin\\x64_retail\\tier0.dll", exePath); + hTier0Module = LoadLibraryW(dllPath); + if (!hTier0Module) + { + LibraryLoadError(GetLastError(), L"tier0.dll", dllPath); + return 1; + } } auto LauncherMain = GetLauncherMain(); if (!LauncherMain) - MessageBoxA(GetForegroundWindow(), "Failed loading launcher.org.dll.\nThe game cannot continue and has to exit.", "Launcher Error", 0); + MessageBoxA(GetForegroundWindow(), "Failed loading launcher.org.dll.\nThe game cannot continue and has to exit.", "Northstar Launcher Proxy Error", 0); //auto result = ((__int64(__fastcall*)())LauncherMain)(); //auto result = ((signed __int64(__fastcall*)(__int64))LauncherMain)(0i64); return ((int(__fastcall*)(HINSTANCE, HINSTANCE, LPSTR, int))LauncherMain)(hInstance, hPrevInstance, lpCmdLine, nCmdShow); diff --git a/loader_launcher_proxy/loader_launcher_proxy.vcxproj b/loader_launcher_proxy/loader_launcher_proxy.vcxproj index 65ef19ba..9cc7a4c7 100644 --- a/loader_launcher_proxy/loader_launcher_proxy.vcxproj +++ b/loader_launcher_proxy/loader_launcher_proxy.vcxproj @@ -78,7 +78,7 @@ <ConformanceMode>true</ConformanceMode> <PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> - <LanguageStandard>Default</LanguageStandard> + <LanguageStandard>stdcpp17</LanguageStandard> </ClCompile> <Link> <SubSystem>Windows</SubSystem> |