Skip to content

Commit

Permalink
d3d9-nine: introduce forwarder DLL
Browse files Browse the repository at this point in the history
Because Wine appears to ignore override settings for .dll.so libraries,
introduce a forwarding DLL that will always be identified as native.

Fixes iXit#150
  • Loading branch information
9ary committed Mar 19, 2023
1 parent dea89dc commit c5e1063
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 14 deletions.
15 changes: 15 additions & 0 deletions d3d9-nine/d3d9-nine-forwarder.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
@ stdcall Direct3DShaderValidatorCreate9() d3d9-nine.Direct3DShaderValidatorCreate9
@ stdcall PSGPError() d3d9-nine.PSGPError
@ stdcall PSGPSampleTexture() d3d9-nine.PSGPSampleTexture
@ stdcall D3DPERF_BeginEvent(long wstr) d3d9-nine.D3DPERF_BeginEvent
@ stdcall D3DPERF_EndEvent() d3d9-nine.D3DPERF_EndEvent
@ stdcall D3DPERF_GetStatus() d3d9-nine.D3DPERF_GetStatus
@ stdcall D3DPERF_QueryRepeatFrame() d3d9-nine.D3DPERF_QueryRepeatFrame
@ stdcall D3DPERF_SetMarker(long wstr) d3d9-nine.D3DPERF_SetMarker
@ stdcall D3DPERF_SetOptions(long) d3d9-nine.D3DPERF_SetOptions
@ stdcall D3DPERF_SetRegion(long wstr) d3d9-nine.D3DPERF_SetRegion
@ stdcall DebugSetLevel() d3d9-nine.DebugSetLevel
@ stdcall DebugSetMute() d3d9-nine.DebugSetMute
@ stdcall Direct3DCreate9(long) d3d9-nine.Direct3DCreate9
@ stdcall Direct3DCreate9Ex(long ptr) d3d9-nine.Direct3DCreate9Ex
Binary file added d3d9-nine/d3d9-nine-forwarder32.dll
Binary file not shown.
Binary file added d3d9-nine/d3d9-nine-forwarder64.dll
Binary file not shown.
49 changes: 49 additions & 0 deletions d3d9-nine/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,52 @@ custom_target(
'@OUTPUT@',
],
)

if wine_version.version_compare('>= 7.3')
d3d9_forwarder_builtin = shared_library(
'd3d9-nine-forwarder',
[
d3d9_res,
],
name_prefix : '',
name_suffix : 'dll.builtin',
install : false,
vs_module_defs : 'd3d9-nine-forwarder.spec',
objects : 'd3d9-nine-forwarder.spec',
link_args : [
'-Wb,--data-only',
'-Wb,--filename=d3d9',
],
)

# Wine checks for a string in the header to identify builtin DLLs.
# Work around this with a simple substitution.
d3d9_forwarder = custom_target(
'd3d9-nine-forwarder.dll',
input : d3d9_forwarder_builtin,
output : 'd3d9-nine-forwarder.dll',
install : true,
install_dir : pe_dir,
command : [
sed,
'-e', 's|Wine builtin DLL|Nine forwarder |',
'@INPUT@',
],
capture : true,
)
else
# Support for building data-only modules was added in wine 7.3.
# For binary releases, use a prebuilt version (without resources).
# This is a small (8KiB) and reproducible file that contains
# no executable code, so it shouldn't be a problem.
if target_machine.cpu_family() == 'x86_64'
prebuilt_forwarder = 'd3d9-nine-forwarder64.dll'
else
prebuilt_forwarder = 'd3d9-nine-forwarder32.dll'
endif
install_data(
prebuilt_forwarder,
rename : 'd3d9-nine-forwarder.dll',
install_dir : pe_dir,
)
endif
10 changes: 10 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ wrc = [
'-o', '@OUTPUT@',
]

wine_version = run_command(
[
find_program('winebuild'),
'--version',
],
check : true,
).stdout().split()[-1]

sed = find_program('sed')

if cc.has_function('dlopen')
dep_dl = null_dep
else
Expand Down
42 changes: 28 additions & 14 deletions ninewinecfg/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "resource.h"

static const char * const fn_nine_dll = "d3d9-nine.dll";
static const char * const fn_forwarder_dll = "d3d9-nine-forwarder.dll";
static const char * const fn_backup_dll = "d3d9-nine.bak";
static const char * const fn_d3d9_dll = "d3d9.dll";
static const char * const fn_nine_exe = "ninewinecfg.exe";
Expand Down Expand Up @@ -222,24 +223,36 @@ static BOOL remove_file(LPCSTR filename)
static BOOL create_symlink(LPCSTR target, LPCSTR filename)
{
BOOL ret;
char *fn = unix_filename(filename);
char *target_fn, *fn;

if (!fn)
return FALSE;
if (!(target_fn = unix_filename(target)))
{
ret = FALSE;
goto done;
}

if (!symlink(target, fn))
if (!(fn = unix_filename(filename)))
{
ret = FALSE;
goto free_target_fn;
}

if (!symlink(target_fn, fn))
{
TRACE("Symlinked '%s' to '%s'\n", nine_dbgstr_a(fn),
nine_dbgstr_a(target));
nine_dbgstr_a(target_fn));
ret = TRUE;
} else {
ERR("Failed to symlinked '%s' to '%s'\n", nine_dbgstr_a(fn),
nine_dbgstr_a(target));
nine_dbgstr_a(target_fn));
ret = FALSE;
}

HeapFree(GetProcessHeap(), 0, fn);
free_target_fn:
HeapFree(GetProcessHeap(), 0, target_fn);

done:
return ret;
}

Expand All @@ -253,11 +266,11 @@ static BOOL is_nine_symlink(LPCSTR filename)
return FALSE;

ret = readlink(fn, buf, sizeof(buf));
if ((ret < strlen(fn_nine_dll)) || (ret == sizeof(buf)))
if ((ret < strlen(fn_forwarder_dll)) || (ret == sizeof(buf)))
return FALSE;

buf[ret] = 0;
return !strcmp(buf + ret - strlen(fn_nine_dll), fn_nine_dll);
return !strcmp(buf + ret - strlen(fn_forwarder_dll), fn_forwarder_dll);
}

static BOOL nine_get_system_path(CHAR *pOut, DWORD SizeOut)
Expand Down Expand Up @@ -397,20 +410,21 @@ static void nine_set(BOOL status, BOOL NoOtherArch)
remove_file(dst);
}

hmod = LoadLibraryExA(fn_nine_dll, NULL, DONT_RESOLVE_DLL_REFERENCES);
hmod = LoadLibraryExA(fn_forwarder_dll, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (hmod)
{
Dl_info info;
CHAR buf[MAX_PATH];
DWORD len = GetModuleFileNameA(hmod, (LPSTR)buf, sizeof(buf));

if (dladdr(hmod, &info) && info.dli_fname)
create_symlink(info.dli_fname, dst);
if (len && len < sizeof(buf))
create_symlink(buf, dst);
else
ERR("dladdr failed to get file path\n");
ERR("GetModuleFileNameA failed to get file path\n");

FreeLibrary(hmod);
} else {
LPWSTR msg = load_message(GetLastError());
ERR("Couldn't load %s: %s\n", fn_nine_dll, nine_dbgstr_w(msg));
ERR("Couldn't load %s: %s\n", fn_forwarder_dll, nine_dbgstr_w(msg));
LocalFree(msg);
}
} else {
Expand Down
2 changes: 2 additions & 0 deletions tools/nine-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DST=$(wine winepath -u 'c:\windows\system32')
echo "installing 32bit binaries to $DST"
pe_dir='i386-windows'
so_dir='i386-unix'
ln -sf "$BASE/wine/$pe_dir/d3d9-nine-forwarder.dll" "$DST/"
ln -sf "$BASE/wine/$so_dir/d3d9-nine.dll.so" "$DST/d3d9-nine.dll"
ln -sf "$BASE/wine/$so_dir/ninewinecfg.exe.so" "$DST/ninewinecfg.exe"

Expand All @@ -31,6 +32,7 @@ DST=$(wine64 winepath -u 'c:\windows\system32')
echo "installing 64bit binaries to $DST"
pe_dir='x86_64-windows'
so_dir='x86_64-unix'
ln -sf "$BASE/wine/$pe_dir/d3d9-nine-forwarder.dll" "$DST/"
ln -sf "$BASE/wine/$so_dir/d3d9-nine.dll.so" "$DST/d3d9-nine.dll"
ln -sf "$BASE/wine/$so_dir/ninewinecfg.exe.so" "$DST/ninewinecfg.exe"

Expand Down

0 comments on commit c5e1063

Please sign in to comment.