// ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * // ************************************************************************** #include "ifile_dialog.h" #define WIN32_LEAN_AND_MEAN #include #include #include #include #include using namespace zen; namespace { bool showFolderPickerImpl(HWND ownerWindow, //throw SysError; return "false" if cancelled by user const wchar_t* defaultFolder, //optional! const GUID* persistenceGuid, // std::wstring& selectedFolder) { ComPtr fileDlg; ZEN_COM_CHECK(::CoCreateInstance(CLSID_FileOpenDialog, //throw SysError nullptr, CLSCTX_ALL, IID_PPV_ARGS(fileDlg.init()))); if (persistenceGuid) ZEN_COM_CHECK(fileDlg->SetClientGuid(*persistenceGuid)); FILEOPENDIALOGOPTIONS dlgOptions = 0; ZEN_COM_CHECK(fileDlg->GetOptions(&dlgOptions)); //throw SysError ZEN_COM_CHECK(fileDlg->SetOptions(dlgOptions | FOS_PICKFOLDERS | FOS_NOVALIDATE | FOS_FORCEFILESYSTEM)); if (defaultFolder) //show last selection instead of top level if no default available { ComPtr folderItem; ZEN_COM_CHECK(::SHCreateItemFromParsingName(defaultFolder, nullptr, IID_PPV_ARGS(folderItem.init()))); ZEN_COM_CHECK(fileDlg->SetFolder(folderItem.get())); } try { ZEN_COM_CHECK(fileDlg->Show(ownerWindow)); //may fail with: HRESULT_FROM_WIN32(ERROR_CANCELLED) } catch (const SysError&) { return false; } ComPtr folderItem; ZEN_COM_CHECK(fileDlg->GetResult(folderItem.init())); LPWSTR folderPath = nullptr; ZEN_COM_CHECK(folderItem->GetDisplayName(SIGDN_FILESYSPATH, &folderPath)); ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(folderPath)); selectedFolder = folderPath; return true; } wchar_t* allocString(const std::wstring& msg) //ownership passed { auto tmp = new wchar_t [msg.size() + 1]; //std::bad_alloc ? ::wmemcpy(tmp, msg.c_str(), msg.size() + 1); //include 0-termination return tmp; } } //################################################################################################## void ifile::showFolderPicker(void* ownerWindow, const wchar_t* defaultFolder, const GuidProxy* guid, wchar_t*& selectedFolder, bool& cancelled, wchar_t*& errorMsg) { selectedFolder = nullptr; cancelled = false; errorMsg = nullptr; try { static_assert(sizeof(GuidProxy) == sizeof(GUID), ""); GUID winGuid = {}; if (guid) ::memcpy(&winGuid, guid, sizeof(GUID)); std::wstring folderPath; if (showFolderPickerImpl(static_cast(ownerWindow), defaultFolder, guid ? &winGuid : nullptr, folderPath)) //throw SysError selectedFolder = allocString(folderPath); else cancelled = true; } catch (const SysError& e) { errorMsg = allocString(e.toString()); //std::bad_alloc ? } } void ifile::freeString(const wchar_t* str) { delete [] str; }