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;