Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qlibrary_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:critical reason:execute-external-code
4
5#include "qplatformdefs.h"
6#include "qlibrary_p.h"
7
8#include "qdir.h"
9#include "qfile.h"
10#include "qfileinfo.h"
11#include <private/qfilesystementry_p.h>
12
13#include <qt_windows.h>
14
15QT_BEGIN_NAMESPACE
16
17using namespace Qt::StringLiterals;
18
19extern QString qt_error_string(int code);
20
21QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
22{
23 Q_UNUSED(fullVersion);
24 return QStringList(QStringLiteral(".dll"));
25}
26
27bool QLibraryPrivate::load_sys()
28{
29 //avoid 'Bad Image' message box
30 UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
31 // We make the following attempts at locating the library:
32 //
33 // Windows
34 // if (absolute)
35 // fileName
36 // fileName + ".dll"
37 // else
38 // fileName + ".dll"
39 // fileName
40 //
41 // NB If it's a plugin we do not ever try the ".dll" extension
42 QMutexLocker locker(&mutex);
43 QStringList attempts;
44
45 if (pluginState != IsAPlugin)
46 attempts.append(fileName + ".dll"_L1);
47
48 // If the fileName is an absolute path we try that first, otherwise we
49 // use the system-specific suffix first
50 QFileSystemEntry fsEntry(fileName);
51 if (fsEntry.isAbsolute())
52 attempts.prepend(fileName);
53 else
54 attempts.append(fileName);
55
56 locker.unlock();
57 Handle hnd = nullptr;
58 for (const QString &attempt : std::as_const(attempts)) {
59 hnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
60
61 // If we have a handle or the last error is something other than "unable
62 // to find the module", then bail out
63 if (hnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
64 break;
65 }
66
67 SetErrorMode(oldmode);
68 locker.relock();
69 if (!hnd) {
70 errorString = QLibrary::tr("Cannot load library %1: %2").arg(
71 QDir::toNativeSeparators(fileName), qt_error_string());
72 } else {
73 // Query the actual name of the library that was loaded
74 errorString.clear();
75
76 wchar_t buffer[MAX_PATH];
77 ::GetModuleFileName(hnd, buffer, MAX_PATH);
78
79 QString moduleFileName = QString::fromWCharArray(buffer);
80 moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(u'\\'));
81 const QDir dir(fsEntry.path());
82 if (dir.path() == "."_L1)
83 qualifiedFileName = moduleFileName;
84 else
85 qualifiedFileName = dir.filePath(moduleFileName);
86
87 if (loadHints() & QLibrary::PreventUnloadHint) {
88 // prevent the unloading of this component
89 HMODULE hmod;
90 bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN |
91 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
92 reinterpret_cast<const wchar_t *>(hnd),
93 &hmod);
94 Q_ASSERT(!ok || hmod == hnd);
95 Q_UNUSED(ok);
96 }
97 }
98 pHnd.storeRelaxed(hnd);
99 return (pHnd != nullptr);
100}
101
102bool QLibraryPrivate::unload_sys()
103{
104 if (!FreeLibrary(pHnd.loadAcquire())) {
105 errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
106 QDir::toNativeSeparators(fileName), qt_error_string());
107 return false;
108 }
109 errorString.clear();
110 return true;
111}
112
113QFunctionPointer QLibraryPrivate::resolve_sys(const char *symbol)
114{
115 FARPROC address = GetProcAddress(pHnd.loadAcquire(), symbol);
116 return QFunctionPointer(address);
117}
118QT_END_NAMESPACE
QString qt_error_string(int code)