From 7e926a9aa9ce31154d623019344eb834f6b6229d Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 12 Nov 2021 11:55:37 -0600 Subject: [PATCH] ntdll: Allow loading system DLLs from a path specified at configure time. Many distributions provide MinGW-compiled system DLLs which are currently bundled with Wine. Unfortunately, while MinGW pkg-config can be used to detect the linking path, there is no standardized runtime path, and many distributions in fact use different paths. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- configure | 14 ++++++++++++++ configure.ac | 2 ++ dlls/ntdll/Makefile.in | 1 + dlls/ntdll/loader.c | 3 +++ dlls/ntdll/unix/env.c | 30 ++++++++++++++++++++++++++++++ dlls/ntdll/unix/loader.c | 23 +++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 1 + 7 files changed, 74 insertions(+) diff --git a/configure b/configure index a2298117ae1..ded6e71b815 100755 --- a/configure +++ b/configure @@ -834,6 +834,7 @@ build_os build_vendor build_cpu build +system_dllpath target_alias host_alias build_alias @@ -931,6 +932,7 @@ with_xrender with_xshape with_xshm with_xxf86vm +with_system_dllpath with_wine_tools with_wine64 enable_largefile @@ -2719,6 +2721,9 @@ Optional Packages: --without-xshape do not use the Xshape extension --without-xshm do not use XShm (shared memory extension) --without-xxf86vm do not use XFree video mode extension + --with-system-dllpath=PATH + load external PE dependencies from colon-separated + path PATH --with-wine-tools=DIR use Wine tools from directory DIR --with-wine64=DIR use the 64-bit Wine in DIR for a Wow64 build --with-x use the X Window System @@ -4765,6 +4770,14 @@ fi +# Check whether --with-system-dllpath was given. +if test ${with_system_dllpath+y} +then : + withval=$with_system_dllpath; system_dllpath=$withval + +fi + + # Check whether --with-wine-tools was given. if test ${with_wine_tools+y} then : @@ -23020,6 +23033,7 @@ LIBS = $LIBS build_alias = $build_alias host_alias = $host_alias target_alias = $target_alias +system_dllpath = $system_dllpath build = $build build_cpu = $build_cpu build_vendor = $build_vendor diff --git a/configure.ac b/configure.ac index 1c716b4ec00..4f7c7209da9 100644 --- a/configure.ac +++ b/configure.ac @@ -90,6 +90,8 @@ AC_ARG_WITH(xshm, AS_HELP_STRING([--without-xshm],[do not use XShm (shared AC_ARG_WITH(xxf86vm, AS_HELP_STRING([--without-xxf86vm],[do not use XFree video mode extension]), [if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_xf86vmode_h=no; ac_cv_header_X11_extensions_xf86vmproto_h=no; fi]) +AC_ARG_WITH(system-dllpath,AS_HELP_STRING([--with-system-dllpath=PATH],[load external PE dependencies from colon-separated path PATH]), + AC_SUBST(system_dllpath,[$withval])) AC_ARG_WITH(wine-tools,AS_HELP_STRING([--with-wine-tools=DIR],[use Wine tools from directory DIR])) AC_ARG_WITH(wine64, AS_HELP_STRING([--with-wine64=DIR],[use the 64-bit Wine in DIR for a Wow64 build])) diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index d3be1fad0bc..7e823208840 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -72,5 +72,6 @@ EXTRA_OBJS = unix/version.o unix_loader_EXTRADEFS = \ -DBINDIR=\"${bindir}\" \ + -DSYSTEMDLLPATH=\"${system_dllpath}\" \ -DDLL_TO_BINDIR=\"`${MAKEDEP} -R ${dlldir} ${bindir}`\" \ -DBIN_TO_DATADIR=\"`${MAKEDEP} -R ${bindir} ${datadir}/wine`\" diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index e32df565c64..aec404f8c9b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -95,6 +95,7 @@ static int free_lib_count; /* recursion depth of LdrUnloadDll calls */ static ULONG path_safe_mode; /* path mode set by RtlSetSearchPathMode */ static ULONG dll_safe_mode = 1; /* dll search mode */ static UNICODE_STRING dll_directory; /* extra path for LdrSetDllDirectory */ +static UNICODE_STRING system_dll_path; /* path to search for system dependency dlls */ static DWORD default_search_flags; /* default flags set by LdrSetDefaultDllDirectories */ static WCHAR *default_load_path; /* default dll search path */ @@ -3993,6 +3994,8 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR load_global_options(); version_init(); + get_env_var( L"WINESYSTEMDLLPATH", 0, &system_dll_path ); + wm = build_main_module(); wm->ldr.LoadCount = -1; diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index 0f195a33846..f36899fe880 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -1281,6 +1281,35 @@ static void add_path_var( WCHAR **env, SIZE_T *pos, SIZE_T *size, const char *na } +static void add_system_dll_path_var( WCHAR **env, SIZE_T *pos, SIZE_T *size ) +{ + WCHAR *path = NULL; + size_t path_len = 0; + DWORD i; + + for (i = 0; system_dll_paths[i]; ++i) + { + WCHAR *nt_name = NULL; + + if (!unix_to_nt_file_name( system_dll_paths[i], &nt_name )) + { + size_t len = wcslen( nt_name ); + path = realloc( path, (path_len + len + 1) * sizeof(WCHAR) ); + memcpy( path + path_len, nt_name, len * sizeof(WCHAR) ); + path[path_len + len] = ';'; + path_len += len + 1; + free( nt_name ); + } + } + if (path_len) + { + path[path_len - 1] = 0; + append_envW( env, pos, size, "WINESYSTEMDLLPATH", path ); + free( path ); + } +} + + /************************************************************************* * add_dynamic_environment * @@ -1303,6 +1332,7 @@ static void add_dynamic_environment( WCHAR **env, SIZE_T *pos, SIZE_T *size ) } sprintf( str, "WINEDLLDIR%u", i ); append_envW( env, pos, size, str, NULL ); + add_system_dll_path_var( env, pos, size ); append_envA( env, pos, size, "WINEUSERNAME", user_name ); append_envA( env, pos, size, "WINEDLLOVERRIDES", overrides ); if (unix_cp.data) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 00b07edb1f3..f19d1d68dc7 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -388,6 +388,7 @@ const char *data_dir = NULL; const char *build_dir = NULL; const char *config_dir = NULL; const char **dll_paths = NULL; +const char **system_dll_paths = NULL; const char *user_name = NULL; SECTION_IMAGE_INFORMATION main_image_info = { NULL }; static HMODULE ntdll_module; @@ -546,6 +547,27 @@ static void set_dll_path(void) } +static void set_system_dll_path(void) +{ + const char *p, *path = SYSTEMDLLPATH; + int count = 0; + + if (path && *path) for (p = path, count = 1; *p; p++) if (*p == ':') count++; + + system_dll_paths = malloc( (count + 1) * sizeof(*system_dll_paths) ); + count = 0; + + if (path && *path) + { + char *path_copy = strdup(path); + for (p = strtok( path_copy, ":" ); p; p = strtok( NULL, ":" )) + system_dll_paths[count++] = strdup( p ); + free( path_copy ); + } + system_dll_paths[count] = NULL; +} + + static void set_home_dir(void) { const char *home = getenv( "HOME" ); @@ -620,6 +642,7 @@ static void init_paths( char *argv[] ) } set_dll_path(); + set_system_dll_path(); set_home_dir(); set_config_dir(); } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b499978b2fe..9a9f60a1678 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -113,6 +113,7 @@ extern const char *build_dir DECLSPEC_HIDDEN; extern const char *config_dir DECLSPEC_HIDDEN; extern const char *user_name DECLSPEC_HIDDEN; extern const char **dll_paths DECLSPEC_HIDDEN; +extern const char **system_dll_paths DECLSPEC_HIDDEN; extern PEB *peb DECLSPEC_HIDDEN; extern USHORT *uctable DECLSPEC_HIDDEN; extern USHORT *lctable DECLSPEC_HIDDEN;