* cygheap.cc (init_cygheap::init_installation_root): Install Cygwin's

installation dir as DLL search path, instead of ".".
	* cygheap.h (class cwdstuff): Add parameter names in function
	declarations for readability.
	(cwdstuff::get): Ad inline implementation fetching the CWD as wide char
	string.
	* dlfcn.cc (dlopen): Add searching for dependent DLLs in DLL
	installation dir or CWD, if all else failed.
	Add comment to explain scenarios this is accommodating.
This commit is contained in:
Corinna Vinschen 2014-10-14 19:14:33 +00:00
parent 2599a694a6
commit 1dd75c50d5
4 changed files with 65 additions and 5 deletions

View File

@ -1,3 +1,15 @@
2014-10-14 Corinna Vinschen <corinna@vinschen.de>
* cygheap.cc (init_cygheap::init_installation_root): Install Cygwin's
installation dir as DLL search path, instead of ".".
* cygheap.h (class cwdstuff): Add parameter names in function
declarations for readability.
(cwdstuff::get): Ad inline implementation fetching the CWD as wide char
string.
* dlfcn.cc (dlopen): Add searching for dependent DLLs in DLL
installation dir or CWD, if all else failed.
Add comment to explain scenarios this is accommodating.
2014-10-14 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::connect): Init connect_state to

View File

@ -170,7 +170,6 @@ init_cygheap::init_installation_root ()
}
}
installation_root[1] = L'?';
RtlInitEmptyUnicodeString (&installation_key, installation_key_buf,
sizeof installation_key_buf);
RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root),
@ -185,6 +184,15 @@ init_cygheap::init_installation_root ()
if (!w)
api_fatal ("Can't initialize Cygwin installation root dir.\n"
"Invalid DLL path");
/* Remove "." from DLL search path and install our /bin dir instead.
Note that this change is propagated to child processes so we don't
have to call SetDllDirectory in each process. */
installation_root[1] = L'\\';
if (!SetDllDirectoryW (installation_root))
debug_printf ("Couldn't set %W as DLL directory, %E", installation_root);
installation_root[1] = L'?';
/* If w < p, the Cygwin DLL resides in the root dir of a drive or network
path. In that case, if we strip off yet another backslash, the path
becomes invalid. We avoid that here so that the DLL also works in this

View File

@ -308,14 +308,23 @@ private:
available in shared memory avoids to test for the version every time
around. Default to new version. */
fcwd_version_t fast_cwd_version;
void override_win32_cwd (bool, ULONG);
void override_win32_cwd (bool init, ULONG old_dismount_count);
public:
UNICODE_STRING win32;
static muto cwd_lock;
const char *get_posix () const { return posix; };
void reset_posix (wchar_t *);
char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH);
void reset_posix (wchar_t *w_cwd);
char *get (char *buf, int need_posix = 1, int with_chroot = 0,
unsigned ulen = NT_MAX_PATH);
PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH)
{
cwd_lock.acquire ();
buf[0] = L'\0';
wcsncat (buf, win32.Buffer, buflen - 1);
cwd_lock.release ();
return buf;
}
HANDLE get_handle () { return dir; }
DWORD get_drive (char * dst)
{

View File

@ -13,7 +13,11 @@ details. */
#include <psapi.h>
#include <stdlib.h>
#include <ctype.h>
#include <wctype.h>
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "perprocess.h"
#include "dlfcn.h"
#include "cygtls.h"
@ -156,7 +160,34 @@ dlopen (const char *name, int flags)
if (flags & RTLD_NOLOAD)
GetModuleHandleExW (0, path, (HMODULE *) &ret);
else
ret = (void *) LoadLibraryW (path);
{
ret = (void *) LoadLibraryW (path);
if (!ret && GetLastError () == ERROR_MOD_NOT_FOUND)
{
/* This may indicate that a dependent DLL could not be loaded.
Typically this occurs because we removed the CWD from the
DLL search path via SetDllDirectory
(see init_cygheap::init_installation_root), and the load
mechanism expects that dlopening a DLL from the CWD allows
to load dependent DLLs from the same dir.
To continue supporting this scenario, call LoadLibraryEx
with the LOAD_WITH_ALTERED_SEARCH_PATH flag. This flag
replaces the application path with the DLL path in the DLL
search order. This functionality needs the full path to
the loaded DLL. */
if (!strchr (name, '/'))
{
wchar_t *path_full = tp.w_get ();
cygheap->cwd.get (path_full);
wcscat (path_full, L"\\");
wcscat (path_full, path);
path = path_full;
}
ret = (void *) LoadLibraryExW (path, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
if (ret && (flags & RTLD_NODELETE))
GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_PIN, path,
(HMODULE *) &ret);