Skip to content

Commit 7632885

Browse files
argentumblattersturm
argentum
authored andcommitted
assorted changes to get parts of the game to run under Wine
1 parent 7c47b5b commit 7632885

File tree

11 files changed

+260
-74
lines changed

11 files changed

+260
-74
lines changed

code/client/citicore/FileMapping.Win32.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ NTSTATUS NTAPI LdrLoadDllStub(const wchar_t* fileName, uint32_t* flags, UNICODE_
9595
UNICODE_STRING newString;
9696
std::wstring moduleNameStr(moduleName->Buffer, moduleName->Length / sizeof(wchar_t));
9797

98-
if (moduleNameStr.find(L"socialclub.dll") != std::string::npos)
98+
if (moduleNameStr.find(L"socialclub.dll") != std::string::npos ||
99+
// check .exe files as well for Wine GetFileVersionInfo* calls
100+
moduleNameStr.find(L".exe") != std::string::npos)
99101
{
100102
moduleNameStr = MapRedirectedFilename(moduleNameStr.c_str());
101103

code/client/citicore/SEHTableHandler.Win32.cpp

+51-23
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ static void* RtlpxLookupFunctionTableOverrideDownLevel(void* exceptionAddress, P
133133

134134
#include <winternl.h>
135135

136+
static PVOID(*g_origRtlImageDirectoryEntryToData)(HMODULE hModule, BOOL a2, WORD directory, ULONG* a4);
137+
138+
static PVOID RtlImageDirectoryEntryToDataStub(HMODULE hModule, BOOL a2, WORD directory, ULONG* size)
139+
{
140+
if ((DWORD64)hModule == g_overrideStart)
141+
{
142+
if (directory == IMAGE_DIRECTORY_ENTRY_EXCEPTION)
143+
{
144+
*size = g_overriddenTable.Size;
145+
return (PVOID)g_overriddenTable.TableAddress;
146+
}
147+
}
148+
149+
return g_origRtlImageDirectoryEntryToData(hModule, a2, directory, size);
150+
}
151+
136152
extern "C" void DLL_EXPORT CoreRT_SetupSEHHandler(void* moduleBase, void* moduleEnd, PRUNTIME_FUNCTION runtimeFunctions, DWORD entryCount)
137153
{
138154
// store passed data
@@ -162,42 +178,54 @@ extern "C" void DLL_EXPORT CoreRT_SetupSEHHandler(void* moduleBase, void* module
162178

163179
// find the location to hook (RtlpxLookupFunctionTable from RtlLookupFunctionTable)
164180
void* baseAddress = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlLookupFunctionTable");
165-
void* internalAddress = FindCallFromAddress(baseAddress);
166181

167-
void* patchFunction = RtlpxLookupFunctionTableOverride;
168-
void** patchOriginal = (void**)&g_originalLookup;
169-
170-
// if we couldn't _reliably_ find it, error out
171-
if (!internalAddress)
182+
if (baseAddress)
172183
{
173-
// Windows 8 uses a Rtl*-style call for Rtlpx
174-
if (!IsWindows8Point1OrGreater())
175-
{
176-
internalAddress = FindCallFromAddress(baseAddress, UD_Ijmp);
184+
void* internalAddress = FindCallFromAddress(baseAddress);
177185

178-
patchFunction = RtlpxLookupFunctionTableOverrideDownLevel;
179-
patchOriginal = (void**)&g_originalLookupDownLevel;
180-
}
186+
void* patchFunction = RtlpxLookupFunctionTableOverride;
187+
void** patchOriginal = (void**)&g_originalLookup;
181188

189+
// if we couldn't _reliably_ find it, error out
182190
if (!internalAddress)
183191
{
184-
// and 2k3 to 7 don't even _have_ Rtlpx - so we directly hook the Rtl* function
185-
if (IsWindows8OrGreater())
192+
// Windows 8 uses a Rtl*-style call for Rtlpx
193+
if (!IsWindows8Point1OrGreater())
186194
{
187-
FatalError("Could not find RtlpxLookupFunctionTable - hooking RtlLookupFunctionTable directly. This will break on a Win8+ system since RtlpxLookupFunctionTable is supposed to exist!\n");
195+
internalAddress = FindCallFromAddress(baseAddress, UD_Ijmp);
196+
197+
patchFunction = RtlpxLookupFunctionTableOverrideDownLevel;
198+
patchOriginal = (void**)&g_originalLookupDownLevel;
188199
}
189200

190-
internalAddress = baseAddress;
201+
if (!internalAddress)
202+
{
203+
// and 2k3 to 7 don't even _have_ Rtlpx - so we directly hook the Rtl* function
204+
if (IsWindows8OrGreater())
205+
{
206+
FatalError("Could not find RtlpxLookupFunctionTable - hooking RtlLookupFunctionTable directly. This will break on a Win8+ system since RtlpxLookupFunctionTable is supposed to exist!\n");
207+
}
208+
209+
internalAddress = baseAddress;
191210

192-
patchFunction = RtlpxLookupFunctionTableOverrideDownLevel;
193-
patchOriginal = (void**)&g_originalLookupDownLevel;
211+
patchFunction = RtlpxLookupFunctionTableOverrideDownLevel;
212+
patchOriginal = (void**)&g_originalLookupDownLevel;
213+
}
194214
}
215+
216+
// patch it
217+
DisableToolHelpScope scope;
218+
MH_CreateHook(internalAddress, patchFunction, patchOriginal);
219+
MH_EnableHook(MH_ALL_HOOKS);
195220
}
221+
else
222+
{
223+
trace("Not running on Windows - no RtlLookupFunctionTable. Is this some fake OS?\n");
196224

197-
// patch it
198-
DisableToolHelpScope scope;
199-
MH_CreateHook(internalAddress, patchFunction, patchOriginal);
200-
MH_EnableHook(MH_ALL_HOOKS);
225+
DisableToolHelpScope scope;
226+
MH_CreateHookApi(L"ntdll.dll", "RtlImageDirectoryEntryToData", RtlImageDirectoryEntryToDataStub, (void**)&g_origRtlImageDirectoryEntryToData);
227+
MH_EnableHook(MH_ALL_HOOKS);
228+
}
201229
}
202230
#else
203231
void DLL_EXPORT CoreRT_SetupSEHHandler(...)

code/client/launcher/ExecutableLoader.cpp

+19-16
Original file line numberDiff line numberDiff line change
@@ -172,30 +172,33 @@ void ExecutableLoader::LoadExceptionTable(IMAGE_NT_HEADERS* ntHeader)
172172
PLIST_ENTRY(NTAPI *rtlGetFunctionTableListHead)(VOID);
173173
rtlGetFunctionTableListHead = (decltype(rtlGetFunctionTableListHead))GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlGetFunctionTableListHead");
174174

175-
auto tableListHead = rtlGetFunctionTableListHead();
176-
auto tableListEntry = tableListHead->Flink;
177-
178-
while (tableListEntry != tableListHead)
175+
if (rtlGetFunctionTableListHead)
179176
{
180-
auto functionTable = CONTAINING_RECORD(tableListEntry, DYNAMIC_FUNCTION_TABLE, Links);
181-
182-
if (functionTable->BaseAddress == (ULONG_PTR)m_module)
177+
auto tableListHead = rtlGetFunctionTableListHead();
178+
auto tableListEntry = tableListHead->Flink;
179+
180+
while (tableListEntry != tableListHead)
183181
{
184-
trace("Replacing function table list entry %p with %p\n", (void*)functionTable->FunctionTable, (void*)functionList);
182+
auto functionTable = CONTAINING_RECORD(tableListEntry, DYNAMIC_FUNCTION_TABLE, Links);
185183

186-
if (functionTable->FunctionTable != functionList)
184+
if (functionTable->BaseAddress == (ULONG_PTR)m_module)
187185
{
188-
DWORD oldProtect;
189-
VirtualProtect(functionTable, sizeof(DYNAMIC_FUNCTION_TABLE), PAGE_READWRITE, &oldProtect);
186+
trace("Replacing function table list entry %p with %p\n", (void*)functionTable->FunctionTable, (void*)functionList);
187+
188+
if (functionTable->FunctionTable != functionList)
189+
{
190+
DWORD oldProtect;
191+
VirtualProtect(functionTable, sizeof(DYNAMIC_FUNCTION_TABLE), PAGE_READWRITE, &oldProtect);
190192

191-
functionTable->EntryCount = entryCount;
192-
functionTable->FunctionTable = functionList;
193+
functionTable->EntryCount = entryCount;
194+
functionTable->FunctionTable = functionList;
193195

194-
VirtualProtect(functionTable, sizeof(DYNAMIC_FUNCTION_TABLE), oldProtect, &oldProtect);
196+
VirtualProtect(functionTable, sizeof(DYNAMIC_FUNCTION_TABLE), oldProtect, &oldProtect);
197+
}
195198
}
196-
}
197199

198-
tableListEntry = functionTable->Links.Flink;
200+
tableListEntry = functionTable->Links.Flink;
201+
}
199202
}
200203
}
201204

code/components/citizen-scripting-lua/src/LuaScriptRuntime.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ static int Lua_SetTickRoutine(lua_State* L)
296296
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
297297

298298
// set the tick callback in the current routine
299-
auto& luaRuntime = LuaScriptRuntime::GetCurrent();
299+
auto luaRuntime = LuaScriptRuntime::GetCurrent().GetRef();
300300

301301
luaRuntime->SetTickRoutine([=] ()
302302
{
@@ -340,7 +340,7 @@ static int Lua_SetEventRoutine(lua_State* L)
340340
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
341341

342342
// set the event callback in the current routine
343-
auto& luaRuntime = LuaScriptRuntime::GetCurrent();
343+
auto luaRuntime = LuaScriptRuntime::GetCurrent().GetRef();
344344

345345
luaRuntime->SetEventRoutine([=] (const char* eventName, const char* eventPayload, size_t payloadSize, const char* eventSource)
346346
{
@@ -387,7 +387,7 @@ static int Lua_SetCallRefRoutine(lua_State* L)
387387
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
388388

389389
// set the event callback in the current routine
390-
auto& luaRuntime = LuaScriptRuntime::GetCurrent();
390+
auto luaRuntime = LuaScriptRuntime::GetCurrent().GetRef();
391391

392392
luaRuntime->SetCallRefRoutine([=] (int32_t refId, const char* argsSerialized, size_t argsSize, char** retval, size_t* retvalLength)
393393
{
@@ -443,7 +443,7 @@ static int Lua_SetDeleteRefRoutine(lua_State* L)
443443
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
444444

445445
// set the event callback in the current routine
446-
auto& luaRuntime = LuaScriptRuntime::GetCurrent();
446+
auto luaRuntime = LuaScriptRuntime::GetCurrent().GetRef();
447447

448448
luaRuntime->SetDeleteRefRoutine([=] (int32_t refId)
449449
{
@@ -483,7 +483,7 @@ static int Lua_SetDuplicateRefRoutine(lua_State* L)
483483
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
484484

485485
// set the event callback in the current routine
486-
auto& luaRuntime = LuaScriptRuntime::GetCurrent();
486+
auto luaRuntime = LuaScriptRuntime::GetCurrent().GetRef();
487487

488488
luaRuntime->SetDuplicateRefRoutine([=] (int32_t refId)
489489
{

code/components/gta-streaming-five/component.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"vendor:minhook",
88
"gta:core",
99
"vfs:core",
10-
"rage:formats"
10+
"rage:formats",
11+
"vendor:tbb"
1112
],
1213
"provides": []
1314
}

code/components/gta-streaming-five/src/CfxCollection.cpp

+21-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#define DEBUG_WAS_SET
2525
#endif
2626

27-
#include <concurrent_unordered_map.h>
27+
#include <tbb/concurrent_unordered_map.h>
2828
#include <unordered_set>
2929

3030
#ifdef DEBUG_WAS_SET
@@ -208,9 +208,9 @@ class CfxCollection : public rage::fiCollection
208208

209209
rage::fiCollection* m_parentCollection;
210210

211-
concurrency::concurrent_unordered_map<uint16_t, CollectionEntry> m_entries;
211+
tbb::concurrent_unordered_map<uint16_t, CollectionEntry> m_entries;
212212

213-
concurrency::concurrent_unordered_map<std::string, uint16_t> m_reverseEntries;
213+
tbb::concurrent_unordered_map<std::string, uint16_t> m_reverseEntries;
214214

215215
HandleEntry m_handles[512];
216216

@@ -403,7 +403,12 @@ class CfxCollection : public rage::fiCollection
403403

404404
m_reverseEntries[name] = idx;
405405

406-
return m_entries.insert({ idx, newEntry }).first;
406+
m_entries[idx] = newEntry;
407+
408+
auto it = m_entries.find(idx);
409+
assert(it != m_entries.end());
410+
411+
return it;
407412
}
408413

409414
auto AddEntry(uint16_t idx, const FileEntry* entry)
@@ -413,7 +418,12 @@ class CfxCollection : public rage::fiCollection
413418
newEntry.valid = true;
414419
memcpy(&newEntry.baseEntry, entry, sizeof(FileEntry));
415420

416-
return m_entries.insert({ idx, newEntry }).first;
421+
m_entries[idx] = newEntry;
422+
423+
auto it = m_entries.find(idx);
424+
assert(it != m_entries.end());
425+
426+
return it;
417427
}
418428

419429
CollectionEntry* GetCfxEntry(uint16_t index)
@@ -449,7 +459,7 @@ class CfxCollection : public rage::fiCollection
449459

450460
if (it == m_entries.end() || !it->second.valid)
451461
{
452-
m_entries.unsafe_erase(index);
462+
//m_entries.unsafe_erase(index);
453463

454464
char entryName[256] = { 0x1E };
455465
PseudoCallContext(this)->GetEntryNameToBuffer(index, entryName, sizeof(entryName));
@@ -477,7 +487,8 @@ class CfxCollection : public rage::fiCollection
477487
{
478488
auto n = std::get<std::string>(rit->second);
479489
m_resourceFlags[n] = std::get<rage::ResourceFlags>(rit->second);
480-
m_reverseEntries.unsafe_erase(entryName);
490+
//m_reverseEntries.unsafe_erase(entryName);
491+
m_reverseEntries[entryName] = -1;
481492

482493
// ignore streaming entries insert was here
483494

@@ -631,7 +642,7 @@ class CfxCollection : public rage::fiCollection
631642
{
632643
auto it = m_reverseEntries.find(name);
633644

634-
if (it == m_reverseEntries.end())
645+
if (it == m_reverseEntries.end() || it->second == -1)
635646
{
636647
uint16_t index = PseudoCallContext(this)->GetEntryByName(name);
637648

@@ -1078,7 +1089,7 @@ class CfxCollection : public rage::fiCollection
10781089
const char* colon = strchr(archive, ':');
10791090

10801091
// temporary: make citizen/ path manually
1081-
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
1092+
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
10821093
basePath << converter.to_bytes(MakeRelativeCitPath(L"/"));
10831094

10841095
basePath << std::string(archive, colon);
@@ -1090,7 +1101,7 @@ class CfxCollection : public rage::fiCollection
10901101
const char* colon = strchr(archive, ':');
10911102

10921103
// temporary: make citizen/ path manually
1093-
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
1104+
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
10941105
basePath << converter.to_bytes(MakeRelativeCitPath(L"citizen/"));
10951106

10961107
basePath << std::string(archive, colon);

code/components/ros-patches-five/include/ros/LoopbackTcpServer.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class LoopbackTcpServerManager : public fwRefCountable
126126

127127
bool GetAddrInfoEx(const char* name, const wchar_t* serviceName, const ADDRINFOEXW* hints, ADDRINFOEXW** addrInfo, int* outValue);
128128

129+
bool GetAddrInfoA(const char* name, const char* serviceName, const addrinfo* hints, addrinfo** addrInfo, int* outValue);
130+
129131
bool Connect(SOCKET s, const sockaddr* name, int namelen, int* outValue);
130132

131133
bool Recv(SOCKET s, char* buf, int len, int flags, int* outValue);
@@ -159,4 +161,4 @@ class LoopbackTcpServerManager : public fwRefCountable
159161
}
160162
};
161163

162-
DECLARE_INSTANCE_TYPE(LoopbackTcpServerManager);
164+
DECLARE_INSTANCE_TYPE(LoopbackTcpServerManager);

code/components/ros-patches-five/src/LegitimacyChecking.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ bool VerifyRetailOwnership()
751751
return false;
752752
}
753753

754+
#include <coreconsole.h>
755+
754756
bool LegitimateCopy()
755757
{
756758
return LoadOwnershipTicket() || (VerifySteamOwnership() && SaveOwnershipTicket(g_entitlementSource)) || (VerifyRetailOwnership() && SaveOwnershipTicket(g_entitlementSource));
@@ -773,3 +775,13 @@ namespace ros
773775
return g_entitlementSource;
774776
}
775777
}
778+
779+
static InitFunction initFunction([]()
780+
{
781+
static ConVar<std::string> tokenVar("cl_ownershipTicket", ConVar_None, "");
782+
783+
if (!tokenVar.GetValue().empty())
784+
{
785+
SaveOwnershipTicket(tokenVar.GetValue());
786+
}
787+
});

code/components/ros-patches-five/src/SCUIStub.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ class LoginHandler2 : public net::HttpHandler
212212
{
213213
if (r.error)
214214
{
215+
trace("ROS error: %s\n", r.error.message);
216+
215217
cb("Error contacting Rockstar Online Services.", "");
216218
}
217219
else
@@ -296,6 +298,9 @@ class LoginHandler2 : public net::HttpHandler
296298
{
297299
if (r.error || r.status_code != 200)
298300
{
301+
trace("ROS error: %s\n", r.error.message);
302+
trace("ROS error text: %s\n", r.text);
303+
299304
cb("Error contacting Rockstar Online Services.", "");
300305
}
301306
else

0 commit comments

Comments
 (0)