forked from Frogging-Family/wine-tkg-git
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
242 additions
and
0 deletions.
There are no files selected for viewing
242 changes: 242 additions & 0 deletions
242
wine-tkg-git/wine-tkg-userpatches/lsteamclient_trampolines.mypatch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
From 2c9734c18076e10abfb143ddcd47eb36d43fdaf4 Mon Sep 17 00:00:00 2001 | ||
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com> | ||
Date: Tue, 22 Nov 2022 11:02:52 +0100 | ||
Subject: [PATCH] HACK: steam: ntdll: Setup steamclient trampolines to | ||
lsteamclient. | ||
|
||
This uses exec page faults to jump from native steamclient into our | ||
lsteamclient entry points. | ||
--- | ||
dlls/ntdll/loader.c | 23 +++++++++++ | ||
dlls/ntdll/unix/loader.c | 70 +++++++++++++++++++++++++++++++++ | ||
dlls/ntdll/unix/signal_i386.c | 7 ++++ | ||
dlls/ntdll/unix/signal_x86_64.c | 7 ++++ | ||
dlls/ntdll/unix/unix_private.h | 1 + | ||
dlls/ntdll/unixlib.h | 7 ++++ | ||
6 files changed, 115 insertions(+) | ||
|
||
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c | ||
index 464d190be87..1e60825b525 100644 | ||
--- a/dlls/ntdll/loader.c | ||
+++ b/dlls/ntdll/loader.c | ||
@@ -2184,12 +2184,16 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, | ||
DWORD flags, BOOL system, WINE_MODREF **pwm ) | ||
{ | ||
static const char builtin_signature[] = "Wine builtin DLL"; | ||
+ static HMODULE lsteamclient = NULL; | ||
char *signature = (char *)((IMAGE_DOS_HEADER *)*module + 1); | ||
+ UNICODE_STRING lsteamclient_us; | ||
BOOL is_builtin; | ||
IMAGE_NT_HEADERS *nt; | ||
WINE_MODREF *wm; | ||
NTSTATUS status; | ||
SIZE_T map_size; | ||
+ WCHAR *basename, *tmp; | ||
+ ULONG basename_len; | ||
|
||
if (!(nt = RtlImageNtHeader( *module ))) return STATUS_INVALID_IMAGE_FORMAT; | ||
|
||
@@ -2210,6 +2214,25 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, | ||
|
||
update_load_config( *module ); | ||
|
||
+ basename = nt_name->Buffer; | ||
+ if ((tmp = wcsrchr(basename, '\\'))) basename = tmp + 1; | ||
+ if ((tmp = wcsrchr(basename, '/'))) basename = tmp + 1; | ||
+ basename_len = wcslen(basename); | ||
+ if (basename_len >= 4 && !wcscmp(basename + basename_len - 4, L".dll")) basename_len -= 4; | ||
+ | ||
+ if ((!RtlCompareUnicodeStrings(basename, basename_len, L"steamclient", 11, TRUE) || | ||
+ !RtlCompareUnicodeStrings(basename, basename_len, L"steamclient64", 13, TRUE) || | ||
+ !RtlCompareUnicodeStrings(basename, basename_len, L"gameoverlayrenderer", 19, TRUE) || | ||
+ !RtlCompareUnicodeStrings(basename, basename_len, L"gameoverlayrenderer64", 21, TRUE)) && | ||
+ RtlCreateUnicodeStringFromAsciiz(&lsteamclient_us, "lsteamclient.dll") && | ||
+ (lsteamclient || LdrLoadDll(load_path, 0, &lsteamclient_us, &lsteamclient) == STATUS_SUCCESS)) | ||
+ { | ||
+ struct steamclient_setup_trampolines_params params = {.src_mod = *module, .tgt_mod = lsteamclient}; | ||
+ WINE_UNIX_CALL( unix_steamclient_setup_trampolines, ¶ms ); | ||
+ wm->ldr.Flags |= LDR_DONT_RESOLVE_REFS; | ||
+ flags |= DONT_RESOLVE_DLL_REFERENCES; | ||
+ } | ||
+ | ||
/* fixup imports */ | ||
|
||
if (!(flags & DONT_RESOLVE_DLL_REFERENCES) && | ||
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c | ||
index 803d8079213..028846f346a 100644 | ||
--- a/dlls/ntdll/unix/loader.c | ||
+++ b/dlls/ntdll/unix/loader.c | ||
@@ -972,6 +972,75 @@ static NTSTATUS load_so_dll( void *args ) | ||
return status; | ||
} | ||
|
||
+static void *steamclient_srcs[128]; | ||
+static void *steamclient_tgts[128]; | ||
+static int steamclient_count; | ||
+ | ||
+void *steamclient_handle_fault( LPCVOID addr, DWORD err ) | ||
+{ | ||
+ int i; | ||
+ | ||
+ if (!(err & EXCEPTION_EXECUTE_FAULT)) return NULL; | ||
+ | ||
+ for (i = 0; i < steamclient_count; ++i) | ||
+ { | ||
+ if (addr == steamclient_srcs[i]) | ||
+ return steamclient_tgts[i]; | ||
+ } | ||
+ | ||
+ return NULL; | ||
+} | ||
+ | ||
+static NTSTATUS steamclient_setup_trampolines( void *args ) | ||
+{ | ||
+ struct steamclient_setup_trampolines_params *params = args; | ||
+ HMODULE src_mod = params->src_mod, tgt_mod = params->tgt_mod; | ||
+ SYSTEM_BASIC_INFORMATION info; | ||
+ IMAGE_NT_HEADERS *src_nt = (IMAGE_NT_HEADERS *)((UINT_PTR)src_mod + ((IMAGE_DOS_HEADER *)src_mod)->e_lfanew); | ||
+ IMAGE_NT_HEADERS *tgt_nt = (IMAGE_NT_HEADERS *)((UINT_PTR)tgt_mod + ((IMAGE_DOS_HEADER *)tgt_mod)->e_lfanew); | ||
+ IMAGE_SECTION_HEADER *src_sec = (IMAGE_SECTION_HEADER *)(src_nt + 1); | ||
+ const IMAGE_EXPORT_DIRECTORY *src_exp, *tgt_exp; | ||
+ const DWORD *names; | ||
+ SIZE_T size; | ||
+ void *addr, *src_addr, *tgt_addr; | ||
+ char *name; | ||
+ UINT_PTR page_mask; | ||
+ int i; | ||
+ | ||
+ virtual_get_system_info( &info, !!NtCurrentTeb()->WowTebOffset ); | ||
+ page_mask = info.PageSize - 1; | ||
+ | ||
+ for (i = 0; i < src_nt->FileHeader.NumberOfSections; ++i) | ||
+ { | ||
+ if (memcmp(src_sec[i].Name, ".text", 5)) continue; | ||
+ addr = (void *)(((UINT_PTR)src_mod + src_sec[i].VirtualAddress) & ~page_mask); | ||
+ size = (src_sec[i].Misc.VirtualSize + page_mask) & ~page_mask; | ||
+ mprotect(addr, size, PROT_READ); | ||
+ } | ||
+ | ||
+ src_exp = get_module_data_dir( src_mod, IMAGE_FILE_EXPORT_DIRECTORY, NULL ); | ||
+ tgt_exp = get_module_data_dir( tgt_mod, IMAGE_FILE_EXPORT_DIRECTORY, NULL ); | ||
+ names = (const DWORD *)((UINT_PTR)src_mod + src_exp->AddressOfNames); | ||
+ for (i = 0; i < src_exp->NumberOfNames; ++i) | ||
+ { | ||
+ if (!names[i] || !(name = (char *)((UINT_PTR)src_mod + names[i]))) continue; | ||
+ if (!(src_addr = (void *)find_named_export(src_mod, src_exp, name))) continue; | ||
+ if (!(tgt_addr = (void *)find_named_export(tgt_mod, tgt_exp, name))) continue; | ||
+ assert(steamclient_count < ARRAY_SIZE(steamclient_srcs)); | ||
+ steamclient_srcs[steamclient_count] = src_addr; | ||
+ steamclient_tgts[steamclient_count] = tgt_addr; | ||
+ steamclient_count++; | ||
+ } | ||
+ | ||
+ src_addr = (void *)((UINT_PTR)src_mod + src_nt->OptionalHeader.AddressOfEntryPoint); | ||
+ tgt_addr = (void *)((UINT_PTR)tgt_mod + tgt_nt->OptionalHeader.AddressOfEntryPoint); | ||
+ assert(steamclient_count < ARRAY_SIZE(steamclient_srcs)); | ||
+ steamclient_srcs[steamclient_count] = src_addr; | ||
+ steamclient_tgts[steamclient_count] = tgt_addr; | ||
+ steamclient_count++; | ||
+ | ||
+ return STATUS_SUCCESS; | ||
+} | ||
|
||
static const unixlib_entry_t unix_call_funcs[] = | ||
{ | ||
@@ -983,6 +1052,7 @@ static const unixlib_entry_t unix_call_funcs[] = | ||
unixcall_wine_server_handle_to_fd, | ||
unixcall_wine_spawnvp, | ||
system_time_precise, | ||
+ steamclient_setup_trampolines, | ||
}; | ||
|
||
|
||
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c | ||
index 751b0081534..d1b2fb66563 100644 | ||
--- a/dlls/ntdll/unix/signal_i386.c | ||
+++ b/dlls/ntdll/unix/signal_i386.c | ||
@@ -1906,6 +1906,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) | ||
struct xcontext xcontext; | ||
ucontext_t *ucontext = sigcontext; | ||
void *stack = setup_exception_record( sigcontext, &rec, &xcontext ); | ||
+ void *steamclient_addr = NULL; | ||
|
||
switch (TRAP_sig(ucontext)) | ||
{ | ||
@@ -1940,6 +1941,12 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) | ||
} | ||
break; | ||
case TRAP_x86_PAGEFLT: /* Page fault */ | ||
+ if ((steamclient_addr = steamclient_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x09 ))) | ||
+ { | ||
+ EIP_sig(ucontext) = (intptr_t)steamclient_addr; | ||
+ return; | ||
+ } | ||
+ | ||
rec.NumberParameters = 2; | ||
rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09; | ||
rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; | ||
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c | ||
index ab544908883..ae100e05e63 100644 | ||
--- a/dlls/ntdll/unix/signal_x86_64.c | ||
+++ b/dlls/ntdll/unix/signal_x86_64.c | ||
@@ -1929,6 +1929,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) | ||
EXCEPTION_RECORD rec = { 0 }; | ||
struct xcontext context; | ||
ucontext_t *ucontext = init_handler( sigcontext ); | ||
+ void *steamclient_addr = NULL; | ||
|
||
rec.ExceptionAddress = (void *)RIP_sig(ucontext); | ||
save_context( &context, ucontext ); | ||
@@ -1960,6 +1961,12 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) | ||
} | ||
break; | ||
case TRAP_x86_PAGEFLT: /* Page fault */ | ||
+ if ((steamclient_addr = steamclient_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x09 ))) | ||
+ { | ||
+ RIP_sig(ucontext) = (intptr_t)steamclient_addr; | ||
+ return; | ||
+ } | ||
+ | ||
rec.NumberParameters = 2; | ||
rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09; | ||
rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; | ||
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h | ||
index 07f2724eac7..c2292765ffb 100644 | ||
--- a/dlls/ntdll/unix/unix_private.h | ||
+++ b/dlls/ntdll/unix/unix_private.h | ||
@@ -226,6 +226,7 @@ extern unsigned int alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, stru | ||
data_size_t *ret_len ); | ||
extern NTSTATUS system_time_precise( void *args ); | ||
|
||
+extern void *steamclient_handle_fault( LPCVOID addr, DWORD err ); | ||
extern void *anon_mmap_fixed( void *start, size_t size, int prot, int flags ); | ||
extern void *anon_mmap_alloc( size_t size, int prot ); | ||
extern void virtual_init(void); | ||
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h | ||
index 9cb444342fe..475e532b8cf 100644 | ||
--- a/dlls/ntdll/unixlib.h | ||
+++ b/dlls/ntdll/unixlib.h | ||
@@ -66,6 +66,12 @@ struct unwind_builtin_dll_params | ||
CONTEXT *context; | ||
}; | ||
|
||
+struct steamclient_setup_trampolines_params | ||
+{ | ||
+ HMODULE src_mod; | ||
+ HMODULE tgt_mod; | ||
+}; | ||
+ | ||
enum ntdll_unix_funcs | ||
{ | ||
unix_load_so_dll, | ||
@@ -76,6 +82,7 @@ enum ntdll_unix_funcs | ||
unix_wine_server_handle_to_fd, | ||
unix_wine_spawnvp, | ||
unix_system_time_precise, | ||
+ unix_steamclient_setup_trampolines, | ||
}; | ||
|
||
extern unixlib_handle_t __wine_unixlib_handle; | ||
-- | ||
GitLab | ||
|