Use system-wide Wine, DXVK & D9VK for Steam Play/Proton (Windows) games directly from Linux Steam client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

210 lines
8.2 KiB

Original patch code by Valve Corporation
Original commits:
https://github.com/ValveSoftware/wine/commit/45a30e45c6ba6f0a28e2df4107d2e73203e97c64
https://github.com/ValveSoftware/wine/commit/46759f772e5e82e1c063c93d743fafa018f406b2
https://github.com/ValveSoftware/wine/commit/667994216734d72e2b9a4df268aae87bd8189d43
https://github.com/ValveSoftware/wine/commit/050f036aa031322e4f32ffd9b4a90edb24b78609
https://github.com/ValveSoftware/wine/commit/647086c049ac7e05750bf01c1cdb5a37f436a558
https://github.com/ValveSoftware/wine/commit/6a02230c44b7a26422fdb6d4edbb8bcbc2f3d035
LICENSE: See https://github.com/ValveSoftware/wine
Target Wine version of this patch file:
Wine 4.9 (Staging)
--- a/dlls/kernel32/module.c
+++ b/dlls/kernel32/module.c
@@ -77,6 +77,32 @@ static CRITICAL_SECTION_DEBUG critsect_d
};
static CRITICAL_SECTION dlldir_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+#if defined(__x86_64__)
+static const WCHAR steamclientW[] = {'s','t','e','a','m','c','l','i','e','n','t','6','4',0};
+static const WCHAR steamclient_pathW[] = {'C',':','\\','P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','S','t','e','a','m','\\','s','t','e','a','m','c','l','i','e','n','t','6','4','.','d','l','l',0};
+#else
+static const WCHAR steamclientW[] = {'s','t','e','a','m','c','l','i','e','n','t',0};
+static const WCHAR steamclient_pathW[] = {'C',':','\\','P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','S','t','e','a','m','\\','s','t','e','a','m','c','l','i','e','n','t','.','d','l','l',0};
+#endif
+static const WCHAR steamProgramPathW[] = {'C',':','\\','P','r','o','g','r','a','m',' ','F','i','l','e','s',' ','(','x','8','6',')','\\','S','t','e','a','m',0};
+static const DWORD steamProgramPathW_len = 28;
+static const WCHAR steamdllW[] = {'S','t','e','a','m','.','d','l','l',0};
+static const DWORD steamdllW_len = 9;
+static HMODULE steamclient_hmod = NULL;
+static HMODULE lsteamclient_hmod = NULL;
+
+static WCHAR *strcasestrW( const WCHAR *str, const WCHAR *sub )
+{
+ while (*str)
+ {
+ const WCHAR *p1 = str, *p2 = sub;
+ while (*p1 && *p2 && tolowerW(*p1) == tolowerW(*p2)) { p1++; p2++; }
+ if (!*p2) return (WCHAR *)str;
+ str++;
+ }
+ return NULL;
+}
+
/****************************************************************************
* GetDllDirectoryA (KERNEL32.@)
*/
@@ -445,10 +471,16 @@ BOOL WINAPI GetModuleHandleExW( DWORD fl
{
void *dummy;
if (!(ret = RtlPcToFileHeader( (void *)name, &dummy ))) status = STATUS_DLL_NOT_FOUND;
+ if(steamclient_hmod != NULL && ret == lsteamclient_hmod)
+ ret = steamclient_hmod;
}
else
{
UNICODE_STRING wstr;
+ if(steamclient_hmod != NULL && strcasestrW(name, steamclientW)){
+ *module = steamclient_hmod;
+ return TRUE;
+ }
RtlInitUnicodeString( &wstr, name );
status = LdrGetDllHandle( NULL, 0, &wstr, &ret );
}
@@ -557,6 +589,11 @@ DWORD WINAPI GetModuleFileNameW( HMODULE
NTSTATUS nts;
WIN16_SUBSYSTEM_TIB *win16_tib;
+ if(steamclient_hmod != NULL && hModule == steamclient_hmod){
+ memcpy(lpFileName, steamclient_pathW, sizeof(steamclient_pathW));
+ return sizeof(steamclient_pathW)/sizeof(WCHAR);
+ }
+
if (!hModule && ((win16_tib = NtCurrentTeb()->Tib.SubSystemTib)) && win16_tib->exe_name)
{
len = min(size, win16_tib->exe_name->Length / sizeof(WCHAR));
@@ -600,11 +637,16 @@ static const WCHAR *get_dll_system_path(
if (!cached_path)
{
WCHAR *p, *path;
- int len = 1;
+ int len = 2;
+
+ len += steamProgramPathW_len;
len += 2 * GetSystemDirectoryW( NULL, 0 );
len += GetWindowsDirectoryW( NULL, 0 );
p = path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+ strcpyW(p, steamProgramPathW);
+ p += steamProgramPathW_len;
+ *p++ = ';';
GetSystemDirectoryW( p, path + len - p);
p += strlenW(p);
/* if system directory ends in "32" add 16-bit version too */
@@ -933,6 +975,7 @@ static HMODULE load_library( const UNICO
NTSTATUS nts;
HMODULE hModule;
WCHAR *load_path;
+ const WCHAR *p;
const DWORD load_library_search_flags = (LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
LOAD_LIBRARY_SEARCH_APPLICATION_DIR |
LOAD_LIBRARY_SEARCH_USER_DIRS |
@@ -946,6 +989,36 @@ static HMODULE load_library( const UNICO
if( flags & unsupported_flags)
FIXME("unsupported flag(s) used (flags: 0x%08x)\n", flags);
+ if((p = strcasestrW(libname->Buffer, steamclientW)) &&
+ (p == libname->Buffer ||
+ *(p - 1) != 'l')){
+
+ if(!lsteamclient_hmod)
+ lsteamclient_hmod = LoadLibraryA("lsteamclient.dll");
+
+ if(!steamclient_hmod){
+ HANDLE f = CreateFileW(steamclient_pathW,
+ GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if(f != INVALID_HANDLE_VALUE){
+ DWORD sz, readed;
+
+ sz = GetFileSize(f, NULL);
+
+ steamclient_hmod = HeapAlloc(GetProcessHeap(), 0, sz);
+ ReadFile(f, steamclient_hmod, sz, &readed, NULL);
+
+ CloseHandle(f);
+ }else{
+ /* this will fail DRM checks, but otherwise should work */
+ ERR("somehow failed to load steamclient\n");
+ steamclient_hmod = lsteamclient_hmod;
+ }
+ }
+
+ return steamclient_hmod;
+ }
+
if (flags & load_library_search_flags)
load_path = get_dll_load_path_search_flags( libname->Buffer, flags );
else
@@ -1101,6 +1174,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeLibrar
return FALSE;
}
+ if(steamclient_hmod != NULL && hLibModule == steamclient_hmod)
+ return TRUE;
+
if ((ULONG_PTR)hLibModule & 3) /* this is a datafile module */
{
void *ptr = (void *)((ULONG_PTR)hLibModule & ~3);
@@ -1155,6 +1231,9 @@ FARPROC get_proc_address( HMODULE hModul
if (!hModule) hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
+ if(steamclient_hmod != NULL && hModule == steamclient_hmod)
+ hModule = lsteamclient_hmod;
+
if ((ULONG_PTR)function >> 16)
{
ANSI_STRING str;
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -3412,6 +3412,22 @@ HANDLE WINAPI OpenProcess( DWORD access,
OBJECT_ATTRIBUTES attr;
CLIENT_ID cid;
+ if(id == 0xfffe)
+ /* STEAMOS HACK:
+ * On Windows, the Steam client puts its process ID into the registry
+ * at:
+ *
+ * [HKCU\Software\Valve\Steam\ActiveProcess]
+ * PID=dword:00000008
+ *
+ * Games get that pid from the registry and then query it with
+ * OpenProcess to ensure Steam is running. Since we aren't running the
+ * Windows Steam in Wine, instead we hack this magic number into the
+ * registry and then substitute the game's process itself in its place
+ * so it can query a valid process.
+ */
+ id = GetCurrentProcessId();
+
cid.UniqueProcess = ULongToHandle(id);
cid.UniqueThread = 0; /* FIXME ? */
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -181,6 +181,7 @@
CurrentVersionNT="Software\Microsoft\Windows NT\CurrentVersion"
FontSubStr="Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes"
Control="System\CurrentControlSet\Control"
+FontsNT="Software\Microsoft\Windows NT\CurrentVersion\Fonts"
[Classes]
HKCR,.chm,,2,"chm.file"
@@ -627,6 +628,11 @@
HKLM,%FontSubStr%,"Times New Roman Greek,161",,"Times New Roman,161"
HKLM,%FontSubStr%,"Times New Roman TUR,162",,"Times New Roman,162"
HKLM,System\CurrentControlSet\Hardware Profiles\Current\Software\Fonts,"LogPixels",0x10003,0x00000060
+HKLM,%FontsNT%,"Arial (TrueType)",,"arial.ttf"
+HKLM,%FontsNT%,"Arial Bold (TrueType)",,"arialbd.ttf"
+HKLM,%FontsNT%,"Times New Roman (TrueType)",,"times.ttf"
+HKLM,%FontsNT%,"Courier New (TrueType)",,"cour.ttf"
+HKCU,Software\Wine\Fonts\Replacements,"Palatino Linotype",,"Times New Roman"
[MCI]
HKLM,%Mci32Str%,"AVIVideo",,"mciavi32.dll"