From 01004504a7a07fb758c7f801b308c77322f7d2a9 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Mon, 13 May 2024 22:24:56 -0400 Subject: [PATCH 1/2] Windows: Fix rare argument parsing bug --- src/main.cpp | 11 +++++++++++ src/qvwin32functions.cpp | 16 ++++++++++++++++ src/qvwin32functions.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index b3d16248..089101fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include "qvapplication.h" +#include "qvwin32functions.h" #include @@ -15,7 +16,17 @@ int main(int argc, char *argv[]) parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument(QObject::tr("file"), QObject::tr("The file to open.")); +#if defined Q_OS_WIN && WIN32_LOADED + // Workaround for unicode characters getting mangled in certain cases. To support unicode arguments on + // Windows, QCoreApplication normally ignores argv and gets them from the Windows API instead. But this + // only happens if it thinks argv hasn't been modified prior to being passed into QCoreApplication's + // constructor. Certain characters like U+2033 (double prime) get converted differently in argv versus + // the value Qt is comparing with (__argv). This makes Qt incorrectly think the data was changed, and + // it skips fetching unicode arguments from the API. + parser.process(QVWin32Functions::getCommandLineArgs()); +#else parser.process(app); +#endif auto *window = QVApplication::newWindow(); if (!parser.positionalArguments().isEmpty()) diff --git a/src/qvwin32functions.cpp b/src/qvwin32functions.cpp index 33c2b1a5..056651e1 100644 --- a/src/qvwin32functions.cpp +++ b/src/qvwin32functions.cpp @@ -145,6 +145,22 @@ void QVWin32Functions::showOpenWithDialog(const QString &filePath, const QWindow qDebug() << "Failed launching open with dialog"; } +// Logic borrowed from Qt's private qWinCmdArgs function +QStringList QVWin32Functions::getCommandLineArgs() +{ + const QString cmdLine = QString::fromWCharArray(GetCommandLine()); + QStringList result; + int size; + if (wchar_t **argv = CommandLineToArgvW((const wchar_t *)cmdLine.utf16(), &size)) { + result.reserve(size); + wchar_t **argvEnd = argv + size; + for (wchar_t **a = argv; a < argvEnd; ++a) + result.append(QString::fromWCharArray(*a)); + LocalFree(argv); + } + return result; +} + QByteArray QVWin32Functions::getIccProfileForWindow(const QWindow *window) { QByteArray result; diff --git a/src/qvwin32functions.h b/src/qvwin32functions.h index 86faf78a..fee6163e 100644 --- a/src/qvwin32functions.h +++ b/src/qvwin32functions.h @@ -14,6 +14,8 @@ class QVWin32Functions static void showOpenWithDialog(const QString &filePath, const QWindow *parent); + static QStringList getCommandLineArgs(); + static QByteArray getIccProfileForWindow(const QWindow *window); }; From 1ea42f1f8651bd37bd8a120a07ced217d4397111 Mon Sep 17 00:00:00 2001 From: Benjamin Owad Date: Sun, 19 May 2024 16:49:40 -0400 Subject: [PATCH 2/2] Add QTBUG link --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 089101fe..718b13d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ int main(int argc, char *argv[]) // constructor. Certain characters like U+2033 (double prime) get converted differently in argv versus // the value Qt is comparing with (__argv). This makes Qt incorrectly think the data was changed, and // it skips fetching unicode arguments from the API. + // https://bugreports.qt.io/browse/QTBUG-125380 parser.process(QVWin32Functions::getCommandLineArgs()); #else parser.process(app);