diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/plugin/qlibrary.h | 3 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_unix.cpp | 23 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_win.cpp | 91 |
3 files changed, 92 insertions, 25 deletions
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h index c77533f..101df74 100644 --- a/src/corelib/plugin/qlibrary.h +++ b/src/corelib/plugin/qlibrary.h @@ -69,7 +69,8 @@ public: enum LoadHint { ResolveAllSymbolsHint = 0x01, ExportExternalSymbolsHint = 0x02, - LoadArchiveMemberHint = 0x04 + LoadArchiveMemberHint = 0x04, + ImprovedSearchHeuristics = 0x08 }; Q_DECLARE_FLAGS(LoadHints, LoadHint) diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 1d0f322..74cf9a8 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -103,9 +103,9 @@ bool QLibraryPrivate::load_sys() else path += QLatin1Char('/'); #endif - // The first filename we want to attempt to load is the filename as the callee specified. - // Thus, the first attempt we do must be with an empty prefix and empty suffix. - QStringList suffixes(QLatin1String("")), prefixes(QLatin1String("")); + + QStringList suffixes; + QStringList prefixes; if (pluginState != IsAPlugin) { #if !defined(Q_OS_SYMBIAN) prefixes << QLatin1String("lib"); @@ -187,6 +187,23 @@ bool QLibraryPrivate::load_sys() } #endif #endif // QT_HPUX_LD + // If using the new search heuristics we do: + // + // If the filename is an absolute path then we want to try that first as it is most likely + // what the callee wants. If we have been given a non-absolute path then lets try the + // native library name first to avoid unnecessary calls to dlopen(). + // + // otherwise: + // + // We use the old behaviour which is to always try the specified filename first + if ((loadHints & QLibrary::ImprovedSearchHeuristics) && !fsEntry.isAbsolute()) { + suffixes.append(QLatin1String("")); + prefixes.append(QLatin1String("")); + } else { + suffixes.prepend(QLatin1String("")); + prefixes.prepend(QLatin1String("")); + } + bool retry = true; for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 0c450e3..2c09f6f 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -45,6 +45,7 @@ #include "qdir.h" #include "qfileinfo.h" #include "qdir.h" +#include <private/qfilesystementry_p.h> #if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN) #undef QT_NO_LIBRARY @@ -59,46 +60,94 @@ extern QString qt_error_string(int code); bool QLibraryPrivate::load_sys() { -#ifdef Q_OS_WINCE - QString attempt = QFileInfo(fileName).absoluteFilePath(); -#else - QString attempt = fileName; -#endif - //avoid 'Bad Image' message box UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); - if (pluginState != IsAPlugin) { + // We make the following attempts at locating the library: + // + // WinCE + // if (loadHints & QLibrary::ImprovedSearchHeuristics) + // if (absolute) + // fileName + // fileName + ".dll" + // else + // fileName + ".dll" + // fileName + // QFileInfo(fileName).absoluteFilePath() + // else + // QFileInfo(fileName).absoluteFilePath(); + // fileName + // fileName + ".dll" + // + // Windows + // if (loadHints & QLibrary::ImprovedSearchHeuristics) + // if (absolute) + // fileName + // fileName + ".dll" + // else + // fileName + ".dll" + // fileName + // else + // fileName + // fileName + ".dll" + // + // NB If it's a plugin we do not ever try the ".dll" extension + QStringList attempts; + QFileSystemEntry fsEntry(fileName); + if (loadHints & QLibrary::ImprovedSearchHeuristics) { + if (pluginState != IsAPlugin) + attempts.append(fileName + QLatin1String(".dll")); + + // If the fileName is an absolute path we try that first, otherwise we + // use the system-specific suffix first + if (fsEntry.isAbsolute()) { + attempts.prepend(fileName); + } else { + attempts.append(fileName); #if defined(Q_OS_WINCE) - if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { - QString secondAttempt = fileName; - pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16()); + attempts.append(QFileInfo(fileName).absoluteFilePath()); +#endif } + } else { +#ifdef Q_OS_WINCE + attempts.append(QFileInfo(fileName).absoluteFilePath()); +#else + attempts.append(fileName); +#endif + if (pluginState != IsAPlugin) { +#if defined(Q_OS_WINCE) + attempts.append(fileName); #endif - if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { - attempt += QLatin1String(".dll"); - pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); + attempts.append(fileName + QLatin1String(".dll")); } } + Q_FOREACH (const QString &attempt, attempts) { + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); + + // If we have a handle or the last error is something other than "unable + // to find the module", then bail out + if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND) + break; + } + SetErrorMode(oldmode); if (!pHnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string()); - } - if (pHnd) { + } else { + // Query the actual name of the library that was loaded errorString.clear(); wchar_t buffer[MAX_PATH]; ::GetModuleFileName(pHnd, buffer, MAX_PATH); - attempt = QString::fromWCharArray(buffer); - const QDir dir = QFileInfo(fileName).dir(); - const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1); + QString moduleFileName = QString::fromWCharArray(buffer); + moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\'))); + const QDir dir(fsEntry.path()); if (dir.path() == QLatin1String(".")) - qualifiedFileName = realfilename; + qualifiedFileName = moduleFileName; else - qualifiedFileName = dir.filePath(realfilename); + qualifiedFileName = dir.filePath(moduleFileName); } return (pHnd != 0); } |