1
1
/* loader-loadlibrary.c -- dynamic linking for Win32
3
3
Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
4
2007, 2008 Free Software Foundation, Inc.
4
2007, 2008, 2010 Free Software Foundation, Inc.
5
5
Written by Thomas Tanner, 1998
7
7
NOTE: The canonical source of this file is maintained with the
99
99
#include <windows.h>
101
#define LOCALFREE(mem) LT_STMT_START { \
102
if (mem) { LocalFree ((void *)mem); mem = NULL; } } LT_STMT_END
103
#define LOADLIB__SETERROR(errmsg) LT__SETERRORSTR (loadlibraryerror (errmsg))
104
#define LOADLIB_SETERROR(errcode) LOADLIB__SETERROR (LT__STRERROR (errcode))
106
static const char *loadlibraryerror (const char *default_errmsg);
107
static DWORD WINAPI wrap_getthreaderrormode (void);
108
static DWORD WINAPI fallback_getthreaderrormode (void);
109
static BOOL WINAPI wrap_setthreaderrormode (DWORD mode, DWORD *oldmode);
110
static BOOL WINAPI fallback_setthreaderrormode (DWORD mode, DWORD *oldmode);
112
typedef DWORD (WINAPI getthreaderrormode_type) (void);
113
typedef BOOL (WINAPI setthreaderrormode_type) (DWORD, DWORD *);
115
static getthreaderrormode_type *getthreaderrormode = wrap_getthreaderrormode;
116
static setthreaderrormode_type *setthreaderrormode = wrap_setthreaderrormode;
117
static char *error_message = 0;
101
120
/* A function called through the vtable when this loader is no
102
121
longer needed by the application. */
104
123
vl_exit (lt_user_data LT__UNUSED loader_data)
126
LOCALFREE (error_message);
173
/* Silence dialog from LoadLibrary on some failures.
174
No way to get the error mode, but to set it,
175
so set it twice to preserve any previous flags. */
176
UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
177
SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
193
/* Silence dialog from LoadLibrary on some failures. */
194
DWORD errormode = getthreaderrormode ();
197
setthreaderrormode (errormode | SEM_FAILCRITICALERRORS, NULL);
179
199
module = LoadLibrary (wpath);
181
201
/* Restore the error mode. */
182
SetErrorMode(errormode);
202
last_error = GetLastError ();
203
setthreaderrormode (errormode, NULL);
204
SetLastError (last_error);
185
207
/* libltdl expects this function to fail if it is unable
247
LT__SETERROR (SYMBOL_NOT_FOUND);
271
LOADLIB_SETERROR (SYMBOL_NOT_FOUND);
279
/* --- HELPER FUNCTIONS --- */
282
/* Return the windows error message, or the passed in error message on
285
loadlibraryerror (const char *default_errmsg)
288
LOCALFREE (error_message);
290
FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
291
FORMAT_MESSAGE_FROM_SYSTEM |
292
FORMAT_MESSAGE_IGNORE_INSERTS,
296
(char *) &error_message,
299
/* Remove trailing CRNL */
300
len = LT_STRLEN (error_message);
301
if (len && error_message[len - 1] == '\n')
302
error_message[--len] = LT_EOS_CHAR;
303
if (len && error_message[len - 1] == '\r')
304
error_message[--len] = LT_EOS_CHAR;
306
return len ? error_message : default_errmsg;
309
/* A function called through the getthreaderrormode variable which checks
310
if the system supports GetThreadErrorMode (or GetErrorMode) and arranges
311
for it or a fallback implementation to be called directly in the future.
312
The selected version is then called. */
314
wrap_getthreaderrormode (void)
316
HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
318
= (getthreaderrormode_type *) GetProcAddress (kernel32,
319
"GetThreadErrorMode");
320
if (!getthreaderrormode)
322
= (getthreaderrormode_type *) GetProcAddress (kernel32,
324
if (!getthreaderrormode)
325
getthreaderrormode = fallback_getthreaderrormode;
326
return getthreaderrormode ();
329
/* A function called through the getthreaderrormode variable for cases
330
where the system does not support GetThreadErrorMode or GetErrorMode */
332
fallback_getthreaderrormode (void)
334
/* Prior to Windows Vista, the only way to get the current error
335
mode was to set a new one. In our case, we are setting a new
336
error mode right after "getting" it while ignoring the error
337
mode in effect when setting the new error mode, so that's
339
return (DWORD) SetErrorMode (SEM_FAILCRITICALERRORS);
342
/* A function called through the setthreaderrormode variable which checks
343
if the system supports SetThreadErrorMode and arranges for it or a
344
fallback implementation to be called directly in the future.
345
The selected version is then called. */
347
wrap_setthreaderrormode (DWORD mode, DWORD *oldmode)
349
HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
351
= (setthreaderrormode_type *) GetProcAddress (kernel32,
352
"SetThreadErrorMode");
353
if (!setthreaderrormode)
354
setthreaderrormode = fallback_setthreaderrormode;
355
return setthreaderrormode (mode, oldmode);
358
/* A function called through the setthreaderrormode variable for cases
359
where the system does not support SetThreadErrorMode. */
361
fallback_setthreaderrormode (DWORD mode, DWORD *oldmode)
363
/* Prior to Windows 7, there was no way to set the thread local error
364
mode, so set the process global error mode instead. */
365
DWORD old = (DWORD) SetErrorMode (mode);