summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemengine_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qfilesystemengine_win.cpp')
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp255
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