tdf#119730 WIN switch to IFileDialog FOS_PICKFOLDERS

Citing SHBrowseForFolderW remarks: "For Windows Vista or later, it
is recommended that you use IFileDialog with the FOS_PICKFOLDERS
option rather than the SHBrowseForFolder function."

Since the minimum required Windows version is already 7 and we
already just provide the Vista file picker, this gets rid of the
Windows XP compatible folder picker code.

Reviewed-on: https://gerrit.libreoffice.org/60144
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
(cherry picked from commit 2129753120d8101f0f484571b6a8cd8eb4d4629c)

Change-Id: I85daae84d4eb36fc827cf20aa277ce6a2f63dd2c
Reviewed-on: https://gerrit.libreoffice.org/63723
Tested-by: Jenkins
Reviewed-by: Michael Stahl <Michael.Stahl@cib.de>
diff --git a/fpicker/Library_fps.mk b/fpicker/Library_fps.mk
index d6be222..cc08f47 100644
--- a/fpicker/Library_fps.mk
+++ b/fpicker/Library_fps.mk
@@ -67,9 +67,6 @@
	fpicker/source/win32/filepicker/VistaFilePicker \
	fpicker/source/win32/filepicker/VistaFilePickerEventHandler \
	fpicker/source/win32/filepicker/VistaFilePickerImpl \
	fpicker/source/win32/folderpicker/FolderPicker \
	fpicker/source/win32/folderpicker/MtaFop \
	fpicker/source/win32/folderpicker/WinFOPImpl \
	fpicker/source/win32/misc/resourceprovider \
	fpicker/source/win32/misc/WinImplHelper \
))
diff --git a/fpicker/source/win32/filepicker/FPServiceInfo.hxx b/fpicker/source/win32/filepicker/FPServiceInfo.hxx
index 36aadf4..edc350c 100644
--- a/fpicker/source/win32/filepicker/FPServiceInfo.hxx
+++ b/fpicker/source/win32/filepicker/FPServiceInfo.hxx
@@ -26,6 +26,12 @@
// the implementation names
#define FILE_PICKER_IMPL_NAME  "com.sun.star.ui.dialogs.Win32FilePicker"

// the service names
#define FOLDER_PICKER_SERVICE_NAME  "com.sun.star.ui.dialogs.SystemFolderPicker"

// the implementation names
#define FOLDER_PICKER_IMPL_NAME  "com.sun.star.ui.dialogs.Win32FolderPicker"

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/filepicker/FPentry.cxx b/fpicker/source/win32/filepicker/FPentry.cxx
index 2166ba8..d62dda4 100644
--- a/fpicker/source/win32/filepicker/FPentry.cxx
+++ b/fpicker/source/win32/filepicker/FPentry.cxx
@@ -25,32 +25,27 @@
#include "../misc/WinImplHelper.hxx"
#include <stdio.h>

#include "../folderpicker/FolderPicker.hxx"
#include "../folderpicker/FOPServiceInfo.hxx"
#include "../folderpicker/WinFOPImpl.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::cppu;
using ::com::sun::star::ui::dialogs::XFilePicker2;
using ::com::sun::star::ui::dialogs::XFolderPicker2;

static Reference< XInterface > createInstance(
    const Reference< XMultiServiceFactory >& rServiceManager )
{
    Reference< XInterface > xDlg;

    xDlg.set(static_cast<XFilePicker2*>(
            new ::fpicker::win32::vista::VistaFilePicker(rServiceManager)));

    return xDlg;
    return Reference<ui::dialogs::XFilePicker2>(
            new ::fpicker::win32::vista::VistaFilePicker(rServiceManager, false));
}

static Reference< XInterface >
createInstance_fop( const Reference< XMultiServiceFactory >& rServiceManager )
{
    return Reference< XInterface >( static_cast< cppu::OWeakObject * >( new CFolderPicker( rServiceManager ) ) );
    return Reference<ui::dialogs::XFolderPicker2>(
            new ::fpicker::win32::vista::VistaFilePicker(rServiceManager, true));
}

extern "C"
diff --git a/fpicker/source/win32/filepicker/VistaFilePicker.cxx b/fpicker/source/win32/filepicker/VistaFilePicker.cxx
index c0dde13..17b6a56 100644
--- a/fpicker/source/win32/filepicker/VistaFilePicker.cxx
+++ b/fpicker/source/win32/filepicker/VistaFilePicker.cxx
@@ -20,6 +20,7 @@
#include "VistaFilePicker.hxx"

#include "../misc/WinImplHelper.hxx"
#include "FPServiceInfo.hxx"
#include "shared.hxx"

#include <com/sun/star/awt/XWindow.hpp>
@@ -46,20 +47,22 @@
{
    css::uno::Sequence< OUString > VistaFilePicker_getSupportedServiceNames()
    {
        css::uno::Sequence< OUString > aRet(2);
        css::uno::Sequence< OUString > aRet(3);
        aRet[0] = "com.sun.star.ui.dialogs.FilePicker";
        aRet[1] = "com.sun.star.ui.dialogs.SystemFilePicker";
        aRet[2] = "com.sun.star.ui.dialogs.SystemFolderPicker";
        return aRet;
    }
}

VistaFilePicker::VistaFilePicker(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
VistaFilePicker::VistaFilePicker(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR, bool bFolderPicker)
    : TVistaFilePickerBase  (m_aMutex                 )
    , m_xSMGR               (xSMGR                    )
    , m_rDialog             (new VistaFilePickerImpl())
    , m_aAsyncExecute       (m_rDialog                )
    , m_nFilePickerThreadId (0                        )
    , m_bInitialized        (false                    )
    , m_bFolderPicker       (bFolderPicker            )
{
}

@@ -233,9 +236,24 @@

    if ( !bInitialized )
    {
        css::uno::Sequence < css::uno::Any > aInitArguments(1);
        aInitArguments[0] <<= css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
        initialize(aInitArguments);
        if (m_bFolderPicker)
        {
            RequestRef rRequest(new Request());
            rRequest->setRequest (VistaFilePickerImpl::E_CREATE_FOLDER_PICKER);
            if ( ! m_aAsyncExecute.isRunning())
                m_aAsyncExecute.create();
            m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
            {
                osl::MutexGuard aGuard(m_aMutex);
                m_bInitialized = true;
            }
        }
        else
        {
            css::uno::Sequence < css::uno::Any > aInitArguments(1);
            aInitArguments[0] <<= css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
            initialize(aInitArguments);
        }
    }
}

@@ -507,11 +525,27 @@
{
}

OUString SAL_CALL VistaFilePicker::getDirectory()
{
    ensureInit();
    css::uno::Sequence< OUString > aFileSeq = getSelectedFiles();
    assert(aFileSeq.getLength() <= 1);
    return aFileSeq.getLength() ? aFileSeq[0] : OUString();
}

void SAL_CALL VistaFilePicker::setDescription( const OUString& aDescription )
{
    setTitle(aDescription);
}

// XServiceInfo

OUString SAL_CALL VistaFilePicker::getImplementationName()
{
    return OUString("com.sun.star.comp.fpicker.VistaFileDialog");
    if (m_bFolderPicker)
        return OUString(FOLDER_PICKER_IMPL_NAME);
    else
        return OUString(FILE_PICKER_IMPL_NAME);
}

sal_Bool SAL_CALL VistaFilePicker::supportsService(const OUString& sServiceName)
diff --git a/fpicker/source/win32/filepicker/VistaFilePicker.hxx b/fpicker/source/win32/filepicker/VistaFilePicker.hxx
index 8f36f54..8a138cc 100644
--- a/fpicker/source/win32/filepicker/VistaFilePicker.hxx
+++ b/fpicker/source/win32/filepicker/VistaFilePicker.hxx
@@ -30,6 +30,7 @@
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>

#include <cppuhelper/compbase.hxx>
#include <cppuhelper/basemutex.hxx>
@@ -47,6 +48,7 @@
                css::ui::dialogs::XFilePicker3,
                css::ui::dialogs::XFilePickerControlAccess,
                css::ui::dialogs::XFilePreview,
                css::ui::dialogs::XFolderPicker2,
                css::lang::XInitialization,
                css::lang::XServiceInfo >   TVistaFilePickerBase;

@@ -67,7 +69,7 @@
    // ctor/dtor


    explicit VistaFilePicker( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR );
    explicit VistaFilePicker( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR, bool bFolderPicker );
    virtual ~VistaFilePicker() override;


@@ -187,22 +189,14 @@

    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;

    /*

    // FilePicker Event functions
    // XFolderPicker functions


    void SAL_CALL fileSelectionChanged(const css::ui::dialogs::FilePickerEvent& aEvent );
    void SAL_CALL directoryChanged(const css::ui::dialogs::FilePickerEvent& aEvent );
    OUString SAL_CALL helpRequested(const css::ui::dialogs::FilePickerEvent& aEvent ) const;
    void SAL_CALL controlStateChanged(const css::ui::dialogs::FilePickerEvent& aEvent );
    void SAL_CALL dialogSizeChanged( );
    virtual OUString SAL_CALL getDirectory( ) override;

    bool startupEventNotification(bool bStartupSuspended);
    void shutdownEventNotification();
    void suspendEventNotification();
    void resumeEventNotification();
    */
    virtual void SAL_CALL setDescription( const OUString& aDescription ) override;


    private:

@@ -234,6 +228,7 @@
        oslThreadIdentifier m_nFilePickerThreadId;

        bool m_bInitialized;
        const bool m_bFolderPicker;
};

} // namespace vista
diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
index dfc99a3..598f42a 100644
--- a/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
+++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.cxx
@@ -36,6 +36,7 @@
#include "../misc/WinImplHelper.hxx"

#include <shlguid.h>
#include <shlobj.h>

 inline bool is_current_process_window(HWND hwnd)
{
@@ -94,28 +95,55 @@

OUString lcl_getURLFromShellItem (IShellItem* pItem)
{
    LPOLESTR pStr = nullptr;
    LPWSTR pStr = nullptr;
    OUString sURL;
    HRESULT hr;

    SIGDN   eConversion = SIGDN_FILESYSPATH;
    HRESULT hr          = pItem->GetDisplayName ( eConversion, &pStr );

    if ( FAILED(hr) )
    {
        eConversion = SIGDN_URL;
        hr          = pItem->GetDisplayName ( eConversion, &pStr );

        if ( FAILED(hr) )
            return OUString();

        sURL = o3tl::toU(pStr);
    }
    else
    hr = pItem->GetDisplayName ( SIGDN_FILESYSPATH, &pStr );
    if (SUCCEEDED(hr))
    {
        ::osl::FileBase::getFileURLFromSystemPath( o3tl::toU(pStr), sURL );
        goto cleanup;
    }

    hr = pItem->GetDisplayName ( SIGDN_URL, &pStr );
    if (SUCCEEDED(hr))
    {
        sURL = o3tl::toU(pStr);
        goto cleanup;
    }

    hr = pItem->GetDisplayName ( SIGDN_PARENTRELATIVEPARSING, &pStr );
    if (SUCCEEDED(hr))
    {
        GUID known_folder_id;
        std::wstring aStr = pStr;
        CoTaskMemFree (pStr);

        if (0 == aStr.compare(0, 3, L"::{"))
            aStr = aStr.substr(2);
        hr = IIDFromString(aStr.c_str(), &known_folder_id);
        if (SUCCEEDED(hr))
        {
            hr = SHGetKnownFolderPath(known_folder_id, 0, NULL, &pStr);
            if (SUCCEEDED(hr))
            {
                ::osl::FileBase::getFileURLFromSystemPath(o3tl::toU(pStr), sURL);
                goto cleanup;
            }
        }
    }

    // Default fallback
    hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &pStr);
    if (SUCCEEDED(hr))
        ::osl::FileBase::getFileURLFromSystemPath(o3tl::toU(pStr), sURL);
    else // shouldn't happen...
        goto bailout;

cleanup:
    CoTaskMemFree (pStr);
bailout:
    return sURL;
}

@@ -143,6 +171,7 @@
VistaFilePickerImpl::VistaFilePickerImpl()
    : m_iDialogOpen  ()
    , m_iDialogSave  ()
    , m_iFolderPicker()
    , m_hLastResult  ()
    , m_lFilters     ()
    , m_iEventHandler(new VistaFilePickerEventHandler(this))
@@ -219,6 +248,10 @@
                    impl_sta_CreateSaveDialog(rRequest);
                    break;

            case E_CREATE_FOLDER_PICKER:
                    impl_sta_CreateFolderPicker(rRequest);
                    break;

            case E_SET_MULTISELECTION_MODE :
                    impl_sta_SetMultiSelectionMode(rRequest);
                    break;
@@ -399,17 +432,36 @@
}


void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest)
void VistaFilePickerImpl::impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags)
{
    // SYNCHRONIZED->
    ::osl::ResettableMutexGuard aLock(m_aMutex);

    m_hLastResult = m_iDialogOpen.create();
    if (FAILED(m_hLastResult))
        return;

    TFileDialog iDialog;
    m_iDialogOpen.query(&iDialog);

    switch (eType)
    {
    case PickerDialog::FileOpen:
        m_hLastResult = m_iDialogOpen.create();
        if (FAILED(m_hLastResult))
            return;
        m_iDialogOpen.query(&iDialog);
        break;

    case PickerDialog::FileSave:
        m_hLastResult = m_iDialogSave.create();
        if (FAILED(m_hLastResult))
            return;
        m_iDialogSave.query(&iDialog);
        break;

    case PickerDialog::Folder:
        m_hLastResult = m_iFolderPicker.create();
        if (FAILED(m_hLastResult))
            return;
        m_iFolderPicker.query(&iDialog);
        break;
    }

    TFileDialogEvents iHandler = m_iEventHandler;

@@ -421,51 +473,11 @@

    nFlags &= ~FOS_FORCESHOWHIDDEN;
    nFlags |=  FOS_PATHMUSTEXIST;
    nFlags |=  FOS_FILEMUSTEXIST;
    nFlags |=  FOS_OVERWRITEPROMPT;
    nFlags |=  FOS_DONTADDTORECENT;
    nFlags |= nOrFlags;

    iDialog->SetOptions ( nFlags );

    ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, ::sal_Int32(0));
    ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
    impl_sta_enableFeatures(nFeatures, nTemplate);

    VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
    if (pHandlerImpl)
        pHandlerImpl->startListening(iDialog);
}


void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest)
{
    // SYNCHRONIZED->
    ::osl::ResettableMutexGuard aLock(m_aMutex);

    m_hLastResult = m_iDialogSave.create();
    if (FAILED(m_hLastResult))
        return;

    TFileDialogEvents  iHandler = m_iEventHandler;
    TFileDialog        iDialog;
    m_iDialogSave.query(&iDialog);

    aLock.clear();
    // <- SYNCHRONIZED

    DWORD nFlags = 0;
    iDialog->GetOptions ( &nFlags );

    nFlags &= ~FOS_FORCESHOWHIDDEN;
    nFlags |=  FOS_PATHMUSTEXIST;
    nFlags |=  FOS_FILEMUSTEXIST;
    nFlags |=  FOS_OVERWRITEPROMPT;
    nFlags |=  FOS_DONTADDTORECENT;

    iDialog->SetOptions ( nFlags );

    ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, ::sal_Int32(0));
    ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
    css::uno::Reference<css::awt::XWindow> xWindow = rRequest->getArgumentOrDefault(PROP_PARENT_WINDOW, css::uno::Reference<css::awt::XWindow>());
    if(xWindow.is())
    {
@@ -481,6 +493,8 @@
        }
    }

    ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, ::sal_Int32(0));
    ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
    impl_sta_enableFeatures(nFeatures, nTemplate);

    VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
@@ -489,6 +503,35 @@
}


void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest)
{
    DWORD nFlags = 0;
    nFlags |=  FOS_FILEMUSTEXIST;
    nFlags |=  FOS_OVERWRITEPROMPT;

    impl_sta_CreateDialog(rRequest, PickerDialog::FileOpen, nFlags);
}


void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest)
{
    DWORD nFlags = 0;
    nFlags |=  FOS_FILEMUSTEXIST;
    nFlags |=  FOS_OVERWRITEPROMPT;

    impl_sta_CreateDialog(rRequest, PickerDialog::FileSave, nFlags);
}


void VistaFilePickerImpl::impl_sta_CreateFolderPicker(const RequestRef& rRequest)
{
    DWORD nFlags = 0;
    nFlags |=  FOS_PICKFOLDERS;

    impl_sta_CreateDialog(rRequest, PickerDialog::Folder, nFlags);
}


static const ::sal_Int32 GROUP_VERSION         =   1;
static const ::sal_Int32 GROUP_TEMPLATE        =   2;
static const ::sal_Int32 GROUP_IMAGETEMPLATE   =   3;
@@ -822,6 +865,7 @@

    TFileOpenDialog iOpen      = m_iDialogOpen;
    TFileSaveDialog iSave      = m_iDialogSave;
    TFolderPickerDialog iPick  = m_iFolderPicker;
    bool bInExecute = m_bInExecute;

    aLock.clear();
@@ -852,6 +896,15 @@
        else
            hResult = iSave->GetResult(&iItem);
    }
    else if (iPick.is())
    {
        if (bInExecute)
            hResult = iPick->GetCurrentSelection(&iItem);
        else
        {
            hResult = iPick->GetResult(&iItem);
        }
    }

    if (FAILED(hResult))
        return;
@@ -898,6 +951,7 @@
    TFileDialog iDialog = impl_getBaseDialogInterface();
    TFileOpenDialog iOpen = m_iDialogOpen;
    TFileSaveDialog iSave = m_iDialogSave;
    TFolderPickerDialog iPick = m_iFolderPicker;

    // it's important to know if we are showing the dialog.
    // Some dialog interface methods can't be called then or some
@@ -977,6 +1031,9 @@
        else
        if (iSave.is())
            hResult = iSave->Show( m_hParentWindow ); // parent window needed
        else
        if (iPick.is())
            hResult = iPick->Show( m_hParentWindow ); // parent window needed
    }
    catch(...)
    {}
@@ -1006,6 +1063,8 @@
        m_iDialogOpen.query(&iDialog);
    if (m_iDialogSave.is())
        m_iDialogSave.query(&iDialog);
    if (m_iFolderPicker.is())
        m_iFolderPicker.query(&iDialog);

    return iDialog;
}
@@ -1022,6 +1081,8 @@
        m_iDialogOpen.query(&iCustom);
    else if (m_iDialogSave.is())
        m_iDialogSave.query(&iCustom);
    else if (m_iFolderPicker.is())
        m_iFolderPicker.query(&iCustom);

    return iCustom;
}
diff --git a/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
index 8f9314e..cb7468c 100644
--- a/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
+++ b/fpicker/source/win32/filepicker/VistaFilePickerImpl.hxx
@@ -109,6 +109,7 @@
            E_GET_CURRENT_FILTER,
            E_CREATE_OPEN_DIALOG,
            E_CREATE_SAVE_DIALOG,
            E_CREATE_FOLDER_PICKER,
            E_SET_MULTISELECTION_MODE,
            E_SET_TITLE,
            E_SET_FILENAME,
@@ -182,6 +183,10 @@
        void impl_sta_CreateSaveDialog(const RequestRef& rRequest);


        /// implementation of request E_CREATE_FOLDER_PICKER
        void impl_sta_CreateFolderPicker(const RequestRef& rRequest);


        /// implementation of request E_SET_MULTISELECTION_MODE
        void impl_sta_SetMultiSelectionMode(const RequestRef& rRequest);

@@ -272,6 +277,14 @@
        void impl_SetDefaultExtension( const OUString& currentFilter );

   private:
        enum class PickerDialog
        {
            FileOpen,
            FileSave,
            Folder,
        };

        void impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags);


        /// COM object representing a file open dialog
@@ -282,6 +295,10 @@
        TFileSaveDialog m_iDialogSave;


        /// COM object representing a folder picker dialog
        TFolderPickerDialog m_iFolderPicker;


        /// knows the return state of the last COM call
        HRESULT m_hLastResult;

diff --git a/fpicker/source/win32/filepicker/vistatypes.h b/fpicker/source/win32/filepicker/vistatypes.h
index 727416e9..4271b0c 100644
--- a/fpicker/source/win32/filepicker/vistatypes.h
+++ b/fpicker/source/win32/filepicker/vistatypes.h
@@ -36,6 +36,7 @@
typedef ComPtr< IFileSaveDialog     , IID_IFileSaveDialog  , CLSID_FileSaveDialog > TFileSaveDialog;
typedef ComPtr< IFileDialogEvents   , IID_IFileDialogEvents                       > TFileDialogEvents;
typedef ComPtr< IFileDialogCustomize, IID_IFileDialogCustomize                    > TFileDialogCustomize;
typedef TFileOpenDialog TFolderPickerDialog;

} // namespace vista
} // namespace win32
diff --git a/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx b/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx
deleted file mode 100644
index d08586e..0000000
--- a/fpicker/source/win32/folderpicker/FOPServiceInfo.hxx
+++ /dev/null
@@ -1,35 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOPSERVICEINFO_HXX
#define INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOPSERVICEINFO_HXX

// the service name is a description of a set of
// interfaces (is the same as component categories in COM)

// the service names
#define FOLDER_PICKER_SERVICE_NAME  "com.sun.star.ui.dialogs.SystemFolderPicker"

// the implementation names
#define FOLDER_PICKER_IMPL_NAME  "com.sun.star.ui.dialogs.Win32FolderPicker"

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/FolderPicker.cxx b/fpicker/source/win32/folderpicker/FolderPicker.cxx
deleted file mode 100644
index 870ec7a..0000000
--- a/fpicker/source/win32/folderpicker/FolderPicker.cxx
+++ /dev/null
@@ -1,134 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <memory>
#include <osl/diagnose.h>

#include "FolderPicker.hxx"
#include <cppuhelper/supportsservice.hxx>
#include "WinFOPImpl.hxx"

using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
using com::sun::star::lang::XMultiServiceFactory;
using com::sun::star::lang::XServiceInfo;
using com::sun::star::lang::IllegalArgumentException;
using osl::MutexGuard;

using namespace cppu;
using namespace com::sun::star::ui::dialogs;

#define FOLDERPICKER_IMPL_NAME  "com.sun.star.ui.dialogs.Win32FolderPicker"

namespace
{
    Sequence< OUString > FolderPicker_getSupportedServiceNames()
    {
        Sequence< OUString > aRet { "com.sun.star.ui.dialogs.SystemFolderPicker" };
        return aRet;
    }
}

CFolderPicker::CFolderPicker( const Reference< XMultiServiceFactory >& xServiceMgr ) :
    m_xServiceMgr( xServiceMgr )
{
    m_pFolderPickerImpl = std::unique_ptr< CWinFolderPickerImpl > ( new CWinFolderPickerImpl( this ) );
}

void SAL_CALL CFolderPicker::setTitle( const OUString& aTitle )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    m_pFolderPickerImpl->setTitle( aTitle );
}

void SAL_CALL CFolderPicker::setDisplayDirectory( const OUString& aDirectory )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    m_pFolderPickerImpl->setDisplayDirectory( aDirectory );
}

OUString SAL_CALL CFolderPicker::getDisplayDirectory( )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    return m_pFolderPickerImpl->getDisplayDirectory( );
}

OUString SAL_CALL CFolderPicker::getDirectory( )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    return m_pFolderPickerImpl->getDirectory( );
}

void SAL_CALL CFolderPicker::setDescription( const OUString& aDescription )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    m_pFolderPickerImpl->setDescription( aDescription );
}

sal_Int16 SAL_CALL CFolderPicker::execute( )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );

    // we should not block in this call else
    // in the case of an event the client can'tgetPImplFromHandle( hWnd )
    // call another function and we run into a
    // deadlock !!!!!
    return m_pFolderPickerImpl->execute( );
}

// XServiceInfo

OUString SAL_CALL CFolderPicker::getImplementationName(  )
{
    return OUString( FOLDERPICKER_IMPL_NAME );
}

sal_Bool SAL_CALL CFolderPicker::supportsService( const OUString& ServiceName )
{
    return cppu::supportsService(this, ServiceName);
}

Sequence< OUString > SAL_CALL CFolderPicker::getSupportedServiceNames(   )
{
    return FolderPicker_getSupportedServiceNames();
}

//  XCancellable

void SAL_CALL CFolderPicker::cancel( )
{
    OSL_ASSERT( m_pFolderPickerImpl.get( ) );
    MutexGuard aGuard( m_aMutex );
    m_pFolderPickerImpl->cancel( );
}

// overwrite base class method, which is called
// by base class dispose function

void CFolderPicker::disposing()
{
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/FolderPicker.hxx b/fpicker/source/win32/folderpicker/FolderPicker.hxx
deleted file mode 100644
index 346a6bf..0000000
--- a/fpicker/source/win32/folderpicker/FolderPicker.hxx
+++ /dev/null
@@ -1,104 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOLDERPICKER_HXX
#define INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOLDERPICKER_HXX

#include <cppuhelper/implbase.hxx>
#include <osl/mutex.hxx>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>

#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>

#include <memory>

#include "WinFOPImpl.hxx"


// class declaration


class CFolderPicker :
    public  cppu::WeakImplHelper<
                css::ui::dialogs::XFolderPicker2,
                css::lang::XServiceInfo >
{
public:

    // ctor/dtor
    explicit CFolderPicker( const css::uno::Reference< css::lang::XMultiServiceFactory >& xServiceMgr );


    // XExecutableDialog


    virtual void SAL_CALL setTitle( const OUString& aTitle ) override;

    virtual sal_Int16 SAL_CALL execute(  ) override;


    // XFolderPicker functions


    virtual void SAL_CALL setDisplayDirectory( const OUString& aDirectory ) override;

    virtual OUString SAL_CALL getDisplayDirectory(  ) override;

    virtual OUString SAL_CALL getDirectory( ) override;

    virtual void SAL_CALL setDescription( const OUString& aDescription ) override;


    // XServiceInfo


    virtual OUString SAL_CALL getImplementationName(  ) override;

    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;

    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) override;


    // XCancellable


    virtual void SAL_CALL cancel( ) override;


    // overwrite base class method, which is called
    // by base class dispose function


    virtual void disposing();

private:
    css::uno::Reference< css::lang::XMultiServiceFactory >  m_xServiceMgr;
    std::unique_ptr< CWinFolderPickerImpl >                 m_pFolderPickerImpl;
    osl::Mutex                                              m_aMutex;

// prevent copy and assignment
private:
    CFolderPicker( const CFolderPicker& );
    CFolderPicker& operator=( const CFolderPicker&  );
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/FopEvtDisp.hxx b/fpicker/source/win32/folderpicker/FopEvtDisp.hxx
deleted file mode 100644
index d070e82..0000000
--- a/fpicker/source/win32/folderpicker/FopEvtDisp.hxx
+++ /dev/null
@@ -1,39 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOPEVTDISP_HXX
#define INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_FOPEVTDISP_HXX

#include <com/sun/star/lang/EventObject.hpp>

class CFOPEventDispatcher
{
public:

    // dispatches a FilePickerEvent to wherever
    virtual void helpRequested( css::lang::EventObject aEvent ) const = 0;

protected:
    ~CFOPEventDispatcher() {}
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/MtaFop.cxx b/fpicker/source/win32/folderpicker/MtaFop.cxx
deleted file mode 100644
index ba951039..0000000
--- a/fpicker/source/win32/folderpicker/MtaFop.cxx
+++ /dev/null
@@ -1,721 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <osl/diagnose.h>
#include <osl/thread.h>
#include <o3tl/char16_t2wchar_t.hxx>
#include <vcl/svapp.hxx>

#include "MtaFop.hxx"
#include <wchar.h>
#include <process.h>
#include "../misc/resourceprovider.hxx"

#include <systools/win32/comtools.hxx>


const sal_uInt32 MSG_BROWSEFORFOLDER = WM_USER + 1;
const sal_uInt32 MSG_SHUTDOWN        = WM_USER + 2;

const sal_uInt32 MAX_WAITTIME        = 2000; // msec

const bool MANUAL_RESET     = true;
const bool AUTO_RESET       = false;
const bool INIT_NONSIGNALED = false;

#define FOLDERPICKER_TITLE            500
#define FOLDER_PICKER_DEF_DESCRIPTION 501

namespace
{
    const wchar_t* const FOLDERPICKER_SRV_DLL_NAME = L"fps.dll";
    const wchar_t g_szWndClsName[]                 = L"FopStaReqWnd###";
    const wchar_t* const CURRENT_INSTANCE          = L"CurrInst";

    struct RequestContext
    {
        HANDLE   hEvent;
        bool bRet;
    };

    inline bool InitializeRequestContext( RequestContext* aRequestContext )
    {
        OSL_ASSERT( aRequestContext );

        aRequestContext->hEvent = CreateEventW(
            nullptr, AUTO_RESET, INIT_NONSIGNALED, nullptr );

        aRequestContext->bRet = false;

        return ( nullptr != aRequestContext->hEvent );
    }

    inline void DeinitializeRequestContext( RequestContext* aRequestContext )
    {
        OSL_ASSERT( aRequestContext && aRequestContext->hEvent );
        CloseHandle( aRequestContext->hEvent );
    }
}


//  static member initialization


ATOM CMtaFolderPicker::s_ClassAtom = 0;
osl::Mutex CMtaFolderPicker::s_Mutex;
sal_Int32 CMtaFolderPicker::s_StaRequestWndRegisterCount = 0;


// ctor


CMtaFolderPicker::CMtaFolderPicker( sal_uInt32 Flags ) :
    m_hStaThread( nullptr ),
    m_uStaThreadId( 0 ),
    m_hEvtThrdReady( nullptr ),
    m_hwndStaRequestWnd( nullptr )
{
    m_hInstance = GetModuleHandleW( FOLDERPICKER_SRV_DLL_NAME );
    OSL_ENSURE( m_hInstance, "The name of the FolderPicker service dll must have changed" );

    ZeroMemory( &m_bi, sizeof( m_bi ) );

    // !!!!!!!!!!!!!!!!!  IMPORTANT !!!!!!!!!!!!!!!!!!!

    // Remember: This HACK prevents you from stepping
    // through your code in the debugger because if you
    // set a break point in the ctor here the debugger
    // may become the owner of the FolderBrowse dialog
    // and so it seems that the Visual Studio and the
    // office are hanging
    m_bi.hwndOwner = GetForegroundWindow( );

    /*
        Flag                Available
        --------------------------------
        BIF_EDITBOX         Version 4.71
        BIF_NEWDIALOGSTYLE  Version 5.0
        BIF_SHAREABLE       Version 5.0
        BIF_VALIDATE        Version 4.71

        Version 4.71 - Internet Explorer 4.0
        Version 5.0  - Internet Explorer 5.0
                       Windows 2000
    */
    m_bi.ulFlags = Flags;

    m_bi.lpfn    = CMtaFolderPicker::FolderPickerCallback;
    m_bi.lParam  = reinterpret_cast< LPARAM >( this );

    m_dialogTitle = CResourceProvider::getResString(FOLDERPICKER_TITLE);
    m_Description = CResourceProvider::getResString(FOLDER_PICKER_DEF_DESCRIPTION);

    // signals that the thread was successfully set up
    m_hEvtThrdReady  = CreateEventW(
        nullptr,
        MANUAL_RESET,
        INIT_NONSIGNALED,
        nullptr );

    if ( m_hEvtThrdReady )
    {
        // setup the sta thread
        m_hStaThread = reinterpret_cast<HANDLE>(_beginthreadex(
            nullptr,
            0,
            CMtaFolderPicker::StaThreadProc,
            this,
            0,
            &m_uStaThreadId ));

        OSL_ASSERT( m_hStaThread );
    }

    OSL_ASSERT( m_hEvtThrdReady );
}


// dtor


CMtaFolderPicker::~CMtaFolderPicker( )
{
    // only if the is a valid event handle
    // there may also be a thread a hidden
    // target request window and so on
    // see ctor
    if ( m_hEvtThrdReady )
    {
        // block calling threads because we
        // are about to shutdown
        ResetEvent( m_hEvtThrdReady );

        // force the destruction of the sta thread request window
        // and the end of the thread
        // remember: DestroyWindow may only be called from within
        // the thread that created the window
        if ( IsWindow( m_hwndStaRequestWnd ) )
        {
            SendMessageW( m_hwndStaRequestWnd, MSG_SHUTDOWN, 0, 0 );

            // we place unregister class here because
            // if we have a valid window we must have
            // successfully registered a window class
            // if the creation of the window itself
            // failed after registering the window
            // class we have unregistered it immediately
            // in createStaRequestWindow below
            UnregisterStaRequestWindowClass( );
        }

        if ( m_hStaThread )
        {
            // wait for thread shutdown
            sal_uInt32 dwResult = WaitForSingleObject( m_hStaThread, MAX_WAITTIME );
            OSL_ENSURE( dwResult == WAIT_OBJECT_0, "sta thread could not terminate" );

            // terminate the thread if it
            // doesn't shutdown itself
            if ( WAIT_OBJECT_0 != dwResult )
                TerminateThread(
                    m_hStaThread, sal::static_int_cast< DWORD >(-1) );

            CloseHandle( m_hStaThread );
        }

        CloseHandle( m_hEvtThrdReady );
    }
}


bool CMtaFolderPicker::browseForFolder( )
{
    bool bRet = false;

    OSL_ASSERT( m_hEvtThrdReady );

    if ( WaitForSingleObject( m_hEvtThrdReady, MAX_WAITTIME ) != WAIT_OBJECT_0 )
    {
        OSL_FAIL( "sta thread not ready" );
        return false;
    }

    RequestContext aReqCtx;

    if ( !InitializeRequestContext( &aReqCtx ) )
    {
        OSL_ASSERT( false );
        return false;
    }

    // marshall request into the sta thread
    BOOL const ret = PostMessageW(
        m_hwndStaRequestWnd,
        MSG_BROWSEFORFOLDER,
        0,
        reinterpret_cast< LPARAM >( &aReqCtx ) );
    SAL_WARN_IF(0 == ret, "fpicker", "ERROR: PostMessage() failed!");

    // waiting for the event to be signaled or
    // window messages so that we don't block
    // our parent window

    bool bContinue = true;

    while ( bContinue )
    {
        DWORD dwResult = MsgWaitForMultipleObjects(
            1, &aReqCtx.hEvent, false, INFINITE, QS_ALLEVENTS );

        switch ( dwResult )
        {
        // the request context event is signaled
        case WAIT_OBJECT_0:
            bContinue = false;
            break;

        // a window message has arrived
        case WAIT_OBJECT_0 + 1:
            Application::Reschedule( true );
            break;

        // should not happen
        default:
            OSL_ASSERT( false );
        }
    }

    /*sal_Bool*/ bRet = aReqCtx.bRet;
    DeinitializeRequestContext( &aReqCtx );

    return bRet;
}


void CMtaFolderPicker::setDisplayDirectory( const OUString& aDirectory )
{
    m_displayDir = aDirectory;
}


OUString CMtaFolderPicker::getDisplayDirectory( )
{
    return m_displayDir;
}


OUString CMtaFolderPicker::getDirectory( )
{
    return m_SelectedDir;
}


void CMtaFolderPicker::setDescription( const OUString& aDescription )
{
    m_Description = aDescription;
}


void CMtaFolderPicker::setTitle( const OUString& aTitle )
{
    m_dialogTitle = aTitle;
}


OUString CMtaFolderPicker::getTitle( )
{
    return m_dialogTitle;
}


// XCancellable


void CMtaFolderPicker::cancel( )
{
    if ( IsWindow( m_hwnd ) )
    {
        // simulate a mouse click to the
        // cancel button
        BOOL const ret = PostMessageW(
            m_hwnd,
            WM_COMMAND,
            MAKEWPARAM( IDCANCEL, BN_CLICKED ),
            reinterpret_cast<LPARAM>(GetDlgItem( m_hwnd, IDCANCEL )) );
        SAL_WARN_IF(0 == ret, "fpicker", "ERROR: PostMessage() failed!");
    }
}


bool CMtaFolderPicker::onBrowseForFolder( )
{
    bool bRet;
    LPITEMIDLIST lpiid;

    // pre SHBrowseFroFolder

    m_bi.pidlRoot       = nullptr;
    m_bi.pszDisplayName = o3tl::toW(m_pathBuff);

    if ( m_Description.getLength( ) )
        m_bi.lpszTitle = o3tl::toW(m_Description.getStr( ));

    lpiid = SHBrowseForFolderW( &m_bi );
    bRet = ( nullptr != lpiid );

    // post SHBrowseForFolder

    m_SelectedDir = getPathFromItemIdList( lpiid );
    releaseItemIdList( lpiid );

    return bRet;
}


void CMtaFolderPicker::releaseItemIdList( LPITEMIDLIST lpItemIdList )
{
    sal::systools::COMReference<IMalloc> pIMalloc;
    SHGetMalloc(&pIMalloc);
    if (pIMalloc.is())
    {
        pIMalloc->Free(lpItemIdList);
        lpItemIdList = nullptr;
    }
}


LPITEMIDLIST CMtaFolderPicker::getItemIdListFromPath( const OUString& aDirectory )
{
    // parameter checking
    if ( !aDirectory.getLength( ) )
        return nullptr;

    LPITEMIDLIST lpItemIdList(nullptr);

    sal::systools::COMReference<IShellFolder> pIShellFolder;
    SHGetDesktopFolder(&pIShellFolder);

    if (pIShellFolder.is())
    {
        pIShellFolder->ParseDisplayName(
            nullptr,
            nullptr,
            const_cast<LPWSTR>(o3tl::toW( aDirectory.getStr( ) )),
            nullptr,
            &lpItemIdList,
            nullptr );
    }

    return lpItemIdList;
}


OUString CMtaFolderPicker::getPathFromItemIdList( LPCITEMIDLIST lpItemIdList )
{
    OUString path;

    if ( lpItemIdList )
    {
        bool bRet = SHGetPathFromIDListW( lpItemIdList, o3tl::toW(m_pathBuff) );
        if ( bRet )
            path = m_pathBuff;
    }

    return path;
}


void CMtaFolderPicker::enableOk( bool bEnable )
{
    OSL_ASSERT( IsWindow( m_hwnd ) );

    SendMessageW(
        m_hwnd,
        BFFM_ENABLEOK,
        static_cast< WPARAM >( 0 ),
        static_cast< LPARAM >( bEnable ) );
}


void CMtaFolderPicker::setSelection( const OUString& aDirectory )
{
    OSL_ASSERT( IsWindow( m_hwnd ) );

    SendMessageW(
        m_hwnd,
        BFFM_SETSELECTIONW,
        static_cast< WPARAM >( true ),
        reinterpret_cast< LPARAM >( aDirectory.getStr( ) ) );
}


void CMtaFolderPicker::setStatusText( const OUString& aStatusText )
{
    OSL_ASSERT( IsWindow( m_hwnd ) );

    SendMessageW(
        m_hwnd,
        BFFM_SETSTATUSTEXTW,
        static_cast< WPARAM >( 0 ),
        reinterpret_cast< LPARAM >( aStatusText.getStr( ) ) );
}


void CMtaFolderPicker::onInitialized( )
{
    LPITEMIDLIST lpiidDisplayDir = getItemIdListFromPath( m_displayDir );

    if ( lpiidDisplayDir )
    {
        SendMessageW(
            m_hwnd,
            BFFM_SETSELECTION,
            WPARAM(false),
            reinterpret_cast<LPARAM>(lpiidDisplayDir) );

        releaseItemIdList( lpiidDisplayDir );
    }
}


sal_uInt32 CMtaFolderPicker::onValidateFailed()
{
    // to be overwritten by subclasses
    return 1;
}


int CALLBACK CMtaFolderPicker::FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
{
    CMtaFolderPicker* pImpl = reinterpret_cast< CMtaFolderPicker* >( lpData );
    OSL_ASSERT( pImpl );

    int nRC = 0;

    switch( uMsg )
    {
        case BFFM_INITIALIZED:
            pImpl->m_hwnd = hwnd;
            pImpl->onInitialized( );
            SetWindowTextW( hwnd, o3tl::toW(pImpl->m_dialogTitle.getStr()) );
        break;

        case BFFM_SELCHANGED:
            pImpl->m_hwnd = hwnd;
            pImpl->onSelChanged(
                pImpl->getPathFromItemIdList(
                    reinterpret_cast< LPITEMIDLIST >( lParam ) ) );
        break;

        case BFFM_VALIDATEFAILEDW:
            nRC = CMtaFolderPicker::onValidateFailed();
            break;

        default:
            OSL_ASSERT( false );
    }

    return nRC;
}


// the window proc


LRESULT CALLBACK CMtaFolderPicker::StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    LRESULT           lResult = 0;
    CMtaFolderPicker* pImpl   = nullptr;

    /*
        we connect to the belonging class instance of this
        window using SetProp, GetProp etc.
        this may fail if somehow the class instance destroyed
        before the window
    */

    switch( uMsg )
    {
        case WM_CREATE:
            {
                LPCREATESTRUCTW lpcs =
                    reinterpret_cast< LPCREATESTRUCTW >( lParam );

                OSL_ASSERT( lpcs->lpCreateParams );

                // connect the instance handle to the window
                SetPropW( hWnd, CURRENT_INSTANCE, lpcs->lpCreateParams );
            }
            break;

        case WM_NCDESTROY:
                // RemoveProp returns the saved value on success
                pImpl = static_cast< CMtaFolderPicker* >(
                    RemovePropW( hWnd, CURRENT_INSTANCE ) );

                OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );
            break;

        case MSG_BROWSEFORFOLDER:
            {
                RequestContext* aReqCtx = reinterpret_cast< RequestContext* >( lParam );
                OSL_ASSERT( aReqCtx );

                pImpl = static_cast< CMtaFolderPicker* >(
                    GetPropW( hWnd, CURRENT_INSTANCE ) );

                OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );

                aReqCtx->bRet = pImpl->onBrowseForFolder( );
                SetEvent( aReqCtx->hEvent );
            }
            break;

        case MSG_SHUTDOWN:
            pImpl = static_cast< CMtaFolderPicker* >(
                GetPropW( hWnd, CURRENT_INSTANCE ) );

            OSL_ASSERT( pImpl && !IsBadReadPtr( pImpl, sizeof( CMtaFolderPicker ) ) );

            DestroyWindow( pImpl->m_hwndStaRequestWnd );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

        default:
            lResult = DefWindowProcW( hWnd, uMsg, wParam, lParam );
            break;
    }

    return lResult;
}


bool CMtaFolderPicker::createStaRequestWindow( )
{
    bool bIsWnd = false;

    if ( RegisterStaRequestWindowClass( ) )
    {
        m_hwndStaRequestWnd = CreateWindowW(
            g_szWndClsName, nullptr,
            0, 0, 0, 0, 0,
            nullptr, nullptr, m_hInstance,
            this // provide the instance of the class
        );

        bIsWnd = IsWindow( m_hwndStaRequestWnd );

        // we do immediately unregister the window class
        // if the creation of the window fails because we
        // don't want to spoil the register class counter
        if ( !bIsWnd )
            UnregisterStaRequestWindowClass( );

        OSL_ENSURE( bIsWnd, "sta request window creation failed" );
    }

    return bIsWnd;
}


unsigned int CMtaFolderPicker::run( )
{
    OSL_ASSERT( m_hEvtThrdReady );

    // setup an sta environment
    HRESULT hr = CoInitialize( nullptr );

    // if we can't setup an sta environment
    // we stop here and return
    if ( FAILED( hr ) )
    {
        OSL_FAIL( "CoInitialize failed" );
        return sal::static_int_cast< unsigned int >(-1);
    }

    unsigned int nRet;

    if ( createStaRequestWindow( ) )
    {
        SetEvent( m_hEvtThrdReady );

        // pumping messages
        MSG msg;
        while( GetMessageW( &msg, nullptr, 0, 0 ) )
            DispatchMessageW( &msg );

        nRet = 0;
    }
    else
    {
        OSL_FAIL( "failed to create sta thread" );
        nRet = sal::static_int_cast< unsigned int >(-1);
    }

    // shutdown sta environment
    CoUninitialize( );

    return nRet;
}


unsigned int WINAPI CMtaFolderPicker::StaThreadProc( LPVOID pParam )
{
    osl_setThreadName("fpicker CMtaFolderPicker::run()");

    CMtaFolderPicker* pInst =
        static_cast<CMtaFolderPicker*>( pParam );

    OSL_ASSERT( pInst );

    HRESULT hr = OleInitialize( nullptr );

    unsigned int    result = pInst->run( );

    if ( SUCCEEDED( hr ) )
        OleUninitialize();

    return result;
}


ATOM CMtaFolderPicker::RegisterStaRequestWindowClass( )
{
    osl::MutexGuard aGuard( s_Mutex );

    if ( 0 == s_ClassAtom )
    {
        WNDCLASSEXW  wcex;

        ZeroMemory( &wcex, sizeof( wcex ) );

        wcex.cbSize         = sizeof(wcex);
        wcex.style          = 0;
        wcex.lpfnWndProc    = CMtaFolderPicker::StaWndProc;
        wcex.cbClsExtra     = 0;
        wcex.cbWndExtra     = 0;
        wcex.hInstance      = m_hInstance;
        wcex.hIcon          = nullptr;
        wcex.hCursor        = nullptr;
        wcex.hbrBackground  = nullptr;
        wcex.lpszMenuName   = nullptr;
        wcex.lpszClassName  = g_szWndClsName;
        wcex.hIconSm        = nullptr;

        s_ClassAtom = RegisterClassExW( &wcex );
        OSL_ASSERT( s_ClassAtom );
    }

    // increment the register class counter
    // so that we keep track of the number
    // of class registrations
    if ( 0 != s_ClassAtom )
        s_StaRequestWndRegisterCount++;

    return s_ClassAtom;
}


void CMtaFolderPicker::UnregisterStaRequestWindowClass( )
{
    osl::MutexGuard aGuard( s_Mutex );

    OSL_ASSERT( 0 != s_ClassAtom );

    // update the register class counter
    // and unregister the window class if
    // counter drops to zero
    if ( 0 != s_ClassAtom )
    {
        s_StaRequestWndRegisterCount--;
        OSL_ASSERT( s_StaRequestWndRegisterCount >= 0 );
    }

    if ( 0 == s_StaRequestWndRegisterCount )
    {
        UnregisterClass( MAKEINTATOM(s_ClassAtom), m_hInstance );

        s_ClassAtom = 0;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/MtaFop.hxx b/fpicker/source/win32/folderpicker/MtaFop.hxx
deleted file mode 100644
index 5d7042e..0000000
--- a/fpicker/source/win32/folderpicker/MtaFop.hxx
+++ /dev/null
@@ -1,137 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_MTAFOP_HXX
#define INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_MTAFOP_HXX

#include <sal/config.h>

#include <sal/log.hxx>
#include <sal/types.h>
#include <rtl/ustring.hxx>
#include <osl/diagnose.h>
#include <osl/mutex.hxx>

#include <utility>
#include <objidl.h>
#include <shlobj.h>
#include "../misc/WinImplHelper.hxx"

// the Mta-Ole clipboard class is for internal use only!
// only one instance of this class should be created, the
// user has to ensure this!
// the class is not thread-safe because it will be used
// only from within the clipboard service and the methods
// of the clipboard service are already synchronized


class CMtaFolderPicker
{
public:
    explicit CMtaFolderPicker( sal_uInt32 Flags );
    virtual ~CMtaFolderPicker( );

    // shell functions
    bool browseForFolder( );

    virtual void setDisplayDirectory( const OUString& aDirectory );
    virtual OUString getDisplayDirectory( );
    virtual OUString getDirectory( );

    virtual void setDescription( const OUString& aDescription );

    virtual void setTitle( const OUString& aTitle );
    OUString getTitle( );


    // XCancellable


    virtual void cancel( );

protected:
    void enableOk( bool bEnable );
    void setSelection( const OUString& aDirectory );
    void setStatusText( const OUString& aStatusText );

    virtual void onInitialized( );
    virtual void onSelChanged( const OUString& aNewPath ) = 0;

private:
    static sal_uInt32 onValidateFailed();

    // helper functions
    static LPITEMIDLIST getItemIdListFromPath( const OUString& aDirectory );
    OUString getPathFromItemIdList( LPCITEMIDLIST lpItemIdList );
    static void releaseItemIdList( LPITEMIDLIST lpItemIdList );

    unsigned int run( );

    // create a hidden windows which serves as an request
    // target; so we guarantee synchronization
    bool createStaRequestWindow( );


    // message handler functions; remember these functions are called
    // from a different thread context!


    bool onBrowseForFolder( );

    static LRESULT CALLBACK StaWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
    static unsigned int WINAPI StaThreadProc( LPVOID pParam );

    static int CALLBACK FolderPickerCallback( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData );

protected:
    HWND m_hwnd;

private:
    ATOM RegisterStaRequestWindowClass( );
    void UnregisterStaRequestWindowClass( );

private:
    HANDLE                      m_hStaThread;
    unsigned                    m_uStaThreadId;
    HANDLE                      m_hEvtThrdReady;
    HWND                        m_hwndStaRequestWnd;
    OUString               m_dialogTitle;
    OUString               m_Description;
    OUString               m_displayDir;
    OUString               m_SelectedDir;
    BROWSEINFOW                 m_bi;
    sal_Unicode                 m_pathBuff[32000]; // max path length under Win2000
    HINSTANCE                   m_hInstance;

    // the request window class has to be registered only
    // once per process, so multiple instance of this class
    // share the registered window class
    static ATOM       s_ClassAtom;
    static osl::Mutex s_Mutex;
    static sal_Int32  s_StaRequestWndRegisterCount;

// prevent copy and assignment
private:
    CMtaFolderPicker( const CMtaFolderPicker& );
    CMtaFolderPicker& operator=( const CMtaFolderPicker& );
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/WinFOPImpl.cxx b/fpicker/source/win32/folderpicker/WinFOPImpl.cxx
deleted file mode 100644
index c649302..0000000
--- a/fpicker/source/win32/folderpicker/WinFOPImpl.cxx
+++ /dev/null
@@ -1,117 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "WinFOPImpl.hxx"

#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include "FopEvtDisp.hxx"
#include <osl/file.hxx>
#include "FolderPicker.hxx"

using com::sun::star::uno::RuntimeException;
using com::sun::star::lang::IllegalArgumentException;

using namespace com::sun::star::ui::dialogs;
using osl::FileBase;

const OUString BACKSLASH( "\\" );

CWinFolderPickerImpl::CWinFolderPickerImpl( CFolderPicker* aFolderPicker ) :
   CMtaFolderPicker( BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS | BIF_EDITBOX | BIF_VALIDATE ),
   m_pFolderPicker( aFolderPicker ),
   m_nLastDlgResult( css::ui::dialogs::ExecutableDialogResults::CANCEL )
{
}

// get directory in URL format, convert it to system format and set the
// member variable
// If the given URL for the directory is invalid the function throws an
// IllegalArgumentException
// If the specified path is well formed but invalid for the underlying
// OS the FolderPicker starts in the root of the file system hierarchy

void CWinFolderPickerImpl::setDisplayDirectory( const OUString& aDirectory )
{
    OUString sysDir;

    if( aDirectory.getLength( ) )
    {
        // assuming that this function succeeds after successful execution
        // of getAbsolutePath
        ::osl::FileBase::RC rc =
            ::osl::FileBase::getSystemPathFromFileURL( aDirectory, sysDir );

        if ( ::osl::FileBase::E_None != rc )
            throw IllegalArgumentException(
                "directory is not a valid file url",
                static_cast< cppu::OWeakObject * >( m_pFolderPicker ),
                1 );

        // we ensure that there is a trailing '/' at the end of
        // he given file url, because the windows functions only
        // works correctly when providing "c:\" or an environment
        // variable like "=c:=c:\.." etc. is set, else the
        // FolderPicker would stand in the root of the shell
        // hierarchy which is the desktop folder
        if ( sysDir.lastIndexOf( BACKSLASH ) != (sysDir.getLength( ) - 1) )
            sysDir += BACKSLASH;
    }

    // call base class method
    CMtaFolderPicker::setDisplayDirectory( sysDir );
}

// we return the directory in URL format

OUString CWinFolderPickerImpl::getDisplayDirectory( )
{
    // call base class method to get the directory in system format
    OUString displayDirectory = CMtaFolderPicker::getDisplayDirectory( );

    OUString displayDirectoryURL;
    if ( displayDirectory.getLength( ) )
        ::osl::FileBase::getFileURLFromSystemPath( displayDirectory, displayDirectoryURL );

    return displayDirectoryURL;
}

OUString CWinFolderPickerImpl::getDirectory( )
{
    OUString sysDir = CMtaFolderPicker::getDirectory( );
    OUString dirURL;

    if ( sysDir.getLength( ) )
        ::osl::FileBase::getFileURLFromSystemPath( sysDir, dirURL );

    return dirURL;
}

sal_Int16 CWinFolderPickerImpl::execute( )
{
    return m_nLastDlgResult = CMtaFolderPicker::browseForFolder( ) ?
        css::ui::dialogs::ExecutableDialogResults::OK :
        css::ui::dialogs::ExecutableDialogResults::CANCEL;
}

void CWinFolderPickerImpl::onSelChanged( const OUString& aNewPath )
{
    setStatusText( aNewPath );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/WinFOPImpl.hxx b/fpicker/source/win32/folderpicker/WinFOPImpl.hxx
deleted file mode 100644
index 98f52da..0000000
--- a/fpicker/source/win32/folderpicker/WinFOPImpl.hxx
+++ /dev/null
@@ -1,64 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_WINFOPIMPL_HXX
#define INCLUDED_FPICKER_SOURCE_WIN32_FOLDERPICKER_WINFOPIMPL_HXX

#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include "MtaFop.hxx"


// forward


class CFolderPicker;

class CWinFolderPickerImpl : public CMtaFolderPicker
{
public:
    explicit CWinFolderPickerImpl( CFolderPicker* aFolderPicker );


    // XExecutableDialog

    /// @throws css::uno::RuntimeException
    virtual sal_Int16 execute(  );


    // XFolderPicker


    virtual void setDisplayDirectory( const OUString& aDirectory ) override;

    virtual OUString getDisplayDirectory( ) override;

    virtual OUString getDirectory( ) override;

protected:
    virtual void onSelChanged( const OUString& aNewPath ) override;

private:
    CFolderPicker*  m_pFolderPicker;
    sal_Int16       m_nLastDlgResult;
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx b/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx
deleted file mode 100644
index 3c6e29d..0000000
--- a/fpicker/source/win32/folderpicker/workbench/Test_fops.cxx
+++ /dev/null
@@ -1,147 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/registry/XSimpleRegistry.hpp>
#include <osl/file.hxx>

#include <cppuhelper/servicefactory.hxx>

#include <rtl/ustring.hxx>
#include <sal/types.h>
#include <osl/diagnose.h>

#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>

#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>

#include <stdio.h>

#include "..\FOPServiceInfo.hxx"

#define _WIN32_DCOM

#if !defined WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>


//  namespaces


using namespace ::cppu                  ;
using namespace ::com::sun::star::uno   ;
using namespace ::com::sun::star::lang  ;
using namespace ::com::sun::star::ui::dialogs;
using namespace std                     ;

#define RDB_SYSPATH "D:\\Projects\\gsl\\sysui\\wntmsci7\\bin\\applicat.rdb"


//  global variables


Reference< XMultiServiceFactory >   g_xFactory;


//  main


int SAL_CALL main(int /*nArgc*/, char* /*Argv[]*/, char* /*Env[]*/  )
{
    CoInitializeEx( NULL, COINIT_MULTITHREADED );

    printf("Starting test of FolderPicker Service\n");

    //CreateDeepDirectory( );


    // get the global service-manager


    // Get global factory for uno services.
    Reference< XMultiServiceFactory > g_xFactory( createRegistryServiceFactory( RDB_SYSPATH ) );

    // Print a message if an error occurred.
    if ( g_xFactory.is() == sal_False )
    {
        OSL_FAIL("Can't create RegistryServiceFactory");
        return(-1);
    }

    printf("Creating RegistryServiceFactory successful\n");


    // try to get an Interface to a XFilePicker Service


    Reference< XFolderPicker2 > xFolderPicker( g_xFactory->createInstance( FOLDER_PICKER_SERVICE_NAME ), UNO_QUERY );

    if ( xFolderPicker.is() == sal_False )
    {
        OSL_FAIL( "Error creating FolderPicker Service" );
        return(-1);
    }

    try
    {
        xFolderPicker->setDisplayDirectory( L"file:///C|" );
        xFolderPicker->setTitle( L"FolderBrowse Dialog" );
        xFolderPicker->execute( );

        OUString rootDir = xFolderPicker->getDisplayDirectory( );
        OUString selectedDir = xFolderPicker->getDirectory( );

        xFolderPicker->setDisplayDirectory( selectedDir );
        xFolderPicker->execute( );

        rootDir = xFolderPicker->getDisplayDirectory( );
        selectedDir = xFolderPicker->getDirectory( );
    }
    catch( css::uno::Exception& )
    {
        MessageBox( NULL, "Exception caught!", "Error", MB_OK );
    }


    // shutdown


    // Cast factory to XComponent
    Reference< XComponent > xComponent( g_xFactory, UNO_QUERY );

    // Print a message if an error occurred.
    if ( xComponent.is() == sal_False )
    {
        OSL_FAIL("Error shuting down");
    }

    // Dispose and clear factory
    xComponent->dispose();
    g_xFactory.clear();

    printf("Test successful\n");

    CoUninitialize( );

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/folderpicker/workbench/makefile.mk b/fpicker/source/win32/folderpicker/workbench/makefile.mk
deleted file mode 100644
index e3948ee..0000000
--- a/fpicker/source/win32/folderpicker/workbench/makefile.mk
+++ /dev/null
@@ -1,54 +0,0 @@
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This file incorporates work covered by the following license notice:
#
#   Licensed to the Apache Software Foundation (ASF) under one or more
#   contributor license agreements. See the NOTICE file distributed
#   with this work for additional information regarding copyright
#   ownership. The ASF licenses this file to you under the Apache
#   License, Version 2.0 (the "License"); you may not use this file
#   except in compliance with the License. You may obtain a copy of
#   the License at http://www.apache.org/licenses/LICENSE-2.0 .
#

PRJ=..$/..$/..$/..

PRJNAME=		sysui
TARGET=			testfops
LIBTARGET=		NO
TARGETTYPE=		CUI

# --- Settings -----------------------------------------------------

.INCLUDE :  settings.mk

.IF "$(COM)" == "MSC"
CFLAGS+=-GR -EHa
.ENDIF

# --- Files --------------------------------------------------------

            
OBJFILES=   	$(OBJ)$/test_fops.obj

APP1TARGET=		test_fops

APP1OBJS=		$(OBJ)$/test_fops.obj 

APP1STDLIBS+=	$(CPPULIB)			\
                $(CPPUHELPERLIB)	\
                $(SALLIB) 	 		\
                $(USER32LIB)\
                $(OLE32LIB)
                
APP1DEF=		$(MISC)$/$(APP1TARGET).def

# --- Targets ------------------------------------------------------

.INCLUDE :		target.mk