7
7
#include " engine/EngineOwnData.h"
8
8
#include " engine/RemoteCall.h"
9
9
#include " fmt/format.h"
10
+ #include " ll/api/Expected.h"
11
+ #include " ll/api/base/Containers.h"
10
12
#include " ll/api/chrono/GameChrono.h"
11
13
#include " ll/api/coro/CoroTask.h"
12
14
#include " ll/api/io/FileUtils.h"
13
15
#include " ll/api/io/LogLevel.h"
16
+ #include " ll/api/memory/Hook.h"
14
17
#include " ll/api/service/GamingStatus.h"
15
18
#include " ll/api/service/ServerInfo.h"
16
19
#include " ll/api/thread/ServerThreadExecutor.h"
17
20
#include " ll/api/utils/StringUtils.h"
21
+ #include " lse/Entry.h"
18
22
#include " main/Global.h"
19
23
#include " utils/Utils.h"
20
24
#include " uv/uv.h"
21
25
#include " v8/v8.h"
22
26
27
+ #define NODE_LIBRARY_NAME_W L" libnode.dll"
28
+ #define NODE_HOST_BINARY_NAME " node.exe"
29
+
23
30
using ll::chrono_literals::operator " " _tick;
24
31
25
32
// pre-declare
@@ -38,7 +45,81 @@ std::unordered_map<script::ScriptEngine*, std::unique_ptr<node::CommonEnvironmen
38
45
std::unordered_map<node::Environment*, bool > isRunning;
39
46
std::vector<node::Environment*> uvLoopTask;
40
47
48
+ ll::Expected<> PatchDelayImport (HMODULE hAddon, HMODULE hLibNode) {
49
+ BYTE* base = (BYTE*)hAddon;
50
+ auto dos = (PIMAGE_DOS_HEADER)base;
51
+ if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
52
+ return ll::makeStringError (" Invalid DOS signature." );
53
+ }
54
+ auto nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew );
55
+ if (nt->Signature != IMAGE_NT_SIGNATURE) {
56
+ return ll::makeStringError (" Invalid NT signature." );
57
+ }
58
+ DWORD rva = nt->OptionalHeader .DataDirectory [IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress ;
59
+ if (!rva) {};
60
+ auto pDesc = (PIMAGE_DELAYLOAD_DESCRIPTOR)(base + rva);
61
+ for (; pDesc->DllNameRVA ; ++pDesc) {
62
+ char * szDll = (char *)(base + pDesc->DllNameRVA );
63
+ if (_stricmp (szDll, NODE_HOST_BINARY_NAME) != 0 ) continue ;
64
+
65
+ auto pIAT = (PIMAGE_THUNK_DATA)(base + pDesc->ImportAddressTableRVA );
66
+ auto pINT = (PIMAGE_THUNK_DATA)(base + pDesc->ImportNameTableRVA );
67
+
68
+ for (; pIAT->u1 .Function ; ++pIAT, ++pINT) {
69
+ FARPROC f = nullptr ;
70
+ if (pINT->u1 .Ordinal & IMAGE_ORDINAL_FLAG) {
71
+ // Import by Ordinal
72
+ WORD ordinal = IMAGE_ORDINAL (pINT->u1 .Ordinal );
73
+ f = GetProcAddress (hLibNode, MAKEINTRESOURCEA (ordinal));
74
+ } else {
75
+ // Import by name
76
+ auto name = (PIMAGE_IMPORT_BY_NAME)(base + pINT->u1 .AddressOfData );
77
+ f = GetProcAddress (hLibNode, name->Name );
78
+ }
79
+ if (f) {
80
+ DWORD oldProt;
81
+ VirtualProtect (&pIAT->u1 .Function , sizeof (void *), PAGE_READWRITE, &oldProt);
82
+ pIAT->u1 .Function = reinterpret_cast <decltype (pIAT->u1 .Function )>(f);
83
+ VirtualProtect (&pIAT->u1 .Function , sizeof (void *), oldProt, &oldProt);
84
+ }
85
+ }
86
+ break ;
87
+ }
88
+ return {};
89
+ }
90
+
91
+ ll::DenseSet<HMODULE> cachedModules{};
92
+
93
+ // patch in node?
94
+ LL_STATIC_HOOK (
95
+ PatchDelayImportHook,
96
+ HookPriority::Normal,
97
+ LoadLibraryExW,
98
+ HMODULE,
99
+ LPCWSTR lpLibFileName,
100
+ HANDLE hFile,
101
+ DWORD dwFlags
102
+ ) {
103
+ auto hAddon = origin (lpLibFileName, hFile, dwFlags);
104
+ if (!cachedModules.contains (hAddon)) {
105
+ cachedModules.emplace (hAddon);
106
+ if (std::wstring_view (lpLibFileName).ends_with (L" .node" )) {
107
+ static HMODULE hLibNode = GetModuleHandle (NODE_LIBRARY_NAME_W);
108
+ if (!(hAddon && hLibNode)) return hAddon;
109
+ auto res = PatchDelayImport (hAddon, hLibNode);
110
+ if (res) return hAddon;
111
+ res.error ().log (lse::LegacyScriptEngine::getInstance ().getSelf ().getLogger ());
112
+ }
113
+ }
114
+ return hAddon;
115
+ }
116
+
117
+ std::unique_ptr<ll::memory::HookRegistrar<PatchDelayImportHook>> hook{};
118
+
41
119
bool initNodeJs () {
120
+ if (lse::LegacyScriptEngine::getInstance ().getConfig ().fixOldAddon .value_or (true )) {
121
+ hook = std::make_unique<ll::memory::HookRegistrar<PatchDelayImportHook>>();
122
+ }
42
123
// Init NodeJs
43
124
auto path = ll::string_utils::u8str2str (ll::sys_utils::getModulePath (nullptr ).value ().u8string ());
44
125
char * cPath = (char *)path.c_str ();
0 commit comments