1370b324cSopenharmony_ci// Windows/Shell.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../Common/MyCom.h" 6370b324cSopenharmony_ci#include "../Common/StringConvert.h" 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci#include "COM.h" 9370b324cSopenharmony_ci#include "FileName.h" 10370b324cSopenharmony_ci#include "MemoryGlobal.h" 11370b324cSopenharmony_ci#include "Shell.h" 12370b324cSopenharmony_ci 13370b324cSopenharmony_ci#ifndef _UNICODE 14370b324cSopenharmony_ciextern bool g_IsNT; 15370b324cSopenharmony_ci#endif 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci// MSVC6 and old SDK don't support this function: 18370b324cSopenharmony_ci// #define LWSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE 19370b324cSopenharmony_ci// LWSTDAPI StrRetToStrW(STRRET *pstr, LPCITEMIDLIST pidl, LPWSTR *ppsz); 20370b324cSopenharmony_ci 21370b324cSopenharmony_ci// #define SHOW_DEBUG_SHELL 22370b324cSopenharmony_ci 23370b324cSopenharmony_ci#ifdef SHOW_DEBUG_SHELL 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#include "../Common/IntToString.h" 26370b324cSopenharmony_ci 27370b324cSopenharmony_cistatic void Print_Number(UInt32 number, const char *s) 28370b324cSopenharmony_ci{ 29370b324cSopenharmony_ci AString s2; 30370b324cSopenharmony_ci s2.Add_UInt32(number); 31370b324cSopenharmony_ci s2.Add_Space(); 32370b324cSopenharmony_ci s2 += s; 33370b324cSopenharmony_ci OutputDebugStringA(s2); 34370b324cSopenharmony_ci} 35370b324cSopenharmony_ci 36370b324cSopenharmony_ci#define ODS(sz) { OutputDebugStringA(sz); } 37370b324cSopenharmony_ci#define ODS_U(s) { OutputDebugStringW(s); } 38370b324cSopenharmony_ci#define ODS_(op) { op; } 39370b324cSopenharmony_ci 40370b324cSopenharmony_ci#else 41370b324cSopenharmony_ci 42370b324cSopenharmony_ci#define ODS(sz) 43370b324cSopenharmony_ci#define ODS_U(s) 44370b324cSopenharmony_ci#define ODS_(op) 45370b324cSopenharmony_ci 46370b324cSopenharmony_ci#endif 47370b324cSopenharmony_ci 48370b324cSopenharmony_ci 49370b324cSopenharmony_cinamespace NWindows { 50370b324cSopenharmony_cinamespace NShell { 51370b324cSopenharmony_ci 52370b324cSopenharmony_ci#ifndef UNDER_CE 53370b324cSopenharmony_ci 54370b324cSopenharmony_ci// SHGetMalloc is unsupported in Windows Mobile? 55370b324cSopenharmony_ci 56370b324cSopenharmony_civoid CItemIDList::Free() 57370b324cSopenharmony_ci{ 58370b324cSopenharmony_ci if (!m_Object) 59370b324cSopenharmony_ci return; 60370b324cSopenharmony_ci /* DOCs: 61370b324cSopenharmony_ci SHGetMalloc was introduced in Windows 95 and Microsoft Windows NT 4.0, 62370b324cSopenharmony_ci but as of Windows 2000 it is no longer necessary. 63370b324cSopenharmony_ci In its place, programs can call the equivalent (and easier to use) CoTaskMemAlloc and CoTaskMemFree. 64370b324cSopenharmony_ci Description from oldnewthings: 65370b324cSopenharmony_ci shell functions could work without COM (if OLE32.DLL is not loaded), 66370b324cSopenharmony_ci but now if OLE32.DLL is loaded, then shell functions and com functions do same things. 67370b324cSopenharmony_ci 22.02: so we use OLE32.DLL function to free memory: 68370b324cSopenharmony_ci */ 69370b324cSopenharmony_ci /* 70370b324cSopenharmony_ci CMyComPtr<IMalloc> shellMalloc; 71370b324cSopenharmony_ci if (::SHGetMalloc(&shellMalloc) != NOERROR) 72370b324cSopenharmony_ci throw 41099; 73370b324cSopenharmony_ci shellMalloc->Free(m_Object); 74370b324cSopenharmony_ci */ 75370b324cSopenharmony_ci CoTaskMemFree(m_Object); 76370b324cSopenharmony_ci m_Object = NULL; 77370b324cSopenharmony_ci} 78370b324cSopenharmony_ci 79370b324cSopenharmony_ci/* 80370b324cSopenharmony_ciCItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) 81370b324cSopenharmony_ci { *this = itemIDList; } 82370b324cSopenharmony_ciCItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) 83370b324cSopenharmony_ci { *this = itemIDList; } 84370b324cSopenharmony_ci 85370b324cSopenharmony_ciCItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) 86370b324cSopenharmony_ci{ 87370b324cSopenharmony_ci Free(); 88370b324cSopenharmony_ci if (object != 0) 89370b324cSopenharmony_ci { 90370b324cSopenharmony_ci UINT32 size = GetSize(object); 91370b324cSopenharmony_ci m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 92370b324cSopenharmony_ci if (m_Object != NULL) 93370b324cSopenharmony_ci MoveMemory(m_Object, object, size); 94370b324cSopenharmony_ci } 95370b324cSopenharmony_ci return *this; 96370b324cSopenharmony_ci} 97370b324cSopenharmony_ci 98370b324cSopenharmony_ciCItemIDList& CItemIDList::operator=(const CItemIDList &object) 99370b324cSopenharmony_ci{ 100370b324cSopenharmony_ci Free(); 101370b324cSopenharmony_ci if (object.m_Object != NULL) 102370b324cSopenharmony_ci { 103370b324cSopenharmony_ci UINT32 size = GetSize(object.m_Object); 104370b324cSopenharmony_ci m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 105370b324cSopenharmony_ci if (m_Object != NULL) 106370b324cSopenharmony_ci MoveMemory(m_Object, object.m_Object, size); 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci return *this; 109370b324cSopenharmony_ci} 110370b324cSopenharmony_ci*/ 111370b324cSopenharmony_ci 112370b324cSopenharmony_ci 113370b324cSopenharmony_cistatic HRESULT ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names) 114370b324cSopenharmony_ci{ 115370b324cSopenharmony_ci names.Clear(); 116370b324cSopenharmony_ci const wchar_t *lim = p + size; 117370b324cSopenharmony_ci UString s; 118370b324cSopenharmony_ci /* 119370b324cSopenharmony_ci if (size == 0 || p[size - 1] != 0) 120370b324cSopenharmony_ci return E_INVALIDARG; 121370b324cSopenharmony_ci if (size == 1) 122370b324cSopenharmony_ci return S_OK; 123370b324cSopenharmony_ci if (p[size - 2] != 0) 124370b324cSopenharmony_ci return E_INVALIDARG; 125370b324cSopenharmony_ci */ 126370b324cSopenharmony_ci for (;;) 127370b324cSopenharmony_ci { 128370b324cSopenharmony_ci const wchar_t *start = p; 129370b324cSopenharmony_ci for (;;) 130370b324cSopenharmony_ci { 131370b324cSopenharmony_ci if (p == lim) return E_INVALIDARG; // S_FALSE 132370b324cSopenharmony_ci if (*p++ == 0) 133370b324cSopenharmony_ci break; 134370b324cSopenharmony_ci } 135370b324cSopenharmony_ci const size_t num = (size_t)(p - start); 136370b324cSopenharmony_ci if (num == 1) 137370b324cSopenharmony_ci { 138370b324cSopenharmony_ci if (p != lim) return E_INVALIDARG; // S_FALSE 139370b324cSopenharmony_ci return S_OK; 140370b324cSopenharmony_ci } 141370b324cSopenharmony_ci s.SetFrom(start, (unsigned)(num - 1)); 142370b324cSopenharmony_ci ODS_U(s) 143370b324cSopenharmony_ci names.Add(s); 144370b324cSopenharmony_ci // names.ReserveOnePosition(); 145370b324cSopenharmony_ci // names.AddInReserved_Ptr_of_new(new UString((unsigned)num - 1, start)); 146370b324cSopenharmony_ci } 147370b324cSopenharmony_ci} 148370b324cSopenharmony_ci 149370b324cSopenharmony_ci 150370b324cSopenharmony_cistatic HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names) 151370b324cSopenharmony_ci{ 152370b324cSopenharmony_ci names.Clear(); 153370b324cSopenharmony_ci AString name; 154370b324cSopenharmony_ci for (; size != 0; size--) 155370b324cSopenharmony_ci { 156370b324cSopenharmony_ci const char c = *p++; 157370b324cSopenharmony_ci if (c == 0) 158370b324cSopenharmony_ci { 159370b324cSopenharmony_ci if (name.IsEmpty()) 160370b324cSopenharmony_ci return S_OK; 161370b324cSopenharmony_ci names.Add(GetUnicodeString(name)); 162370b324cSopenharmony_ci name.Empty(); 163370b324cSopenharmony_ci } 164370b324cSopenharmony_ci else 165370b324cSopenharmony_ci name += c; 166370b324cSopenharmony_ci } 167370b324cSopenharmony_ci return E_INVALIDARG; 168370b324cSopenharmony_ci} 169370b324cSopenharmony_ci 170370b324cSopenharmony_ci 171370b324cSopenharmony_ci#define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } 172370b324cSopenharmony_ci 173370b324cSopenharmony_cistatic HRESULT DataObject_GetData_HGLOBAL(IDataObject *dataObject, CLIPFORMAT cf, NCOM::CStgMedium &medium) 174370b324cSopenharmony_ci{ 175370b324cSopenharmony_ci FORMATETC etc = INIT_FORMATETC_HGLOBAL(cf); 176370b324cSopenharmony_ci RINOK(dataObject->GetData(&etc, &medium)) 177370b324cSopenharmony_ci if (medium.tymed != TYMED_HGLOBAL) 178370b324cSopenharmony_ci return E_INVALIDARG; 179370b324cSopenharmony_ci return S_OK; 180370b324cSopenharmony_ci} 181370b324cSopenharmony_ci 182370b324cSopenharmony_cistatic HRESULT DataObject_GetData_HDROP_Names(IDataObject *dataObject, UStringVector &names) 183370b324cSopenharmony_ci{ 184370b324cSopenharmony_ci names.Clear(); 185370b324cSopenharmony_ci NCOM::CStgMedium medium; 186370b324cSopenharmony_ci 187370b324cSopenharmony_ci /* Win10 : if (dataObject) is from IContextMenu::Initialize() and 188370b324cSopenharmony_ci if (len_of_path >= MAX_PATH (260) for some file in data object) 189370b324cSopenharmony_ci { 190370b324cSopenharmony_ci GetData() returns HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) 191370b324cSopenharmony_ci "The data area passed to a system call is too small", 192370b324cSopenharmony_ci Is there a way to fix this code for long paths? 193370b324cSopenharmony_ci } */ 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci RINOK(DataObject_GetData_HGLOBAL(dataObject, CF_HDROP, medium)) 196370b324cSopenharmony_ci const size_t blockSize = GlobalSize(medium.hGlobal); 197370b324cSopenharmony_ci if (blockSize < sizeof(DROPFILES)) 198370b324cSopenharmony_ci return E_INVALIDARG; 199370b324cSopenharmony_ci NMemory::CGlobalLock dropLock(medium.hGlobal); 200370b324cSopenharmony_ci const DROPFILES *dropFiles = (const DROPFILES *)dropLock.GetPointer(); 201370b324cSopenharmony_ci if (!dropFiles) 202370b324cSopenharmony_ci return E_INVALIDARG; 203370b324cSopenharmony_ci if (blockSize < dropFiles->pFiles 204370b324cSopenharmony_ci || dropFiles->pFiles < sizeof(DROPFILES) 205370b324cSopenharmony_ci // || dropFiles->pFiles != sizeof(DROPFILES) 206370b324cSopenharmony_ci ) 207370b324cSopenharmony_ci return E_INVALIDARG; 208370b324cSopenharmony_ci const size_t size = blockSize - dropFiles->pFiles; 209370b324cSopenharmony_ci const void *namesData = (const Byte *)(const void *)dropFiles + dropFiles->pFiles; 210370b324cSopenharmony_ci HRESULT hres; 211370b324cSopenharmony_ci if (dropFiles->fWide) 212370b324cSopenharmony_ci { 213370b324cSopenharmony_ci if (size % sizeof(wchar_t) != 0) 214370b324cSopenharmony_ci return E_INVALIDARG; 215370b324cSopenharmony_ci hres = ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names); 216370b324cSopenharmony_ci } 217370b324cSopenharmony_ci else 218370b324cSopenharmony_ci hres = ReadAnsiStrings((const char *)namesData, size, names); 219370b324cSopenharmony_ci 220370b324cSopenharmony_ci ODS_(Print_Number(names.Size(), "DataObject_GetData_HDROP_Names")) 221370b324cSopenharmony_ci return hres; 222370b324cSopenharmony_ci} 223370b324cSopenharmony_ci 224370b324cSopenharmony_ci 225370b324cSopenharmony_ci 226370b324cSopenharmony_ci// CF_IDLIST: 227370b324cSopenharmony_ci#define MYWIN_CFSTR_SHELLIDLIST TEXT("Shell IDList Array") 228370b324cSopenharmony_ci 229370b324cSopenharmony_citypedef struct 230370b324cSopenharmony_ci{ 231370b324cSopenharmony_ci UINT cidl; 232370b324cSopenharmony_ci UINT aoffset[1]; 233370b324cSopenharmony_ci} MYWIN_CIDA; 234370b324cSopenharmony_ci/* 235370b324cSopenharmony_ci cidl : number of PIDLs that are being transferred, not including the parent folder. 236370b324cSopenharmony_ci aoffset : An array of offsets, relative to the beginning of this structure. 237370b324cSopenharmony_ci aoffset[0] - fully qualified PIDL of a parent folder. 238370b324cSopenharmony_ci If this PIDL is empty, the parent folder is the desktop. 239370b324cSopenharmony_ci aoffset[1] ... aoffset[cidl] : offset to one of the PIDLs to be transferred. 240370b324cSopenharmony_ci All of these PIDLs are relative to the PIDL of the parent folder. 241370b324cSopenharmony_ci*/ 242370b324cSopenharmony_ci 243370b324cSopenharmony_cistatic HRESULT DataObject_GetData_IDLIST(IDataObject *dataObject, UStringVector &names) 244370b324cSopenharmony_ci{ 245370b324cSopenharmony_ci names.Clear(); 246370b324cSopenharmony_ci NCOM::CStgMedium medium; 247370b324cSopenharmony_ci RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT) 248370b324cSopenharmony_ci RegisterClipboardFormat(MYWIN_CFSTR_SHELLIDLIST), medium)) 249370b324cSopenharmony_ci const size_t blockSize = GlobalSize(medium.hGlobal); 250370b324cSopenharmony_ci if (blockSize < sizeof(MYWIN_CIDA) || blockSize >= (UInt32)((UInt32)0 - 1)) 251370b324cSopenharmony_ci return E_INVALIDARG; 252370b324cSopenharmony_ci NMemory::CGlobalLock dropLock(medium.hGlobal); 253370b324cSopenharmony_ci const MYWIN_CIDA *cida = (const MYWIN_CIDA *)dropLock.GetPointer(); 254370b324cSopenharmony_ci if (!cida) 255370b324cSopenharmony_ci return E_INVALIDARG; 256370b324cSopenharmony_ci if (cida->cidl == 0) 257370b324cSopenharmony_ci { 258370b324cSopenharmony_ci // is it posssible to have no selected items? 259370b324cSopenharmony_ci // it's unexpected case. 260370b324cSopenharmony_ci return E_INVALIDARG; 261370b324cSopenharmony_ci } 262370b324cSopenharmony_ci if (cida->cidl >= (blockSize - (UInt32)sizeof(MYWIN_CIDA)) / sizeof(UINT)) 263370b324cSopenharmony_ci return E_INVALIDARG; 264370b324cSopenharmony_ci const UInt32 start = cida->cidl * (UInt32)sizeof(UINT) + (UInt32)sizeof(MYWIN_CIDA); 265370b324cSopenharmony_ci 266370b324cSopenharmony_ci STRRET strret; 267370b324cSopenharmony_ci CMyComPtr<IShellFolder> parentFolder; 268370b324cSopenharmony_ci { 269370b324cSopenharmony_ci const UINT offset = cida->aoffset[0]; 270370b324cSopenharmony_ci if (offset < start || offset >= blockSize 271370b324cSopenharmony_ci // || offset != start 272370b324cSopenharmony_ci ) 273370b324cSopenharmony_ci return E_INVALIDARG; 274370b324cSopenharmony_ci 275370b324cSopenharmony_ci CMyComPtr<IShellFolder> desktopFolder; 276370b324cSopenharmony_ci RINOK(::SHGetDesktopFolder(&desktopFolder)) 277370b324cSopenharmony_ci if (!desktopFolder) 278370b324cSopenharmony_ci return E_FAIL; 279370b324cSopenharmony_ci 280370b324cSopenharmony_ci LPCITEMIDLIST const lpcItem = (LPCITEMIDLIST)(const void *)((const Byte *)cida + offset); 281370b324cSopenharmony_ci 282370b324cSopenharmony_ci #ifdef SHOW_DEBUG_SHELL 283370b324cSopenharmony_ci { 284370b324cSopenharmony_ci const HRESULT res = desktopFolder->GetDisplayNameOf( 285370b324cSopenharmony_ci lpcItem, SHGDN_FORPARSING, &strret); 286370b324cSopenharmony_ci if (res == S_OK && strret.uType == STRRET_WSTR) 287370b324cSopenharmony_ci { 288370b324cSopenharmony_ci ODS_U(strret.pOleStr) 289370b324cSopenharmony_ci /* if lpcItem is empty, the path will be 290370b324cSopenharmony_ci "C:\Users\user_name\Desktop" 291370b324cSopenharmony_ci if lpcItem is "My Computer" folder, the path will be 292370b324cSopenharmony_ci "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" */ 293370b324cSopenharmony_ci CoTaskMemFree(strret.pOleStr); 294370b324cSopenharmony_ci } 295370b324cSopenharmony_ci } 296370b324cSopenharmony_ci #endif 297370b324cSopenharmony_ci 298370b324cSopenharmony_ci RINOK(desktopFolder->BindToObject(lpcItem, 299370b324cSopenharmony_ci NULL, IID_IShellFolder, (void **)&parentFolder)) 300370b324cSopenharmony_ci if (!parentFolder) 301370b324cSopenharmony_ci return E_FAIL; 302370b324cSopenharmony_ci } 303370b324cSopenharmony_ci 304370b324cSopenharmony_ci names.ClearAndReserve(cida->cidl); 305370b324cSopenharmony_ci UString path; 306370b324cSopenharmony_ci 307370b324cSopenharmony_ci // for (int y = 0; y < 1; y++) // for debug 308370b324cSopenharmony_ci for (unsigned i = 1; i <= cida->cidl; i++) 309370b324cSopenharmony_ci { 310370b324cSopenharmony_ci const UINT offset = cida->aoffset[i]; 311370b324cSopenharmony_ci if (offset < start || offset >= blockSize) 312370b324cSopenharmony_ci return E_INVALIDARG; 313370b324cSopenharmony_ci const void *p = (const Byte *)(const void *)cida + offset; 314370b324cSopenharmony_ci /* ITEMIDLIST of file can contain more than one SHITEMID item. 315370b324cSopenharmony_ci In win10 only SHGDN_FORPARSING returns path that contains 316370b324cSopenharmony_ci all path parts related to parts of ITEMIDLIST. 317370b324cSopenharmony_ci So we can use only SHGDN_FORPARSING here. 318370b324cSopenharmony_ci Don't use (SHGDN_INFOLDER) 319370b324cSopenharmony_ci Don't use (SHGDN_INFOLDER | SHGDN_FORPARSING) 320370b324cSopenharmony_ci */ 321370b324cSopenharmony_ci RINOK(parentFolder->GetDisplayNameOf((LPCITEMIDLIST)p, SHGDN_FORPARSING, &strret)) 322370b324cSopenharmony_ci 323370b324cSopenharmony_ci /* 324370b324cSopenharmony_ci // MSVC6 and old SDK do not support StrRetToStrW(). 325370b324cSopenharmony_ci LPWSTR lpstr; 326370b324cSopenharmony_ci RINOK (StrRetToStrW(&strret, NULL, &lpstr)) 327370b324cSopenharmony_ci ODS_U(lpstr) 328370b324cSopenharmony_ci path = lpstr; 329370b324cSopenharmony_ci CoTaskMemFree(lpstr); 330370b324cSopenharmony_ci */ 331370b324cSopenharmony_ci if (strret.uType != STRRET_WSTR) 332370b324cSopenharmony_ci return E_INVALIDARG; 333370b324cSopenharmony_ci ODS_U(strret.pOleStr) 334370b324cSopenharmony_ci path = strret.pOleStr; 335370b324cSopenharmony_ci // the path could have super path prefix "\\\\?\\" 336370b324cSopenharmony_ci // we can remove super path prefix here, if we don't need that prefix 337370b324cSopenharmony_ci #ifdef Z7_LONG_PATH 338370b324cSopenharmony_ci // we remove super prefix, if we can work without that prefix 339370b324cSopenharmony_ci NFile::NName::If_IsSuperPath_RemoveSuperPrefix(path); 340370b324cSopenharmony_ci #endif 341370b324cSopenharmony_ci names.AddInReserved(path); 342370b324cSopenharmony_ci CoTaskMemFree(strret.pOleStr); 343370b324cSopenharmony_ci } 344370b324cSopenharmony_ci 345370b324cSopenharmony_ci ODS_(Print_Number(cida->cidl, "CFSTR_SHELLIDLIST END")) 346370b324cSopenharmony_ci return S_OK; 347370b324cSopenharmony_ci} 348370b324cSopenharmony_ci 349370b324cSopenharmony_ci 350370b324cSopenharmony_ciHRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &paths) 351370b324cSopenharmony_ci{ 352370b324cSopenharmony_ci ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names START") 353370b324cSopenharmony_ci HRESULT hres = NShell::DataObject_GetData_HDROP_Names(dataObject, paths); 354370b324cSopenharmony_ci // if (hres == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) 355370b324cSopenharmony_ci if (hres != S_OK) 356370b324cSopenharmony_ci { 357370b324cSopenharmony_ci ODS("-- DataObject_GetData_IDLIST START") 358370b324cSopenharmony_ci // for (int y = 0; y < 10000; y++) // for debug 359370b324cSopenharmony_ci hres = NShell::DataObject_GetData_IDLIST(dataObject, paths); 360370b324cSopenharmony_ci } 361370b324cSopenharmony_ci ODS("-- DataObject_GetData_HDROP_or_IDLIST_Names END") 362370b324cSopenharmony_ci return hres; 363370b324cSopenharmony_ci} 364370b324cSopenharmony_ci 365370b324cSopenharmony_ci 366370b324cSopenharmony_ci 367370b324cSopenharmony_ci// #if (NTDDI_VERSION >= NTDDI_VISTA) 368370b324cSopenharmony_citypedef struct 369370b324cSopenharmony_ci{ 370370b324cSopenharmony_ci UINT cItems; // number of items in rgdwFileAttributes array 371370b324cSopenharmony_ci DWORD dwSumFileAttributes; // all of the attributes ORed together 372370b324cSopenharmony_ci DWORD dwProductFileAttributes; // all of the attributes ANDed together 373370b324cSopenharmony_ci DWORD rgdwFileAttributes[1]; // array 374370b324cSopenharmony_ci} MYWIN_FILE_ATTRIBUTES_ARRAY; 375370b324cSopenharmony_ci 376370b324cSopenharmony_ci#define MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY TEXT("File Attributes Array") 377370b324cSopenharmony_ci 378370b324cSopenharmony_ciHRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs) 379370b324cSopenharmony_ci{ 380370b324cSopenharmony_ci attribs.Clear(); 381370b324cSopenharmony_ci NCOM::CStgMedium medium; 382370b324cSopenharmony_ci RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT) 383370b324cSopenharmony_ci RegisterClipboardFormat(MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY), medium)) 384370b324cSopenharmony_ci const size_t blockSize = GlobalSize(medium.hGlobal); 385370b324cSopenharmony_ci if (blockSize < sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY)) 386370b324cSopenharmony_ci return E_INVALIDARG; 387370b324cSopenharmony_ci NMemory::CGlobalLock dropLock(medium.hGlobal); 388370b324cSopenharmony_ci const MYWIN_FILE_ATTRIBUTES_ARRAY *faa = (const MYWIN_FILE_ATTRIBUTES_ARRAY *)dropLock.GetPointer(); 389370b324cSopenharmony_ci if (!faa) 390370b324cSopenharmony_ci return E_INVALIDARG; 391370b324cSopenharmony_ci const unsigned numFiles = faa->cItems; 392370b324cSopenharmony_ci if (numFiles == 0) 393370b324cSopenharmony_ci { 394370b324cSopenharmony_ci // is it posssible to have empty array here? 395370b324cSopenharmony_ci return E_INVALIDARG; 396370b324cSopenharmony_ci } 397370b324cSopenharmony_ci if ((blockSize - (sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY) - sizeof(DWORD))) 398370b324cSopenharmony_ci / sizeof(DWORD) != numFiles) 399370b324cSopenharmony_ci return E_INVALIDARG; 400370b324cSopenharmony_ci // attribs.Sum = faa->dwSumFileAttributes; 401370b324cSopenharmony_ci // attribs.Product = faa->dwProductFileAttributes; 402370b324cSopenharmony_ci // attribs.Vals.SetFromArray(faa->rgdwFileAttributes, numFiles); 403370b324cSopenharmony_ci // attribs.IsDirVector.ClearAndSetSize(numFiles); 404370b324cSopenharmony_ci 405370b324cSopenharmony_ci if ((faa->dwSumFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) 406370b324cSopenharmony_ci { 407370b324cSopenharmony_ci /* in win10: if selected items are volumes (c:\, d:\ ..) in My Compter, 408370b324cSopenharmony_ci all items have FILE_ATTRIBUTE_DIRECTORY attribute 409370b324cSopenharmony_ci ntfs volume also have FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM 410370b324cSopenharmony_ci udf volume: FILE_ATTRIBUTE_READONLY 411370b324cSopenharmony_ci dvd-rom device: (-1) : all bits are set 412370b324cSopenharmony_ci */ 413370b324cSopenharmony_ci const DWORD *attr = faa->rgdwFileAttributes; 414370b324cSopenharmony_ci // DWORD product = (UInt32)0 - 1, sum = 0; 415370b324cSopenharmony_ci for (unsigned i = 0; i < numFiles; i++) 416370b324cSopenharmony_ci { 417370b324cSopenharmony_ci if (attr[i] & FILE_ATTRIBUTE_DIRECTORY) 418370b324cSopenharmony_ci { 419370b324cSopenharmony_ci // attribs.ThereAreDirs = true; 420370b324cSopenharmony_ci attribs.FirstDirIndex = (int)i; 421370b324cSopenharmony_ci break; 422370b324cSopenharmony_ci } 423370b324cSopenharmony_ci // attribs.IsDirVector[i] = (attr[i] & FILE_ATTRIBUTE_DIRECTORY) != 0; 424370b324cSopenharmony_ci // product &= v; 425370b324cSopenharmony_ci // sum |= v; 426370b324cSopenharmony_ci } 427370b324cSopenharmony_ci // ODS_(Print_Number(product, "Product calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) 428370b324cSopenharmony_ci // ODS_(Print_Number(sum, "Sum calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) 429370b324cSopenharmony_ci } 430370b324cSopenharmony_ci // ODS_(Print_Number(attribs.Product, "Product FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) 431370b324cSopenharmony_ci // ODS_(Print_Number(attribs.Sum, "Sum FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) 432370b324cSopenharmony_ci ODS_(Print_Number(numFiles, "FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names")) 433370b324cSopenharmony_ci return S_OK; 434370b324cSopenharmony_ci} 435370b324cSopenharmony_ci 436370b324cSopenharmony_ci 437370b324cSopenharmony_ci///////////////////////////// 438370b324cSopenharmony_ci// CDrop 439370b324cSopenharmony_ci 440370b324cSopenharmony_ci/* 441370b324cSopenharmony_ci win10: 442370b324cSopenharmony_ci DragQueryFile() implementation code is not effective because 443370b324cSopenharmony_ci there is no pointer inside DROP internal file list, so 444370b324cSopenharmony_ci DragQueryFile(fileIndex) runs all names in range [0, fileIndex]. 445370b324cSopenharmony_ci DragQueryFile(,, buf, bufSize) 446370b324cSopenharmony_ci if (buf == NULL) by spec 447370b324cSopenharmony_ci { 448370b324cSopenharmony_ci returns value is the required size 449370b324cSopenharmony_ci in characters, of the buffer, not including the terminating null character 450370b324cSopenharmony_ci tests show that if (bufSize == 0), then it also returns required size. 451370b324cSopenharmony_ci } 452370b324cSopenharmony_ci if (bufSize != NULL) 453370b324cSopenharmony_ci { 454370b324cSopenharmony_ci returns: the count of the characters copied, not including null character. 455370b324cSopenharmony_ci win10: null character is also copied at position buf[ret_count]; 456370b324cSopenharmony_ci } 457370b324cSopenharmony_ci*/ 458370b324cSopenharmony_ci 459370b324cSopenharmony_ci/* 460370b324cSopenharmony_civoid CDrop::Attach(HDROP object) 461370b324cSopenharmony_ci{ 462370b324cSopenharmony_ci Free(); 463370b324cSopenharmony_ci m_Object = object; 464370b324cSopenharmony_ci m_Assigned = true; 465370b324cSopenharmony_ci} 466370b324cSopenharmony_ci 467370b324cSopenharmony_civoid CDrop::Free() 468370b324cSopenharmony_ci{ 469370b324cSopenharmony_ci if (m_MustBeFinished && m_Assigned) 470370b324cSopenharmony_ci Finish(); 471370b324cSopenharmony_ci m_Assigned = false; 472370b324cSopenharmony_ci} 473370b324cSopenharmony_ci 474370b324cSopenharmony_ciUINT CDrop::QueryCountOfFiles() 475370b324cSopenharmony_ci{ 476370b324cSopenharmony_ci return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); 477370b324cSopenharmony_ci} 478370b324cSopenharmony_ci 479370b324cSopenharmony_civoid CDrop::QueryFileName(UINT fileIndex, UString &fileName) 480370b324cSopenharmony_ci{ 481370b324cSopenharmony_ci #ifndef _UNICODE 482370b324cSopenharmony_ci if (!g_IsNT) 483370b324cSopenharmony_ci { 484370b324cSopenharmony_ci AString fileNameA; 485370b324cSopenharmony_ci const UINT len = QueryFile(fileIndex, (LPTSTR)NULL, 0); 486370b324cSopenharmony_ci const UINT numCopied = QueryFile(fileIndex, fileNameA.GetBuf(len + 2), len + 2); 487370b324cSopenharmony_ci fileNameA.ReleaseBuf_CalcLen(len); 488370b324cSopenharmony_ci if (numCopied != len) 489370b324cSopenharmony_ci throw 20221223; 490370b324cSopenharmony_ci fileName = GetUnicodeString(fileNameA); 491370b324cSopenharmony_ci } 492370b324cSopenharmony_ci else 493370b324cSopenharmony_ci #endif 494370b324cSopenharmony_ci { 495370b324cSopenharmony_ci // kReserve must be >= 3 for additional buffer size 496370b324cSopenharmony_ci // safety and for optimal performance 497370b324cSopenharmony_ci const unsigned kReserve = 3; 498370b324cSopenharmony_ci { 499370b324cSopenharmony_ci unsigned len = 0; 500370b324cSopenharmony_ci wchar_t *buf = fileName.GetBuf_GetMaxAvail(len); 501370b324cSopenharmony_ci if (len >= kReserve) 502370b324cSopenharmony_ci { 503370b324cSopenharmony_ci const UINT numCopied = QueryFile(fileIndex, buf, len); 504370b324cSopenharmony_ci if (numCopied < len - 1) 505370b324cSopenharmony_ci { 506370b324cSopenharmony_ci // (numCopied < len - 1) case means that it have copied full string. 507370b324cSopenharmony_ci fileName.ReleaseBuf_CalcLen(numCopied); 508370b324cSopenharmony_ci return; 509370b324cSopenharmony_ci } 510370b324cSopenharmony_ci } 511370b324cSopenharmony_ci } 512370b324cSopenharmony_ci const UINT len = QueryFile(fileIndex, (LPWSTR)NULL, 0); 513370b324cSopenharmony_ci const UINT numCopied = QueryFile(fileIndex, 514370b324cSopenharmony_ci fileName.GetBuf(len + kReserve), len + kReserve); 515370b324cSopenharmony_ci fileName.ReleaseBuf_CalcLen(len); 516370b324cSopenharmony_ci if (numCopied != len) 517370b324cSopenharmony_ci throw 20221223; 518370b324cSopenharmony_ci } 519370b324cSopenharmony_ci} 520370b324cSopenharmony_ci 521370b324cSopenharmony_ci 522370b324cSopenharmony_civoid CDrop::QueryFileNames(UStringVector &fileNames) 523370b324cSopenharmony_ci{ 524370b324cSopenharmony_ci UINT numFiles = QueryCountOfFiles(); 525370b324cSopenharmony_ci 526370b324cSopenharmony_ci Print_Number(numFiles, "\n====== CDrop::QueryFileNames START ===== \n"); 527370b324cSopenharmony_ci 528370b324cSopenharmony_ci fileNames.ClearAndReserve(numFiles); 529370b324cSopenharmony_ci UString s; 530370b324cSopenharmony_ci for (UINT i = 0; i < numFiles; i++) 531370b324cSopenharmony_ci { 532370b324cSopenharmony_ci QueryFileName(i, s); 533370b324cSopenharmony_ci if (!s.IsEmpty()) 534370b324cSopenharmony_ci fileNames.AddInReserved(s); 535370b324cSopenharmony_ci } 536370b324cSopenharmony_ci Print_Number(numFiles, "\n====== CDrop::QueryFileNames END ===== \n"); 537370b324cSopenharmony_ci} 538370b324cSopenharmony_ci*/ 539370b324cSopenharmony_ci 540370b324cSopenharmony_ci 541370b324cSopenharmony_ci// #if (NTDDI_VERSION >= NTDDI_VISTA) 542370b324cSopenharmony_ci// SHGetPathFromIDListEx returns a win32 file system path for the item in the name space. 543370b324cSopenharmony_citypedef int Z7_WIN_GPFIDL_FLAGS; 544370b324cSopenharmony_ci 545370b324cSopenharmony_ciextern "C" { 546370b324cSopenharmony_citypedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); 547370b324cSopenharmony_citypedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); 548370b324cSopenharmony_ci} 549370b324cSopenharmony_ci 550370b324cSopenharmony_ci#ifndef _UNICODE 551370b324cSopenharmony_ci 552370b324cSopenharmony_cibool GetPathFromIDList(LPCITEMIDLIST itemIDList, AString &path) 553370b324cSopenharmony_ci{ 554370b324cSopenharmony_ci path.Empty(); 555370b324cSopenharmony_ci const unsigned len = MAX_PATH + 16; 556370b324cSopenharmony_ci const bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); 557370b324cSopenharmony_ci path.ReleaseBuf_CalcLen(len); 558370b324cSopenharmony_ci return result; 559370b324cSopenharmony_ci} 560370b324cSopenharmony_ci 561370b324cSopenharmony_ci#endif 562370b324cSopenharmony_ci 563370b324cSopenharmony_cibool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) 564370b324cSopenharmony_ci{ 565370b324cSopenharmony_ci path.Empty(); 566370b324cSopenharmony_ci unsigned len = MAX_PATH + 16; 567370b324cSopenharmony_ci 568370b324cSopenharmony_ci#ifdef _UNICODE 569370b324cSopenharmony_ci bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len))); 570370b324cSopenharmony_ci#else 571370b324cSopenharmony_ci const 572370b324cSopenharmony_ci Func_SHGetPathFromIDListW 573370b324cSopenharmony_ci shGetPathFromIDListW = Z7_GET_PROC_ADDRESS( 574370b324cSopenharmony_ci Func_SHGetPathFromIDListW, ::GetModuleHandleW(L"shell32.dll"), 575370b324cSopenharmony_ci "SHGetPathFromIDListW"); 576370b324cSopenharmony_ci if (!shGetPathFromIDListW) 577370b324cSopenharmony_ci return false; 578370b324cSopenharmony_ci bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len))); 579370b324cSopenharmony_ci#endif 580370b324cSopenharmony_ci 581370b324cSopenharmony_ci if (!result) 582370b324cSopenharmony_ci { 583370b324cSopenharmony_ci ODS("==== GetPathFromIDList() SHGetPathFromIDList() returned false") 584370b324cSopenharmony_ci /* for long path we need SHGetPathFromIDListEx(). 585370b324cSopenharmony_ci win10: SHGetPathFromIDListEx() for long path returns path with 586370b324cSopenharmony_ci with super path prefix "\\\\?\\". */ 587370b324cSopenharmony_ci const 588370b324cSopenharmony_ci Func_SHGetPathFromIDListEx 589370b324cSopenharmony_ci func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS( 590370b324cSopenharmony_ci Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L"shell32.dll"), 591370b324cSopenharmony_ci "SHGetPathFromIDListEx"); 592370b324cSopenharmony_ci if (func_SHGetPathFromIDListEx) 593370b324cSopenharmony_ci { 594370b324cSopenharmony_ci ODS("==== GetPathFromIDList() (SHGetPathFromIDListEx)") 595370b324cSopenharmony_ci do 596370b324cSopenharmony_ci { 597370b324cSopenharmony_ci len *= 4; 598370b324cSopenharmony_ci result = BOOLToBool(func_SHGetPathFromIDListEx(itemIDList, path.GetBuf(len), len, 0)); 599370b324cSopenharmony_ci if (result) 600370b324cSopenharmony_ci break; 601370b324cSopenharmony_ci } 602370b324cSopenharmony_ci while (len <= (1 << 16)); 603370b324cSopenharmony_ci } 604370b324cSopenharmony_ci } 605370b324cSopenharmony_ci 606370b324cSopenharmony_ci path.ReleaseBuf_CalcLen(len); 607370b324cSopenharmony_ci return result; 608370b324cSopenharmony_ci} 609370b324cSopenharmony_ci 610370b324cSopenharmony_ci#endif 611370b324cSopenharmony_ci 612370b324cSopenharmony_ci#ifdef UNDER_CE 613370b324cSopenharmony_ci 614370b324cSopenharmony_cibool BrowseForFolder(LPBROWSEINFO, CSysString) 615370b324cSopenharmony_ci{ 616370b324cSopenharmony_ci return false; 617370b324cSopenharmony_ci} 618370b324cSopenharmony_ci 619370b324cSopenharmony_cibool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) 620370b324cSopenharmony_ci{ 621370b324cSopenharmony_ci return false; 622370b324cSopenharmony_ci} 623370b324cSopenharmony_ci 624370b324cSopenharmony_cibool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, 625370b324cSopenharmony_ci LPCTSTR /* initialFolder */, CSysString & /* resultPath */) 626370b324cSopenharmony_ci{ 627370b324cSopenharmony_ci /* 628370b324cSopenharmony_ci // SHBrowseForFolder doesn't work before CE 6.0 ? 629370b324cSopenharmony_ci if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) 630370b324cSopenharmony_ci MessageBoxW(0, L"no", L"", 0); 631370b324cSopenharmony_ci else 632370b324cSopenharmony_ci MessageBoxW(0, L"yes", L"", 0); 633370b324cSopenharmony_ci */ 634370b324cSopenharmony_ci /* 635370b324cSopenharmony_ci UString s = "all files"; 636370b324cSopenharmony_ci s += " (*.*)"; 637370b324cSopenharmony_ci return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); 638370b324cSopenharmony_ci */ 639370b324cSopenharmony_ci return false; 640370b324cSopenharmony_ci} 641370b324cSopenharmony_ci 642370b324cSopenharmony_ci#else 643370b324cSopenharmony_ci 644370b324cSopenharmony_ci/* win10: SHBrowseForFolder() doesn't support long paths, 645370b324cSopenharmony_ci even if long path suppport is enabled in registry and in manifest. 646370b324cSopenharmony_ci and SHBrowseForFolder() doesn't support super path prefix "\\\\?\\". */ 647370b324cSopenharmony_ci 648370b324cSopenharmony_cibool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) 649370b324cSopenharmony_ci{ 650370b324cSopenharmony_ci resultPath.Empty(); 651370b324cSopenharmony_ci NWindows::NCOM::CComInitializer comInitializer; 652370b324cSopenharmony_ci LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); 653370b324cSopenharmony_ci if (!itemIDList) 654370b324cSopenharmony_ci return false; 655370b324cSopenharmony_ci CItemIDList itemIDListHolder; 656370b324cSopenharmony_ci itemIDListHolder.Attach(itemIDList); 657370b324cSopenharmony_ci return GetPathFromIDList(itemIDList, resultPath); 658370b324cSopenharmony_ci} 659370b324cSopenharmony_ci 660370b324cSopenharmony_ci 661370b324cSopenharmony_cistatic int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 662370b324cSopenharmony_ci{ 663370b324cSopenharmony_ci #ifndef UNDER_CE 664370b324cSopenharmony_ci switch (uMsg) 665370b324cSopenharmony_ci { 666370b324cSopenharmony_ci case BFFM_INITIALIZED: 667370b324cSopenharmony_ci { 668370b324cSopenharmony_ci SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); 669370b324cSopenharmony_ci break; 670370b324cSopenharmony_ci } 671370b324cSopenharmony_ci /* 672370b324cSopenharmony_ci case BFFM_SELCHANGED: 673370b324cSopenharmony_ci { 674370b324cSopenharmony_ci TCHAR dir[MAX_PATH]; 675370b324cSopenharmony_ci if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) 676370b324cSopenharmony_ci SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); 677370b324cSopenharmony_ci else 678370b324cSopenharmony_ci SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); 679370b324cSopenharmony_ci break; 680370b324cSopenharmony_ci } 681370b324cSopenharmony_ci */ 682370b324cSopenharmony_ci default: 683370b324cSopenharmony_ci break; 684370b324cSopenharmony_ci } 685370b324cSopenharmony_ci #endif 686370b324cSopenharmony_ci return 0; 687370b324cSopenharmony_ci} 688370b324cSopenharmony_ci 689370b324cSopenharmony_ci 690370b324cSopenharmony_cistatic bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, 691370b324cSopenharmony_ci LPCTSTR initialFolder, CSysString &resultPath) 692370b324cSopenharmony_ci{ 693370b324cSopenharmony_ci CSysString displayName; 694370b324cSopenharmony_ci BROWSEINFO browseInfo; 695370b324cSopenharmony_ci browseInfo.hwndOwner = owner; 696370b324cSopenharmony_ci browseInfo.pidlRoot = NULL; 697370b324cSopenharmony_ci 698370b324cSopenharmony_ci // there are Unicode/Astring problems in some WinCE SDK ? 699370b324cSopenharmony_ci /* 700370b324cSopenharmony_ci #ifdef UNDER_CE 701370b324cSopenharmony_ci browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH); 702370b324cSopenharmony_ci browseInfo.lpszTitle = (LPCSTR)title; 703370b324cSopenharmony_ci #else 704370b324cSopenharmony_ci */ 705370b324cSopenharmony_ci browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); 706370b324cSopenharmony_ci browseInfo.lpszTitle = title; 707370b324cSopenharmony_ci // #endif 708370b324cSopenharmony_ci browseInfo.ulFlags = ulFlags; 709370b324cSopenharmony_ci browseInfo.lpfn = initialFolder ? BrowseCallbackProc : NULL; 710370b324cSopenharmony_ci browseInfo.lParam = (LPARAM)initialFolder; 711370b324cSopenharmony_ci return BrowseForFolder(&browseInfo, resultPath); 712370b324cSopenharmony_ci} 713370b324cSopenharmony_ci 714370b324cSopenharmony_ci#ifdef Z7_OLD_WIN_SDK 715370b324cSopenharmony_ci// ShlObj.h: 716370b324cSopenharmony_ci#ifndef BIF_NEWDIALOGSTYLE 717370b324cSopenharmony_ci#define BIF_NEWDIALOGSTYLE 0x0040 718370b324cSopenharmony_ci#endif 719370b324cSopenharmony_ci#endif 720370b324cSopenharmony_ci 721370b324cSopenharmony_cibool BrowseForFolder(HWND owner, LPCTSTR title, 722370b324cSopenharmony_ci LPCTSTR initialFolder, CSysString &resultPath) 723370b324cSopenharmony_ci{ 724370b324cSopenharmony_ci return BrowseForFolder(owner, title, 725370b324cSopenharmony_ci #ifndef UNDER_CE 726370b324cSopenharmony_ci BIF_NEWDIALOGSTYLE | 727370b324cSopenharmony_ci #endif 728370b324cSopenharmony_ci BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); 729370b324cSopenharmony_ci // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 730370b324cSopenharmony_ci} 731370b324cSopenharmony_ci 732370b324cSopenharmony_ci#ifndef _UNICODE 733370b324cSopenharmony_ci 734370b324cSopenharmony_ciextern "C" { 735370b324cSopenharmony_citypedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi); 736370b324cSopenharmony_ci} 737370b324cSopenharmony_ci 738370b324cSopenharmony_cistatic bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) 739370b324cSopenharmony_ci{ 740370b324cSopenharmony_ci NWindows::NCOM::CComInitializer comInitializer; 741370b324cSopenharmony_ci const 742370b324cSopenharmony_ci Func_SHBrowseForFolderW 743370b324cSopenharmony_ci f_SHBrowseForFolderW = Z7_GET_PROC_ADDRESS( 744370b324cSopenharmony_ci Func_SHBrowseForFolderW, ::GetModuleHandleW(L"shell32.dll"), 745370b324cSopenharmony_ci "SHBrowseForFolderW"); 746370b324cSopenharmony_ci if (!f_SHBrowseForFolderW) 747370b324cSopenharmony_ci return false; 748370b324cSopenharmony_ci LPITEMIDLIST itemIDList = f_SHBrowseForFolderW(browseInfo); 749370b324cSopenharmony_ci if (!itemIDList) 750370b324cSopenharmony_ci return false; 751370b324cSopenharmony_ci CItemIDList itemIDListHolder; 752370b324cSopenharmony_ci itemIDListHolder.Attach(itemIDList); 753370b324cSopenharmony_ci return GetPathFromIDList(itemIDList, resultPath); 754370b324cSopenharmony_ci} 755370b324cSopenharmony_ci 756370b324cSopenharmony_cistatic 757370b324cSopenharmony_ciint CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 758370b324cSopenharmony_ci{ 759370b324cSopenharmony_ci switch (uMsg) 760370b324cSopenharmony_ci { 761370b324cSopenharmony_ci case BFFM_INITIALIZED: 762370b324cSopenharmony_ci { 763370b324cSopenharmony_ci SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); 764370b324cSopenharmony_ci break; 765370b324cSopenharmony_ci } 766370b324cSopenharmony_ci /* 767370b324cSopenharmony_ci case BFFM_SELCHANGED: 768370b324cSopenharmony_ci { 769370b324cSopenharmony_ci wchar_t dir[MAX_PATH * 2]; 770370b324cSopenharmony_ci 771370b324cSopenharmony_ci if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) 772370b324cSopenharmony_ci SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); 773370b324cSopenharmony_ci else 774370b324cSopenharmony_ci SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); 775370b324cSopenharmony_ci break; 776370b324cSopenharmony_ci } 777370b324cSopenharmony_ci */ 778370b324cSopenharmony_ci default: 779370b324cSopenharmony_ci break; 780370b324cSopenharmony_ci } 781370b324cSopenharmony_ci return 0; 782370b324cSopenharmony_ci} 783370b324cSopenharmony_ci 784370b324cSopenharmony_ci 785370b324cSopenharmony_cistatic bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, 786370b324cSopenharmony_ci LPCWSTR initialFolder, UString &resultPath) 787370b324cSopenharmony_ci{ 788370b324cSopenharmony_ci UString displayName; 789370b324cSopenharmony_ci BROWSEINFOW browseInfo; 790370b324cSopenharmony_ci browseInfo.hwndOwner = owner; 791370b324cSopenharmony_ci browseInfo.pidlRoot = NULL; 792370b324cSopenharmony_ci browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH); 793370b324cSopenharmony_ci browseInfo.lpszTitle = title; 794370b324cSopenharmony_ci browseInfo.ulFlags = ulFlags; 795370b324cSopenharmony_ci browseInfo.lpfn = initialFolder ? BrowseCallbackProc2 : NULL; 796370b324cSopenharmony_ci browseInfo.lParam = (LPARAM)initialFolder; 797370b324cSopenharmony_ci return BrowseForFolder(&browseInfo, resultPath); 798370b324cSopenharmony_ci} 799370b324cSopenharmony_ci 800370b324cSopenharmony_cibool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) 801370b324cSopenharmony_ci{ 802370b324cSopenharmony_ci if (g_IsNT) 803370b324cSopenharmony_ci return BrowseForFolder(owner, title, 804370b324cSopenharmony_ci BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 805370b324cSopenharmony_ci // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 806370b324cSopenharmony_ci , initialFolder, resultPath); 807370b324cSopenharmony_ci // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 808370b324cSopenharmony_ci CSysString s; 809370b324cSopenharmony_ci bool res = BrowseForFolder(owner, GetSystemString(title), 810370b324cSopenharmony_ci BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 811370b324cSopenharmony_ci // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 812370b324cSopenharmony_ci , GetSystemString(initialFolder), s); 813370b324cSopenharmony_ci resultPath = GetUnicodeString(s); 814370b324cSopenharmony_ci return res; 815370b324cSopenharmony_ci} 816370b324cSopenharmony_ci 817370b324cSopenharmony_ci#endif 818370b324cSopenharmony_ci 819370b324cSopenharmony_ci#endif 820370b324cSopenharmony_ci 821370b324cSopenharmony_ci}} 822