summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowsservices.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-11-28 10:13:56 +0100
committerOliver Wolff <oliver.wolff@qt.io>2022-08-26 08:53:41 +0200
commit7e89e6bfe83761bb3dd80dddf4ccc1c332cae80d (patch)
tree7aecbd95e68f2a92be199dd0122f29108430325b /src/plugins/platforms/windows/qwindowsservices.cpp
parentb9053b55f8e0f1750526e117d9c059a0bd883baf (diff)
Windows QPA/QPlatformServices::openUrl(): Add work around for anchors on local file URLs
Retrieve the browser executable and pass the URL as command line argument in this case to work around ShellExecute() failing to handle anchors. Pick-to: 6.4 6.3 6.2 5.15 Fixes: QTBUG-14460 Change-Id: I44ccd1126d5db6a387b36729837edc045908a670 Reviewed-by: André de la Rocha <andre.rocha@qt.io>
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsservices.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp67
1 files changed, 61 insertions, 6 deletions
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index fbad934a05..f2bd90f4bd 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -14,6 +14,7 @@
#include <QtCore/private/qwinregistry_p.h>
#include <shlobj.h>
+#include <shlwapi.h>
#include <intshcut.h>
QT_BEGIN_NAMESPACE
@@ -25,12 +26,17 @@ enum { debug = 0 };
class QWindowsShellExecuteThread : public QThread
{
public:
- explicit QWindowsShellExecuteThread(const wchar_t *path) : m_path(path) { }
+ explicit QWindowsShellExecuteThread(const wchar_t *operation, const wchar_t *file,
+ const wchar_t *parameters)
+ : m_operation(operation)
+ , m_file(file)
+ , m_parameters(parameters) { }
void run() override
{
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
- m_result = ShellExecute(nullptr, nullptr, m_path, nullptr, nullptr, SW_SHOWNORMAL);
+ m_result = ShellExecute(nullptr, m_operation, m_file, m_parameters, nullptr,
+ SW_SHOWNORMAL);
CoUninitialize();
}
}
@@ -39,9 +45,55 @@ public:
private:
HINSTANCE m_result = nullptr;
- const wchar_t *m_path;
+ const wchar_t *m_operation;
+ const wchar_t *m_file;
+ const wchar_t *m_parameters;
};
+static QString msgShellExecuteFailed(const QUrl &url, quintptr code)
+{
+ QString result;
+ QTextStream(&result) <<"ShellExecute '" << url.toString() << "' failed (error " << code << ").";
+ return result;
+}
+
+// Retrieve the web browser and open the URL. This should be used for URLs with
+// fragments which don't work when using ShellExecute() directly (QTBUG-14460,
+// QTBUG-55300).
+static bool openWebBrowser(const QUrl &url)
+{
+ WCHAR browserExecutable[MAX_PATH] = {};
+ const wchar_t operation[] = L"open";
+ DWORD browserExecutableSize = MAX_PATH;
+ if (FAILED(AssocQueryString(0, ASSOCSTR_EXECUTABLE, L"http", operation,
+ browserExecutable, &browserExecutableSize))) {
+ return false;
+ }
+ QString browser = QString::fromWCharArray(browserExecutable, browserExecutableSize - 1);
+ // Workaround for "old" MS Edge entries. Instead of LaunchWinApp.exe we can just use msedge.exe
+ if (browser.contains("LaunchWinApp.exe"_L1, Qt::CaseInsensitive))
+ browser = "msedge.exe"_L1;
+ const QString urlS = url.toString(QUrl::FullyEncoded);
+
+ // Run ShellExecute() in a thread since it may spin the event loop.
+ // Prevent it from interfering with processing of posted events (QTBUG-85676).
+ QWindowsShellExecuteThread thread(operation,
+ reinterpret_cast<const wchar_t *>(browser.utf16()),
+ reinterpret_cast<const wchar_t *>(urlS.utf16()));
+ thread.start();
+ thread.wait();
+
+ const auto result = reinterpret_cast<quintptr>(thread.result());
+ if (debug)
+ qDebug() << __FUNCTION__ << urlS << QString::fromWCharArray(browserExecutable) << result;
+ // ShellExecute returns a value greater than 32 if successful
+ if (result <= 32) {
+ qWarning("%s", qPrintable(msgShellExecuteFailed(url, result)));
+ return false;
+ }
+ return true;
+}
+
static inline bool shellExecute(const QUrl &url)
{
const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery()
@@ -51,7 +103,9 @@ static inline bool shellExecute(const QUrl &url)
// Run ShellExecute() in a thread since it may spin the event loop.
// Prevent it from interfering with processing of posted events (QTBUG-85676).
- QWindowsShellExecuteThread thread(reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()));
+ QWindowsShellExecuteThread thread(nullptr,
+ reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
+ nullptr);
thread.start();
thread.wait();
@@ -59,7 +113,7 @@ static inline bool shellExecute(const QUrl &url)
// ShellExecute returns a value greater than 32 if successful
if (result <= 32) {
- qWarning("ShellExecute '%ls' failed (error %zu).", qUtf16Printable(url.toString()), result);
+ qWarning("%s", qPrintable(msgShellExecuteFailed(url, result)));
return false;
}
return true;
@@ -136,7 +190,8 @@ bool QWindowsServices::openUrl(const QUrl &url)
const QString scheme = url.scheme();
if (scheme == u"mailto" && launchMail(url))
return true;
- return shellExecute(url);
+ return url.isLocalFile() && url.hasFragment()
+ ? openWebBrowser(url) : shellExecute(url);
}
bool QWindowsServices::openDocument(const QUrl &url)