/****************************************************************************
**
** Copyright (C) 2016 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$
**
****************************************************************************/

#include "qfilesystemwatcher.h"
#include "qfilesystemwatcher_win_p.h"

#include <qdebug.h>
#include <qfileinfo.h>
#include <qstringlist.h>
#include <qset.h>
#include <qscopeguard.h>
#include <qdatetime.h>
#include <qdir.h>
#include <qtextstream.h>
#include <private/qlocking_p.h>

#include <qt_windows.h>

#ifndef Q_OS_WINRT
#  include <qabstractnativeeventfilter.h>
#  include <qcoreapplication.h>
#  include <qdir.h>
#  include <private/qeventdispatcher_win_p.h>
#  include <private/qthread_p.h>
#  include <dbt.h>
#  include <algorithm>
#  include <vector>
#endif // !Q_OS_WINRT

QT_BEGIN_NAMESPACE

// #define WINQFSW_DEBUG
#ifdef WINQFSW_DEBUG
#  define DEBUG qDebug
#else
#  define DEBUG if (false) qDebug
#endif

static Qt::HANDLE createChangeNotification(const QString &path, uint flags)
{
    // Volume and folder paths need a trailing slash for proper notification
    // (e.g. "c:" -> "c:/").
    QString nativePath = QDir::toNativeSeparators(path);
    if ((flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) == 0 && !nativePath.endsWith(QLatin1Char('\\')))
        nativePath.append(QLatin1Char('\\'));
    const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()),
                                                      FALSE, flags);
    DEBUG() << __FUNCTION__ << nativePath << Qt::hex <<showbase << flags << "returns" << result;
    return result;
}

#ifndef Q_OS_WINRT
///////////
// QWindowsRemovableDriveListener
// Listen for the various WM_DEVICECHANGE message indicating drive addition/removal
// requests and removals.
///////////
class QWindowsRemovableDriveListener : public QObject, public QAbstractNativeEventFilter
{
    Q_OBJECT
public:
    // Device UUids as declared in ioevent.h (GUID_IO_VOLUME_LOCK, ...)
    enum VolumeUuid { UnknownUuid, UuidIoVolumeLock, UuidIoVolumeLockFailed,
                      UuidIoVolumeUnlock, UuidIoMediaRemoval };

    struct RemovableDriveEntry {
        HDEVNOTIFY devNotify;
        wchar_t drive;
    };

    explicit QWindowsRemovableDriveListener(QObject *parent = nullptr);
    ~QWindowsRemovableDriveListener();

    // Call from QFileSystemWatcher::addPaths() to set up notifications on drives
    void addPath(const QString &path);

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    bool nativeEventFilter(const QByteArray &, void *messageIn, qintptr *) override;
#else
    bool nativeEventFilter(const QByteArray &, void *messageIn, long *) override;
#endif

signals:
    void driveAdded();
    void driveRemoved(); // Some drive removed
    void driveRemoved(const QString &); // Watched/known drive removed
    void driveLockForRemoval(const QString &);
    void driveLockForRemovalFailed(const QString &);

private:
    static VolumeUuid volumeUuid(const UUID &needle);
    void handleDbtCustomEvent(const MSG *msg);
    void handleDbtDriveArrivalRemoval(const MSG *msg);

    std::vector<RemovableDriveEntry> m_removableDrives;
    quintptr m_lastMessageHash;
};

QWindowsRemovableDriveListener::QWindowsRemovableDriveListener(QObject *parent)
    : QObject(parent)
    , m_lastMessageHash(0)
{
}

static void stopDeviceNotification(QWindowsRemovableDriveListener::RemovableDriveEntry &e)
{
    UnregisterDeviceNotification(e.devNotify);
    e.devNotify = 0;
}

template <class Iterator> // Search sequence of RemovableDriveEntry for HDEVNOTIFY.
static inline Iterator findByHDevNotify(Iterator i1, Iterator i2, HDEVNOTIFY hdevnotify)
{
    return std::find_if(i1, i2,
                        [hdevnotify] (const QWindowsRemovableDriveListener::RemovableDriveEntry &e) { return e.devNotify == hdevnotify; });
}

QWindowsRemovableDriveListener::~QWindowsRemovableDriveListener()
{
    std::for_each(m_removableDrives.begin(), m_removableDrives.end(), stopDeviceNotification);
}

static QString pathFromEntry(const QWindowsRemovableDriveListener::RemovableDriveEntry &re)
{
    QString path = QStringLiteral("A:/");
    path[0] = QChar::fromLatin1(re.drive);
    return path;
}

// Handle WM_DEVICECHANGE+DBT_CUSTOMEVENT, which is sent based on the registration
// on the volume handle with QEventDispatcherWin32's message window in the class.
// Capture the GUID_IO_VOLUME_LOCK indicating the drive is to be removed.
QWindowsRemovableDriveListener::VolumeUuid QWindowsRemovableDriveListener::volumeUuid(const UUID &needle)
{
    static const struct VolumeUuidMapping // UUIDs from IoEvent.h (missing in MinGW)
    {
        VolumeUuid v;
        UUID uuid;
    } mapping[] = {
        { UuidIoVolumeLock, // GUID_IO_VOLUME_LOCK
          {0x50708874, 0xc9af, 0x11d1, {0x8f, 0xef, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
        { UuidIoVolumeLockFailed, // GUID_IO_VOLUME_LOCK_FAILED
          {0xae2eed10, 0x0ba8, 0x11d2, {0x8f, 0xfb, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
        { UuidIoVolumeUnlock, // GUID_IO_VOLUME_UNLOCK
          {0x9a8c3d68, 0xd0cb, 0x11d1, {0x8f, 0xef, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
        { UuidIoMediaRemoval, // GUID_IO_MEDIA_REMOVAL
          {0xd07433c1, 0xa98e, 0x11d2, {0x91, 0x7a, 0x0, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}} }
    };

    static const VolumeUuidMapping *end = mapping + sizeof(mapping) / sizeof(mapping[0]);
    const VolumeUuidMapping *m =
        std::find_if(mapping, end, [&needle] (const VolumeUuidMapping &m) { return IsEqualGUID(m.uuid, needle); });
    return m != end ? m->v : UnknownUuid;
}

inline void QWindowsRemovableDriveListener::handleDbtCustomEvent(const MSG *msg)
{
    const DEV_BROADCAST_HDR *broadcastHeader = reinterpret_cast<const DEV_BROADCAST_HDR *>(msg->lParam);
    if (broadcastHeader->dbch_devicetype != DBT_DEVTYP_HANDLE)
        return;
    const DEV_BROADCAST_HANDLE *broadcastHandle = reinterpret_cast<const DEV_BROADCAST_HANDLE *>(broadcastHeader);
    const auto it = findByHDevNotify(m_removableDrives.cbegin(), m_removableDrives.cend(),
                                     broadcastHandle->dbch_hdevnotify);
    if (it == m_removableDrives.cend())
        return;
    switch (volumeUuid(broadcastHandle->dbch_eventguid)) {
    case UuidIoVolumeLock: // Received for removable USB media
        emit driveLockForRemoval(pathFromEntry(*it));
        break;
    case UuidIoVolumeLockFailed:
        emit driveLockForRemovalFailed(pathFromEntry(*it));
        break;
    case UuidIoVolumeUnlock:
        break;
    case UuidIoMediaRemoval: // Received for optical drives
        break;
    default:
        break;
    }
}

// Handle WM_DEVICECHANGE+DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE which are
// sent to all top level windows and cannot be registered for (that is, their
// triggering depends on top level windows being present)
inline void QWindowsRemovableDriveListener::handleDbtDriveArrivalRemoval(const MSG *msg)
{
    const DEV_BROADCAST_HDR *broadcastHeader = reinterpret_cast<const DEV_BROADCAST_HDR *>(msg->lParam);
    switch (broadcastHeader->dbch_devicetype) {
    case DBT_DEVTYP_HANDLE: // WM_DEVICECHANGE/DBT_DEVTYP_HANDLE is sent for our registered drives.
        if (msg->wParam == DBT_DEVICEREMOVECOMPLETE) {
            const DEV_BROADCAST_HANDLE *broadcastHandle = reinterpret_cast<const DEV_BROADCAST_HANDLE *>(broadcastHeader);
            const auto it = findByHDevNotify(m_removableDrives.begin(), m_removableDrives.end(),
                                           broadcastHandle->dbch_hdevnotify);
            // Emit for removable USB drives we were registered for.
            if (it != m_removableDrives.end()) {
                emit driveRemoved(pathFromEntry(*it));
                stopDeviceNotification(*it);
                m_removableDrives.erase(it);
            }
        }
        break;
    case DBT_DEVTYP_VOLUME: {
        const DEV_BROADCAST_VOLUME *broadcastVolume = reinterpret_cast<const DEV_BROADCAST_VOLUME *>(broadcastHeader);
        // WM_DEVICECHANGE/DBT_DEVTYP_VOLUME messages are sent to all toplevel windows. Compare a hash value to ensure
        // it is handled only once.
        const quintptr newHash = reinterpret_cast<quintptr>(broadcastVolume) + msg->wParam
            + quintptr(broadcastVolume->dbcv_flags) + quintptr(broadcastVolume->dbcv_unitmask);
        if (newHash == m_lastMessageHash)
            return;
        m_lastMessageHash = newHash;
        // Check for DBTF_MEDIA (inserted/Removed Optical drives). Ignore for now.
        if (broadcastVolume->dbcv_flags & DBTF_MEDIA)
            return;
        // Continue with plugged in USB media where dbcv_flags=0.
        switch (msg->wParam) {
        case DBT_DEVICEARRIVAL:
            emit driveAdded();
            break;
        case DBT_DEVICEREMOVECOMPLETE: // See above for handling of drives registered with watchers
            emit driveRemoved();
            break;
        }
    }
        break;
    }
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, qintptr *)
#else
bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, long *)
#endif
{
    const MSG *msg = reinterpret_cast<const MSG *>(messageIn);
    if (msg->message == WM_DEVICECHANGE) {
        switch (msg->wParam) {
        case DBT_CUSTOMEVENT:
            handleDbtCustomEvent(msg);
            break;
        case DBT_DEVICEARRIVAL:
        case DBT_DEVICEREMOVECOMPLETE:
            handleDbtDriveArrivalRemoval(msg);
            break;
        }
    }
    return false;
}

// Set up listening for WM_DEVICECHANGE+DBT_CUSTOMEVENT for a removable drive path,
void QWindowsRemovableDriveListener::addPath(const QString &p)
{
    const wchar_t drive = p.size() >= 2 && p.at(0).isLetter() && p.at(1) == QLatin1Char(':')
        ? wchar_t(p.at(0).toUpper().unicode()) : L'\0';
    if (!drive)
        return;
    // Already listening?
    if (std::any_of(m_removableDrives.cbegin(), m_removableDrives.cend(),
                    [drive](const RemovableDriveEntry &e) { return e.drive == drive; })) {
        return;
    }

    wchar_t devicePath[8] = L"\\\\.\\A:\\";
    devicePath[4] = drive;
    RemovableDriveEntry re;
    re.drive = drive;
    if (GetDriveTypeW(devicePath + 4) != DRIVE_REMOVABLE)
        return;
    const HANDLE volumeHandle =
        CreateFile(devicePath, FILE_READ_ATTRIBUTES,
                   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0,
                   OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, //  Volume requires BACKUP_SEMANTICS
                   0);
    if (volumeHandle == INVALID_HANDLE_VALUE) {
        qErrnoWarning("CreateFile %ls failed.", devicePath);
        return;
    }

    DEV_BROADCAST_HANDLE notify;
    ZeroMemory(&notify, sizeof(notify));
    notify.dbch_size = sizeof(notify);
    notify.dbch_devicetype = DBT_DEVTYP_HANDLE;
    notify.dbch_handle = volumeHandle;
    QThreadData *currentData = QThreadData::current();
    QEventDispatcherWin32 *winEventDispatcher = static_cast<QEventDispatcherWin32 *>(currentData->ensureEventDispatcher());
    re.devNotify = RegisterDeviceNotification(winEventDispatcher->internalHwnd(),
                                              &notify, DEVICE_NOTIFY_WINDOW_HANDLE);
    // Empirically found: The notifications also work when the handle is immediately
    // closed. Do it here to avoid having to close/reopen in lock message handling.
    CloseHandle(volumeHandle);
    if (!re.devNotify) {
        qErrnoWarning("RegisterDeviceNotification %ls failed.", devicePath);
        return;
    }

    m_removableDrives.push_back(re);
}
#endif // !Q_OS_WINRT

///////////
// QWindowsFileSystemWatcherEngine
///////////
QWindowsFileSystemWatcherEngine::Handle::Handle()
    : handle(INVALID_HANDLE_VALUE), flags(0u)
{
}

QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine(QObject *parent)
    : QFileSystemWatcherEngine(parent)
{
#ifndef Q_OS_WINRT
    if (QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance()) {
        m_driveListener = new QWindowsRemovableDriveListener(this);
        eventDispatcher->installNativeEventFilter(m_driveListener);
        parent->setProperty("_q_driveListener",
                            QVariant::fromValue(static_cast<QObject *>(m_driveListener)));
        QObject::connect(m_driveListener, &QWindowsRemovableDriveListener::driveLockForRemoval,
                         this, &QWindowsFileSystemWatcherEngine::driveLockForRemoval);
        QObject::connect(m_driveListener, &QWindowsRemovableDriveListener::driveLockForRemovalFailed,
                         this, &QWindowsFileSystemWatcherEngine::driveLockForRemovalFailed);
        QObject::connect(m_driveListener,
                         QOverload<const QString &>::of(&QWindowsRemovableDriveListener::driveRemoved),
                         this, &QWindowsFileSystemWatcherEngine::driveRemoved);
    } else {
        qWarning("QFileSystemWatcher: Removable drive notification will not work"
                 " if there is no QCoreApplication instance.");
    }
#endif // !Q_OS_WINRT
}

QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
    for (auto *thread : qAsConst(threads))
        thread->stop();
    for (auto *thread : qAsConst(threads))
        thread->wait();
    qDeleteAll(threads);
}

QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
                                                       QStringList *files,
                                                       QStringList *directories)
{
    DEBUG() << "Adding" << paths.count() << "to existing" << (files->count() + directories->count()) << "watchers";
    QStringList unhandled;
    for (const QString &path : paths) {
        auto sg = qScopeGuard([&] { unhandled.push_back(path); });
        QString normalPath = path;
        if ((normalPath.endsWith(QLatin1Char('/')) && !normalPath.endsWith(QLatin1String(":/")))
            || (normalPath.endsWith(QLatin1Char('\\')) && !normalPath.endsWith(QLatin1String(":\\")))) {
            normalPath.chop(1);
        }
        QFileInfo fileInfo(normalPath);
        if (!fileInfo.exists())
            continue;

        bool isDir = fileInfo.isDir();
        if (isDir) {
            if (directories->contains(path))
                continue;
        } else {
            if (files->contains(path))
                continue;
        }

        DEBUG() << "Looking for a thread/handle for" << normalPath;

        const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath();
        const uint flags = isDir
                           ? (FILE_NOTIFY_CHANGE_DIR_NAME
                              | FILE_NOTIFY_CHANGE_ATTRIBUTES
                              | FILE_NOTIFY_CHANGE_FILE_NAME)
                           : (FILE_NOTIFY_CHANGE_DIR_NAME
                              | FILE_NOTIFY_CHANGE_FILE_NAME
                              | FILE_NOTIFY_CHANGE_ATTRIBUTES
                              | FILE_NOTIFY_CHANGE_SIZE
                              | FILE_NOTIFY_CHANGE_LAST_WRITE
                              | FILE_NOTIFY_CHANGE_SECURITY);

        QWindowsFileSystemWatcherEngine::PathInfo pathInfo;
        pathInfo.absolutePath = absolutePath;
        pathInfo.isDir = isDir;
        pathInfo.path = path;
        pathInfo = fileInfo;

        // Look for a thread
        QWindowsFileSystemWatcherEngineThread *thread = 0;
        QWindowsFileSystemWatcherEngine::Handle handle;
        QList<QWindowsFileSystemWatcherEngineThread *>::const_iterator jt, end;
        end = threads.constEnd();
        for(jt = threads.constBegin(); jt != end; ++jt) {
            thread = *jt;
            const auto locker = qt_scoped_lock(thread->mutex);

            const auto hit = thread->handleForDir.find(QFileSystemWatcherPathKey(absolutePath));
            if (hit != thread->handleForDir.end() && hit.value().flags < flags) {
                // Requesting to add a file whose directory has been added previously.
                // Recreate the notification handle to add the missing notification attributes
                // for files (FILE_NOTIFY_CHANGE_ATTRIBUTES...)
                DEBUG() << "recreating" << absolutePath << Qt::hex << Qt::showbase << hit.value().flags
                    << "->" << flags;
                const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags);
                if (fileHandle != INVALID_HANDLE_VALUE) {
                    const int index = thread->handles.indexOf(hit.value().handle);
                    const auto pit = thread->pathInfoForHandle.find(hit.value().handle);
                    Q_ASSERT(index != -1);
                    Q_ASSERT(pit != thread->pathInfoForHandle.end());
                    FindCloseChangeNotification(hit.value().handle);
                    thread->handles[index] = hit.value().handle = fileHandle;
                    hit.value().flags = flags;
                    thread->pathInfoForHandle.insert(fileHandle, pit.value());
                    thread->pathInfoForHandle.erase(pit);
                }
            }
            // In addition, check on flags for sufficient notification attributes
            if (hit != thread->handleForDir.end() && hit.value().flags >= flags) {
                handle = hit.value();
                // found a thread now insert...
                DEBUG() << "Found a thread" << thread;

                QWindowsFileSystemWatcherEngineThread::PathInfoHash &h =
                    thread->pathInfoForHandle[handle.handle];
                const QFileSystemWatcherPathKey key(fileInfo.absoluteFilePath());
                if (!h.contains(key)) {
                    thread->pathInfoForHandle[handle.handle].insert(key, pathInfo);
                    if (isDir)
                        directories->append(path);
                    else
                        files->append(path);
                }
                sg.dismiss();
                thread->wakeup();
                break;
            }
        }

        // no thread found, first create a handle
        if (handle.handle == INVALID_HANDLE_VALUE) {
            DEBUG() << "No thread found";
            handle.handle = createChangeNotification(absolutePath, flags);
            handle.flags = flags;
            if (handle.handle == INVALID_HANDLE_VALUE)
                continue;

            // now look for a thread to insert
            bool found = false;
            for (QWindowsFileSystemWatcherEngineThread *thread : qAsConst(threads)) {
                const auto locker = qt_scoped_lock(thread->mutex);
                if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) {
                    DEBUG() << "Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath()
                            << "to existing thread " << thread;
                    thread->handles.append(handle.handle);
                    thread->handleForDir.insert(QFileSystemWatcherPathKey(absolutePath), handle);

                    thread->pathInfoForHandle[handle.handle].insert(QFileSystemWatcherPathKey(fileInfo.absoluteFilePath()), pathInfo);
                    if (isDir)
                        directories->append(path);
                    else
                        files->append(path);

                    sg.dismiss();
                    found = true;
                    thread->wakeup();
                    break;
                }
            }
            if (!found) {
                QWindowsFileSystemWatcherEngineThread *thread = new QWindowsFileSystemWatcherEngineThread();
                DEBUG() << "  ###Creating new thread" << thread << '(' << (threads.count()+1) << "threads)";
                thread->handles.append(handle.handle);
                thread->handleForDir.insert(QFileSystemWatcherPathKey(absolutePath), handle);

                thread->pathInfoForHandle[handle.handle].insert(QFileSystemWatcherPathKey(fileInfo.absoluteFilePath()), pathInfo);
                if (isDir)
                    directories->append(path);
                else
                    files->append(path);

                connect(thread, SIGNAL(fileChanged(QString,bool)),
                        this, SIGNAL(fileChanged(QString,bool)));
                connect(thread, SIGNAL(directoryChanged(QString,bool)),
                        this, SIGNAL(directoryChanged(QString,bool)));

                thread->msg = '@';
                thread->start();
                threads.append(thread);
                sg.dismiss();
            }
        }
    }

#ifndef Q_OS_WINRT
    if (Q_LIKELY(m_driveListener)) {
        for (const QString &path : paths) {
            if (!unhandled.contains(path))
                m_driveListener->addPath(path);
        }
    }
#endif // !Q_OS_WINRT
    return unhandled;
}

QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths,
                                                          QStringList *files,
                                                          QStringList *directories)
{
    DEBUG() << "removePaths" << paths;
    QStringList unhandled;
    for (const QString &path : paths) {
        auto sg = qScopeGuard([&] { unhandled.push_back(path); });
        QString normalPath = path;
        if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
            normalPath.chop(1);
        QFileInfo fileInfo(normalPath);
        DEBUG() << "removing" << normalPath;
        QString absolutePath = fileInfo.absoluteFilePath();
        QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
        end = threads.end();
        for(jt = threads.begin(); jt!= end; ++jt) {
            QWindowsFileSystemWatcherEngineThread *thread = *jt;
            if (*jt == 0)
                continue;

            auto locker = qt_unique_lock(thread->mutex);

            QWindowsFileSystemWatcherEngine::Handle handle = thread->handleForDir.value(QFileSystemWatcherPathKey(absolutePath));
            if (handle.handle == INVALID_HANDLE_VALUE) {
                // perhaps path is a file?
                absolutePath = fileInfo.absolutePath();
                handle = thread->handleForDir.value(QFileSystemWatcherPathKey(absolutePath));
            }
            if (handle.handle != INVALID_HANDLE_VALUE) {
                QWindowsFileSystemWatcherEngineThread::PathInfoHash &h =
                        thread->pathInfoForHandle[handle.handle];
                if (h.remove(QFileSystemWatcherPathKey(fileInfo.absoluteFilePath()))) {
                    // ###
                    files->removeAll(path);
                    directories->removeAll(path);
                    sg.dismiss();

                    if (h.isEmpty()) {
                        DEBUG() << "Closing handle" << handle.handle;
                        FindCloseChangeNotification(handle.handle);    // This one might generate a notification

                        int indexOfHandle = thread->handles.indexOf(handle.handle);
                        Q_ASSERT(indexOfHandle != -1);
                        thread->handles.remove(indexOfHandle);

                        thread->handleForDir.remove(QFileSystemWatcherPathKey(absolutePath));
                        // h is now invalid

                        if (thread->handleForDir.isEmpty()) {
                            DEBUG() << "Stopping thread " << thread;
                            locker.unlock();
                            thread->stop();
                            thread->wait();
                            locker.lock();
                            // We can't delete the thread until the mutex locker is
                            // out of scope
                        }
                    }
                }
                // Found the file, go to next one
                break;
            }
        }
    }

    // Remove all threads that we stopped
    QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
    end = threads.end();
    for(jt = threads.begin(); jt != end; ++jt) {
        if (!(*jt)->isRunning()) {
            delete *jt;
            *jt = 0;
        }
    }

    threads.removeAll(0);
    return unhandled;
}

///////////
// QWindowsFileSystemWatcherEngineThread
///////////

QWindowsFileSystemWatcherEngineThread::QWindowsFileSystemWatcherEngineThread()
        : msg(0)
{
    if (HANDLE h = CreateEvent(0, false, false, 0)) {
        handles.reserve(MAXIMUM_WAIT_OBJECTS);
        handles.append(h);
    }
}


QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
{
    CloseHandle(handles.at(0));
    handles[0] = INVALID_HANDLE_VALUE;

    for (HANDLE h : qAsConst(handles)) {
        if (h == INVALID_HANDLE_VALUE)
            continue;
        FindCloseChangeNotification(h);
    }
}

Q_DECL_COLD_FUNCTION
static QString msgFindNextFailed(const QWindowsFileSystemWatcherEngineThread::PathInfoHash &pathInfos)
{
    QString str;
    str += QLatin1String("QFileSystemWatcher: FindNextChangeNotification failed for");
    for (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo : pathInfos)
        str += QLatin1String(" \"") + QDir::toNativeSeparators(pathInfo.absolutePath) + QLatin1Char('"');
    str += QLatin1Char(' ');
    return str;
}

void QWindowsFileSystemWatcherEngineThread::run()
{
    auto locker = qt_unique_lock(mutex);
    forever {
        QVector<HANDLE> handlesCopy = handles;
        locker.unlock();
        DEBUG() << "QWindowsFileSystemWatcherThread" << this << "waiting on" << handlesCopy.count() << "handles";
        DWORD r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
        locker.lock();
        do {
            if (r == WAIT_OBJECT_0) {
                int m = msg;
                msg = 0;
                if (m == 'q') {
                    DEBUG() << "thread" << this << "told to quit";
                    return;
                }
                if (m != '@')
                    DEBUG() << "QWindowsFileSystemWatcherEngine: unknown message sent to thread: " << char(m);
                break;
            }
            if (r > WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + uint(handlesCopy.count())) {
                int at = r - WAIT_OBJECT_0;
                Q_ASSERT(at < handlesCopy.count());
                HANDLE handle = handlesCopy.at(at);

                // When removing a path, FindCloseChangeNotification might actually fire a notification
                // for some reason, so we must check if the handle exist in the handles vector
                if (handles.contains(handle)) {
                    DEBUG() << "thread" << this << "Acknowledged handle:" << at << handle;
                    QWindowsFileSystemWatcherEngineThread::PathInfoHash &h = pathInfoForHandle[handle];
                    bool fakeRemove = false;

                    if (!FindNextChangeNotification(handle)) {
                        const DWORD error = GetLastError();

                        if (error == ERROR_ACCESS_DENIED) {
                            // for directories, our object's handle appears to be woken up when the target of a
                            // watch is deleted, before the watched thing is actually deleted...
                            // anyway.. we're given an error code of ERROR_ACCESS_DENIED in that case.
                            fakeRemove = true;
                        }

                        qErrnoWarning(error, "%ls", qUtf16Printable(msgFindNextFailed(h)));
                    }
                    for (auto it = h.begin(), end = h.end(); it != end; /*erasing*/ ) {
                        auto x = it++;
                        QString absolutePath = x.value().absolutePath;
                        QFileInfo fileInfo(x.value().path);
                        DEBUG() << "checking" << x.key();

                        // i'm not completely sure the fileInfo.exist() check will ever work... see QTBUG-2331
                        // ..however, I'm not completely sure enough to remove it.
                        if (fakeRemove || !fileInfo.exists()) {
                            DEBUG() << x.key() << "removed!";
                            if (x.value().isDir)
                                emit directoryChanged(x.value().path, true);
                            else
                                emit fileChanged(x.value().path, true);
                            h.erase(x);

                            // close the notification handle if the directory has been removed
                            if (h.isEmpty()) {
                                DEBUG() << "Thread closing handle" << handle;
                                FindCloseChangeNotification(handle);    // This one might generate a notification

                                int indexOfHandle = handles.indexOf(handle);
                                Q_ASSERT(indexOfHandle != -1);
                                handles.remove(indexOfHandle);

                                handleForDir.remove(QFileSystemWatcherPathKey(absolutePath));
                                // h is now invalid
                                break;
                            }
                        } else if (x.value().isDir) {
                            DEBUG() << x.key() << "directory changed!";
                            emit directoryChanged(x.value().path, false);
                            x.value() = fileInfo;
                        } else if (x.value() != fileInfo) {
                            DEBUG() << x.key() << "file changed!";
                            emit fileChanged(x.value().path, false);
                            x.value() = fileInfo;
                        }
                    }
                }
            } else {
                // qErrnoWarning("QFileSystemWatcher: error while waiting for change notification");
                break;  // avoid endless loop
            }
            handlesCopy = handles;
            r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, 0);
        } while (r != WAIT_TIMEOUT);
    }
}


void QWindowsFileSystemWatcherEngineThread::stop()
{
    msg = 'q';
    SetEvent(handles.at(0));
}

void QWindowsFileSystemWatcherEngineThread::wakeup()
{
    msg = '@';
    SetEvent(handles.at(0));
}

QT_END_NAMESPACE

#ifndef Q_OS_WINRT
#  include "qfilesystemwatcher_win.moc"
#endif
