diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-27 08:16:14 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2020-07-29 08:41:46 +0000 |
commit | 45d340851d5f88fb27fb7be011079fa1ae238a3f (patch) | |
tree | 33e63ea2c2e2be42c8c72702b5980e604adef128 /src/plugins | |
parent | 9033002778caafcd7fb4647c34a45b5bafc5f5d3 (diff) | |
download | qtbase-45d340851d5f88fb27fb7be011079fa1ae238a3f.tar.gz |
Windows: Prevent event processing during QDesktopServices::openUrl()
The platform implementation uses the Win32 API ShellExecute(),
which may spin an event loop to do COM processing, causing things
like QMetaCallEvent being processed. Run it in a thread
to suppress this.
Fixes: QTBUG-85676
Change-Id: I240ca78b41b39ded22e466662ffce8e9b03c10a2
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
(cherry picked from commit ed114b728d9dc5265333c593254d9f6527464a60)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsservices.cpp | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index 09ae55cd99..8a95cc53a8 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -44,6 +44,8 @@ #include <QtCore/qurl.h> #include <QtCore/qdebug.h> #include <QtCore/qdir.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qthread.h> #include <QtCore/private/qwinregistry_p.h> @@ -54,15 +56,33 @@ QT_BEGIN_NAMESPACE enum { debug = 0 }; +static quintptr runShellExecute(const wchar_t *path) +{ + HINSTANCE result = nullptr; + if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { + result = ShellExecute(nullptr, nullptr, path, nullptr, nullptr, SW_SHOWNORMAL); + CoUninitialize(); + } + return reinterpret_cast<quintptr>(result); +} + static inline bool shellExecute(const QUrl &url) { const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery() ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded); - const auto result = - reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr, - reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()), - nullptr, nullptr, SW_SHOWNORMAL)); + + + // Run ShellExecute() in a thread since it may spin the event loop. + // Prevent it from interfering with processing of posted events (QTBUG-85676). + quintptr result = 0; + quintptr *resultPtr = &result; + const auto path = reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()); + QScopedPointer<QThread> thread(QThread::create([path, resultPtr] + () { *resultPtr = runShellExecute(path); })); + thread->start(); + thread->wait(); + // ShellExecute returns a value greater than 32 if successful if (result <= 32) { qWarning("ShellExecute '%ls' failed (error %zu).", qUtf16Printable(url.toString()), result); |