GIF89a;
EcchiShell v1.0
/
/
proc/
self/
root/
usr/
share/
libtool/
name)
{
vtable->name = "lt_loadlibrary";
vtable->module_open = vm_open;
vtable->module_close = vm_close;
vtable->find_sym = vm_sym;
vtable->dlloader_exit = vl_exit;
vtable->dlloader_data = loader_data;
vtable->priority = LT_DLLOADER_APPEND;
}
if (vtable && (vtable->dlloader_data != loader_data))
{
LT__SETERROR (INIT_LOADER);
return 0;
}
return vtable;
}
/* --- IMPLEMENTATION --- */
#include
#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;
}
/* A function called through the vtable to open a module with this
loader. Returns an opaque representation of the newly opened
module for processing with this loader's other vtable functions. */
static lt_module
vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
lt_dladvise LT__UNUSED advise)
{
lt_module module = 0;
char *ext;
char wpath[MAX_PATH];
size_t len;
if (!filename)
{
/* Get the name of main module */
*wpath = 0;
GetModuleFileName (NULL, wpath, sizeof (wpath));
filename = wpath;
}
else
{
len = LT_STRLEN (filename);
if (len >= MAX_PATH)
{
LT__SETERROR (CANNOT_OPEN);
return 0;
}
#if HAVE_DECL_CYGWIN_CONV_PATH
if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, filename, wpath, MAX_PATH))
{
LT__SETERROR (CANNOT_OPEN);
return 0;
}
len = 0;
#elif defined(__CYGWIN__)
cygwin_conv_to_full_win32_path (filename, wpath);
len = 0;
#else
strcpy(wpath, filename);
#endif
ext = strrchr (wpath, '.');
if (!ext)
{
/* Append a `.' to stop Windows from adding an
implicit `.dll' extension. */
if (!len)
len = strlen (wpath);
if (len + 1 >= MAX_PATH)
{
LT__SETERROR (CANNOT_OPEN);
return 0;
}
wpath[len] = '.';
wpath[len+1] = '\0';
}
}
{
/* 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. */
last_error = GetLastError ();
setthreaderrormode (errormode, NULL);
SetLastError (last_error);
}
/* libltdl expects this function to fail if it is unable
to physically load the library. Sadly, LoadLibrary
will search the loaded libraries for a match and return
one of them if the path search load fails.
We check whether LoadLibrary is returning a handle to
an already loaded module, and simulate failure if we
find one. */
{
lt_dlhandle cur = 0;
while ((cur = lt_dlhandle_iterate (iface_id, cur)))
{
if (!cur->module)
{
cur = 0;
break;
}
if (cur->module == module)
{
break;
}
}
if (!module)
LOADLIB_SETERROR (CANNOT_OPEN);
else if (cur)
{
LT__SETERROR (CANNOT_OPEN);
module = 0;
}
}
return module;
}
/* A function called through the vtable when a particular module
should be unloaded. */
static int
vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
{
int errors = 0;
if (FreeLibrary ((HMODULE) module) == 0)
{
LOADLIB_SETERROR (CANNOT_CLOSE);
++errors;
}
return errors;
}
/* A function called through the vtable to get the address of
a symbol loaded from a particular module. */
static void *
vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
{
void *address = (void *) GetProcAddress ((HMODULE) module, name);
if (!address)
{
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;
}