aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LauncherInjector/main.cpp228
-rw-r--r--LauncherInjector/memalloc.cpp11
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp7
-rw-r--r--NorthstarDedicatedTest/gameutils.cpp19
-rw-r--r--NorthstarDedicatedTest/hooks.cpp82
-rw-r--r--NorthstarDedicatedTest/memalloc.cpp30
-rw-r--r--loader_launcher_proxy/Memory.cpp22
-rw-r--r--loader_launcher_proxy/dllmain.cpp76
-rw-r--r--loader_launcher_proxy/loader_launcher_proxy.vcxproj2
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>