aboutsummaryrefslogtreecommitdiff
path: root/loader_launcher_proxy/dllmain.cpp
blob: 7a778208e2f8548aacd58333c672a08f4e869414 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "pch.h"
#include <stdio.h>
#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);

// does not seem to ever be used
extern "C" _declspec(dllexport) void* __fastcall CreateInterface(const char* pName, int* pReturnCode)
{
    //AppSystemCreateInterfaceFn(pName, pReturnCode);
    printf("external CreateInterface: name: %s\n", pName);

    static CreateInterfaceFn launcher_CreateInterface = (CreateInterfaceFn)GetProcAddress(hLauncherModule, "CreateInterface");
    auto res = launcher_CreateInterface(pName, pReturnCode);

    printf("external CreateInterface: return code: %p\n", res);
    return res;
}

bool GetExePathWide(wchar_t* dest, DWORD destSize)
{
    if (!dest) return NULL;
    if (destSize < MAX_PATH) return NULL;

    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[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, "Northstar Launcher Proxy Error", 0);
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

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;
        }
    }

    ((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.", "Northstar Launcher Proxy Error", 0);
            return 1;
        }

        bool loadNorthstar = ShouldLoadNorthstar();

        if (loadNorthstar)
        {
            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);
        if (!hLauncherModule)
        {
            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.", "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);
}

// doubt that will help us here (in launcher.dll) though
extern "C" {
    __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
    __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}