diff options
Diffstat (limited to 'src/corelib/io/qfilesystemengine_win.cpp')
-rw-r--r-- | src/corelib/io/qfilesystemengine_win.cpp | 255 |
1 files changed, 117 insertions, 138 deletions
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 60285cfea8..3ec32e31a1 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qfilesystemengine_p.h" #include "qoperatingsystemversion.h" @@ -56,6 +20,7 @@ #if QT_CONFIG(regularexpression) #include "qregularexpression.h" #endif +#include "qstring.h" #include <sys/types.h> #include <direct.h> @@ -72,6 +37,8 @@ #define SECURITY_WIN32 #include <security.h> +#include <QtCore/private/qfunctions_win_p.h> + #ifndef SPI_GETPLATFORMTYPE #define SPI_GETPLATFORMTYPE 257 #endif @@ -137,12 +104,6 @@ typedef struct _REPARSE_DATA_BUFFER { CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif -#if defined(QT_BOOTSTRAPPED) -# define QT_FEATURE_fslibs -1 -#else -# define QT_FEATURE_fslibs 1 -#endif // QT_BOOTSTRAPPED - #if QT_CONFIG(fslibs) #include <aclapi.h> #include <authz.h> @@ -151,9 +112,12 @@ static PSID currentUserSID = nullptr; static PSID currentGroupSID = nullptr; static PSID worldSID = nullptr; static HANDLE currentUserImpersonatedToken = nullptr; +#endif // fslibs QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; +#if QT_CONFIG(fslibs) namespace { struct GlobalSid { @@ -407,20 +371,46 @@ constexpr NonSpecificPermissions toNonSpecificPermissions(PermissionTag tag, return NonSpecificPermissions::fromInt((permissions.toInt() >> int(tag)) & 0x7); } +[[maybe_unused]] // Not currently used; included to show how to do it (without bit-rotting). constexpr QFileDevice::Permissions toSpecificPermissions(PermissionTag tag, NonSpecificPermissions permissions) { return QFileDevice::Permissions::fromInt(permissions.toInt() << int(tag)); } -QT_END_NAMESPACE - } // anonymous namespace #endif // QT_CONFIG(fslibs) -QT_BEGIN_NAMESPACE +#if QT_DEPRECATED_SINCE(6,6) +int qt_ntfs_permission_lookup = 0; +#endif + +static QBasicAtomicInt qt_ntfs_permission_lookup_v2 = Q_BASIC_ATOMIC_INITIALIZER(0); + +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + +bool qEnableNtfsPermissionChecks() noexcept +{ + return qt_ntfs_permission_lookup_v2.fetchAndAddRelaxed(1) +QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup) + != 0; +} + +bool qDisableNtfsPermissionChecks() noexcept +{ + return qt_ntfs_permission_lookup_v2.fetchAndSubRelaxed(1) +QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup) + == 1; +} -Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0; +bool qAreNtfsPermissionChecksEnabled() noexcept +{ + return qt_ntfs_permission_lookup_v2.loadRelaxed() +QT_IF_DEPRECATED_SINCE(6, 6, /*nothing*/, + qt_ntfs_permission_lookup) + ; +} +QT_WARNING_POP /*! \class QNativeFilePermissions @@ -476,8 +466,8 @@ QNativeFilePermissions::QNativeFilePermissions(std::optional<QFileDevice::Permis ACCESS_MASK denyMask, allowMask; }; - auto makeMasks = [this, isDir](NonSpecificPermissions allowPermissions, - NonSpecificPermissions denyPermissions, bool owner) { + auto makeMasks = [isDir](NonSpecificPermissions allowPermissions, + NonSpecificPermissions denyPermissions, bool owner) { constexpr ACCESS_MASK AllowRead = FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA; constexpr ACCESS_MASK DenyRead = FILE_READ_DATA | FILE_READ_EA; @@ -593,6 +583,9 @@ QNativeFilePermissions::QNativeFilePermissions(std::optional<QFileDevice::Permis sa.bInheritHandle = FALSE; isNull = false; +#else + Q_UNUSED(perms); + Q_UNUSED(isDir); #endif // QT_CONFIG(fslibs) ok = true; } @@ -602,7 +595,7 @@ QNativeFilePermissions::QNativeFilePermissions(std::optional<QFileDevice::Permis Return pointer to a \c SECURITY_ATTRIBUTES object describing the permissions. The returned pointer many be null if default permissions were requested or - during bootstrap. The calles must call \c isOk() to check if the object + during bootstrap. The callers must call \c isOk() to check if the object was successfully constructed before using this method. */ SECURITY_ATTRIBUTES *QNativeFilePermissions::securityAttributes() @@ -681,14 +674,14 @@ static QString readSymLink(const QFileSystemEntry &link) #if QT_CONFIG(fslibs) && QT_CONFIG(regularexpression) initGlobalSid(); - QRegularExpression matchVolumeRe(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), + QRegularExpression matchVolumeRe("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"_L1, QRegularExpression::CaseInsensitiveOption); auto matchVolume = matchVolumeRe.match(result); if (matchVolume.hasMatch()) { Q_ASSERT(matchVolume.capturedStart() == 0); DWORD len; wchar_t buffer[MAX_PATH]; - const QString volumeName = QLatin1String("\\\\?\\") + matchVolume.captured(); + const QString volumeName = "\\\\?\\"_L1 + matchVolume.captured(); if (GetVolumePathNamesForVolumeName(reinterpret_cast<LPCWSTR>(volumeName.utf16()), buffer, MAX_PATH, &len) != 0) { @@ -705,21 +698,16 @@ static QString readLink(const QFileSystemEntry &link) #if QT_CONFIG(fslibs) QString ret; - bool neededCoInit = false; IShellLink *psl; // pointer to IShellLink i/f WIN32_FIND_DATA wfd; wchar_t szGotPath[MAX_PATH]; + QComHelper comHelper; + // Get pointer to the IShellLink interface. HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); - if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(nullptr); - hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, - (LPVOID *)&psl); - } if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. IPersistFile *ppf; hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); @@ -735,8 +723,6 @@ static QString readLink(const QFileSystemEntry &link) } psl->Release(); } - if (neededCoInit) - CoUninitialize(); return ret; #else @@ -748,10 +734,10 @@ static QString readLink(const QFileSystemEntry &link) static bool uncShareExists(const QString &server) { // This code assumes the UNC path is always like \\?\UNC\server... - const auto parts = QStringView{server}.split(QLatin1Char('\\'), Qt::SkipEmptyParts); + const auto parts = QStringView{server}.split(u'\\', Qt::SkipEmptyParts); if (parts.count() >= 3) { QStringList shares; - if (QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(2), &shares)) + if (QFileSystemEngine::uncListSharesOnServer("\\\\"_L1 + parts.at(2), &shares)) return parts.count() < 4 || shares.contains(parts.at(3).toString(), Qt::CaseInsensitive); } @@ -761,11 +747,11 @@ static bool uncShareExists(const QString &server) static inline bool getFindData(QString path, WIN32_FIND_DATA &findData) { // path should not end with a trailing slash - while (path.endsWith(QLatin1Char('\\'))) + while (path.endsWith(u'\\')) path.chop(1); // can't handle drives - if (!path.endsWith(QLatin1Char(':'))) { + if (!path.endsWith(u':')) { HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData); if (hFind != INVALID_HANDLE_VALUE) { ::FindClose(hFind); @@ -776,7 +762,6 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData) return false; } -#if defined(__IFileOperation_INTERFACE_DEFINED__) class FileOperationProgressSink : public IFileOperationProgressSink { public: @@ -837,9 +822,10 @@ public: return (dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE) ? S_OK : E_FAIL; } HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD /* dwFlags */, IShellItem * /* psiItem */, - HRESULT /* hrDelete */, + HRESULT hrDelete, IShellItem *psiNewlyCreated) override { + deleteResult = hrDelete; if (psiNewlyCreated) { wchar_t *pszName = nullptr; psiNewlyCreated->GetDisplayName(SIGDN_FILESYSPATH, &pszName); @@ -860,10 +846,10 @@ public: HRESULT STDMETHODCALLTYPE ResumeTimer() override { return S_OK; } QString targetPath; + HRESULT deleteResult = S_OK; private: ULONG ref; }; -#endif bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list) { @@ -900,6 +886,18 @@ void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data) QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data) { + QFileSystemEntry ret = getRawLinkPath(link, data); + if (!ret.isEmpty() && ret.isRelative()) { + QString target = absoluteName(link).path() + u'/' + ret.filePath(); + ret = QFileSystemEntry(QDir::cleanPath(target)); + } + return ret; +} + +//static +QFileSystemEntry QFileSystemEngine::getRawLinkPath(const QFileSystemEntry &link, + QFileSystemMetaData &data) +{ Q_CHECK_FILE_NAME(link, link); if (data.missingFlags(QFileSystemMetaData::LinkType)) @@ -910,12 +908,7 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, target = readLink(link); else if (data.isLink()) target = readSymLink(link); - QFileSystemEntry ret(target); - if (!target.isEmpty() && ret.isRelative()) { - target.prepend(absoluteName(link).path() + QLatin1Char('/')); - ret = QFileSystemEntry(QDir::cleanPath(target)); - } - return ret; + return QFileSystemEntry(target); } //static @@ -932,7 +925,7 @@ QFileSystemEntry QFileSystemEngine::junctionTarget(const QFileSystemEntry &link, target = readSymLink(link); QFileSystemEntry ret(target); if (!target.isEmpty() && ret.isRelative()) { - target.prepend(absoluteName(link).path() + QLatin1Char('/')); + target.prepend(absoluteName(link).path() + u'/'); ret = QFileSystemEntry(QDir::cleanPath(target)); } return ret; @@ -975,8 +968,8 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) // (which is an invalid filename) this function will strip the space off and viola, // the file is later reported as existing. Therefore, we re-add the whitespace that // was at the end of path in order to keep the filename invalid. - if (!path.isEmpty() && path.at(path.size() - 1) == QLatin1Char(' ')) - absPath.append(QLatin1Char(' ')); + if (!path.isEmpty() && path.at(path.size() - 1) == u' ') + absPath.append(u' '); return absPath; } @@ -993,17 +986,17 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) else ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(entry.filePath())); } else { - ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath()); + ret = QDir::cleanPath(QDir::currentPath() + u'/' + entry.filePath()); } // The path should be absolute at this point. // From the docs : // Absolute paths begin with the directory separator "/" // (optionally preceded by a drive specification under Windows). - if (ret.at(0) != QLatin1Char('/')) { + if (ret.at(0) != u'/') { Q_ASSERT(ret.length() >= 2); Q_ASSERT(ret.at(0).isLetter()); - Q_ASSERT(ret.at(1) == QLatin1Char(':')); + Q_ASSERT(ret.at(1) == u':'); // Force uppercase drive letters. ret[0] = ret.at(0).toUpper(); @@ -1076,7 +1069,7 @@ QByteArray QFileSystemEngine::id(HANDLE fHandle) //static bool QFileSystemEngine::setFileTime(HANDLE fHandle, const QDateTime &newDate, - QAbstractFileEngine::FileTime time, QSystemError &error) + QFile::FileTime time, QSystemError &error) { FILETIME fTime; FILETIME *pLastWrite = nullptr; @@ -1084,15 +1077,15 @@ bool QFileSystemEngine::setFileTime(HANDLE fHandle, const QDateTime &newDate, FILETIME *pCreationTime = nullptr; switch (time) { - case QAbstractFileEngine::ModificationTime: + case QFile::FileModificationTime: pLastWrite = &fTime; break; - case QAbstractFileEngine::AccessTime: + case QFile::FileAccessTime: pLastAccess = &fTime; break; - case QAbstractFileEngine::BirthTime: + case QFile::FileBirthTime: pCreationTime = &fTime; break; @@ -1115,8 +1108,7 @@ QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEng { QString name; #if QT_CONFIG(fslibs) - extern int qt_ntfs_permission_lookup; - if (qt_ntfs_permission_lookup > 0) { + if (qAreNtfsPermissionChecksEnabled()) { initGlobalSid(); { PSID pOwner = 0; @@ -1170,7 +1162,7 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst QFileSystemMetaData::MetaDataFlags what) { #if QT_CONFIG(fslibs) - if (qt_ntfs_permission_lookup > 0) { + if (qAreNtfsPermissionChecksEnabled()) { initGlobalSid(); QString fname = entry.nativeFilePath(); @@ -1196,7 +1188,7 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst // Check for generic permissions and file-specific bits that most closely // represent POSIX permissions. - // Contants like FILE_GENERIC_{READ,WRITE,EXECUTE} cannot be used + // Constants like FILE_GENERIC_{READ,WRITE,EXECUTE} cannot be used // here because they contain permission bits shared between all of them. if (accessMask & (GENERIC_READ | FILE_READ_DATA)) data.entryFlags |= readFlags; @@ -1263,9 +1255,8 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst QString fname = entry.filePath(); QString ext = fname.right(4).toLower(); - if (data.isDirectory() || ext == QLatin1String(".exe") || ext == QLatin1String(".com") - || ext == QLatin1String(".bat") || ext == QLatin1String(".pif") - || ext == QLatin1String(".cmd")) { + if (data.isDirectory() || ext == ".exe"_L1 || ext == ".com"_L1 + || ext == ".bat"_L1 || ext == ".pif"_L1 || ext == ".cmd"_L1) { data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission | QFileSystemMetaData::GroupExecutePermission | QFileSystemMetaData::OtherExecutePermission @@ -1300,7 +1291,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa DWORD drivesBitmask = ::GetLogicalDrives(); ::SetErrorMode(oldErrorMode); int drivebit = - 1 << (fname.filePath().at(0).toUpper().unicode() - QLatin1Char('A').unicode()); + 1 << (fname.filePath().at(0).toUpper().unicode() - u'A'); if (drivesBitmask & drivebit) { fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM; entryExists = true; @@ -1308,7 +1299,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa } else { const QString &path = fname.nativeFilePath(); bool is_dir = false; - if (path.startsWith(QLatin1String("\\\\?\\UNC"))) { + if (path.startsWith("\\\\?\\UNC"_L1)) { // UNC - stat doesn't work for all cases (Windows bug) int s = path.indexOf(path.at(0),7); if (s > 0) { @@ -1397,7 +1388,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM // Check for ".lnk": Directories named ".lnk" should be skipped, corrupted // link files should still be detected as links. const QString origFilePath = entry.filePath(); - if (origFilePath.endsWith(QLatin1String(".lnk")) && !isDirPath(origFilePath, nullptr)) { + if (origFilePath.endsWith(".lnk"_L1) && !isDirPath(origFilePath, nullptr)) { data.entryFlags |= QFileSystemMetaData::WinLnkType; fname = QFileSystemEntry(readLink(entry)); } else { @@ -1470,8 +1461,8 @@ static inline bool rmDir(const QString &path) bool QFileSystemEngine::isDirPath(const QString &dirPath, bool *existed) { QString path = dirPath; - if (path.length() == 2 && path.at(1) == QLatin1Char(':')) - path += QLatin1Char('\\'); + if (path.length() == 2 && path.at(1) == u':') + path += u'\\'; const QString longPath = QFSFileEnginePrivate::longFileName(path); DWORD fileAttrib = ::GetFileAttributes(reinterpret_cast<const wchar_t*>(longPath.utf16())); @@ -1500,11 +1491,11 @@ static bool createDirectoryWithParents(const QString &nativeName, bool shouldMkdirFirst = true) { const auto isUNCRoot = [](const QString &nativeName) { - return nativeName.startsWith(QLatin1String("\\\\")) + return nativeName.startsWith("\\\\"_L1) && nativeName.count(QDir::separator()) <= 3; }; const auto isDriveName = [](const QString &nativeName) { - return nativeName.size() == 2 && nativeName.at(1) == QLatin1Char(':'); + return nativeName.size() == 2 && nativeName.at(1) == u':'; }; const auto isDir = [](const QString &nativeName) { bool exists = false; @@ -1572,7 +1563,7 @@ bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool remo for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { const auto chunkRef = QStringView{dirName}.left(slash); if (chunkRef.length() == 2 && chunkRef.at(0).isLetter() - && chunkRef.at(1) == QLatin1Char(':')) { + && chunkRef.at(1) == u':') { break; } const QString chunk = chunkRef.toString(); @@ -1592,8 +1583,8 @@ QString QFileSystemEngine::rootPath() { QString ret = QString::fromLatin1(qgetenv("SystemDrive")); if (ret.isEmpty()) - ret = QLatin1String("c:"); - ret.append(QLatin1Char('/')); + ret = "c:"_L1; + ret.append(u'/'); return ret; } @@ -1651,13 +1642,13 @@ QString QFileSystemEngine::tempPath() QString::fromWCharArray(tempPath, len); } if (!ret.isEmpty()) { - while (ret.endsWith(QLatin1Char('\\'))) + while (ret.endsWith(u'\\')) ret.chop(1); ret = QDir::fromNativeSeparators(ret); } if (ret.isEmpty()) { - ret = QLatin1String("C:/tmp"); - } else if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) + ret = "C:/tmp"_L1; + } else if (ret.length() >= 2 && ret[1] == u':') ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return ret; } @@ -1680,23 +1671,20 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) QFileSystemEntry QFileSystemEngine::currentPath() { - QString ret; - DWORD size = 0; - wchar_t currentName[PATH_MAX]; - size = ::GetCurrentDirectory(PATH_MAX, currentName); - if (size != 0) { - if (size > PATH_MAX) { - wchar_t *newCurrentName = new wchar_t[size]; - if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0) - ret = QString::fromWCharArray(newCurrentName, size); - delete [] newCurrentName; - } else { - ret = QString::fromWCharArray(currentName, size); - } + QString ret(PATH_MAX, Qt::Uninitialized); + DWORD size = GetCurrentDirectoryW(PATH_MAX, reinterpret_cast<wchar_t *>(ret.data())); + if (size > PATH_MAX) { + // try again after enlarging the buffer + ret.resize(size); + size = GetCurrentDirectoryW(size, reinterpret_cast<wchar_t *>(ret.data())); + + // note: the current directory may have changed underneath us; if the + // new one is even bigger, we may return a truncated string! } - if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) + if (size >= 2 && ret.at(1) == u':') ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. - return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath()); + ret.resize(size); + return QFileSystemEntry(std::move(ret), QFileSystemEntry::FromNativePath()); } //static @@ -1704,18 +1692,11 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy QSystemError &error) { bool ret = false; + QComHelper comHelper; IShellLink *psl = nullptr; HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<void **>(&psl)); - bool neededCoInit = false; - if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(nullptr); - hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, - reinterpret_cast<void **>(&psl)); - } - if (SUCCEEDED(hres)) { const auto name = QDir::toNativeSeparators(source.filePath()); const auto pathName = QDir::toNativeSeparators(source.path()); @@ -1735,9 +1716,6 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy if (!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); - if (neededCoInit) - CoUninitialize(); - return ret; } @@ -1805,8 +1783,8 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, // we need the "display name" of the file, so can't use nativeAbsoluteFilePath const QString sourcePath = QDir::toNativeSeparators(absoluteName(source).filePath()); -# if defined(__IFileOperation_INTERFACE_DEFINED__) - CoInitialize(nullptr); + QComHelper comHelper; + IFileOperation *pfo = nullptr; IShellItem *deleteItem = nullptr; FileOperationProgressSink *sink = nullptr; @@ -1819,7 +1797,6 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, deleteItem->Release(); if (pfo) pfo->Release(); - CoUninitialize(); if (!SUCCEEDED(hres)) error = QSystemError(hres, QSystemError::NativeError); }); @@ -1840,11 +1817,13 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, hres = pfo->PerformOperations(); if (!SUCCEEDED(hres)) return false; - newLocation = QFileSystemEntry(sink->targetPath); -# endif // no IFileOperation in SDK (mingw, likely) - fall back to SHFileOperation + if (!SUCCEEDED(sink->deleteResult)) { + error = QSystemError(sink->deleteResult, QSystemError::NativeError); + return false; + } + newLocation = QFileSystemEntry(sink->targetPath); return true; - } //static @@ -1883,7 +1862,7 @@ static inline QDateTime fileTimeToQDateTime(const FILETIME *time) FileTimeToSystemTime(time, &sTime); return QDateTime(QDate(sTime.wYear, sTime.wMonth, sTime.wDay), QTime(sTime.wHour, sTime.wMinute, sTime.wSecond, sTime.wMilliseconds), - Qt::UTC); + QTimeZone::UTC); } QDateTime QFileSystemMetaData::birthTime() const |