Skip to content

Commit

Permalink
add lsteamclient trampolines
Browse files Browse the repository at this point in the history
  • Loading branch information
marzent committed Jan 28, 2024
1 parent 2b60c23 commit ce28168
Showing 1 changed file with 242 additions and 0 deletions.
242 changes: 242 additions & 0 deletions wine-tkg-git/wine-tkg-userpatches/lsteamclient_trampolines.mypatch
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, &params );
+ 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

0 comments on commit ce28168

Please sign in to comment.