From 6545404afad30b60d1a8e9a2abaf301abaf8f6a5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Apr 2015 10:57:20 +0200 Subject: Windows: Fix QLockFile hanging when file cannot be created. Return QLockFile::PermissionError when file does not exist, preventing the stale file detection logic from triggering. Add Windows-only autotest trying to create a lock file in a system folder guarded with checks for elevated processes and UAC virtualization. Task-number: QTBUG-45631 Change-Id: I1790f8f925660f6bf1df94c2ced901e6ec57cbb0 Reviewed-by: Joerg Bornemann Reviewed-by: Oliver Wolff --- tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp | 65 +++++++++++++++++++++++ tests/auto/corelib/io/qlockfile/tst_qlockfile.pro | 1 + 2 files changed, 66 insertions(+) (limited to 'tests/auto/corelib/io/qlockfile') diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp index 90f65e9dbc..bef3d3a012 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -36,8 +36,11 @@ #include #include #include +#include #if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) #include +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +# include #endif class tst_QLockFile : public QObject @@ -58,6 +61,7 @@ private slots: void staleLongLockFromBusyProcess(); void staleLockRace(); void noPermissions(); + void noPermissionsWindows(); public: QString m_helperApp; @@ -415,5 +419,66 @@ void tst_QLockFile::noPermissions() QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError)); } +enum ProcessProperty { + ElevatedProcess = 0x1, + VirtualStore = 0x2 +}; + +Q_DECLARE_FLAGS(ProcessProperties, ProcessProperty) +Q_DECLARE_OPERATORS_FOR_FLAGS(ProcessProperties) + +static inline ProcessProperties processProperties() +{ + ProcessProperties result; +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) + HANDLE processToken = NULL; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &processToken)) { + DWORD elevation; // struct containing a DWORD, not present in some MinGW headers. + DWORD cbSize = sizeof(elevation); + if (GetTokenInformation(processToken, TokenElevation, &elevation, cbSize, &cbSize) + && elevation) { + result |= ElevatedProcess; + } + // Check for UAC virtualization (compatibility mode for old software + // allowing it to write to system folders by mirroring them under + // "\Users\...\AppData\Local\VirtualStore\", which is typically the case + // for MinGW). + DWORD virtualStoreEnabled = 0; + cbSize = sizeof(virtualStoreEnabled); + if (GetTokenInformation(processToken, TokenVirtualizationEnabled, &virtualStoreEnabled, cbSize, &cbSize) + && virtualStoreEnabled) { + result |= VirtualStore; + } + CloseHandle(processToken); + } +#endif + return result; +} + +void tst_QLockFile::noPermissionsWindows() +{ + // Windows: Do the permissions test in a system directory in which + // files cannot be created. +#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) + QSKIP("This test is for desktop Windows only"); +#endif +#ifdef Q_OS_WIN + if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7) + QSKIP("This test requires at least Windows 7"); +#endif + if (const int p = processProperties()) { + const QByteArray message = "This test cannot be run (properties=0x" + + QByteArray::number(p, 16) + ')'; + QSKIP(message.constData()); + } + + const QString fileName = QFile::decodeName(qgetenv("ProgramFiles")) + + QLatin1Char('/') + QCoreApplication::applicationName() + + QDateTime::currentDateTime().toString(QStringLiteral("yyMMddhhmm")); + QLockFile lockFile(fileName); + QVERIFY(!lockFile.lock()); + QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError)); +} + QTEST_MAIN(tst_QLockFile) #include "tst_qlockfile.moc" diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro index 2f7009b736..6eb72343bc 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro @@ -4,3 +4,4 @@ TARGET = tst_qlockfile SOURCES += tst_qlockfile.cpp QT = core testlib concurrent +win32:!wince:!winrt:LIBS += -ladvapi32 -- cgit v1.2.3