Always pass lower-case filenames to wine_dll_load().
Clear dlerror() before and after calls to dlopen/dlsym to work around
a glibc bug (thanks to James Abbatiello for tracking the bug).
diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c
index 0e7c125..bd12ea5 100644
--- a/dlls/odbc32/proxyodbc.c
+++ b/dlls/odbc32/proxyodbc.c
@@ -196,11 +196,13 @@
else
strcpy(gProxyHandle.dmLibName, "libodbc.so");
+ dlerror(); /* clear dlerror first */
gProxyHandle.dmHandle = dlopen(gProxyHandle.dmLibName, RTLD_LAZY);
if (gProxyHandle.dmHandle == NULL) /* fail to load unixODBC driver manager */
{
- WARN("failed to open library %s\n", gProxyHandle.dmLibName);
+ const char *err = dlerror();
+ WARN("failed to open library %s: %s\n", gProxyHandle.dmLibName, err);
gProxyHandle.dmLibName[0] = '\0';
gProxyHandle.nErrorType = ERROR_LIBRARY_NOT_FOUND;
return FALSE;
@@ -230,6 +232,7 @@
if (gProxyHandle.dmHandle == NULL)
return FALSE;
+ dlerror(); /* clear dlerror first */
for ( i = 0; i < NUM_SQLFUNC; i ++ )
{
gProxyHandle.functions[i] = template_func[i];
diff --git a/if1632/builtin.c b/if1632/builtin.c
index af5d782..907c4cd 100644
--- a/if1632/builtin.c
+++ b/if1632/builtin.c
@@ -122,6 +122,7 @@
strcpy( dllname, name );
p = strrchr( dllname, '.' );
if (!p) strcat( dllname, ".dll" );
+ for (p = dllname; *p; p++) *p = FILE_tolower(*p);
for (i = 0; i < nb_dlls; i++)
{
diff --git a/library/loader.c b/library/loader.c
index d230160..35a7b42 100644
--- a/library/loader.c
+++ b/library/loader.c
@@ -83,23 +83,25 @@
{
#ifdef HAVE_DL_API
int i, namelen = strlen(name);
- char *buffer, *p;
+ char *buffer, *p, *ext;
void *ret = NULL;
if (!init_done) build_dll_path();
- /* check for .dll or .exe extension to remove */
- if ((p = strrchr( name, '.' )))
- {
- if (!strcasecmp( p, ".dll" ) || !strcasecmp( p, ".exe" )) namelen -= 4;
- }
+ /* clear dlerror to avoid glibc bug */
+ dlerror();
buffer = malloc( dll_path_maxlen + namelen + 8 );
/* store the name at the end of the buffer, prefixed by /lib and followed by .so */
p = buffer + dll_path_maxlen;
memcpy( p, "/lib", 4 );
- for (i = 0, p += 4; i < namelen; i++, p++) *p = tolower(name[i]);
+ p += 4;
+ memcpy( p, name, namelen+1 );
+ ext = strrchr( p, '.' );
+ p += namelen;
+ /* check for .dll or .exe extension to remove */
+ if (ext && (!strcmp( ext, ".dll" ) || !strcmp( ext, ".exe" ))) p = ext;
memcpy( p, ".so", 4 );
for (i = 0; i < nb_dll_paths; i++)
@@ -108,6 +110,7 @@
char *p = buffer + dll_path_maxlen - len;
memcpy( p, dll_paths[i], len );
if ((ret = dlopen( p, RTLD_NOW ))) break;
+ dlerror(); /* clear dlerror to avoid glibc bug */
}
/* now try the default dlopen search path */
@@ -327,7 +330,7 @@
for (i = 0; i < nb_dlls; i++)
{
if (!builtin_dlls[i].nt) continue;
- if (!strcasecmp( builtin_dlls[i].filename, filename ))
+ if (!strcmp( builtin_dlls[i].filename, filename ))
{
const IMAGE_NT_HEADERS *nt = builtin_dlls[i].nt;
builtin_dlls[i].nt = NULL;
@@ -356,6 +359,7 @@
* wine_dll_load_main_exe
*
* Try to load the .so for the main exe, optionally searching for it in PATH.
+ * Note: dlerror() is cleared before returning because of a glibc bug.
*/
void *wine_dll_load_main_exe( const char *name, int search_path )
{
@@ -367,6 +371,7 @@
if (!path)
{
/* no path, try only the specified name */
+ dlerror(); /* clear dlerror to avoid glibc bug */
ret = dlopen( name, RTLD_NOW );
}
else
@@ -389,6 +394,7 @@
if ((len = p - path) > 0)
{
memcpy( basename - len, path, len );
+ dlerror(); /* clear dlerror to avoid glibc bug */
if ((ret = dlopen( basename - len, RTLD_NOW ))) break;
}
if (!*p) break;
@@ -397,6 +403,7 @@
if (tmp != buffer) free( tmp );
}
}
+ if (!ret) dlerror(); /* clear dlerror to avoid glibc bug */
#endif /* HAVE_DL_API */
return ret;
}
diff --git a/loader/elf.c b/loader/elf.c
index e0f2e3a..462b48c 100644
--- a/loader/elf.c
+++ b/loader/elf.c
@@ -154,8 +154,10 @@
points to the ENTIRE DOS filename of the library
t is returned by HeapAlloc() above and so is also used
with HeapFree() below */
- dlhandle = ELFDLL_dlopen(s,RTLD_NOW);
+ dlerror(); /* clear dlerror because of glibc bug */
+ dlhandle = dlopen(s,RTLD_NOW);
if (!dlhandle) {
+ dlerror(); /* clear dlerror because of glibc bug */
HeapFree( GetProcessHeap(), 0, t );
SetLastError( ERROR_FILE_NOT_FOUND );
return NULL;
@@ -181,12 +183,19 @@
ERR("Can't import from UNIX dynamic libs by ordinal, sorry.\n");
return (FARPROC)0;
}
+ dlerror(); /* clear dlerror() first */
fun = dlsym(wm->dlhandle,funcName);
- /* we sometimes have an excess '_' at the beginning of the name */
- if (!fun && (funcName[0]=='_')) {
+ if (!fun)
+ {
+ dlerror(); /* clear dlerror() to avoid glibc bug */
+ /* we sometimes have an excess '_' at the beginning of the name */
+ if (funcName[0]=='_')
+ {
funcName++ ;
fun = dlsym(wm->dlhandle,funcName);
- }
+ if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
+ }
+ }
if (!fun) {
/* Function@nrofargs usually marks a stdcall function
* with nrofargs bytes that are popped at the end
@@ -199,6 +208,7 @@
nrofargs = 0;
sscanf(t+1,"%d",&nrofargs);
fun = dlsym(wm->dlhandle,fn);
+ if (!fun) dlerror(); /* clear dlerror() to avoid glibc bug */
HeapFree( GetProcessHeap(), 0, fn );
}
}
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index a56378d..b5dec5e 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -23,6 +23,7 @@
#include "wine/library.h"
#include "global.h"
#include "module.h"
+#include "file.h"
#include "heap.h"
#include "main.h"
#include "winerror.h"
@@ -46,12 +47,14 @@
if (!(handle = wine_dll_load( name )))
{
- LPSTR pErr;
- pErr = dlerror();
- if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
- ERR("failed to load %s: %s\n", name, pErr);
- else /* WARN() for libraries that are supposed to be native */
- WARN("failed to load %s: %s\n", name, pErr );
+ LPSTR pErr;
+ if ((pErr = dlerror()))
+ {
+ if (strstr(pErr, "undefined symbol")) /* undef symbol -> ERR() */
+ ERR("failed to load %s: %s\n", name, pErr);
+ else /* WARN() for libraries that are supposed to be native */
+ WARN("failed to load %s: %s\n", name, pErr );
+ }
}
return handle;
#else
@@ -136,6 +139,7 @@
strcpy( dllname, name );
p = strrchr( dllname, '.' );
if (!p) strcat( dllname, ".dll" );
+ for (p = dllname; *p; p++) *p = FILE_tolower(*p);
if (!(handle = BUILTIN32_dlopen( dllname ))) goto error;