Windows: Allow for passing a modified argv to QCoreApplication.
Check by comparing __argc/__argv whether a modified argv was passed to QCoreApplication. If that is the case, build QCoreApplication::arguments() from that argv instead of using the command line. [ChangeLog][Important Behavior Changes][QCoreApplication] On Windows, QCoreApplication::arguments() now returns a list built from argv on Windows as well if a modified argv was passed to the class' constructor. Task-number: QTBUG-30330 Task-number: QTSOLBUG-184 Change-Id: I2498bb554130e7bfaeada3aebe786dfdd0eb534d Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
57469a8e10
commit
dff18b8e80
@ -378,6 +378,34 @@ Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
|
|||||||
static bool quitLockRefEnabled = true;
|
static bool quitLockRefEnabled = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
|
// Check whether the command line arguments match those passed to main()
|
||||||
|
// by comparing to the global __argv/__argc (MS extension).
|
||||||
|
// Deep comparison is required since argv/argc is rebuilt by WinMain for
|
||||||
|
// GUI apps or when using MinGW due to its globbing.
|
||||||
|
static inline bool isArgvModified(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (__argc != argc)
|
||||||
|
return true;
|
||||||
|
if (__argv == argv)
|
||||||
|
return false;
|
||||||
|
for (int a = 0; a < argc; ++a) {
|
||||||
|
if (argv[a] != __argv[a] && strcmp(argv[a], __argv[a]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool contains(int argc, char **argv, const char *needle)
|
||||||
|
{
|
||||||
|
for (int a = 0; a < argc; ++a) {
|
||||||
|
if (!strcmp(argv[a], needle))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||||
|
|
||||||
QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
|
QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
|
||||||
:
|
:
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
@ -385,9 +413,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
|
|||||||
#endif
|
#endif
|
||||||
argc(aargc)
|
argc(aargc)
|
||||||
, argv(aargv)
|
, argv(aargv)
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
, origArgc(aargc)
|
, modifiedArgv(false)
|
||||||
, origArgv(new char *[aargc])
|
|
||||||
#endif
|
#endif
|
||||||
, application_type(QCoreApplicationPrivate::Tty)
|
, application_type(QCoreApplicationPrivate::Tty)
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
@ -404,9 +431,9 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
|
|||||||
argc = 0;
|
argc = 0;
|
||||||
argv = (char **)∅
|
argv = (char **)∅
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
std::copy(argv, argv + argc, origArgv);
|
modifiedArgv = isArgvModified(argc, argv);
|
||||||
#endif
|
#endif // Q_OS_WIN && !Q_OS_WINRT
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
QCoreApplicationPrivate::is_app_closing = false;
|
QCoreApplicationPrivate::is_app_closing = false;
|
||||||
@ -430,9 +457,6 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate()
|
|||||||
{
|
{
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
cleanupThreadData();
|
cleanupThreadData();
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
delete [] origArgv;
|
|
||||||
#endif
|
#endif
|
||||||
QCoreApplicationPrivate::clearApplicationFilePath();
|
QCoreApplicationPrivate::clearApplicationFilePath();
|
||||||
}
|
}
|
||||||
@ -2131,10 +2155,11 @@ qint64 QCoreApplication::applicationPid()
|
|||||||
Latin1 locale. Most modern Unix systems do not have this limitation, as they are
|
Latin1 locale. Most modern Unix systems do not have this limitation, as they are
|
||||||
Unicode-based.
|
Unicode-based.
|
||||||
|
|
||||||
On NT-based Windows, this limitation does not apply either.
|
On Windows, the list is built from the argc and argv parameters only if
|
||||||
On Windows, the arguments() are not built from the contents of argv/argc, as
|
modified argv/argc parameters are passed to the constructor. In that case,
|
||||||
the content does not support Unicode. Instead, the arguments() are constructed
|
encoding problems might occur.
|
||||||
from the return value of
|
|
||||||
|
Otherwise, the arguments() are constructed from the return value of
|
||||||
\l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{GetCommandLine()}.
|
\l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{GetCommandLine()}.
|
||||||
As a result of this, the string given by arguments().at(0) might not be
|
As a result of this, the string given by arguments().at(0) might not be
|
||||||
the program name on Windows, depending on how the application was started.
|
the program name on Windows, depending on how the application was started.
|
||||||
@ -2169,21 +2194,20 @@ QStringList QCoreApplication::arguments()
|
|||||||
}
|
}
|
||||||
#endif // Q_OS_WINCE
|
#endif // Q_OS_WINCE
|
||||||
|
|
||||||
char ** const origArgv = self->d_func()->origArgv;
|
if (!self->d_func()->modifiedArgv) {
|
||||||
const int origArgc = self->d_func()->origArgc;
|
const QStringList allArguments = qWinCmdArgs(cmdline);
|
||||||
char ** const avEnd = av + ac;
|
Q_ASSERT(allArguments.size() == __argc);
|
||||||
|
for (int i = 0; i < __argc; ++i) {
|
||||||
|
if (contains(ac, av, __argv[i]))
|
||||||
|
list.append(allArguments.at(i));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
} // Fall back to rebuilding from argv/argc when a modified argv was passed.
|
||||||
|
#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
|
|
||||||
const QStringList allArguments = qWinCmdArgs(cmdline);
|
|
||||||
Q_ASSERT(allArguments.size() == origArgc);
|
|
||||||
for (int i = 0; i < origArgc; ++i)
|
|
||||||
if (std::find(av, avEnd, origArgv[i]) != avEnd)
|
|
||||||
list.push_back(allArguments.at(i));
|
|
||||||
|
|
||||||
#else
|
|
||||||
for (int a = 0; a < ac; ++a) {
|
for (int a = 0; a < ac; ++a) {
|
||||||
list << QString::fromLocal8Bit(av[a]);
|
list << QString::fromLocal8Bit(av[a]);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -115,9 +115,8 @@ public:
|
|||||||
|
|
||||||
int &argc;
|
int &argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
#ifdef Q_OS_WIN
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||||
int origArgc;
|
bool modifiedArgv;
|
||||||
char **origArgv; // store unmodified arguments for QCoreApplication::arguments()
|
|
||||||
#endif
|
#endif
|
||||||
void appendApplicationPathToLibraryPaths(void);
|
void appendApplicationPathToLibraryPaths(void);
|
||||||
|
|
||||||
|
@ -109,11 +109,11 @@ void tst_QCoreApplication::qAppName()
|
|||||||
QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName));
|
QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// "QCoreApplication::arguments() always parses arguments from actual command line on Windows
|
|
||||||
// making this test invalid."
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
void tst_QCoreApplication::argc()
|
void tst_QCoreApplication::argc()
|
||||||
{
|
{
|
||||||
|
#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
|
||||||
|
QSKIP("QCoreApplication::arguments() parses arguments from actual command line on this platform.");
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
|
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
|
||||||
@ -150,7 +150,6 @@ void tst_QCoreApplication::argc()
|
|||||||
QCOMPARE(app.arguments().count(), 1);
|
QCOMPARE(app.arguments().count(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
class EventGenerator : public QObject
|
class EventGenerator : public QObject
|
||||||
{
|
{
|
||||||
|
@ -43,9 +43,7 @@ private slots:
|
|||||||
void sendEventsOnProcessEvents(); // this must be the first test
|
void sendEventsOnProcessEvents(); // this must be the first test
|
||||||
void getSetCheck();
|
void getSetCheck();
|
||||||
void qAppName();
|
void qAppName();
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
void argc();
|
void argc();
|
||||||
#endif
|
|
||||||
void postEvent();
|
void postEvent();
|
||||||
void removePostedEvents();
|
void removePostedEvents();
|
||||||
#ifndef QT_NO_THREAD
|
#ifndef QT_NO_THREAD
|
||||||
|
Loading…
x
Reference in New Issue
Block a user