nextcloud-desktop/src/mirall/folderwatcher_win.cpp

115 lines
3.7 KiB
C++
Raw Normal View History

2012-12-04 21:15:37 +04:00
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
2014-01-13 19:16:19 +04:00
* the Free Software Foundation; version 2 of the License.
2012-12-04 21:15:37 +04:00
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <QThread>
#include <QDebug>
2012-12-04 21:15:37 +04:00
#include "mirall/folderwatcher.h"
#include "mirall/folderwatcher_win.h"
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
2012-12-04 21:15:37 +04:00
namespace Mirall {
void WatcherThread::run()
{
2014-11-06 02:36:04 +03:00
_handle = CreateFileW(
(wchar_t*)_path.utf16(),
FILE_LIST_DIRECTORY,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
2012-12-04 21:15:37 +04:00
2014-11-06 02:36:04 +03:00
size_t bufsize = 4096;
size_t maxlen = 4096;
while(true) {
char fileNotify[bufsize];
// TODO: handle CreateFileW failure
FILE_NOTIFY_INFORMATION *pFileNotify =
(FILE_NOTIFY_INFORMATION*)fileNotify;
DWORD dwBytesReturned = 0;
SecureZeroMemory(pFileNotify, bufsize);
if(ReadDirectoryChangesW( _handle, (LPVOID)pFileNotify,
bufsize, true,
FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwBytesReturned, NULL, NULL))
{
FILE_NOTIFY_INFORMATION *curEntry = pFileNotify;
while(true) {
size_t len = pFileNotify->FileNameLength / 2;
QString file = _path + "\\" + QString::fromWCharArray(pFileNotify->FileName, len);
2012-12-04 21:15:37 +04:00
QString longfile;
2014-11-06 02:36:04 +03:00
QScopedArrayPointer<TCHAR> buffer(new TCHAR[maxlen]);
if (GetLongPathNameW(reinterpret_cast<LPCWSTR>(file.utf16()), buffer.data(), maxlen) == 0) {
qDebug() << Q_FUNC_INFO << "Error converting file name to full length, resorting to original name.";
longfile = file;
} else {
longfile = QString::fromUtf16(reinterpret_cast<const ushort *>(buffer.data()), maxlen-1);
2014-11-06 02:36:04 +03:00
}
2014-11-06 02:36:04 +03:00
qDebug() << Q_FUNC_INFO << "Found change in" << file;
emit changed(longfile);
if (curEntry->NextEntryOffset == 0) {
break;
}
curEntry = (FILE_NOTIFY_INFORMATION*)
(char*)curEntry + curEntry->NextEntryOffset;
}
} else {
switch(GetLastError()) {
case ERROR_NOTIFY_ENUM_DIR:
qDebug() << Q_FUNC_INFO << "Too many events for buffer, resizing";
bufsize *= 2;
break;
default:
qDebug() << Q_FUNC_INFO << "General error while watching. Exiting.";
CloseHandle(_handle);
_handle = NULL;
break;
2012-12-06 19:26:27 +04:00
}
}
}
2012-12-04 21:15:37 +04:00
}
2012-12-06 19:26:27 +04:00
WatcherThread::~WatcherThread()
{
if (_handle)
FindCloseChangeNotification(_handle);
}
FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p, const QString& path)
: _parent(p)
{
_thread = new WatcherThread(path);
2012-12-06 19:26:27 +04:00
connect(_thread, SIGNAL(changed(const QString&)),
_parent,SLOT(changeDetected(const QString&)));
_thread->start();
}
FolderWatcherPrivate::~FolderWatcherPrivate()
{
2012-12-06 19:26:27 +04:00
_thread->terminate();
_thread->wait();
delete _thread;
}
} // namespace Mirall