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).
This commit is contained in:
Alexandre Julliard 2000-12-05 21:17:59 +00:00
parent 01eeb01f0b
commit 886604c715
5 changed files with 44 additions and 19 deletions

View File

@ -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];

View File

@ -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++)
{

View File

@ -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;
}

View File

@ -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,11 +183,18 @@ 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);
if (!fun)
{
dlerror(); /* clear dlerror() to avoid glibc bug */
/* we sometimes have an excess '_' at the beginning of the name */
if (!fun && (funcName[0]=='_')) {
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
@ -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 );
}
}

View File

@ -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"
@ -47,12 +48,14 @@ void *BUILTIN32_dlopen( const char *name )
if (!(handle = wine_dll_load( name )))
{
LPSTR pErr;
pErr = dlerror();
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
return NULL;
@ -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;