]> granicus.if.org Git - imagemagick/commitdiff
(no commit message)
authorcristy <urban-warrior@git.imagemagick.org>
Sun, 6 Jun 2010 23:39:36 +0000 (23:39 +0000)
committercristy <urban-warrior@git.imagemagick.org>
Sun, 6 Jun 2010 23:39:36 +0000 (23:39 +0000)
ltdl/libltdl/lt_dlloader.h
ltdl/libltdl/slist.h
ltdl/loaders/loadlibrary.c
ltdl/lt_dlloader.c
ltdl/ltdl.c
ltdl/slist.c

index ae131fae9107a9219893576739d1df187611cb49..589fd0dc326ff0944d033c962f5c20bc6afca37e 100644 (file)
@@ -73,8 +73,8 @@ typedef struct {
 LT_SCOPE int           lt_dlloader_add    (const lt_dlvtable *vtable);
 LT_SCOPE lt_dlloader   lt_dlloader_next   (const lt_dlloader loader);
 
-LT_SCOPE lt_dlvtable * lt_dlloader_remove      (char *name);
-LT_SCOPE const lt_dlvtable *lt_dlloader_find   (char *name);
+LT_SCOPE lt_dlvtable * lt_dlloader_remove      (const char *name);
+LT_SCOPE const lt_dlvtable *lt_dlloader_find   (const char *name);
 LT_SCOPE const lt_dlvtable *lt_dlloader_get    (lt_dlloader loader);
 
 
index e4b7ead8d927a32d40f74869318dcd09a0cbea4b..4d5650997d6dc58718f10418eb4cf73bb5535e3f 100644 (file)
@@ -1,6 +1,6 @@
 /* slist.h -- generalised singly linked lists
 
-   Copyright (C) 2000, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2004, 2009 Free Software Foundation, Inc.
    Written by Gary V. Vaughan, 2000
 
    NOTE: The canonical source of this file is maintained with the
@@ -48,6 +48,8 @@ or obtained by writing to the Free Software Foundation, Inc.,
 #  define LT_SCOPE
 #endif
 
+#include <stddef.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -65,7 +67,7 @@ LT_SCOPE SList *slist_concat  (SList *head, SList *tail);
 LT_SCOPE SList *slist_cons     (SList *item, SList *slist);
 
 LT_SCOPE SList *slist_delete   (SList *slist, void (*delete_fct) (void *item));
-LT_SCOPE void *        slist_remove    (SList **phead, SListCallback *find,
+LT_SCOPE SList *slist_remove   (SList **phead, SListCallback *find,
                                 void *matchdata);
 LT_SCOPE SList *slist_reverse  (SList *slist);
 LT_SCOPE SList *slist_sort     (SList *slist, SListCompare *compare,
index 5644676516d681bc4fa967f58e80c094c2f131ff..179c00980d04d9c1e5f0e699fba062dad98adb64 100644 (file)
@@ -1,7 +1,7 @@
 /* loader-loadlibrary.c --  dynamic linking for Win32
 
    Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
-                 2007, 2008 Free Software Foundation, Inc.
+                 2007, 2008, 2010 Free Software Foundation, Inc.
    Written by Thomas Tanner, 1998
 
    NOTE: The canonical source of this file is maintained with the
@@ -98,12 +98,32 @@ get_vtable (lt_user_data loader_data)
 
 #include <windows.h>
 
+#define LOCALFREE(mem)                                      LT_STMT_START { \
+       if (mem) { LocalFree ((void *)mem); mem = NULL; }    } LT_STMT_END
+#define LOADLIB__SETERROR(errmsg) LT__SETERRORSTR (loadlibraryerror (errmsg))
+#define LOADLIB_SETERROR(errcode) LOADLIB__SETERROR (LT__STRERROR (errcode))
+
+static const char *loadlibraryerror (const char *default_errmsg);
+static DWORD WINAPI wrap_getthreaderrormode (void);
+static DWORD WINAPI fallback_getthreaderrormode (void);
+static BOOL WINAPI wrap_setthreaderrormode (DWORD mode, DWORD *oldmode);
+static BOOL WINAPI fallback_setthreaderrormode (DWORD mode, DWORD *oldmode);
+
+typedef DWORD (WINAPI getthreaderrormode_type) (void);
+typedef BOOL (WINAPI setthreaderrormode_type) (DWORD, DWORD *);
+
+static getthreaderrormode_type *getthreaderrormode = wrap_getthreaderrormode;
+static setthreaderrormode_type *setthreaderrormode = wrap_setthreaderrormode;
+static char *error_message = 0;
+
+
 /* A function called through the vtable when this loader is no
    longer needed by the application.  */
 static int
 vl_exit (lt_user_data LT__UNUSED loader_data)
 {
   vtable = NULL;
+  LOCALFREE (error_message);
   return 0;
 }
 
@@ -156,7 +176,7 @@ vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
          /* Append a `.' to stop Windows from adding an
             implicit `.dll' extension. */
          if (!len)
-           len = LT_STRLEN (wpath);
+           len = strlen (wpath);
 
          if (len + 1 >= MAX_PATH)
            {
@@ -170,16 +190,18 @@ vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
     }
 
   {
-    /* Silence dialog from LoadLibrary on some failures.
-       No way to get the error mode, but to set it,
-       so set it twice to preserve any previous flags. */
-    UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
-    SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
+    /* Silence dialog from LoadLibrary on some failures. */
+    DWORD errormode = getthreaderrormode ();
+    DWORD last_error;
+
+    setthreaderrormode (errormode | SEM_FAILCRITICALERRORS, NULL);
 
     module = LoadLibrary (wpath);
 
     /* Restore the error mode. */
-    SetErrorMode(errormode);
+    last_error = GetLastError ();
+    setthreaderrormode (errormode, NULL);
+    SetLastError (last_error);
   }
 
   /* libltdl expects this function to fail if it is unable
@@ -207,7 +229,9 @@ vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
           }
       }
 
-    if (cur || !module)
+    if (!module)
+      LOADLIB_SETERROR (CANNOT_OPEN);
+    else if (cur)
       {
         LT__SETERROR (CANNOT_OPEN);
         module = 0;
@@ -225,9 +249,9 @@ vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
 {
   int errors = 0;
 
-  if (FreeLibrary((HMODULE) module) == 0)
+  if (FreeLibrary ((HMODULE) module) == 0)
     {
-      LT__SETERROR (CANNOT_CLOSE);
+      LOADLIB_SETERROR (CANNOT_CLOSE);
       ++errors;
     }
 
@@ -244,8 +268,102 @@ vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
 
   if (!address)
     {
-      LT__SETERROR (SYMBOL_NOT_FOUND);
+      LOADLIB_SETERROR (SYMBOL_NOT_FOUND);
     }
 
   return address;
 }
+
+
+
+/* --- HELPER FUNCTIONS --- */
+
+
+/* Return the windows error message, or the passed in error message on
+   failure. */
+static const char *
+loadlibraryerror (const char *default_errmsg)
+{
+  size_t len;
+  LOCALFREE (error_message);
+
+  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL,
+                  GetLastError (),
+                  0,
+                  (char *) &error_message,
+                  0, NULL);
+
+  /* Remove trailing CRNL */
+  len = LT_STRLEN (error_message);
+  if (len && error_message[len - 1] == '\n')
+    error_message[--len] = LT_EOS_CHAR;
+  if (len && error_message[len - 1] == '\r')
+    error_message[--len] = LT_EOS_CHAR;
+
+  return len ? error_message : default_errmsg;
+}
+
+/* A function called through the getthreaderrormode variable which checks
+   if the system supports GetThreadErrorMode (or GetErrorMode) and arranges
+   for it or a fallback implementation to be called directly in the future.
+   The selected version is then called. */
+static DWORD WINAPI
+wrap_getthreaderrormode (void)
+{
+  HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
+  getthreaderrormode
+    = (getthreaderrormode_type *) GetProcAddress (kernel32,
+                                                 "GetThreadErrorMode");
+  if (!getthreaderrormode)
+    getthreaderrormode
+      = (getthreaderrormode_type *) GetProcAddress (kernel32,
+                                                   "GetErrorMode");
+  if (!getthreaderrormode)
+    getthreaderrormode = fallback_getthreaderrormode;
+  return getthreaderrormode ();
+}
+
+/* A function called through the getthreaderrormode variable for cases
+   where the system does not support GetThreadErrorMode or GetErrorMode */
+static DWORD WINAPI
+fallback_getthreaderrormode (void)
+{
+  /* Prior to Windows Vista, the only way to get the current error
+     mode was to set a new one. In our case, we are setting a new
+     error mode right after "getting" it while ignoring the error
+     mode in effect when setting the new error mode, so that's
+     fairly ok. */
+  return (DWORD) SetErrorMode (SEM_FAILCRITICALERRORS);
+}
+
+/* A function called through the setthreaderrormode variable which checks
+   if the system supports SetThreadErrorMode and arranges for it or a
+   fallback implementation to be called directly in the future.
+   The selected version is then called. */
+static BOOL WINAPI
+wrap_setthreaderrormode (DWORD mode, DWORD *oldmode)
+{
+  HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
+  setthreaderrormode
+    = (setthreaderrormode_type *) GetProcAddress (kernel32,
+                                                 "SetThreadErrorMode");
+  if (!setthreaderrormode)
+    setthreaderrormode = fallback_setthreaderrormode;
+  return setthreaderrormode (mode, oldmode);
+}
+
+/* A function called through the setthreaderrormode variable for cases
+   where the system does not support SetThreadErrorMode. */
+static BOOL WINAPI
+fallback_setthreaderrormode (DWORD mode, DWORD *oldmode)
+{
+  /* Prior to Windows 7, there was no way to set the thread local error
+     mode, so set the process global error mode instead. */
+  DWORD old = (DWORD) SetErrorMode (mode);
+  if (oldmode)
+    *oldmode = old;
+  return TRUE;
+}
index 4e66a6ca18284ae745ed326020d5278b7791ff63..2c99a22d486e2445dd86d574b5f7928469ac4883 100644 (file)
@@ -150,7 +150,7 @@ lt_dlloader_get     (lt_dlloader loader)
    modules need this loader; in either case, the loader list is not
    changed if NULL is returned.  */
 lt_dlvtable *
-lt_dlloader_remove (char *name)
+lt_dlloader_remove (const char *name)
 {
   const lt_dlvtable *  vtable  = lt_dlloader_find (name);
   static const char    id_string[] = "lt_dlloader_remove";
@@ -199,12 +199,12 @@ lt_dlloader_remove (char *name)
 
   /* If we got this far, remove the loader from our global list.  */
   return (lt_dlvtable *)
-      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, name));
+      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) name));
 }
 
 
 const lt_dlvtable *
-lt_dlloader_find (char *name)
+lt_dlloader_find (const char *name)
 {
-  return lt_dlloader_get (slist_find (loaders, loader_callback, name));
+  return lt_dlloader_get (slist_find (loaders, loader_callback, (void *) name));
 }
index 7c426351c7cdcf721764f8122569ea70052e518d..4e1a4025f4cb0600264b7e148af534d8ed27e925 100644 (file)
@@ -208,7 +208,7 @@ LT_BEGIN_C_DECLS
 LT_SCOPE const lt_dlvtable *   get_vtable (lt_user_data data);
 LT_END_C_DECLS
 #ifdef HAVE_LIBDLLOADER
-extern lt_dlsymlist            preloaded_symbols;
+extern lt_dlsymlist            preloaded_symbols[];
 #endif
 
 /* Initialize libltdl. */
@@ -234,7 +234,7 @@ lt_dlinit (void)
 #ifdef HAVE_LIBDLLOADER
       if (!errors)
        {
-         errors += lt_dlpreload (&preloaded_symbols);
+         errors += lt_dlpreload (preloaded_symbols);
        }
 
       if (!errors)
@@ -994,7 +994,7 @@ trim (char **dest, const char *str)
 
   FREE (*dest);
 
-  if (!end)
+  if (!end || end == str)
     return 1;
 
   if (len > 3 && str[0] == '\'')
@@ -1265,7 +1265,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
       if (vtable)
        {
          /* name + "." + libext + NULL */
-         archive_name = MALLOC (char, LT_STRLEN (name) + LT_STRLEN (libext) + 2);
+         archive_name = MALLOC (char, LT_STRLEN (name) + strlen (libext) + 2);
          *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
 
          if ((*phandle == NULL) || (archive_name == NULL))
@@ -1487,7 +1487,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
 }
 
 
-/* If the last error messge store was `FILE_NOT_FOUND', then return
+/* If the last error message stored was `FILE_NOT_FOUND', then return
    non-zero.  */
 static int
 file_not_found (void)
@@ -1507,7 +1507,7 @@ file_not_found (void)
 static int
 has_library_ext (const char *filename)
 {
-  char *       ext     = 0;
+  const char * ext     = 0;
 
   assert (filename);
 
@@ -1615,6 +1615,9 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
 {
   lt_dlhandle  handle  = 0;
   int          errors  = 0;
+  const char * saved_error     = 0;
+
+  LT__GETERROR (saved_error);
 
   /* Can't have symbols hidden and visible at the same time!  */
   if (advise && advise->is_symlocal && advise->is_symglobal)
@@ -1651,6 +1654,7 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
 
 #if defined(LT_MODULE_EXT)
       /* Try appending SHLIB_EXT.   */
+      LT__SETERRORSTR (saved_error);
       errors = try_dlopen (&handle, filename, shlib_ext, advise);
 
       /* As before, if the file was found but loading failed, return now
@@ -2062,7 +2066,7 @@ lt_dlerror (void)
   LT__GETERROR (error);
   LT__SETERRORSTR (0);
 
-  return error ? error : NULL;
+  return error;
 }
 
 static int
index c99f39914a63599662fd615efa18436425a987b1..25906a43aa02d669d8e4596c3dee625d25fe689c 100644 (file)
@@ -1,6 +1,6 @@
 /* slist.c -- generalised singly linked lists
 
-   Copyright (C) 2000, 2004, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
    Written by Gary V. Vaughan, 2000
 
    NOTE: The canonical source of this file is maintained with the
@@ -32,6 +32,7 @@ or obtained by writing to the Free Software Foundation, Inc.,
 
 #include "slist.h"
 #include <stddef.h>
+#include <stdlib.h>
 
 static SList * slist_sort_merge    (SList *left, SList *right,
                                     SListCompare *compare, void *userdata);
@@ -73,7 +74,7 @@ slist_delete (SList *head, void (*delete_fct) (void *item))
            the stale item, you should probably return that from FIND if
           it makes a successful match.  Don't forget to slist_unbox()
           every item in a boxed list before operating on its contents.   */
-void *
+SList *
 slist_remove (SList **phead, SListCallback *find, void *matchdata)
 {
   SList *stale = 0;
@@ -107,7 +108,7 @@ slist_remove (SList **phead, SListCallback *find, void *matchdata)
        }
     }
 
-  return result;
+  return (SList *) result;
 }
 
 /* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
@@ -314,6 +315,9 @@ slist_sort (SList *slist, SListCompare *compare, void *userdata)
   left = slist;
   right = slist->next;
 
+  if (!right)
+    return left;
+
   /* Skip two items with RIGHT and one with SLIST, until RIGHT falls off
      the end.  SLIST must be about half way along.  */
   while (right && (right = right->next))