From 886604c7159d044f0eab167ffb05038e16bf7110 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 5 Dec 2000 21:17:59 +0000 Subject: [PATCH] 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). --- dlls/odbc32/proxyodbc.c | 5 ++++- if1632/builtin.c | 1 + library/loader.c | 23 +++++++++++++++-------- loader/elf.c | 18 ++++++++++++++---- relay32/builtin32.c | 16 ++++++++++------ 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/dlls/odbc32/proxyodbc.c b/dlls/odbc32/proxyodbc.c index 0e7c12520bd..bd12ea5cb07 100644 --- a/dlls/odbc32/proxyodbc.c +++ b/dlls/odbc32/proxyodbc.c @@ -196,11 +196,13 @@ BOOL ODBC_LoadDriverManager() 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 @@ BOOL ODBC_LoadDMFunctions() 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 af5d7826e32..907c4cdaa46 100644 --- a/if1632/builtin.c +++ b/if1632/builtin.c @@ -122,6 +122,7 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name ) 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 d2301609c54..35a7b422972 100644 --- a/library/loader.c +++ b/library/loader.c @@ -83,23 +83,25 @@ static void *dlopen_dll( const char *name ) { #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 @@ static void *dlopen_dll( const char *name ) 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 @@ void *wine_dll_load( const char *filename ) 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 @@ void wine_dll_unload( void *handle ) * 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 @@ void *wine_dll_load_main_exe( const char *name, int search_path ) 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 @@ void *wine_dll_load_main_exe( const char *name, int search_path ) 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 @@ void *wine_dll_load_main_exe( const char *name, int search_path ) 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 e0f2e3add82..462b48c6f0c 100644 --- a/loader/elf.c +++ b/loader/elf.c @@ -154,8 +154,10 @@ WINE_MODREF *ELF_LoadLibraryExA( LPCSTR libname, DWORD flags) 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 @@ static FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, BOOL 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 @@ static FARPROC ELF_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, BOOL 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 a56378dacb1..b5dec5ec4d7 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 @@ void *BUILTIN32_dlopen( const char *name ) 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 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) 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;