diff options
Diffstat (limited to 'LauncherInjector')
-rw-r--r-- | LauncherInjector/LauncherInjector.vcxproj | 71 | ||||
-rw-r--r-- | LauncherInjector/main.cpp | 266 | ||||
-rw-r--r-- | LauncherInjector/resources.rc | 39 |
3 files changed, 216 insertions, 160 deletions
diff --git a/LauncherInjector/LauncherInjector.vcxproj b/LauncherInjector/LauncherInjector.vcxproj index e205207d..8870c732 100644 --- a/LauncherInjector/LauncherInjector.vcxproj +++ b/LauncherInjector/LauncherInjector.vcxproj @@ -1,14 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> @@ -27,19 +19,6 @@ <ProjectName>NorthstarLauncher</ProjectName> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v143</PlatformToolset> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v143</PlatformToolset> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> @@ -58,12 +37,6 @@ </ImportGroup> <ImportGroup Label="Shared"> </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> @@ -71,50 +44,12 @@ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <LinkIncremental>true</LinkIncremental> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <LinkIncremental>false</LinkIncremental> </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <SDLCheck>true</SDLCheck> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <ConformanceMode>true</ConformanceMode> - <LanguageStandard>stdcpp17</LanguageStandard> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <SDLCheck>true</SDLCheck> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <ConformanceMode>true</ConformanceMode> - <LanguageStandard>stdcpp17</LanguageStandard> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ClCompile> <WarningLevel>Level3</WarningLevel> @@ -122,10 +57,13 @@ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <ConformanceMode>true</ConformanceMode> <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/F8000000 %(AdditionalOptions)</AdditionalOptions> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <StackReserveSize>8000000</StackReserveSize> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> @@ -137,12 +75,15 @@ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <ConformanceMode>true</ConformanceMode> <LanguageStandard>stdcpp17</LanguageStandard> + <AdditionalOptions>/F8000000 %(AdditionalOptions)</AdditionalOptions> </ClCompile> <Link> <SubSystem>Console</SubSystem> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> <GenerateDebugInformation>true</GenerateDebugInformation> + <AdditionalDependencies>shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <StackReserveSize>8000000</StackReserveSize> </Link> </ItemDefinitionGroup> <ItemGroup> diff --git a/LauncherInjector/main.cpp b/LauncherInjector/main.cpp index 5828e9e2..7697e80d 100644 --- a/LauncherInjector/main.cpp +++ b/LauncherInjector/main.cpp @@ -1,12 +1,25 @@ +#define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <TlHelp32.h> #include <filesystem> #include <sstream> -#include <iostream> #include <fstream> +#include <Shlwapi.h> namespace fs = std::filesystem; +extern "C" { + __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +} + +HMODULE hLauncherModule; +HMODULE hHookModule; +HMODULE hTier0Module; + +wchar_t exePath[4096]; +wchar_t buffer[8192]; + DWORD GetProcessByName(std::wstring processName) { HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); @@ -33,132 +46,195 @@ DWORD GetProcessByName(std::wstring processName) return 0; } -#define PROCESS_NAME L"Titanfall2-unpacked.exe" -#define DLL_NAME L"Northstar.dll" +bool GetExePathWide(wchar_t* dest, DWORD destSize) +{ + if (!dest) return NULL; + if (destSize < MAX_PATH) return NULL; -int main(int argc, char* argv[]) { - if (!fs::exists(PROCESS_NAME)) + DWORD length = GetModuleFileNameW(NULL, dest, destSize); + return length && PathRemoveFileSpecW(dest); +} + +FARPROC GetLauncherMain() +{ + static FARPROC Launcher_LauncherMain; + if (!Launcher_LauncherMain) + Launcher_LauncherMain = GetProcAddress(hLauncherModule, "LauncherMain"); + return Launcher_LauncherMain; +} + +void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* location) +{ + char text[4096]; + 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()); + + if (!fs::exists("Titanfall2.exe") && fs::exists("..\\Titanfall2.exe")) { - MessageBoxA(0, "Titanfall2-unpacked.exe not found! Please launch from your titanfall 2 directory and ensure you have Northstar installed correctly!", "", MB_OK); - return 1; + auto curDir = std::filesystem::current_path().filename().string(); + auto aboveDir = std::filesystem::current_path().parent_path().filename().string(); + sprintf_s(text, "%s\n\nWe detected that in your case you have extracted the files into a *subdirectory* of your Titanfall 2 installation.\nPlease move all the files and folders from current folder (\"%s\") into the Titanfall 2 installation directory just above (\"%s\").\n\nPlease try out the above steps by yourself before reaching out to the community for support.", text, curDir.c_str(), aboveDir.c_str()); } - if (!fs::exists(DLL_NAME)) + MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Error", 0); +} + +void EnsureOriginStarted() +{ + if (GetProcessByName(L"Origin.exe") || GetProcessByName(L"EADesktop.exe")) + return; // already started + + // 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, "Northstar.dll not found! Please launch from your titanfall 2 directory and ensure you have Northstar installed correctly!", "", MB_OK); - return 1; + MessageBoxA(0, "Error: failed reading Origin path!", "Northstar Launcher Error", MB_OK); + return; } - bool isdedi = false; - for (int i = 0; i < argc; i++) - if (!strcmp(argv[i], "-dedicated")) - isdedi = true; - - if (!isdedi && !GetProcessByName(L"Origin.exe") && !GetProcessByName(L"EADesktop.exe")) + 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!", "Northstar Launcher Error", 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, (LPSTR)"", 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); - // get cmdline args from file - std::wstring args; - std::ifstream cmdlineArgFile; + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); +} - args.append(L" "); - for (int i = 0; i < argc; i++) +void PrependPath() +{ + wchar_t* pPath; + size_t len; + errno_t err = _wdupenv_s(&pPath, &len, L"PATH"); + if (!err) { - std::string str = argv[i]; - - args.append(std::wstring(str.begin(), str.end())); - args.append(L" "); + 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); } - - if (!isdedi) - cmdlineArgFile = std::ifstream("ns_startup_args.txt"); else - cmdlineArgFile = std::ifstream("ns_startup_args_dedi.txt"); - - if (cmdlineArgFile) { - std::stringstream argBuffer; - argBuffer << cmdlineArgFile.rdbuf(); - cmdlineArgFile.close(); - - std::string str = argBuffer.str(); - args.append(std::wstring(str.begin(), str.end())); + 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); } +} - //if (isdedi) - // // copy -dedicated into args if we have it in commandline args - // args.append(L" -dedicated"); - - STARTUPINFO startupInfo; - PROCESS_INFORMATION processInfo; +bool ShouldLoadNorthstar(int argc, char* argv[]) +{ + bool loadNorthstar = true; + for (int i = 0; i < argc; i++) + if (!strcmp(argv[i], "-vanilla")) + loadNorthstar = false; - memset(&startupInfo, 0, sizeof(startupInfo)); - memset(&processInfo, 0, sizeof(processInfo)); + if (!loadNorthstar) + return loadNorthstar; - CreateProcessW(PROCESS_NAME, (LPWSTR)args.c_str(), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfo); + 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; +} - HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); - LPTHREAD_START_ROUTINE pLoadLibraryW = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW"); +bool 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 false; + } + } - SIZE_T dwLength = (wcslen(DLL_NAME) + 1) * 2; - LPVOID lpLibName = VirtualAllocEx(processInfo.hProcess, NULL, dwLength, MEM_COMMIT, PAGE_READWRITE); + ((bool (*)()) Hook_Init)(); + return true; +} - SIZE_T written = 0; - WriteProcessMemory(processInfo.hProcess, lpLibName, DLL_NAME, dwLength, &written); +int main(int argc, char* argv[]) { - HANDLE hThread = CreateRemoteThread(processInfo.hProcess, NULL, NULL, pLoadLibraryW, lpLibName, NULL, NULL); + // checked to avoid starting origin, Northstar.dll will check for -dedicated as well on its own + bool noOriginStartup = false; + for (int i = 0; i < argc; i++) + if (!strcmp(argv[i], "-noOriginStartup") || !strcmp(argv[i], "-dedicated")) + noOriginStartup = true; - if (hThread == NULL) + if (!noOriginStartup) { - // injection failed - - std::string errorMessage = "Injection failed! CreateRemoteThread returned "; - errorMessage += std::to_string(GetLastError()).c_str(); - errorMessage += ", make sure bob hasn't accidentally shipped a debug build"; - - MessageBoxA(0, errorMessage.c_str(), "", MB_OK); - return 0; + EnsureOriginStarted(); } - WaitForSingleObject(hThread, INFINITE); - - //MessageBoxA(0, std::to_string(GetLastError()).c_str(), "", MB_OK); + { + if (!GetExePathWide(exePath, sizeof(exePath))) + { + MessageBoxA(GetForegroundWindow(), "Failed getting game directory.\nThe game cannot continue and has to exit.", "Northstar Launcher Error", 0); + return 1; + } - CloseHandle(hThread); + PrependPath(); - ResumeThread(processInfo.hThread); + printf("[*] Loading tier0.dll\n"); + swprintf_s(buffer, L"%s\\bin\\x64_retail\\tier0.dll", exePath); + hTier0Module = LoadLibraryExW(buffer, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hTier0Module) + { + LibraryLoadError(GetLastError(), L"tier0.dll", buffer); + return 1; + } - VirtualFreeEx(processInfo.hProcess, lpLibName, dwLength, MEM_RELEASE); + bool loadNorthstar = ShouldLoadNorthstar(argc, argv); + if (loadNorthstar) + { + printf("[*] Loading Northstar\n"); + if (!LoadNorthstar()) + return 1; + } + else + printf("[*] Going to load the vanilla game\n"); - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); + printf("[*] Loading launcher.dll\n"); + swprintf_s(buffer, L"%s\\bin\\x64_retail\\launcher.dll", exePath); + hLauncherModule = LoadLibraryExW(buffer, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hLauncherModule) + { + LibraryLoadError(GetLastError(), L"launcher.dll", buffer); + return 1; + } + } - return 0; + printf("[*] Launching the game...\n"); + auto LauncherMain = GetLauncherMain(); + if (!LauncherMain) + 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 }
\ No newline at end of file diff --git a/LauncherInjector/resources.rc b/LauncherInjector/resources.rc index a51894c4..c065b7bb 100644 --- a/LauncherInjector/resources.rc +++ b/LauncherInjector/resources.rc @@ -54,6 +54,45 @@ END // remains consistent on all systems. IDI_ICON1 ICON "ns_icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "Northstar Developers" + VALUE "FileDescription", "Northstar Launcher" + VALUE "FileVersion", "1.3.0.0" + VALUE "InternalName", "NorthstarLauncher.exe" + VALUE "LegalCopyright", "Copyright (C) 2021" + VALUE "OriginalFilename", "NorthstarLauncher.exe" + VALUE "ProductName", "Northstar Launcher" + VALUE "ProductVersion", "1.3.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + #endif // English (United Kingdom) resources ///////////////////////////////////////////////////////////////////////////// |