#include <QThread>
#include <QDir>
+#include "common/asserts.h"
+#include "common/utility.h"
#include "filesystem.h"
#include "folderwatcher.h"
#include "folderwatcher_win.h"
bool *increaseBufferSize)
{
*increaseBufferSize = false;
- QString longPath = FileSystem::longWinPath(_path);
+ const QString longPath = FileSystem::longWinPath(_path);
_directory = CreateFileW(
- (wchar_t *)longPath.utf16(),
+ longPath.toStdWString().data(),
FILE_LIST_DIRECTORY,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
nullptr,
nullptr);
if (_directory == INVALID_HANDLE_VALUE) {
- DWORD errorCode = GetLastError();
- qCWarning(lcFolderWatcher) << "Failed to create handle for" << _path << ", error:" << errorCode;
+ qCWarning(lcFolderWatcher) << "Failed to create handle for" << _path << ", error:" << Utility::formatLastWinError();
_directory = 0;
return;
}
// QVarLengthArray ensures the stack-buffer is aligned like double and qint64.
QVarLengthArray<char, 4096 * 10> fileNotifyBuffer;
- fileNotifyBuffer.resize(OCC::Utility::convertSizeToInt(fileNotifyBufferSize));
+ fileNotifyBuffer.resize(static_cast<int>(fileNotifyBufferSize));
const size_t fileNameBufferSize = 4096;
TCHAR fileNameBuffer[fileNameBufferSize];
ResetEvent(_resultEvent);
FILE_NOTIFY_INFORMATION *pFileNotifyBuffer =
- (FILE_NOTIFY_INFORMATION *)fileNotifyBuffer.data();
+ reinterpret_cast<FILE_NOTIFY_INFORMATION *>(fileNotifyBuffer.data());
DWORD dwBytesReturned = 0;
- SecureZeroMemory(pFileNotifyBuffer, fileNotifyBufferSize);
- if (!ReadDirectoryChangesW(_directory, (LPVOID)pFileNotifyBuffer,
- OCC::Utility::convertSizeToDWORD(fileNotifyBufferSize), true,
+ if (!ReadDirectoryChangesW(_directory, pFileNotifyBuffer,
+ static_cast<DWORD>(fileNotifyBufferSize), true,
FILE_NOTIFY_CHANGE_FILE_NAME
| FILE_NOTIFY_CHANGE_DIR_NAME
| FILE_NOTIFY_CHANGE_LAST_WRITE
&dwBytesReturned,
&overlapped,
nullptr)) {
- DWORD errorCode = GetLastError();
+ const DWORD errorCode = GetLastError();
if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
qCDebug(lcFolderWatcher) << "The buffer for changes overflowed! Triggering a generic change and resizing";
emit changed(_path);
*increaseBufferSize = true;
} else {
- qCWarning(lcFolderWatcher) << "ReadDirectoryChangesW error" << errorCode;
+ qCWarning(lcFolderWatcher) << "ReadDirectoryChangesW error" << Utility::formatWinError(errorCode);
}
break;
}
break;
}
if (result != 0) {
- qCWarning(lcFolderWatcher) << "WaitForMultipleObjects failed" << result << GetLastError();
+ qCWarning(lcFolderWatcher) << "WaitForMultipleObjects failed" << result << Utility::formatLastWinError();
break;
}
bool ok = GetOverlappedResult(_directory, &overlapped, &dwBytesReturned, false);
if (!ok) {
- DWORD errorCode = GetLastError();
+ const DWORD errorCode = GetLastError();
if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
qCDebug(lcFolderWatcher) << "The buffer for changes overflowed! Triggering a generic change and resizing";
emit lostChanges();
emit changed(_path);
*increaseBufferSize = true;
} else {
- qCWarning(lcFolderWatcher) << "GetOverlappedResult error" << errorCode;
+ qCWarning(lcFolderWatcher) << "GetOverlappedResult error" << Utility::formatWinError(errorCode);
}
break;
}
FILE_NOTIFY_INFORMATION *curEntry = pFileNotifyBuffer;
forever {
- size_t len = curEntry->FileNameLength / 2;
- QString file = _path + "\\" + QString::fromWCharArray(curEntry->FileName, OCC::Utility::convertSizeToInt(len));
+ const int len = curEntry->FileNameLength / sizeof(wchar_t);
+ QString longfile = longPath + QString::fromWCharArray(curEntry->FileName, len);
// Unless the file was removed or renamed, get its full long name
// TODO: We could still try expanding the path in the tricky cases...
- QString longfile = file;
if (curEntry->Action != FILE_ACTION_REMOVED
&& curEntry->Action != FILE_ACTION_RENAMED_OLD_NAME) {
- size_t longNameSize = GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), fileNameBuffer, fileNameBufferSize);
+ const auto wfile = longfile.toStdWString();
+ const int longNameSize = GetLongPathNameW(wfile.data(), fileNameBuffer, fileNameBufferSize);
if (longNameSize > 0) {
- longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(fileNameBuffer), OCC::Utility::convertSizeToInt(longNameSize));
+ longfile = QString::fromWCharArray(fileNameBuffer, longNameSize);
} else {
- qCWarning(lcFolderWatcher) << "Error converting file name to full length, keeping original name.";
+ qCWarning(lcFolderWatcher) << "Error converting file name" << longfile << "to full length, keeping original name." << Utility::formatLastWinError();
}
}
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
+ // The prefix is needed for native Windows functions before Windows 10, version 1607
+ const bool hasLongPathPrefix = longPath.startsWith(QStringLiteral("\\\\?\\"));
+ if (hasLongPathPrefix)
+ {
+ longfile.remove(0, 4);
+ }
+#endif
longfile = QDir::cleanPath(longfile);
// Skip modifications of folders: One of these is triggered for changes
// and new files in a folder, probably because of the folder's mtime
// changing. We don't need them.
- bool skip = curEntry->Action == FILE_ACTION_MODIFIED
+ const bool skip = curEntry->Action == FILE_ACTION_MODIFIED
&& QFileInfo(longfile).isDir();
if (!skip) {
if (curEntry->NextEntryOffset == 0) {
break;
}
- curEntry = (FILE_NOTIFY_INFORMATION *)((char *)curEntry + curEntry->NextEntryOffset);
+ // FILE_NOTIFY_INFORMATION has no fixed size and the offset is in bytes therefor we first need to cast to char
+ curEntry = reinterpret_cast<FILE_NOTIFY_INFORMATION *>(reinterpret_cast<char*>(curEntry) + curEntry->NextEntryOffset);
}
}
// If this buffer fills up before we've extracted its data we will lose
// change information. Therefore start big.
size_t bufferSize = 4096 * 10;
- size_t maxBuffer = 64 * 1024;
+ const size_t maxBuffer = 64 * 1024;
while (!_done) {
bool increaseBufferSize = false;