Skip to content

Commit c5e1063

Browse files
committed
d3d9-nine: introduce forwarder DLL
Because Wine appears to ignore override settings for .dll.so libraries, introduce a forwarding DLL that will always be identified as native. Fixes #150
1 parent dea89dc commit c5e1063

File tree

7 files changed

+104
-14
lines changed

7 files changed

+104
-14
lines changed

d3d9-nine/d3d9-nine-forwarder.spec

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
@ stdcall Direct3DShaderValidatorCreate9() d3d9-nine.Direct3DShaderValidatorCreate9
3+
@ stdcall PSGPError() d3d9-nine.PSGPError
4+
@ stdcall PSGPSampleTexture() d3d9-nine.PSGPSampleTexture
5+
@ stdcall D3DPERF_BeginEvent(long wstr) d3d9-nine.D3DPERF_BeginEvent
6+
@ stdcall D3DPERF_EndEvent() d3d9-nine.D3DPERF_EndEvent
7+
@ stdcall D3DPERF_GetStatus() d3d9-nine.D3DPERF_GetStatus
8+
@ stdcall D3DPERF_QueryRepeatFrame() d3d9-nine.D3DPERF_QueryRepeatFrame
9+
@ stdcall D3DPERF_SetMarker(long wstr) d3d9-nine.D3DPERF_SetMarker
10+
@ stdcall D3DPERF_SetOptions(long) d3d9-nine.D3DPERF_SetOptions
11+
@ stdcall D3DPERF_SetRegion(long wstr) d3d9-nine.D3DPERF_SetRegion
12+
@ stdcall DebugSetLevel() d3d9-nine.DebugSetLevel
13+
@ stdcall DebugSetMute() d3d9-nine.DebugSetMute
14+
@ stdcall Direct3DCreate9(long) d3d9-nine.Direct3DCreate9
15+
@ stdcall Direct3DCreate9Ex(long ptr) d3d9-nine.Direct3DCreate9Ex

d3d9-nine/d3d9-nine-forwarder32.dll

8 KB
Binary file not shown.

d3d9-nine/d3d9-nine-forwarder64.dll

8 KB
Binary file not shown.

d3d9-nine/meson.build

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,52 @@ custom_target(
7373
'@OUTPUT@',
7474
],
7575
)
76+
77+
if wine_version.version_compare('>= 7.3')
78+
d3d9_forwarder_builtin = shared_library(
79+
'd3d9-nine-forwarder',
80+
[
81+
d3d9_res,
82+
],
83+
name_prefix : '',
84+
name_suffix : 'dll.builtin',
85+
install : false,
86+
vs_module_defs : 'd3d9-nine-forwarder.spec',
87+
objects : 'd3d9-nine-forwarder.spec',
88+
link_args : [
89+
'-Wb,--data-only',
90+
'-Wb,--filename=d3d9',
91+
],
92+
)
93+
94+
# Wine checks for a string in the header to identify builtin DLLs.
95+
# Work around this with a simple substitution.
96+
d3d9_forwarder = custom_target(
97+
'd3d9-nine-forwarder.dll',
98+
input : d3d9_forwarder_builtin,
99+
output : 'd3d9-nine-forwarder.dll',
100+
install : true,
101+
install_dir : pe_dir,
102+
command : [
103+
sed,
104+
'-e', 's|Wine builtin DLL|Nine forwarder |',
105+
'@INPUT@',
106+
],
107+
capture : true,
108+
)
109+
else
110+
# Support for building data-only modules was added in wine 7.3.
111+
# For binary releases, use a prebuilt version (without resources).
112+
# This is a small (8KiB) and reproducible file that contains
113+
# no executable code, so it shouldn't be a problem.
114+
if target_machine.cpu_family() == 'x86_64'
115+
prebuilt_forwarder = 'd3d9-nine-forwarder64.dll'
116+
else
117+
prebuilt_forwarder = 'd3d9-nine-forwarder32.dll'
118+
endif
119+
install_data(
120+
prebuilt_forwarder,
121+
rename : 'd3d9-nine-forwarder.dll',
122+
install_dir : pe_dir,
123+
)
124+
endif

meson.build

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ wrc = [
5757
'-o', '@OUTPUT@',
5858
]
5959

60+
wine_version = run_command(
61+
[
62+
find_program('winebuild'),
63+
'--version',
64+
],
65+
check : true,
66+
).stdout().split()[-1]
67+
68+
sed = find_program('sed')
69+
6070
if cc.has_function('dlopen')
6171
dep_dl = null_dep
6272
else

ninewinecfg/main.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "resource.h"
3030

3131
static const char * const fn_nine_dll = "d3d9-nine.dll";
32+
static const char * const fn_forwarder_dll = "d3d9-nine-forwarder.dll";
3233
static const char * const fn_backup_dll = "d3d9-nine.bak";
3334
static const char * const fn_d3d9_dll = "d3d9.dll";
3435
static const char * const fn_nine_exe = "ninewinecfg.exe";
@@ -222,24 +223,36 @@ static BOOL remove_file(LPCSTR filename)
222223
static BOOL create_symlink(LPCSTR target, LPCSTR filename)
223224
{
224225
BOOL ret;
225-
char *fn = unix_filename(filename);
226+
char *target_fn, *fn;
226227

227-
if (!fn)
228-
return FALSE;
228+
if (!(target_fn = unix_filename(target)))
229+
{
230+
ret = FALSE;
231+
goto done;
232+
}
229233

230-
if (!symlink(target, fn))
234+
if (!(fn = unix_filename(filename)))
235+
{
236+
ret = FALSE;
237+
goto free_target_fn;
238+
}
239+
240+
if (!symlink(target_fn, fn))
231241
{
232242
TRACE("Symlinked '%s' to '%s'\n", nine_dbgstr_a(fn),
233-
nine_dbgstr_a(target));
243+
nine_dbgstr_a(target_fn));
234244
ret = TRUE;
235245
} else {
236246
ERR("Failed to symlinked '%s' to '%s'\n", nine_dbgstr_a(fn),
237-
nine_dbgstr_a(target));
247+
nine_dbgstr_a(target_fn));
238248
ret = FALSE;
239249
}
240250

241251
HeapFree(GetProcessHeap(), 0, fn);
252+
free_target_fn:
253+
HeapFree(GetProcessHeap(), 0, target_fn);
242254

255+
done:
243256
return ret;
244257
}
245258

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

255268
ret = readlink(fn, buf, sizeof(buf));
256-
if ((ret < strlen(fn_nine_dll)) || (ret == sizeof(buf)))
269+
if ((ret < strlen(fn_forwarder_dll)) || (ret == sizeof(buf)))
257270
return FALSE;
258271

259272
buf[ret] = 0;
260-
return !strcmp(buf + ret - strlen(fn_nine_dll), fn_nine_dll);
273+
return !strcmp(buf + ret - strlen(fn_forwarder_dll), fn_forwarder_dll);
261274
}
262275

263276
static BOOL nine_get_system_path(CHAR *pOut, DWORD SizeOut)
@@ -397,20 +410,21 @@ static void nine_set(BOOL status, BOOL NoOtherArch)
397410
remove_file(dst);
398411
}
399412

400-
hmod = LoadLibraryExA(fn_nine_dll, NULL, DONT_RESOLVE_DLL_REFERENCES);
413+
hmod = LoadLibraryExA(fn_forwarder_dll, NULL, DONT_RESOLVE_DLL_REFERENCES);
401414
if (hmod)
402415
{
403-
Dl_info info;
416+
CHAR buf[MAX_PATH];
417+
DWORD len = GetModuleFileNameA(hmod, (LPSTR)buf, sizeof(buf));
404418

405-
if (dladdr(hmod, &info) && info.dli_fname)
406-
create_symlink(info.dli_fname, dst);
419+
if (len && len < sizeof(buf))
420+
create_symlink(buf, dst);
407421
else
408-
ERR("dladdr failed to get file path\n");
422+
ERR("GetModuleFileNameA failed to get file path\n");
409423

410424
FreeLibrary(hmod);
411425
} else {
412426
LPWSTR msg = load_message(GetLastError());
413-
ERR("Couldn't load %s: %s\n", fn_nine_dll, nine_dbgstr_w(msg));
427+
ERR("Couldn't load %s: %s\n", fn_forwarder_dll, nine_dbgstr_w(msg));
414428
LocalFree(msg);
415429
}
416430
} else {

tools/nine-install.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ DST=$(wine winepath -u 'c:\windows\system32')
1313
echo "installing 32bit binaries to $DST"
1414
pe_dir='i386-windows'
1515
so_dir='i386-unix'
16+
ln -sf "$BASE/wine/$pe_dir/d3d9-nine-forwarder.dll" "$DST/"
1617
ln -sf "$BASE/wine/$so_dir/d3d9-nine.dll.so" "$DST/d3d9-nine.dll"
1718
ln -sf "$BASE/wine/$so_dir/ninewinecfg.exe.so" "$DST/ninewinecfg.exe"
1819

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

0 commit comments

Comments
 (0)