/* Return the contents of the first item in the global loader list with a matching NAME after removing it from that list. If there was no match, return NULL; if there is an error, return NULL and set an error for lt_dlerror; do not set an error if only resident modules need this loader; in either case, the loader list is not changed if NULL is returned. */ lt_dlvtable * lt_dlloader_remove (const char *name) { const lt_dlvtable * vtable = lt_dlloader_find (name); static const char id_string[] = "lt_dlloader_remove"; lt_dlinterface_id iface; lt_dlhandle handle = 0; int in_use = 0; int in_use_by_resident = 0; if (!vtable) { LT__SETERROR (INVALID_LOADER); return 0; } /* Fail if there are any open modules which use this loader. */ iface = lt_dlinterface_register (id_string, NULL); while ((handle = lt_dlhandle_iterate (iface, handle))) { lt_dlhandle cur = handle; if (cur->vtable == vtable) { in_use = 1; if (lt_dlisresident (handle)) in_use_by_resident = 1; } } lt_dlinterface_free (iface); if (in_use) { if (!in_use_by_resident) LT__SETERROR (REMOVE_LOADER); return 0; } /* Call the loader finalisation function. */ if (vtable && vtable->dlloader_exit) { if ((*vtable->dlloader_exit) (vtable->dlloader_data) != 0) { /* If there is an exit function, and it returns non-zero then it must set an error, and we will not remove it from the list. */ return 0; } } /* If we got this far, remove the loader from our global list. */ return (lt_dlvtable *) slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) name)); }
/* 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 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 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 = LT_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. 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); module = LoadLibrary (wpath); /* Restore the error mode. */ SetErrorMode(errormode); } /* 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__handle * cur = 0; while ((cur = (lt__handle *) lt_dlhandle_iterate (iface_id, (lt_dlhandle) cur))) { if (!cur->module) { cur = 0; break; } if (cur->module == module) { break; } } if (cur || !module) { LT__SETERROR (CANNOT_OPEN); module = 0; } } return module; }