diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index aaf3d1f5fb..7705f1ab95 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -231,7 +231,8 @@ bool QSaveFile::open(OpenMode mode) d->finalFileName = existingFile.filePath(); } - d->fileEngine = new QTemporaryFileEngine(QTemporaryFileEngine::Win32NonShared); + d->fileEngine = new QTemporaryFileEngine(QTemporaryFileEngine::Win32NonShared + | QTemporaryFileEngine::Win32OpenForDelete); // if the target file exists, we'll copy its permissions below, // but until then, let's ensure the temporary file is not accessible // to a third party diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 4712e65a41..518fef4309 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -37,6 +37,15 @@ ** ****************************************************************************/ +#if WINVER < 0x0600 +# undef WINVER +# define WINVER 0x0600 +#endif +#if _WIN32_WINNT < 0x0600 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +#endif + #include "qtemporaryfile.h" #ifndef QT_NO_TEMPORARYFILE @@ -46,6 +55,11 @@ #include "private/qfile_p.h" #include "private/qsystemerror_p.h" +#ifdef Q_OS_WIN +#include "qbytearray.h" +#include "qt_windows.h" +#endif + #if !defined(Q_OS_WIN) #include "private/qcore_unix_p.h" // overrides QT_OPEN #include @@ -153,15 +167,18 @@ static bool createFileFromTemplate(NativeFileHandle &file, Q_UNUSED(mode); const DWORD shareMode = (flags & QTemporaryFileEngine::Win32NonShared) ? 0u : (FILE_SHARE_READ | FILE_SHARE_WRITE); + const DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE | ((flags + & QTemporaryFileEngine::Win32OpenForDelete) + ? DELETE : 0u); # ifndef Q_OS_WINRT file = CreateFile((const wchar_t *)path.constData(), - GENERIC_READ | GENERIC_WRITE, + desiredAccess, shareMode, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); # else // !Q_OS_WINRT file = CreateFile2((const wchar_t *)path.constData(), - GENERIC_READ | GENERIC_WRITE, + desiredAccess, shareMode, CREATE_NEW, NULL); # endif // Q_OS_WINRT @@ -393,6 +410,23 @@ bool QTemporaryFileEngine::rename(const QString &newName) bool QTemporaryFileEngine::renameOverwrite(const QString &newName) { +#ifdef Q_OS_WIN + Q_D(const QFSFileEngine); + if (flags & QTemporaryFileEngine::Win32OpenForDelete && d->fileHandle != INVALID_HANDLE_VALUE) { + QString newPath = QFileSystemEntry(newName).nativeFilePath(); + QByteArray fileRenameInfoData(sizeof(FILE_RENAME_INFO) + newPath.size() * sizeof(wchar_t), '\0'); + FILE_RENAME_INFO &fileRenameInfo = *((FILE_RENAME_INFO *)fileRenameInfoData.data()); + fileRenameInfo.ReplaceIfExists = TRUE; + fileRenameInfo.RootDirectory = nullptr; + fileRenameInfo.FileNameLength = newPath.size(); + newPath.toWCharArray(fileRenameInfo.FileName); + bool ret = ::SetFileInformationByHandle(d->fileHandle, FileRenameInfo, &fileRenameInfo, fileRenameInfoData.size()) != 0; + //if (!ret) + // setError(QFile::RenameError, QSystemError(::GetLastError(), QSystemError::NativeError).toString()); + if (ret) return ret; + // Fallback to MoveFileEx + } +#endif QFSFileEngine::close(); return QFSFileEngine::renameOverwrite(newName); } diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index b0fab3a255..d347369707 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -85,7 +85,7 @@ class QTemporaryFileEngine : public QFSFileEngine { Q_DECLARE_PRIVATE(QFSFileEngine) public: - enum Flags { Win32NonShared = 0x1 }; + enum Flags { Win32NonShared = 0x1, Win32OpenForDelete = 0x2 }; explicit QTemporaryFileEngine(int _flags = 0) : flags(_flags) {}