Repository navigation
Expand file tree
/
Copy pathdllmain.cpp
More file actions
128 lines (100 loc) · 3.32 KB
/
Copy pathdllmain.cpp
File metadata and controls
128 lines (100 loc) · 3.32 KB
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
// DLL entry, hook install thread
#include "pch.h"
#include <Windows.h>
#include <atomic>
#include <cstdio>
#include "MinHook.h"
#include "log.h"
#include "AddressSet.h"
#include "BuiltInModules.h"
#include "DebugConsole.h"
#include "FeatureModule.h"
#include "HookUtils.h"
#include "Settings.h"
bool g_HookBatchMode = false;
// Build marker, checked in the binary by the build script
static const char kBuildMarker[] = "TEXTURESTREAMER,V0_18_20260928";
namespace
{
static std::atomic_bool gStarted{ false };
}
// Loads settings, resolves addresses, and installs every registered feature module.
static DWORD WINAPI InitThread(LPVOID)
{
BootTrace("InitThread entered");
InitLog();
BootTrace("InitThread log opened");
Log("[DLL] InitThread started. %s\n", kBuildMarker);
HMODULE hGame = GetModuleHandleW(nullptr);
LoadSettings();
SetBootTrace(GetSettings().debugLog);
BootTrace("InitThread settings loaded", true);
const MH_STATUS st = MH_Initialize();
Log("[DLL] MH_Initialize -> %d\n", static_cast<int>(st));
if (st != MH_OK && st != MH_ERROR_ALREADY_INITIALIZED)
return 0;
if (!ResolveAddressSet(hGame))
{
Log("[DLL] ResolveAddressSet failed.\n");
return 0;
}
InstallCrashHandler();
RegisterBuiltInFeatureModules();
g_HookBatchMode = true;
const bool allOk = FeatureModuleRegistry::Instance().InstallAll(hGame);
g_HookBatchMode = false;
const MH_STATUS applySt = MH_ApplyQueued();
Log("[DLL] FeatureModuleRegistry::InstallAll -> %s\n", allOk ? "OK" : "PARTIAL/FAIL");
Log("[DLL] MH_ApplyQueued -> %d\n", static_cast<int>(applySt));
if (GetSettings().debugWindow)
StartDebugConsole();
Log("[DLL] InitThread done.\n");
BootTrace("InitThread done");
return 0;
}
// Removes all hooks when the DLL unloads normally.
static void UninstallAll(bool processTerminating)
{
if (processTerminating)
return;
FeatureModuleRegistry::Instance().UninstallAll();
MH_Uninitialize();
Log("[DLL] UninstallAll done.\n");
fflush(stdout);
fflush(stderr);
CloseLog();
}
// Standard Windows DLL entry point.
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
{
BootTrace("DllMain attach", true);
DisableThreadLibraryCalls(hModule);
// Pin: Lua frees loadlib handles when its state closes at shutdown, which would
// unmap the hooks' code while game threads can still be running it.
HMODULE pinned = nullptr;
BootTrace(
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, reinterpret_cast<LPCWSTR>(hModule), &pinned)
? "DllMain pinned"
: "DllMain pin FAILED");
bool expected = false;
if (!gStarted.compare_exchange_strong(expected, true))
return TRUE;
HANDLE hThread = CreateThread(nullptr, 0, InitThread, nullptr, 0, nullptr);
BootTrace(hThread ? "DllMain CreateThread ok" : "DllMain CreateThread FAILED");
if (hThread)
CloseHandle(hThread);
BootTrace("DllMain return");
return TRUE;
}
case DLL_PROCESS_DETACH:
{
UninstallAll(lpReserved != nullptr);
return TRUE;
}
}
return TRUE;
}