refs #782 Changes to CAtomicFile::replaceOriginal on Windows:

* Remember to supply canonical paths with native path separators to Win32 API calls.
* Supply the flag to MoveFileEx to wait for the move to really happen.
* Support long paths (more than 260 characters).
This commit is contained in:
Mathew Sutcliffe
2016-10-27 00:21:48 +01:00
committed by Klaus Basan
parent d9d16dc8e0
commit 1d22bd9acf

View File

@@ -130,13 +130,18 @@ namespace BlackMisc
#elif defined(Q_OS_WIN32) #elif defined(Q_OS_WIN32)
void CAtomicFile::replaceOriginal() void CAtomicFile::replaceOriginal()
{ {
auto result = MoveFileExA(qPrintable(fileName()), qPrintable(m_originalFilename), MOVEFILE_REPLACE_EXISTING); auto encode = [](const QString &s)
{
const auto prefix = "\\\\?\\"; // support long paths: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath
return (prefix + QDir::toNativeSeparators(QDir::cleanPath(QFileInfo(s).absoluteFilePath()))).toStdWString();
};
auto result = MoveFileEx(encode(fileName()).c_str(), encode(m_originalFilename).c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
if (! result) if (! result)
{ {
m_renameError = true; m_renameError = true;
wchar_t *s = nullptr; wchar_t *s = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 0, reinterpret_cast<LPWSTR>(&s), 0, nullptr); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 0, reinterpret_cast<LPWSTR>(&s), 0, nullptr);
setErrorString(QString::fromWCharArray(s)); setErrorString(QString::fromWCharArray(s).simplified());
LocalFree(reinterpret_cast<HLOCAL>(s)); LocalFree(reinterpret_cast<HLOCAL>(s));
} }
} }