/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins 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$
**
****************************************************************************/

#define QT_NO_URL_CAST_FROM_STRING 1

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601
#endif

#include "qwindowscombase.h"
#include "qwindowsdialoghelpers.h"

#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowstheme.h" // Color conversion helpers

#include <QtGui/qguiapplication.h>
#include <QtGui/qcolor.h>

#include <QtCore/qdebug.h>
#include <QtCore/qregularexpression.h>
#include <QtCore/qtimer.h>
#include <QtCore/qdir.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qsharedpointer.h>
#include <QtCore/qobject.h>
#include <QtCore/qthread.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qmutex.h>
#include <QtCore/quuid.h>
#include <QtCore/qtemporaryfile.h>
#include <QtCore/private/qsystemlibrary_p.h>

#include <algorithm>
#include <vector>

#include <QtCore/qt_windows.h>

// #define USE_NATIVE_COLOR_DIALOG /* Testing purposes only */

QT_BEGIN_NAMESPACE

#ifndef QT_NO_DEBUG_STREAM
/* Output UID (IID, CLSID) as C++ constants.
 * The constants are contained in the Windows SDK libs, but not for MinGW. */
static inline QString guidToString(const GUID &g)
{
    QString rc;
    QTextStream str(&rc);
    str.setIntegerBase(16);
    str.setNumberFlags(str.numberFlags() | QTextStream::ShowBase);
    str << '{' << g.Data1 << ", " << g.Data2 << ", " << g.Data3;
    str.setFieldWidth(2);
    str.setFieldAlignment(QTextStream::AlignRight);
    str.setPadChar(QLatin1Char('0'));
    str << ",{" << g.Data4[0] << ", " << g.Data4[1]  << ", " << g.Data4[2]  << ", " << g.Data4[3]
        << ", " << g.Data4[4] << ", " << g.Data4[5]  << ", " << g.Data4[6]  << ", " << g.Data4[7]
        << "}};";
    return rc;
}

inline QDebug operator<<(QDebug d, const GUID &g)
{
    QDebugStateSaver saver(d);
    d.nospace();
    d << guidToString(g);
    return d;
}
#endif // !QT_NO_DEBUG_STREAM

// Return an allocated wchar_t array from a QString, reserve more memory if desired.
static wchar_t *qStringToWCharArray(const QString &s, size_t reserveSize = 0)
{
    const size_t stringSize = s.size();
    wchar_t *result = new wchar_t[qMax(stringSize + 1, reserveSize)];
    s.toWCharArray(result);
    result[stringSize] = 0;
    return result;
}

namespace QWindowsDialogs
{
/*!
    \fn eatMouseMove()

    After closing a windows dialog with a double click (i.e. open a file)
    the message queue still contains a dubious WM_MOUSEMOVE message where
    the left button is reported to be down (wParam != 0).
    remove all those messages (usually 1) and post the last one with a
    reset button state.

    \ingroup qt-lighthouse-win
*/

void eatMouseMove()
{
    MSG msg = {nullptr, 0, 0, 0, 0, {0, 0} };
    while (PeekMessage(&msg, nullptr, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
        ;
    if (msg.message == WM_MOUSEMOVE)
        PostMessage(msg.hwnd, msg.message, 0, msg.lParam);
    qCDebug(lcQpaDialogs) << __FUNCTION__ << "triggered=" << (msg.message == WM_MOUSEMOVE);
}

} // namespace QWindowsDialogs

/*!
    \class QWindowsNativeDialogBase
    \brief Base class for Windows native dialogs.

    Base classes for native dialogs (using the CLSID-based
    dialog interfaces "IFileDialog", etc. available from Windows
    Vista on) that mimick the behaviour of their QDialog
    counterparts as close as possible.

    Instances of derived classes are controlled by
    QWindowsDialogHelperBase-derived classes.

    A major difference is that there is only an exec(), which
    is a modal, blocking call; there is no non-blocking show().
    There 2 types of native dialogs:

    \list
    \li Dialogs provided by the Comdlg32 library (ChooseColor,
       ChooseFont). They only provide a modal, blocking
       function call (with idle processing).
    \li File dialogs are classes derived from IFileDialog. They
       inherit IModalWindow and their exec() method (calling
       IModalWindow::Show()) is similarly blocking, but methods
       like close() can be called on them from event handlers.
    \endlist

    \sa QWindowsDialogHelperBase
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsNativeDialogBase : public QObject
{
    Q_OBJECT
public:
    virtual void setWindowTitle(const QString &title) = 0;
    bool executed() const { return m_executed; }
    void exec(HWND owner = nullptr) { doExec(owner); m_executed = true; }

signals:
    void accepted();
    void rejected();

public slots:
    virtual void close() = 0;

protected:
    QWindowsNativeDialogBase() : m_executed(false) {}

private:
    virtual void doExec(HWND owner = nullptr) = 0;

    bool m_executed;
};

/*!
    \class QWindowsDialogHelperBase
    \brief Helper for native Windows dialogs.

    Provides basic functionality and introduces new virtuals.
    The native dialog is created in setVisible_sys() since
    then modality and the state of DontUseNativeDialog is known.

    Modal dialogs are then run by exec(). Non-modal dialogs are shown using a
    separate thread started in show() should they support it.

    \sa QWindowsDialogThread, QWindowsNativeDialogBase
    \internal
    \ingroup qt-lighthouse-win
*/

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::cleanupThread()
{
    if (m_thread) { // Thread may be running if the dialog failed to close.
        if (m_thread->isRunning())
            m_thread->wait(500);
        if (m_thread->isRunning()) {
            m_thread->terminate();
            m_thread->wait(300);
            if (m_thread->isRunning())
                qCCritical(lcQpaDialogs) <<__FUNCTION__ << "Failed to terminate thread.";
            else
                qCWarning(lcQpaDialogs) << __FUNCTION__ << "Thread terminated.";
        }
        delete m_thread;
        m_thread = nullptr;
    }
}

template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::nativeDialog() const
{
    if (m_nativeDialog.isNull()) {
         qWarning("%s invoked with no native dialog present.", __FUNCTION__);
         return nullptr;
    }
    return m_nativeDialog.data();
}

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::timerEvent(QTimerEvent *)
{
    startDialogThread();
}

template <class BaseClass>
QWindowsNativeDialogBase *QWindowsDialogHelperBase<BaseClass>::ensureNativeDialog()
{
    // Create dialog and apply common settings. Check "executed" flag as well
    // since for example IFileDialog::Show() works only once.
    if (m_nativeDialog.isNull() || m_nativeDialog->executed())
        m_nativeDialog = QWindowsNativeDialogBasePtr(createNativeDialog());
    return m_nativeDialog.data();
}

/*!
    \class QWindowsDialogThread
    \brief Run a non-modal native dialog in a separate thread.

    \sa QWindowsDialogHelperBase
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsDialogThread : public QThread
{
public:
    using QWindowsNativeDialogBasePtr = QSharedPointer<QWindowsNativeDialogBase>;

    explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner)
        : m_dialog(d), m_owner(owner) {}
    void run();

private:
    const QWindowsNativeDialogBasePtr m_dialog;
    const HWND m_owner;
};

void QWindowsDialogThread::run()
{
    qCDebug(lcQpaDialogs) << '>' << __FUNCTION__;
    m_dialog->exec(m_owner);
    qCDebug(lcQpaDialogs) << '<' << __FUNCTION__;
}

template <class BaseClass>
bool QWindowsDialogHelperBase<BaseClass>::show(Qt::WindowFlags,
                                                   Qt::WindowModality windowModality,
                                                   QWindow *parent)
{
    const bool modal = (windowModality != Qt::NonModal);
    if (!parent)
        parent = QGuiApplication::focusWindow(); // Need a parent window, else the application loses activation when closed.
    if (parent) {
        m_ownerWindow = QWindowsWindow::handleOf(parent);
    } else {
        m_ownerWindow = nullptr;
    }
    qCDebug(lcQpaDialogs) << __FUNCTION__ << "modal=" << modal
        << " modal supported? " << supportsNonModalDialog(parent)
        << "native=" << m_nativeDialog.data() << "owner" << m_ownerWindow;
    if (!modal && !supportsNonModalDialog(parent))
        return false; // Was it changed in-between?
    if (!ensureNativeDialog())
        return false;
    // Start a background thread to show the dialog. For modal dialogs,
    // a subsequent call to exec() may follow. So, start an idle timer
    // which will start the dialog thread. If exec() is then called, the
    // timer is stopped and dialog->exec() is called directly.
    cleanupThread();
    if (modal) {
        m_timerId = this->startTimer(0);
    } else {
        startDialogThread();
    }
    return true;
}

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::startDialogThread()
{
    Q_ASSERT(!m_nativeDialog.isNull());
    Q_ASSERT(!m_thread);
    m_thread = new QWindowsDialogThread(m_nativeDialog, m_ownerWindow);
    m_thread->start();
    stopTimer();
}

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::stopTimer()
{
    if (m_timerId) {
        this->killTimer(m_timerId);
        m_timerId = 0;
    }
}

// Find a file dialog window created by IFileDialog by process id, window
// title and class, which starts with a hash '#'.

struct FindDialogContext
{
    explicit FindDialogContext(const QString &titleIn)
        : title(qStringToWCharArray(titleIn)), processId(GetCurrentProcessId()), hwnd(nullptr) {}

    const QScopedArrayPointer<wchar_t> title;
    const DWORD processId;
    HWND hwnd; // contains the HWND of the window found.
};

static BOOL QT_WIN_CALLBACK findDialogEnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    auto *context = reinterpret_cast<FindDialogContext *>(lParam);
    DWORD winPid = 0;
    GetWindowThreadProcessId(hwnd, &winPid);
    if (winPid != context->processId)
        return TRUE;
    wchar_t buf[256];
    if (!RealGetWindowClass(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || buf[0] != L'#')
        return TRUE;
    if (!GetWindowTextW(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || wcscmp(buf, context->title.data()) != 0)
        return TRUE;
    context->hwnd = hwnd;
    return FALSE;
}

static inline HWND findDialogWindow(const QString &title)
{
    FindDialogContext context(title);
    EnumWindows(findDialogEnumWindowsProc, reinterpret_cast<LPARAM>(&context));
    return context.hwnd;
}

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::hide()
{
    if (m_nativeDialog)
        m_nativeDialog->close();
    m_ownerWindow = nullptr;
}

template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::exec()
{
    qCDebug(lcQpaDialogs) << __FUNCTION__;
    stopTimer();
    if (QWindowsNativeDialogBase *nd = nativeDialog()) {
         nd->exec(m_ownerWindow);
         m_nativeDialog.clear();
    }
}

/*!
    \class QWindowsFileDialogSharedData
    \brief Explicitly shared file dialog parameters that are not in QFileDialogOptions.

    Contain Parameters that need to be cached while the native dialog does not
    exist yet. In addition, the data are updated by the change notifications of the
    IFileDialogEvent, as querying them after the dialog has closed
    does not reliably work. Provides thread-safe setters (for the non-modal case).

    \internal
    \ingroup qt-lighthouse-win
    \sa QFileDialogOptions
*/

class QWindowsFileDialogSharedData
{
public:
    QWindowsFileDialogSharedData() : m_data(new Data) {}
    void fromOptions(const QSharedPointer<QFileDialogOptions> &o);

    QUrl directory() const;
    void setDirectory(const QUrl &);
    QString selectedNameFilter() const;
    void setSelectedNameFilter(const QString &);
    QList<QUrl> selectedFiles() const;
    void setSelectedFiles(const QList<QUrl> &);
    QString selectedFile() const;

private:
    class Data : public QSharedData {
    public:
        QUrl directory;
        QString selectedNameFilter;
        QList<QUrl> selectedFiles;
        QMutex mutex;
    };
    QExplicitlySharedDataPointer<Data> m_data;
};

inline QUrl QWindowsFileDialogSharedData::directory() const
{
    m_data->mutex.lock();
    const QUrl result = m_data->directory;
    m_data->mutex.unlock();
    return result;
}

inline void QWindowsFileDialogSharedData::setDirectory(const QUrl &d)
{
    QMutexLocker locker(&m_data->mutex);
    m_data->directory = d;
}

inline QString QWindowsFileDialogSharedData::selectedNameFilter() const
{
    m_data->mutex.lock();
    const QString result = m_data->selectedNameFilter;
    m_data->mutex.unlock();
    return result;
}

inline void QWindowsFileDialogSharedData::setSelectedNameFilter(const QString &f)
{
    QMutexLocker locker(&m_data->mutex);
    m_data->selectedNameFilter = f;
}

inline QList<QUrl> QWindowsFileDialogSharedData::selectedFiles() const
{
    m_data->mutex.lock();
    const QList<QUrl> result = m_data->selectedFiles;
    m_data->mutex.unlock();
    return result;
}

inline QString QWindowsFileDialogSharedData::selectedFile() const
{
    const QList<QUrl> files = selectedFiles();
    return files.isEmpty() ? QString() : files.front().toLocalFile();
}

inline void QWindowsFileDialogSharedData::setSelectedFiles(const QList<QUrl> &urls)
{
    QMutexLocker locker(&m_data->mutex);
    m_data->selectedFiles = urls;
}

inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFileDialogOptions> &o)
{
    QMutexLocker locker(&m_data->mutex);
    m_data->directory = o->initialDirectory();
    m_data->selectedFiles = o->initiallySelectedFiles();
    m_data->selectedNameFilter = o->initiallySelectedNameFilter();
}

/*!
    \class QWindowsNativeFileDialogEventHandler
    \brief Listens to IFileDialog events and forwards them to QWindowsNativeFileDialogBase

    Events like 'folder change' that have an equivalent signal
    in QFileDialog are forwarded.

    \sa QWindowsNativeFileDialogBase, QWindowsFileDialogHelper
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsNativeFileDialogBase;

class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
{
    Q_DISABLE_COPY_MOVE(QWindowsNativeFileDialogEventHandler)
public:
    static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);

    // IFileDialogEvents methods
    IFACEMETHODIMP OnFileOk(IFileDialog *);
    IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; }
    IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *);
    IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; }
    IFACEMETHODIMP OnSelectionChange(IFileDialog *);
    IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; }
    IFACEMETHODIMP OnTypeChange(IFileDialog *);
    IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; }

    QWindowsNativeFileDialogEventHandler(QWindowsNativeFileDialogBase *nativeFileDialog) :
        m_nativeFileDialog(nativeFileDialog) {}

private:
    QWindowsNativeFileDialogBase *m_nativeFileDialog;
};

IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFileDialogBase *nativeFileDialog)
{
    IFileDialogEvents *result;
    auto *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog);
    if (FAILED(eventHandler->QueryInterface(IID_IFileDialogEvents, reinterpret_cast<void **>(&result)))) {
        qErrnoWarning("Unable to obtain IFileDialogEvents");
        return nullptr;
    }
    eventHandler->Release();
    return result;
}

/*!
    \class QWindowsShellItem
    \brief Wrapper for IShellItem

    \sa QWindowsNativeFileDialogBase
    \internal
    \ingroup qt-lighthouse-win
*/
class QWindowsShellItem
{
public:
    using IShellItems = std::vector<IShellItem *>;

    explicit QWindowsShellItem(IShellItem *item);

    SFGAOF attributes() const { return m_attributes; }
    QString normalDisplay() const // base name, usually
        { return displayName(m_item, SIGDN_NORMALDISPLAY); }
    QString urlString() const
        { return displayName(m_item, SIGDN_URL); }
    QString fileSysPath() const
        { return displayName(m_item, SIGDN_FILESYSPATH); }
    QString desktopAbsoluteParsing() const
        { return displayName(m_item, SIGDN_DESKTOPABSOLUTEPARSING); }
    QString path() const; // Only set for 'FileSystem' (SFGAO_FILESYSTEM) items
    QUrl url() const;

    bool isFileSystem() const  { return (m_attributes & SFGAO_FILESYSTEM) != 0; }
    bool isDir() const         { return (m_attributes & SFGAO_FOLDER) != 0; }
    // Supports IStream
    bool canStream() const     { return (m_attributes & SFGAO_STREAM) != 0; }

    bool copyData(QIODevice *out, QString *errorMessage);

    static IShellItems itemsFromItemArray(IShellItemArray *items);

#ifndef QT_NO_DEBUG_STREAM
    void format(QDebug &d) const;
#endif

private:
    static QString displayName(IShellItem *item, SIGDN mode);
    static QString libraryItemDefaultSaveFolder(IShellItem *item);
    QUrl urlValue() const;

    IShellItem *m_item;
    SFGAOF m_attributes;
};

QWindowsShellItem::QWindowsShellItem(IShellItem *item)
    : m_item(item)
    , m_attributes(0)
{
    if (FAILED(item->GetAttributes(SFGAO_CAPABILITYMASK | SFGAO_DISPLAYATTRMASK | SFGAO_CONTENTSMASK | SFGAO_STORAGECAPMASK, &m_attributes)))
        m_attributes = 0;
}

QString QWindowsShellItem::path() const
{
    if (isFileSystem())
        return QDir::cleanPath(QWindowsShellItem::displayName(m_item, SIGDN_FILESYSPATH));
    // Check for a "Library" item
    if (isDir())
        return QWindowsShellItem::libraryItemDefaultSaveFolder(m_item);
    return QString();
}

QUrl QWindowsShellItem::urlValue() const // plain URL as returned by SIGDN_URL, not set for all items
{
    QUrl result;
    const QString urlString = displayName(m_item, SIGDN_URL);
    if (!urlString.isEmpty()) {
        const QUrl parsed = QUrl(urlString);
        if (parsed.isValid()) {
            result = parsed;
        } else {
            qWarning("%s: Unable to decode URL \"%s\": %s", __FUNCTION__,
                     qPrintable(urlString), qPrintable(parsed.errorString()));
        }
    }
    return result;
}

QUrl QWindowsShellItem::url() const
{
    // Prefer file if existent to avoid any misunderstandings about UNC shares
    const QString fsPath = path();
    if (!fsPath.isEmpty())
        return QUrl::fromLocalFile(fsPath);
    const QUrl urlV = urlValue();
    if (urlV.isValid())
        return urlV;
    // Last resort: encode the absolute desktop parsing id as data URL
    const QString data = QStringLiteral("data:text/plain;base64,")
        + QLatin1String(desktopAbsoluteParsing().toLatin1().toBase64());
    return QUrl(data);
}

QString QWindowsShellItem::displayName(IShellItem *item, SIGDN mode)
{
    LPWSTR name = nullptr;
    QString result;
    if (SUCCEEDED(item->GetDisplayName(mode, &name))) {
        result = QString::fromWCharArray(name);
        CoTaskMemFree(name);
    }
    return result;
}

QWindowsShellItem::IShellItems QWindowsShellItem::itemsFromItemArray(IShellItemArray *items)
{
    IShellItems result;
    DWORD itemCount = 0;
    if (FAILED(items->GetCount(&itemCount)) || itemCount == 0)
        return result;
    result.reserve(itemCount);
    for (DWORD i = 0; i < itemCount; ++i) {
        IShellItem *item = nullptr;
        if (SUCCEEDED(items->GetItemAt(i, &item)))
            result.push_back(item);
    }
    return result;
}

bool QWindowsShellItem::copyData(QIODevice *out, QString *errorMessage)
{
    if (!canStream()) {
        *errorMessage = QLatin1String("Item not streamable");
        return false;
    }
    IStream *istream = nullptr;
    HRESULT hr = m_item->BindToHandler(nullptr, BHID_Stream, IID_PPV_ARGS(&istream));
    if (FAILED(hr)) {
        *errorMessage = QLatin1String("BindToHandler() failed: ")
                        + QLatin1String(QWindowsContext::comErrorString(hr));
        return false;
    }
    enum : ULONG { bufSize = 102400 };
    char buffer[bufSize];
    ULONG bytesRead;
    forever {
        bytesRead = 0;
        hr = istream->Read(buffer, bufSize, &bytesRead); // S_FALSE: EOF reached
        if ((hr == S_OK || hr == S_FALSE) && bytesRead)
            out->write(buffer, bytesRead);
        else
            break;
    }
    istream->Release();
    if (hr != S_OK && hr != S_FALSE) {
        *errorMessage = QLatin1String("Read() failed: ")
                        + QLatin1String(QWindowsContext::comErrorString(hr));
        return false;
    }
    return true;
}

// Helper for "Libraries": collections of folders appearing from Windows 7
// on, visible in the file dialogs.

// Load a library from a IShellItem (sanitized copy of the inline function
// SHLoadLibraryFromItem from ShObjIdl.h, which does not exist for MinGW).
static IShellLibrary *sHLoadLibraryFromItem(IShellItem *libraryItem, DWORD mode)
{
    // ID symbols present from Windows 7 on:
    static const CLSID classId_ShellLibrary = {0xd9b3211d, 0xe57f, 0x4426, {0xaa, 0xef, 0x30, 0xa8, 0x6, 0xad, 0xd3, 0x97}};
    static const IID   iId_IShellLibrary    = {0x11a66efa, 0x382e, 0x451a, {0x92, 0x34, 0x1e, 0xe, 0x12, 0xef, 0x30, 0x85}};

    IShellLibrary *helper = nullptr;
    IShellLibrary *result =  nullptr;
    if (SUCCEEDED(CoCreateInstance(classId_ShellLibrary, nullptr, CLSCTX_INPROC_SERVER, iId_IShellLibrary, reinterpret_cast<void **>(&helper))))
        if (SUCCEEDED(helper->LoadLibraryFromItem(libraryItem, mode)))
            helper->QueryInterface(iId_IShellLibrary, reinterpret_cast<void **>(&result));
    if (helper)
        helper->Release();
    return result;
}

// Return default save folders of a library-type item.
QString QWindowsShellItem::libraryItemDefaultSaveFolder(IShellItem *item)
{
    QString result;
    if (IShellLibrary *library = sHLoadLibraryFromItem(item, STGM_READ | STGM_SHARE_DENY_WRITE)) {
        IShellItem *item = nullptr;
        if (SUCCEEDED(library->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem, reinterpret_cast<void **>(&item)))) {
            result = QDir::cleanPath(QWindowsShellItem::displayName(item, SIGDN_FILESYSPATH));
            item->Release();
        }
        library->Release();
    }
    return result;
}

#ifndef QT_NO_DEBUG_STREAM
void QWindowsShellItem::format(QDebug &d) const
{
    d << "attributes=0x" << Qt::hex << attributes() << Qt::dec;
    if (isFileSystem())
        d << " [filesys]";
    if (isDir())
        d << " [dir]";
    if (canStream())
        d << " [stream]";
    d << ", normalDisplay=\"" << normalDisplay()
        << "\", desktopAbsoluteParsing=\"" << desktopAbsoluteParsing()
        << "\", urlString=\"" << urlString() << "\", fileSysPath=\"" << fileSysPath() << '"';
    const QString pathS = path();
    if (!pathS.isEmpty())
        d << ", path=\"" << pathS << '"';
    const QUrl urlV = urlValue();
    if (urlV.isValid())
        d << "\", url=" << urlV;
}

QDebug operator<<(QDebug d, const QWindowsShellItem &i)
{
    QDebugStateSaver saver(d);
    d.nospace();
    d.noquote();
    d << "QShellItem(";
    i.format(d);
    d << ')';
    return d;
}

QDebug operator<<(QDebug d, IShellItem *i)
{
    QDebugStateSaver saver(d);
    d.nospace();
    d.noquote();
    d << "IShellItem(" << static_cast<const void *>(i);
    if (i) {
        d << ", ";
        QWindowsShellItem(i).format(d);
    }
    d << ')';
    return d;
}
#endif // !QT_NO_DEBUG_STREAM

/*!
    \class QWindowsNativeFileDialogBase
    \brief Windows native file dialog wrapper around IFileOpenDialog, IFileSaveDialog.

    Provides convenience methods.
    Note that only IFileOpenDialog has multi-file functionality.

    \sa QWindowsNativeFileDialogEventHandler, QWindowsFileDialogHelper
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase
{
    Q_OBJECT
    Q_PROPERTY(bool hideFiltersDetails READ hideFiltersDetails WRITE setHideFiltersDetails)
public:
    ~QWindowsNativeFileDialogBase() override;

    inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data);

    void setWindowTitle(const QString &title) override;
    inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options);
    inline void setDirectory(const QUrl &directory);
    inline void updateDirectory() { setDirectory(m_data.directory()); }
    inline QString directory() const;
    void doExec(HWND owner = nullptr) override;
    virtual void setNameFilters(const QStringList &f);
    inline void selectNameFilter(const QString &filter);
    inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
    inline QString selectedNameFilter() const;
    void selectFile(const QString &fileName) const;
    bool hideFiltersDetails() const    { return m_hideFiltersDetails; }
    void setHideFiltersDetails(bool h) { m_hideFiltersDetails = h; }
    void setDefaultSuffix(const QString &s);
    inline bool hasDefaultSuffix() const  { return m_hasDefaultSuffix; }
    inline void setLabelText(QFileDialogOptions::DialogLabel l, const QString &text);

    // Return the selected files for tracking in OnSelectionChanged().
    virtual QList<QUrl> selectedFiles() const = 0;
    // Return the result for tracking in OnFileOk(). Differs from selection for
    // example by appended default suffixes, etc.
    virtual QList<QUrl> dialogResult() const = 0;

    inline void onFolderChange(IShellItem *);
    inline void onSelectionChange();
    inline void onTypeChange();
    inline bool onFileOk();

signals:
    void directoryEntered(const QUrl &directory);
    void currentChanged(const QUrl &file);
    void filterSelected(const QString & filter);

public slots:
    void close() override;

protected:
    explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data);
    bool init(const CLSID &clsId, const IID &iid);
    void setDefaultSuffixSys(const QString &s);
    inline IFileDialog * fileDialog() const { return m_fileDialog; }
    static IShellItem *shellItem(const QUrl &url);

    const QWindowsFileDialogSharedData &data() const { return m_data; }
    QWindowsFileDialogSharedData &data() { return m_data; }

private:
    IFileDialog *m_fileDialog = nullptr;
    IFileDialogEvents *m_dialogEvents = nullptr;
    DWORD m_cookie = 0;
    QStringList m_nameFilters;
    bool m_hideFiltersDetails = false;
    bool m_hasDefaultSuffix = false;
    QWindowsFileDialogSharedData m_data;
    QString m_title;
};

QWindowsNativeFileDialogBase::QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data) :
    m_data(data)
{
}

QWindowsNativeFileDialogBase::~QWindowsNativeFileDialogBase()
{
    if (m_dialogEvents && m_fileDialog)
        m_fileDialog->Unadvise(m_cookie);
    if (m_dialogEvents)
        m_dialogEvents->Release();
    if (m_fileDialog)
        m_fileDialog->Release();
}

bool QWindowsNativeFileDialogBase::init(const CLSID &clsId, const IID &iid)
{
    HRESULT hr = CoCreateInstance(clsId, nullptr, CLSCTX_INPROC_SERVER,
                                  iid, reinterpret_cast<void **>(&m_fileDialog));
    if (FAILED(hr)) {
        qErrnoWarning("CoCreateInstance failed");
        return false;
    }
    m_dialogEvents = QWindowsNativeFileDialogEventHandler::create(this);
    if (!m_dialogEvents)
        return false;
    // Register event handler
    hr = m_fileDialog->Advise(m_dialogEvents, &m_cookie);
    if (FAILED(hr)) {
        qErrnoWarning("IFileDialog::Advise failed");
        return false;
    }
    qCDebug(lcQpaDialogs) << __FUNCTION__ << m_fileDialog << m_dialogEvents <<  m_cookie;

    return true;
}

void QWindowsNativeFileDialogBase::setWindowTitle(const QString &title)
{
    m_title = title;
    m_fileDialog->SetTitle(reinterpret_cast<const wchar_t *>(title.utf16()));
}

IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
{
    if (url.isLocalFile()) {
        IShellItem *result = nullptr;
        const QString native = QDir::toNativeSeparators(url.toLocalFile());
        const HRESULT hr =
                SHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()),
                                            nullptr, IID_IShellItem,
                                            reinterpret_cast<void **>(&result));
        if (FAILED(hr)) {
            qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
            return nullptr;
        }
        return result;
    } else if (url.scheme() == QLatin1String("clsid")) {
        // Support for virtual folders via GUID
        // (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx)
        // specified as "clsid:<GUID>" (without '{', '}').
        IShellItem *result = nullptr;
        const auto uuid = QUuid::fromString(url.path());
        if (uuid.isNull()) {
            qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
            return nullptr;
        }
        PIDLIST_ABSOLUTE idList;
        HRESULT hr = SHGetKnownFolderIDList(uuid, 0, nullptr, &idList);
        if (FAILED(hr)) {
            qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
            return nullptr;
        }
        hr = SHCreateItemFromIDList(idList, IID_IShellItem, reinterpret_cast<void **>(&result));
        CoTaskMemFree(idList);
        if (FAILED(hr)) {
            qErrnoWarning("%s: SHCreateItemFromIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
            return nullptr;
        }
        return result;
    } else {
        qWarning() << __FUNCTION__ << ": Unhandled scheme: " << url.scheme();
    }
    return nullptr;
}

void QWindowsNativeFileDialogBase::setDirectory(const QUrl &directory)
{
    if (!directory.isEmpty()) {
        if (IShellItem *psi = QWindowsNativeFileDialogBase::shellItem(directory)) {
            m_fileDialog->SetFolder(psi);
            psi->Release();
        }
    }
}

QString QWindowsNativeFileDialogBase::directory() const
{
    QString result;
    IShellItem *item = nullptr;
    if (m_fileDialog && SUCCEEDED(m_fileDialog->GetFolder(&item)) && item) {
        result = QWindowsShellItem(item).path();
        item->Release();
    }
    return result;
}

void QWindowsNativeFileDialogBase::doExec(HWND owner)
{
    qCDebug(lcQpaDialogs) << '>' << __FUNCTION__;
    // Show() blocks until the user closes the dialog, the dialog window
    // gets a WM_CLOSE or the parent window is destroyed.
    const HRESULT hr = m_fileDialog->Show(owner);
    QWindowsDialogs::eatMouseMove();
    qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << Qt::hex << hr;
    // Emit accepted() only if there is a result as otherwise UI hangs occur.
    // For example, typing in invalid URLs results in empty result lists.
    if (hr == S_OK && !m_data.selectedFiles().isEmpty()) {
        emit accepted();
    } else {
        emit rejected();
    }
}

void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode,
                                           QFileDialogOptions::AcceptMode acceptMode,
                                           QFileDialogOptions::FileDialogOptions options)
{
    DWORD flags = FOS_PATHMUSTEXIST;
    if (QWindowsContext::readAdvancedExplorerSettings(L"Hidden", 1) == 1) // 1:show, 2:hidden
        flags |= FOS_FORCESHOWHIDDEN;
    if (options & QFileDialogOptions::DontResolveSymlinks)
        flags |= FOS_NODEREFERENCELINKS;
    switch (mode) {
    case QFileDialogOptions::AnyFile:
        if (acceptMode == QFileDialogOptions::AcceptSave)
            flags |= FOS_NOREADONLYRETURN;
        if (!(options & QFileDialogOptions::DontConfirmOverwrite))
            flags |= FOS_OVERWRITEPROMPT;
        break;
    case QFileDialogOptions::ExistingFile:
        flags |= FOS_FILEMUSTEXIST;
        break;
    case QFileDialogOptions::Directory:
    case QFileDialogOptions::DirectoryOnly:
        // QTBUG-63645: Restrict to file system items, as Qt cannot deal with
        // places like 'Network', etc.
        flags |= FOS_PICKFOLDERS | FOS_FILEMUSTEXIST | FOS_FORCEFILESYSTEM;
        break;
    case QFileDialogOptions::ExistingFiles:
        flags |= FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT;
        break;
    }
    qCDebug(lcQpaDialogs) << __FUNCTION__ << "mode=" << mode
        << "acceptMode=" << acceptMode << "options=" << options
        << "results in" << Qt::showbase << Qt::hex << flags;

    if (FAILED(m_fileDialog->SetOptions(flags)))
        qErrnoWarning("%s: SetOptions() failed", __FUNCTION__);
}

// Split a list of name filters into description and actual filters
struct FilterSpec
{
    QString description;
    QString filter;
};

static QList<FilterSpec> filterSpecs(const QStringList &filters,
                                     bool hideFilterDetails,
                                     int *totalStringLength)
{
    QList<FilterSpec> result;
    result.reserve(filters.size());
    *totalStringLength = 0;

    const QRegularExpression filterSeparatorRE(QStringLiteral("[;\\s]+"));
    const QString separator = QStringLiteral(";");
    Q_ASSERT(filterSeparatorRE.isValid());
    // Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc'
    // into description and filters specification as '*.txt;*.doc'
    for (const QString &filterString : filters) {
        const int openingParenPos = filterString.lastIndexOf(QLatin1Char('('));
        const int closingParenPos = openingParenPos != -1 ?
            filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1;
        FilterSpec filterSpec;
        filterSpec.filter = closingParenPos == -1 ?
            filterString :
            filterString.mid(openingParenPos + 1, closingParenPos - openingParenPos - 1).trimmed();
        if (filterSpec.filter.isEmpty())
            filterSpec.filter += QLatin1Char('*');
        filterSpec.filter.replace(filterSeparatorRE, separator);
        filterSpec.description = filterString;
        if (hideFilterDetails && openingParenPos != -1) { // Do not show pattern in description
            filterSpec.description.truncate(openingParenPos);
            while (filterSpec.description.endsWith(QLatin1Char(' ')))
                filterSpec.description.truncate(filterSpec.description.size() - 1);
        }
        *totalStringLength += filterSpec.filter.size() + filterSpec.description.size();
        result.push_back(filterSpec);
    }
    return result;
}

void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters)
{
    /* Populates an array of COMDLG_FILTERSPEC from list of filters,
     * store the strings in a flat, contiguous buffer. */
    m_nameFilters = filters;
    int totalStringLength = 0;
    const QList<FilterSpec> specs = filterSpecs(filters, m_hideFiltersDetails, &totalStringLength);
    const int size = specs.size();

    QScopedArrayPointer<WCHAR> buffer(new WCHAR[totalStringLength + 2 * size]);
    QScopedArrayPointer<COMDLG_FILTERSPEC> comFilterSpec(new COMDLG_FILTERSPEC[size]);

    WCHAR *ptr = buffer.data();
    // Split filter specification as 'Texts (*.txt[;] *.doc)'
    // into description and filters specification as '*.txt;*.doc'

    for (int i = 0; i < size; ++i) {
        // Display glitch (CLSID only): Any filter not filtering on suffix (such as
        // '*', 'a.*') will be duplicated in combo: 'All files (*) (*)',
        // 'AAA files (a.*) (a.*)'
        QString description = specs[i].description;
        const QString &filter = specs[i].filter;
        if (!m_hideFiltersDetails && !filter.startsWith(QLatin1String("*."))) {
            const int pos = description.lastIndexOf(QLatin1Char('('));
            if (pos > 0)
                description.truncate(pos);
        }
        // Add to buffer.
        comFilterSpec[i].pszName = ptr;
        ptr += description.toWCharArray(ptr);
        *ptr++ = 0;
        comFilterSpec[i].pszSpec = ptr;
        ptr += specs[i].filter.toWCharArray(ptr);
        *ptr++ = 0;
    }

    m_fileDialog->SetFileTypes(size, comFilterSpec.data());
}

void QWindowsNativeFileDialogBase::setDefaultSuffix(const QString &s)
{
    setDefaultSuffixSys(s);
    m_hasDefaultSuffix = !s.isEmpty();
}

void QWindowsNativeFileDialogBase::setDefaultSuffixSys(const QString &s)
{
    // If this parameter is non-empty, it will be appended by the dialog for the 'Any files'
    // filter ('*'). If this parameter is non-empty and the current filter has a suffix,
    // the dialog will append the filter's suffix.
    auto *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
    m_fileDialog->SetDefaultExtension(wSuffix);
}

static inline IFileDialog2 *getFileDialog2(IFileDialog *fileDialog)
{
    IFileDialog2 *result;
    return SUCCEEDED(fileDialog->QueryInterface(IID_IFileDialog2, reinterpret_cast<void **>(&result)))
        ? result : nullptr;
}

void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel l, const QString &text)
{
    auto *wText = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(text.utf16()));
    switch (l) {
    case QFileDialogOptions::FileName:
        m_fileDialog->SetFileNameLabel(wText);
        break;
    case QFileDialogOptions::Accept:
        m_fileDialog->SetOkButtonLabel(wText);
        break;
    case QFileDialogOptions::Reject:
        if (IFileDialog2 *dialog2 = getFileDialog2(m_fileDialog)) {
            dialog2->SetCancelButtonLabel(wText);
            dialog2->Release();
        }
        break;
    case QFileDialogOptions::LookIn:
    case QFileDialogOptions::FileType:
    case QFileDialogOptions::DialogLabelCount:
        break;
    }
}

static bool isHexRange(const QString& s, int start, int end)
{
    for (;start < end; ++start) {
        QChar ch = s.at(start);
        if (!(ch.isDigit()
              || (ch >= QLatin1Char('a') && ch <= QLatin1Char('f'))
              || (ch >= QLatin1Char('A') && ch <= QLatin1Char('F'))))
            return false;
    }
    return true;
}

static inline bool isClsid(const QString &s)
{
    // detect "374DE290-123F-4565-9164-39C4925E467B".
    const QChar dash(QLatin1Char('-'));
    return s.size() == 36
            && isHexRange(s, 0, 8)
            && s.at(8) == dash
            && isHexRange(s, 9, 13)
            && s.at(13) == dash
            && isHexRange(s, 14, 18)
            && s.at(18) == dash
            && isHexRange(s, 19, 23)
            && s.at(23) == dash
            && isHexRange(s, 24, 36);
}

void QWindowsNativeFileDialogBase::selectFile(const QString &fileName) const
{
    // Hack to prevent CLSIDs from being set as file name due to
    // QFileDialogPrivate::initialSelection() being QString-based.
    if (!isClsid(fileName))
        m_fileDialog->SetFileName((wchar_t*)fileName.utf16());
}

// Return the index of the selected filter, accounting for QFileDialog
// sometimes stripping the filter specification depending on the
// hideFilterDetails setting.
static int indexOfNameFilter(const QStringList &filters, const QString &needle)
{
    const int index = filters.indexOf(needle);
    if (index >= 0)
        return index;
    for (int i = 0; i < filters.size(); ++i)
        if (filters.at(i).startsWith(needle))
            return i;
    return -1;
}

void QWindowsNativeFileDialogBase::selectNameFilter(const QString &filter)
{
    if (filter.isEmpty())
        return;
    const int index = indexOfNameFilter(m_nameFilters, filter);
    if (index < 0) {
        qWarning("%s: Invalid parameter '%s' not found in '%s'.",
                 __FUNCTION__, qPrintable(filter),
                 qPrintable(m_nameFilters.join(QLatin1String(", "))));
        return;
    }
    m_fileDialog->SetFileTypeIndex(index + 1); // one-based.
}

QString QWindowsNativeFileDialogBase::selectedNameFilter() const
{
    UINT uIndex = 0;
    if (SUCCEEDED(m_fileDialog->GetFileTypeIndex(&uIndex))) {
        const int index = uIndex - 1; // one-based
        if (index < m_nameFilters.size())
            return m_nameFilters.at(index);
    }
    return QString();
}

void QWindowsNativeFileDialogBase::onFolderChange(IShellItem *item)
{
    if (item) {
        const QUrl directory = QWindowsShellItem(item).url();
        m_data.setDirectory(directory);
        emit directoryEntered(directory);
    }
}

void QWindowsNativeFileDialogBase::onSelectionChange()
{
    const QList<QUrl> current = selectedFiles();
    m_data.setSelectedFiles(current);
    qCDebug(lcQpaDialogs) << __FUNCTION__ << current << current.size();

    if (current.size() == 1)
        emit currentChanged(current.front());
}

void QWindowsNativeFileDialogBase::onTypeChange()
{
    const QString filter = selectedNameFilter();
    m_data.setSelectedNameFilter(filter);
    emit filterSelected(filter);
}

bool QWindowsNativeFileDialogBase::onFileOk()
{
    // Store selected files as GetResults() returns invalid data after the dialog closes.
    m_data.setSelectedFiles(dialogResult());
    return true;
}

void QWindowsNativeFileDialogBase::close()
{
    m_fileDialog->Close(S_OK);
    // IFileDialog::Close() does not work unless invoked from a callback.
    // Try to find the window and send it a WM_CLOSE in addition.
    const HWND hwnd = findDialogWindow(m_title);
    qCDebug(lcQpaDialogs) << __FUNCTION__ << "closing" << hwnd;
    if (hwnd && IsWindowVisible(hwnd))
        PostMessageW(hwnd, WM_CLOSE, 0, 0);
}

HRESULT QWindowsNativeFileDialogEventHandler::OnFolderChanging(IFileDialog *, IShellItem *item)
{
    m_nativeFileDialog->onFolderChange(item);
    return S_OK;
}

HRESULT QWindowsNativeFileDialogEventHandler::OnSelectionChange(IFileDialog *)
{
    m_nativeFileDialog->onSelectionChange();
    return S_OK;
}

HRESULT QWindowsNativeFileDialogEventHandler::OnTypeChange(IFileDialog *)
{
    m_nativeFileDialog->onTypeChange();
    return S_OK;
}

HRESULT QWindowsNativeFileDialogEventHandler::OnFileOk(IFileDialog *)
{
    return m_nativeFileDialog->onFileOk() ? S_OK : S_FALSE;
}

/*!
    \class QWindowsNativeSaveFileDialog
    \brief Windows native file save dialog wrapper around IFileSaveDialog.

    Implements single-selection methods.

    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
{
    Q_OBJECT
public:
    explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data)
        : QWindowsNativeFileDialogBase(data) {}
    void setNameFilters(const QStringList &f) override;
    QList<QUrl> selectedFiles() const override;
    QList<QUrl> dialogResult() const override;
};

// Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo".
// Also handles the simple name filter case "*.txt" -> "txt"
static inline QString suffixFromFilter(const QString &filter)
{
    int suffixPos = filter.indexOf(QLatin1String("*."));
    if (suffixPos < 0)
        return QString();
    suffixPos += 2;
    int endPos = filter.indexOf(QLatin1Char(' '), suffixPos + 1);
    if (endPos < 0)
        endPos = filter.indexOf(QLatin1Char(';'), suffixPos + 1);
    if (endPos < 0)
        endPos = filter.indexOf(QLatin1Char(')'), suffixPos + 1);
    if (endPos < 0)
        endPos = filter.size();
    return filter.mid(suffixPos, endPos - suffixPos);
}

void QWindowsNativeSaveFileDialog::setNameFilters(const QStringList &f)
{
    QWindowsNativeFileDialogBase::setNameFilters(f);
    // QTBUG-31381, QTBUG-30748: IFileDialog will update the suffix of the selected name
    // filter only if a default suffix is set (see docs). Set the first available
    // suffix unless we have a defaultSuffix.
    if (!hasDefaultSuffix()) {
        for (const QString &filter : f) {
            const QString suffix = suffixFromFilter(filter);
            if (!suffix.isEmpty()) {
                setDefaultSuffixSys(suffix);
                break;
            }
        }
    } // m_hasDefaultSuffix
}

QList<QUrl> QWindowsNativeSaveFileDialog::dialogResult() const
{
    QList<QUrl> result;
    IShellItem *item = nullptr;
    if (SUCCEEDED(fileDialog()->GetResult(&item)) && item)
        result.append(QWindowsShellItem(item).url());
    return result;
}

QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const
{
    QList<QUrl> result;
    IShellItem *item = nullptr;
    const HRESULT hr = fileDialog()->GetCurrentSelection(&item);
    if (SUCCEEDED(hr) && item) {
        result.append(QWindowsShellItem(item).url());
        item->Release();
    }
    return result;
}

/*!
    \class QWindowsNativeOpenFileDialog
    \brief Windows native file save dialog wrapper around IFileOpenDialog.

    Implements multi-selection methods.

    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
{
public:
    explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) :
        QWindowsNativeFileDialogBase(data) {}
    QList<QUrl> selectedFiles() const override;
    QList<QUrl> dialogResult() const override;

private:
    inline IFileOpenDialog *openFileDialog() const
        { return static_cast<IFileOpenDialog *>(fileDialog()); }
};

// Helpers for managing a list of temporary copies of items with no
// file system representation (SFGAO_FILESYSTEM unset, for example devices
// using MTP) returned by IFileOpenDialog. This emulates the behavior
// of the Win32 API GetOpenFileName() used in Qt 4 (QTBUG-57070).

Q_GLOBAL_STATIC(QStringList, temporaryItemCopies)

static void cleanupTemporaryItemCopies()
{
    for (const QString &file : qAsConst(*temporaryItemCopies()))
        QFile::remove(file);
}

// Determine temporary file pattern from a shell item's display
// name. This can be a URL.

static bool validFileNameCharacter(QChar c)
{
    return c.isLetterOrNumber() || c == QLatin1Char('_') || c == QLatin1Char('-');
}

QString tempFilePattern(QString name)
{
    const int lastSlash = qMax(name.lastIndexOf(QLatin1Char('/')),
                               name.lastIndexOf(QLatin1Char('\\')));
    if (lastSlash != -1)
        name.remove(0, lastSlash + 1);

    int lastDot = name.lastIndexOf(QLatin1Char('.'));
    if (lastDot < 0)
        lastDot = name.size();
    name.insert(lastDot, QStringLiteral("_XXXXXX"));

    for (int i = lastDot - 1; i >= 0; --i) {
        if (!validFileNameCharacter(name.at(i)))
            name[i] = QLatin1Char('_');
    }

    name.prepend(QDir::tempPath() + QLatin1Char('/'));
    return name;
}

static QString createTemporaryItemCopy(QWindowsShellItem &qItem, QString *errorMessage)
{
    if (!qItem.canStream()) {
        *errorMessage = QLatin1String("Item not streamable");
        return QString();
    }

    QTemporaryFile targetFile(tempFilePattern(qItem.normalDisplay()));
    targetFile.setAutoRemove(false);
    if (!targetFile.open())  {
        *errorMessage = QLatin1String("Cannot create temporary file: ")
                        + targetFile.errorString();
        return QString();
    }
    if (!qItem.copyData(&targetFile, errorMessage))
        return QString();
    const QString result = targetFile.fileName();
    if (temporaryItemCopies()->isEmpty())
        qAddPostRoutine(cleanupTemporaryItemCopies);
    temporaryItemCopies()->append(result);
    return result;
}

static QUrl itemToDialogUrl(QWindowsShellItem &qItem, QString *errorMessage)
{
    QUrl url = qItem.url();
    if (url.isLocalFile() || url.scheme().startsWith(QLatin1String("http")))
        return url;
    const QString path = qItem.path();
    if (path.isEmpty() && !qItem.isDir() && qItem.canStream()) {
        const QString temporaryCopy = createTemporaryItemCopy(qItem, errorMessage);
        if (temporaryCopy.isEmpty()) {
            QDebug(errorMessage).noquote() << "Unable to create a local copy of"
                << qItem << ": " << errorMessage;
            return QUrl();
        }
        return QUrl::fromLocalFile(temporaryCopy);
    }
    if (!url.isValid())
        QDebug(errorMessage).noquote() << "Invalid URL obtained from" << qItem;
    return url;
}

QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const
{
    QList<QUrl> result;
    IShellItemArray *items = nullptr;
    if (SUCCEEDED(openFileDialog()->GetResults(&items)) && items) {
        QString errorMessage;
        for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) {
            QWindowsShellItem qItem(item);
            const QUrl url = itemToDialogUrl(qItem, &errorMessage);
            if (!url.isValid()) {
                qWarning("%s", qPrintable(errorMessage));
                result.clear();
                break;
            }
            result.append(url);
        }
    }
    return result;
}

QList<QUrl> QWindowsNativeOpenFileDialog::selectedFiles() const
{
    QList<QUrl> result;
    IShellItemArray *items = nullptr;
    const HRESULT hr = openFileDialog()->GetSelectedItems(&items);
    if (SUCCEEDED(hr) && items) {
        for (IShellItem *item : QWindowsShellItem::itemsFromItemArray(items)) {
            const QWindowsShellItem qItem(item);
            const QUrl url = qItem.url();
            if (url.isValid())
                result.append(url);
            else
                qWarning().nospace() << __FUNCTION__<< ": Unable to obtain URL of " << qItem;
        }
    }
    return result;
}

/*!
    \brief Factory method for QWindowsNativeFileDialogBase returning
    QWindowsNativeOpenFileDialog or QWindowsNativeSaveFileDialog depending on
    QFileDialog::AcceptMode.
*/

QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOptions::AcceptMode am,
                                                                   const QWindowsFileDialogSharedData &data)
{
    QWindowsNativeFileDialogBase *result = nullptr;
    if (am == QFileDialogOptions::AcceptOpen) {
        result = new QWindowsNativeOpenFileDialog(data);
        if (!result->init(CLSID_FileOpenDialog, IID_IFileOpenDialog)) {
            delete result;
            return nullptr;
        }
    } else {
        result = new QWindowsNativeSaveFileDialog(data);
        if (!result->init(CLSID_FileSaveDialog, IID_IFileSaveDialog)) {
            delete result;
            return nullptr;
        }
    }
    return result;
}

/*!
    \class QWindowsFileDialogHelper
    \brief Helper for native Windows file dialogs

    For Qt 4 compatibility, do not create native non-modal dialogs on widgets,
    but only on QQuickWindows, which do not have a fallback.

    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper>
{
public:
    QWindowsFileDialogHelper() {}
    bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const override { return false; }
    bool defaultNameFilterDisables() const override
        { return false; }
    void setDirectory(const QUrl &directory) override;
    QUrl directory() const override;
    void selectFile(const QUrl &filename) override;
    QList<QUrl> selectedFiles() const override;
    void setFilter() override;
    void selectNameFilter(const QString &filter) override;
    QString selectedNameFilter() const override;

private:
    QWindowsNativeDialogBase *createNativeDialog() override;
    inline QWindowsNativeFileDialogBase *nativeFileDialog() const
        { return static_cast<QWindowsNativeFileDialogBase *>(nativeDialog()); }

    // Cache for the case no native dialog is created.
    QWindowsFileDialogSharedData m_data;
};

QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
{
    QWindowsNativeFileDialogBase *result = QWindowsNativeFileDialogBase::create(options()->acceptMode(), m_data);
    if (!result)
        return nullptr;
    QObject::connect(result, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept);
    QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject);
    QObject::connect(result, &QWindowsNativeFileDialogBase::directoryEntered,
                     this, &QPlatformFileDialogHelper::directoryEntered);
    QObject::connect(result, &QWindowsNativeFileDialogBase::currentChanged,
                     this, &QPlatformFileDialogHelper::currentChanged);
    QObject::connect(result, &QWindowsNativeFileDialogBase::filterSelected,
                     this, &QPlatformFileDialogHelper::filterSelected);

    // Apply settings.
    const QSharedPointer<QFileDialogOptions> &opts = options();
    m_data.fromOptions(opts);
    const QFileDialogOptions::FileMode mode = opts->fileMode();
    result->setWindowTitle(opts->windowTitle());
    result->setMode(mode, opts->acceptMode(), opts->options());
    result->setHideFiltersDetails(opts->testOption(QFileDialogOptions::HideNameFilterDetails));
    const QStringList nameFilters = opts->nameFilters();
    if (!nameFilters.isEmpty())
        result->setNameFilters(nameFilters);
    if (opts->isLabelExplicitlySet(QFileDialogOptions::FileName))
        result->setLabelText(QFileDialogOptions::FileName, opts->labelText(QFileDialogOptions::FileName));
    if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
        result->setLabelText(QFileDialogOptions::Accept, opts->labelText(QFileDialogOptions::Accept));
    if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject))
        result->setLabelText(QFileDialogOptions::Reject, opts->labelText(QFileDialogOptions::Reject));
    result->updateDirectory();
    result->updateSelectedNameFilter();
    const QList<QUrl> initialSelection = opts->initiallySelectedFiles();
    if (!initialSelection.empty()) {
        const QUrl &url = initialSelection.constFirst();
        if (url.isLocalFile()) {
            QFileInfo info(url.toLocalFile());
            if (!info.isDir())
                result->selectFile(info.fileName());
        } else {
            result->selectFile(url.path()); // TODO url.fileName() once it exists
        }
    }
    // No need to select initialNameFilter if mode is Dir
    if (mode != QFileDialogOptions::Directory && mode != QFileDialogOptions::DirectoryOnly) {
        const QString initialNameFilter = opts->initiallySelectedNameFilter();
        if (!initialNameFilter.isEmpty())
            result->selectNameFilter(initialNameFilter);
    }
    const QString defaultSuffix = opts->defaultSuffix();
    if (!defaultSuffix.isEmpty())
        result->setDefaultSuffix(defaultSuffix);
    return result;
}

void QWindowsFileDialogHelper::setDirectory(const QUrl &directory)
{
    qCDebug(lcQpaDialogs) << __FUNCTION__ << directory.toString();

    m_data.setDirectory(directory);
    if (hasNativeDialog())
        nativeFileDialog()->updateDirectory();
}

QUrl QWindowsFileDialogHelper::directory() const
{
    return m_data.directory();
}

void QWindowsFileDialogHelper::selectFile(const QUrl &fileName)
{
    qCDebug(lcQpaDialogs) << __FUNCTION__ << fileName.toString();

    if (hasNativeDialog()) // Might be invoked from the QFileDialog constructor.
        nativeFileDialog()->selectFile(fileName.toLocalFile()); // ## should use QUrl::fileName() once it exists
}

QList<QUrl> QWindowsFileDialogHelper::selectedFiles() const
{
    return m_data.selectedFiles();
}

void QWindowsFileDialogHelper::setFilter()
{
    qCDebug(lcQpaDialogs) << __FUNCTION__;
}

void QWindowsFileDialogHelper::selectNameFilter(const QString &filter)
{
    m_data.setSelectedNameFilter(filter);
    if (hasNativeDialog())
        nativeFileDialog()->updateSelectedNameFilter();
}

QString QWindowsFileDialogHelper::selectedNameFilter() const
{
    return m_data.selectedNameFilter();
}

/*!
    \class QWindowsXpNativeFileDialog
    \brief Native Windows directory dialog for Windows XP using SHlib-functions.

    Uses the synchronous GetOpenFileNameW(), GetSaveFileNameW() from ComDlg32
    or SHBrowseForFolder() for directories.

    \internal
    \sa QWindowsXpFileDialogHelper

    \ingroup qt-lighthouse-win
*/

class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase
{
    Q_OBJECT
public:
    using OptionsPtr = QSharedPointer<QFileDialogOptions>;

    static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);

    void setWindowTitle(const QString &t) override { m_title =  t; }
    void doExec(HWND owner = nullptr) override;

    int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam);

public slots:
    void close() override {}

private:
    typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW);
    typedef BOOL (APIENTRY *PtrGetSaveFileNameW)(LPOPENFILENAMEW);

    explicit QWindowsXpNativeFileDialog(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
    void populateOpenFileName(OPENFILENAME *ofn, HWND owner) const;
    QList<QUrl> execExistingDir(HWND owner);
    QList<QUrl> execFileNames(HWND owner, int *selectedFilterIndex) const;

    const OptionsPtr m_options;
    QString m_title;
    QPlatformDialogHelper::DialogCode m_result;
    QWindowsFileDialogSharedData m_data;

    static PtrGetOpenFileNameW m_getOpenFileNameW;
    static PtrGetSaveFileNameW m_getSaveFileNameW;
};

QWindowsXpNativeFileDialog::PtrGetOpenFileNameW QWindowsXpNativeFileDialog::m_getOpenFileNameW = nullptr;
QWindowsXpNativeFileDialog::PtrGetSaveFileNameW QWindowsXpNativeFileDialog::m_getSaveFileNameW = nullptr;

QWindowsXpNativeFileDialog *QWindowsXpNativeFileDialog::create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data)
{
    // GetOpenFileNameW() GetSaveFileName() are resolved
    // dynamically as not to create a dependency on Comdlg32, which
    // is used on XP only.
    if (!m_getOpenFileNameW) {
        QSystemLibrary library(QStringLiteral("Comdlg32"));
        m_getOpenFileNameW = (PtrGetOpenFileNameW)(library.resolve("GetOpenFileNameW"));
        m_getSaveFileNameW = (PtrGetSaveFileNameW)(library.resolve("GetSaveFileNameW"));
    }
    if (m_getOpenFileNameW && m_getSaveFileNameW)
        return new QWindowsXpNativeFileDialog(options, data);
    return nullptr;
}

QWindowsXpNativeFileDialog::QWindowsXpNativeFileDialog(const OptionsPtr &options,
                                                       const QWindowsFileDialogSharedData &data) :
    m_options(options), m_result(QPlatformDialogHelper::Rejected), m_data(data)
{
    setWindowTitle(m_options->windowTitle());
}

void QWindowsXpNativeFileDialog::doExec(HWND owner)
{
    int selectedFilterIndex = -1;
    const QList<QUrl> selectedFiles =
        m_options->fileMode() == QFileDialogOptions::DirectoryOnly ?
        execExistingDir(owner) : execFileNames(owner, &selectedFilterIndex);
    m_data.setSelectedFiles(selectedFiles);
    QWindowsDialogs::eatMouseMove();
    if (selectedFiles.isEmpty()) {
        m_result = QPlatformDialogHelper::Rejected;
        emit rejected();
    } else {
        const QStringList nameFilters = m_options->nameFilters();
        if (selectedFilterIndex >= 0 && selectedFilterIndex < nameFilters.size())
            m_data.setSelectedNameFilter(nameFilters.at(selectedFilterIndex));
        const QUrl &firstFile = selectedFiles.constFirst();
        m_data.setDirectory(firstFile.adjusted(QUrl::RemoveFilename));
        m_result = QPlatformDialogHelper::Accepted;
        emit accepted();
    }
}

// Callback for QWindowsNativeXpFileDialog directory dialog.
// MFC Directory Dialog. Contrib: Steve Williams (minor parts from Scott Powers)

static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
    auto *dialog = reinterpret_cast<QWindowsXpNativeFileDialog *>(lpData);
    return dialog->existingDirCallback(hwnd, uMsg, lParam);
}

/* The correct declaration of the SHGetPathFromIDList symbol is
 * being used in mingw-w64 as of r6215, which is a v3 snapshot.  */
#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
typedef ITEMIDLIST *qt_LpItemIdList;
#else
using qt_LpItemIdList = PIDLIST_ABSOLUTE;
#endif

int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
{
    switch (uMsg) {
    case BFFM_INITIALIZED: {
        if (!m_title.isEmpty())
            SetWindowText(hwnd, reinterpret_cast<const wchar_t *>(m_title.utf16()));
        const QString initialFile = QDir::toNativeSeparators(m_data.directory().toLocalFile());
        if (!initialFile.isEmpty())
            SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initialFile.utf16()));
    }
        break;
    case BFFM_SELCHANGED: {
        wchar_t path[MAX_PATH];
        const bool ok = SHGetPathFromIDList(reinterpret_cast<qt_LpItemIdList>(lParam), path)
                        && path[0];
        SendMessage(hwnd, BFFM_ENABLEOK, ok ? 1 : 0, 1);
    }
        break;
    }
    return 0;
}

QList<QUrl> QWindowsXpNativeFileDialog::execExistingDir(HWND owner)
{
    BROWSEINFO bi;
    wchar_t initPath[MAX_PATH];
    initPath[0] = 0;
    bi.hwndOwner = owner;
    bi.pidlRoot = nullptr;
    bi.lpszTitle = nullptr;
    bi.pszDisplayName = initPath;
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE;
    bi.lpfn = xpFileDialogGetExistingDirCallbackProc;
    bi.lParam = LPARAM(this);
    QList<QUrl> selectedFiles;
    if (qt_LpItemIdList pItemIDList = SHBrowseForFolder(&bi)) {
        wchar_t path[MAX_PATH];
        path[0] = 0;
        if (SHGetPathFromIDList(pItemIDList, path) && path[0])
            selectedFiles.push_back(QUrl::fromLocalFile(QDir::cleanPath(QString::fromWCharArray(path))));
        IMalloc *pMalloc;
        if (SHGetMalloc(&pMalloc) == NOERROR) {
            pMalloc->Free(pItemIDList);
            pMalloc->Release();
        }
    }
    return selectedFiles;
}

// Open/Save files
void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND owner) const
{
    ZeroMemory(ofn, sizeof(OPENFILENAME));
    ofn->lStructSize = sizeof(OPENFILENAME);
    ofn->hwndOwner = owner;

    // Create a buffer with the filter strings.
    int totalStringLength = 0;
    const QList<FilterSpec> specs =
        filterSpecs(m_options->nameFilters(), m_options->options() & QFileDialogOptions::HideNameFilterDetails, &totalStringLength);
    const int size = specs.size();
    auto *ptr = new wchar_t[totalStringLength + 2 * size + 1];
    ofn->lpstrFilter = ptr;
    for (const FilterSpec &spec : specs) {
        ptr += spec.description.toWCharArray(ptr);
        *ptr++ = 0;
        ptr += spec.filter.toWCharArray(ptr);
        *ptr++ = 0;
    }
    *ptr = 0;
    const int nameFilterIndex = indexOfNameFilter(m_options->nameFilters(), m_data.selectedNameFilter());
    if (nameFilterIndex >= 0)
        ofn->nFilterIndex = nameFilterIndex + 1; // 1..n based.
    // lpstrFile receives the initial selection and is the buffer
    // for the target. If it contains any invalid character, the dialog
    // will not show.
    ofn->nMaxFile = 65535;
    const QString initiallySelectedFile =
        QDir::toNativeSeparators(m_data.selectedFile()).remove(QLatin1Char('<')).
            remove(QLatin1Char('>')).remove(QLatin1Char('"')).remove(QLatin1Char('|'));
    ofn->lpstrFile = qStringToWCharArray(initiallySelectedFile, ofn->nMaxFile);
    ofn->lpstrInitialDir = qStringToWCharArray(QDir::toNativeSeparators(m_data.directory().toLocalFile()));
    ofn->lpstrTitle = (wchar_t*)m_title.utf16();
    // Determine lpstrDefExt. Note that the current MSDN docs document this
    // member wrong. It should rather be documented as "the default extension
    // if no extension was given and if the current filter does not have an
    // extension (e.g (*)). If the current filter has an extension, use
    // the extension of the current filter".
    if (m_options->acceptMode() == QFileDialogOptions::AcceptSave) {
        QString defaultSuffix = m_options->defaultSuffix();
        if (defaultSuffix.startsWith(QLatin1Char('.')))
            defaultSuffix.remove(0, 1);
        // QTBUG-33156, also create empty strings to trigger the appending mechanism.
        ofn->lpstrDefExt = qStringToWCharArray(defaultSuffix);
    }
    // Flags.
    ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST);
    if (m_options->fileMode() == QFileDialogOptions::ExistingFile
        || m_options->fileMode() == QFileDialogOptions::ExistingFiles)
        ofn->Flags |= (OFN_FILEMUSTEXIST);
    if (m_options->fileMode() == QFileDialogOptions::ExistingFiles)
        ofn->Flags |= (OFN_ALLOWMULTISELECT);
    if (!(m_options->options() & QFileDialogOptions::DontConfirmOverwrite))
        ofn->Flags |= OFN_OVERWRITEPROMPT;
}

QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedFilterIndex) const
{
    *selectedFilterIndex = -1;
    OPENFILENAME ofn;
    populateOpenFileName(&ofn, owner);
    QList<QUrl> result;
    const bool isSave = m_options->acceptMode() == QFileDialogOptions::AcceptSave;
    if (isSave ? m_getSaveFileNameW(&ofn) : m_getOpenFileNameW(&ofn)) {
        *selectedFilterIndex = ofn.nFilterIndex - 1;
        const QString dir = QDir::cleanPath(QString::fromWCharArray(ofn.lpstrFile));
        result.push_back(QUrl::fromLocalFile(dir));
        // For multiselection, the first item is the path followed
        // by "\0<file1>\0<file2>\0\0".
        if (ofn.Flags & (OFN_ALLOWMULTISELECT)) {
            wchar_t *ptr = ofn.lpstrFile + dir.size() + 1;
            if (*ptr) {
                result.pop_front();
                const QString path = dir + QLatin1Char('/');
                while (*ptr) {
                    const QString fileName = QString::fromWCharArray(ptr);
                    result.push_back(QUrl::fromLocalFile(path + fileName));
                    ptr += fileName.size() + 1;
                } // extract multiple files
            } // has multiple files
        } // multiple flag set
    }
    delete [] ofn.lpstrFile;
    delete [] ofn.lpstrInitialDir;
    delete [] ofn.lpstrFilter;
    delete [] ofn.lpstrDefExt;
    return result;
}

/*!
    \class QWindowsXpFileDialogHelper
    \brief Dialog helper using QWindowsXpNativeFileDialog

    \sa QWindowsXpNativeFileDialog
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper>
{
public:
    QWindowsXpFileDialogHelper() = default;
    bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const override { return false; }
    bool defaultNameFilterDisables() const override
        { return true; }
    void setDirectory(const QUrl &directory) override;
    QUrl directory() const override;
    void selectFile(const QUrl &url) override;
    QList<QUrl> selectedFiles() const override;
    void setFilter() override {}
    void selectNameFilter(const QString &) override;
    QString selectedNameFilter() const override;

private:
    QWindowsNativeDialogBase *createNativeDialog() override;
    inline QWindowsXpNativeFileDialog *nativeFileDialog() const
        { return static_cast<QWindowsXpNativeFileDialog *>(nativeDialog()); }

    QWindowsFileDialogSharedData m_data;
};

QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog()
{
    m_data.fromOptions(options());
    if (QWindowsXpNativeFileDialog *result = QWindowsXpNativeFileDialog::create(options(), m_data)) {
        QObject::connect(result, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept);
        QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject);
        return result;
    }
    return nullptr;
}

void QWindowsXpFileDialogHelper::setDirectory(const QUrl &directory)
{
    m_data.setDirectory(directory); // Dialog cannot be updated at run-time.
}

QUrl QWindowsXpFileDialogHelper::directory() const
{
    return m_data.directory();
}

void QWindowsXpFileDialogHelper::selectFile(const QUrl &url)
{
    m_data.setSelectedFiles(QList<QUrl>() << url); // Dialog cannot be updated at run-time.
}

QList<QUrl> QWindowsXpFileDialogHelper::selectedFiles() const
{
    return m_data.selectedFiles();
}

void QWindowsXpFileDialogHelper::selectNameFilter(const QString &f)
{
    m_data.setSelectedNameFilter(f); // Dialog cannot be updated at run-time.
}

QString QWindowsXpFileDialogHelper::selectedNameFilter() const
{
    return m_data.selectedNameFilter();
}

/*!
    \class QWindowsNativeColorDialog
    \brief Native Windows color dialog.

    Wrapper around Comdlg32's ChooseColor() function.
    Not currently in use as QColorDialog is equivalent.

    \sa QWindowsColorDialogHelper
    \sa #define USE_NATIVE_COLOR_DIALOG
    \internal
    \ingroup qt-lighthouse-win
*/

using SharedPointerColor = QSharedPointer<QColor>;

#ifdef USE_NATIVE_COLOR_DIALOG
class QWindowsNativeColorDialog : public QWindowsNativeDialogBase
{
    Q_OBJECT
public:
    enum { CustomColorCount = 16 };

    explicit QWindowsNativeColorDialog(const SharedPointerColor &color);

    void setWindowTitle(const QString &) override {}

public slots:
    void close() override {}

private:
    void doExec(HWND owner = 0) override;

    COLORREF m_customColors[CustomColorCount];
    QPlatformDialogHelper::DialogCode m_code;
    SharedPointerColor m_color;
};

QWindowsNativeColorDialog::QWindowsNativeColorDialog(const SharedPointerColor &color) :
    m_code(QPlatformDialogHelper::Rejected), m_color(color)
{
    std::fill(m_customColors, m_customColors + 16, COLORREF(0));
}

void QWindowsNativeColorDialog::doExec(HWND owner)
{
    typedef BOOL (WINAPI *ChooseColorWType)(LPCHOOSECOLORW);

    CHOOSECOLOR chooseColor;
    ZeroMemory(&chooseColor, sizeof(chooseColor));
    chooseColor.lStructSize = sizeof(chooseColor);
    chooseColor.hwndOwner = owner;
    chooseColor.lpCustColors = m_customColors;
    QRgb *qCustomColors = QColorDialogOptions::customColors();
    const int customColorCount = qMin(QColorDialogOptions::customColorCount(),
                                      int(CustomColorCount));
    for (int c= 0; c < customColorCount; ++c)
        m_customColors[c] = qColorToCOLORREF(QColor(qCustomColors[c]));
    chooseColor.rgbResult = qColorToCOLORREF(*m_color);
    chooseColor.Flags = CC_FULLOPEN | CC_RGBINIT;
    static ChooseColorWType chooseColorW = 0;
    if (!chooseColorW) {
        QSystemLibrary library(QStringLiteral("Comdlg32"));
        chooseColorW = (ChooseColorWType)library.resolve("ChooseColorW");
    }
    if (chooseColorW) {
        m_code = chooseColorW(&chooseColor) ?
            QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
        QWindowsDialogs::eatMouseMove();
    } else {
        m_code = QPlatformDialogHelper::Rejected;
    }
    if (m_code == QPlatformDialogHelper::Accepted) {
        *m_color = COLORREFToQColor(chooseColor.rgbResult);
        for (int c= 0; c < customColorCount; ++c)
            qCustomColors[c] = COLORREFToQColor(m_customColors[c]).rgb();
        emit accepted();
    } else {
        emit rejected();
    }
}

/*!
    \class QWindowsColorDialogHelper
    \brief Helper for native Windows color dialogs

    Not currently in use as QColorDialog is equivalent.

    \sa #define USE_NATIVE_COLOR_DIALOG
    \sa QWindowsNativeColorDialog
    \internal
    \ingroup qt-lighthouse-win
*/

class QWindowsColorDialogHelper : public QWindowsDialogHelperBase<QPlatformColorDialogHelper>
{
public:
    QWindowsColorDialogHelper() : m_currentColor(new QColor) {}

    virtual bool supportsNonModalDialog()
        { return false; }

    virtual QColor currentColor() const { return *m_currentColor; }
    virtual void setCurrentColor(const QColor &c) { *m_currentColor = c; }

private:
    inline QWindowsNativeColorDialog *nativeFileDialog() const
        { return static_cast<QWindowsNativeColorDialog *>(nativeDialog()); }
    virtual QWindowsNativeDialogBase *createNativeDialog();

    SharedPointerColor m_currentColor;
};

QWindowsNativeDialogBase *QWindowsColorDialogHelper::createNativeDialog()
{
    QWindowsNativeColorDialog *nativeDialog = new QWindowsNativeColorDialog(m_currentColor);
    nativeDialog->setWindowTitle(options()->windowTitle());
    connect(nativeDialog, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept);
    connect(nativeDialog, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject);
    return nativeDialog;
}
#endif // USE_NATIVE_COLOR_DIALOG

namespace QWindowsDialogs {

// QWindowsDialogHelperBase creation functions
bool useHelper(QPlatformTheme::DialogType type)
{
    if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs)
        return false;
    switch (type) {
    case QPlatformTheme::FileDialog:
        return true;
    case QPlatformTheme::ColorDialog:
#ifdef USE_NATIVE_COLOR_DIALOG
        return true;
#else
        break;
#endif
    case QPlatformTheme::FontDialog:
    case QPlatformTheme::MessageDialog:
        break;
    default:
        break;
    }
    return false;
}

QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type)
{
    if (QWindowsIntegration::instance()->options() & QWindowsIntegration::NoNativeDialogs)
        return nullptr;
    switch (type) {
    case QPlatformTheme::FileDialog:
        if (QWindowsIntegration::instance()->options() & QWindowsIntegration::XpNativeDialogs)
            return new QWindowsXpFileDialogHelper();
        return new QWindowsFileDialogHelper;
    case QPlatformTheme::ColorDialog:
#ifdef USE_NATIVE_COLOR_DIALOG
        return new QWindowsColorDialogHelper();
#else
        break;
#endif
    case QPlatformTheme::FontDialog:
    case QPlatformTheme::MessageDialog:
        break;
    default:
        break;
    }
    return nullptr;
}

} // namespace QWindowsDialogs
QT_END_NAMESPACE

#include "qwindowsdialoghelpers.moc"
