Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/shared/filedialogs_vista.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "shared.h" | |
| 2 #include "filedialogs.h" | |
| 3 #include <shlobj.h> | |
| 4 #include <shobjidl.h> | |
| 5 #include <shtypes.h> | |
| 6 #include <atlbase.h> | |
| 7 #include <atlcom.h> | |
| 8 | |
| 9 #define dTEXT(X) pfc::stringcvt::string_os_from_utf8(X) | |
| 10 | |
| 11 class FilterSpec { | |
| 12 public: | |
| 13 void clear() { | |
| 14 m_types.set_size(0); m_strings.remove_all(); | |
| 15 } | |
| 16 void Sanity() { | |
| 17 if ( GetCount() > 200 ) SetAllFiles(); | |
| 18 } | |
| 19 void SetAllFiles() { | |
| 20 FromString( "All files|*.*" ); | |
| 21 } | |
| 22 void FromString(const char * in) { | |
| 23 clear(); | |
| 24 if (in == NULL) return; | |
| 25 pfc::chain_list_v2_t<COMDLG_FILTERSPEC> types; | |
| 26 | |
| 27 for(t_size inWalk = 0; ; ) { | |
| 28 | |
| 29 t_size base1 = inWalk; | |
| 30 t_size delta1 = ScanForSeparator(in+base1); | |
| 31 t_size base2 = base1 + delta1; | |
| 32 if (in[base2] == 0) break; | |
| 33 ++base2; | |
| 34 t_size delta2 = ScanForSeparator(in+base2); | |
| 35 if (delta1 > 0 && delta2 > 0) { | |
| 36 COMDLG_FILTERSPEC spec; | |
| 37 spec.pszName = MakeString(in+base1,delta1); | |
| 38 spec.pszSpec = MakeString(in+base2,delta2); | |
| 39 types.add_item(spec); | |
| 40 } | |
| 41 inWalk = base2 + delta2; | |
| 42 if (in[inWalk] == 0) break; | |
| 43 ++inWalk; | |
| 44 } | |
| 45 | |
| 46 pfc::list_to_array(m_types,types); | |
| 47 } | |
| 48 | |
| 49 t_size GetCount() const {return m_types.get_count();} | |
| 50 const COMDLG_FILTERSPEC * GetPtr() const {return m_types.get_ptr();} | |
| 51 private: | |
| 52 static t_size ScanForSeparator(const char * in) { | |
| 53 for(t_size walk = 0; ; ++walk) { | |
| 54 if (in[walk] == 0 || in[walk] == '|') return walk; | |
| 55 } | |
| 56 } | |
| 57 WCHAR * MakeString(const char * in, t_size inLen) { | |
| 58 t_size len = pfc::stringcvt::estimate_utf8_to_wide(in,inLen); | |
| 59 WCHAR* str = AllocString(len); | |
| 60 pfc::stringcvt::convert_utf8_to_wide(str,len,in,inLen); | |
| 61 return str; | |
| 62 } | |
| 63 WCHAR * AllocString(t_size size) { | |
| 64 auto iter = m_strings.insert_last(); | |
| 65 iter->set_size(size); | |
| 66 return iter->get_ptr(); | |
| 67 } | |
| 68 pfc::chain_list_v2_t<pfc::array_t<WCHAR> > m_strings; | |
| 69 pfc::array_t<COMDLG_FILTERSPEC> m_types; | |
| 70 }; | |
| 71 | |
| 72 static HRESULT AddOptionsHelper(pfc::com_ptr_t<IFileDialog> dlg, DWORD opts) { | |
| 73 DWORD options; | |
| 74 HRESULT state; | |
| 75 if (FAILED(state = dlg->GetOptions(&options))) return state; | |
| 76 options |= opts; | |
| 77 if (FAILED(state = dlg->SetOptions( options ))) return state; | |
| 78 return S_OK; | |
| 79 } | |
| 80 | |
| 81 namespace { | |
| 82 | |
| 83 // SPECIAL | |
| 84 // Deal with slow or nonworking net shares, do not lockup the calling thread in such cases, just split away | |
| 85 // Particularly relevant to net shares referred by raw IP, these get us stuck for a long time | |
| 86 class PDNArg_t : public pfc::refcounted_object_root { | |
| 87 public: | |
| 88 CoTaskMemObject<LPITEMIDLIST> m_idList; | |
| 89 pfc::string8 m_path; | |
| 90 HRESULT m_result; | |
| 91 }; | |
| 92 | |
| 93 static unsigned CALLBACK PDNProc(void * arg) { | |
| 94 pfc::refcounted_object_ptr_t<PDNArg_t> ptr; ptr.attach( reinterpret_cast<PDNArg_t*>( arg ) ); | |
| 95 CoInitialize(0); | |
| 96 | |
| 97 SFGAOF dummy = {}; | |
| 98 ptr->m_result = SHParseDisplayName(dTEXT(ptr->m_path),NULL,&ptr->m_idList.m_ptr,0,&dummy); | |
| 99 | |
| 100 CoUninitialize(); | |
| 101 | |
| 102 return 0; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 static HRESULT SetFolderHelper(pfc::com_ptr_t<IFileDialog> dlg, const char * folderPath) { | |
| 107 CoTaskMemObject<LPITEMIDLIST> idList; | |
| 108 | |
| 109 // Do SHParseDisplayName() off-thread as it is known to lock up on bad net share references | |
| 110 pfc::refcounted_object_ptr_t<PDNArg_t> ptr = new PDNArg_t(); | |
| 111 ptr->m_path = folderPath; | |
| 112 ptr->m_result = E_FAIL; | |
| 113 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, PDNProc, reinterpret_cast<void*>(ptr._duplicate_ptr()), 0, NULL); | |
| 114 DWORD status = WaitForSingleObject( hThread, 3000 ); | |
| 115 CloseHandle(hThread); | |
| 116 if (status != WAIT_OBJECT_0) return E_FAIL; | |
| 117 if (FAILED(ptr->m_result)) return ptr->m_result; | |
| 118 | |
| 119 pfc::com_ptr_t<IShellItem> item; | |
| 120 HRESULT state; | |
| 121 if (FAILED(state = SHCreateShellItem(NULL,NULL,ptr->m_idList.m_ptr,item.receive_ptr()))) return state; | |
| 122 return dlg->SetFolder(item.get_ptr()); | |
| 123 } | |
| 124 | |
| 125 namespace { | |
| 126 class _EH { | |
| 127 public: | |
| 128 void operator<<(HRESULT hr) { | |
| 129 if (FAILED(hr)) throw exception_com(hr); | |
| 130 } | |
| 131 }; | |
| 132 static _EH EH; | |
| 133 }; | |
| 134 | |
| 135 BOOL Vista_GetOpenFileName(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::string_base & p_filename,BOOL b_save) { | |
| 136 modal_dialog_scope modalScope(parent); | |
| 137 | |
| 138 pfc::com_ptr_t<IFileDialog> dlg; | |
| 139 | |
| 140 if (b_save) { | |
| 141 if (FAILED(CoCreateInstance(__uuidof(FileSaveDialog), NULL, CLSCTX_ALL, IID_IFileSaveDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); | |
| 142 } else { | |
| 143 if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); | |
| 144 } | |
| 145 | |
| 146 { | |
| 147 FilterSpec spec; spec.FromString(p_ext_mask); | |
| 148 spec.Sanity(); | |
| 149 if (FAILED(dlg->SetFileTypes((UINT)spec.GetCount(),spec.GetPtr()))) return FALSE; | |
| 150 if (def_ext_mask < spec.GetCount()) { | |
| 151 if (FAILED(dlg->SetFileTypeIndex(def_ext_mask + 1))) return FALSE; | |
| 152 } | |
| 153 } | |
| 154 if (p_def_ext != NULL) { | |
| 155 if (FAILED(dlg->SetDefaultExtension(dTEXT(p_def_ext)))) return FALSE; | |
| 156 } | |
| 157 if (p_title != NULL) { | |
| 158 if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; | |
| 159 } | |
| 160 | |
| 161 if (!p_filename.is_empty()) { | |
| 162 pfc::string path(p_filename); | |
| 163 pfc::string fn = pfc::io::path::getFileName(path); | |
| 164 pfc::string parent = pfc::io::path::getParent(path); | |
| 165 if (!parent.isEmpty()) SetFolderHelper(dlg,parent.ptr()); | |
| 166 dlg->SetFileName(dTEXT(fn.ptr())); | |
| 167 } else if (p_directory != NULL) { | |
| 168 SetFolderHelper(dlg,p_directory); | |
| 169 } | |
| 170 | |
| 171 if (FAILED(AddOptionsHelper(dlg, FOS_FORCEFILESYSTEM))) return FALSE; | |
| 172 | |
| 173 if (FAILED( dlg->Show(parent) ) ) return FALSE; | |
| 174 | |
| 175 { | |
| 176 pfc::com_ptr_t<IShellItem> result; | |
| 177 if (FAILED(dlg->GetResult(result.receive_ptr()))) return FALSE; | |
| 178 | |
| 179 CoTaskMemObject<WCHAR*> nameBuf; | |
| 180 if (FAILED(result->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; | |
| 181 | |
| 182 p_filename = pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ); | |
| 183 } | |
| 184 return TRUE; | |
| 185 } | |
| 186 | |
| 187 BOOL Vista_GetOpenFileNameMulti(HWND parent,const char * p_ext_mask,unsigned def_ext_mask,const char * p_def_ext,const char * p_title,const char * p_directory,pfc::ptrholder_t<uGetOpenFileNameMultiResult> & out) { | |
| 188 modal_dialog_scope modalScope(parent); | |
| 189 | |
| 190 pfc::com_ptr_t<IFileOpenDialog> dlg; | |
| 191 if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); | |
| 192 | |
| 193 { | |
| 194 FilterSpec spec; spec.FromString(p_ext_mask); | |
| 195 spec.Sanity(); | |
| 196 if (FAILED(dlg->SetFileTypes((UINT)spec.GetCount(),spec.GetPtr()))) return FALSE; | |
| 197 if (def_ext_mask < spec.GetCount()) { | |
| 198 if (FAILED(dlg->SetFileTypeIndex(def_ext_mask + 1))) return FALSE; | |
| 199 } | |
| 200 } | |
| 201 if (p_def_ext != NULL) { | |
| 202 if (FAILED(dlg->SetDefaultExtension(dTEXT(p_def_ext)))) return FALSE; | |
| 203 } | |
| 204 if (p_title != NULL) { | |
| 205 if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; | |
| 206 } | |
| 207 | |
| 208 if (p_directory != NULL) { | |
| 209 SetFolderHelper(dlg,p_directory); | |
| 210 } | |
| 211 | |
| 212 if (FAILED(AddOptionsHelper(dlg, FOS_ALLOWMULTISELECT | FOS_FORCEFILESYSTEM))) return FALSE; | |
| 213 | |
| 214 if (FAILED( dlg->Show(parent) ) ) return FALSE; | |
| 215 | |
| 216 { | |
| 217 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 218 pfc::com_ptr_t<IShellItemArray> results; | |
| 219 if (FAILED(dlg->GetResults(results.receive_ptr()))) return FALSE; | |
| 220 DWORD total; | |
| 221 if (FAILED(results->GetCount(&total))) return FALSE; | |
| 222 for(DWORD itemWalk = 0; itemWalk < total; ++itemWalk) { | |
| 223 pfc::com_ptr_t<IShellItem> item; | |
| 224 if (SUCCEEDED(results->GetItemAt(itemWalk,item.receive_ptr()))) { | |
| 225 CoTaskMemObject<WCHAR*> nameBuf; | |
| 226 if (FAILED(item->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; | |
| 227 | |
| 228 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); | |
| 229 | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 if (result->get_count() == 0) return FALSE; | |
| 234 | |
| 235 out = result.detach(); | |
| 236 } | |
| 237 | |
| 238 return TRUE; | |
| 239 } | |
| 240 #if 0 | |
| 241 namespace { | |
| 242 class CFileDialogEvents_LocateFile : public IFileDialogEvents { | |
| 243 public: | |
| 244 CFileDialogEvents_LocateFile(pfc::stringp tofind) : m_tofind(tofind) {} | |
| 245 HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *pfd) {return S_OK;} | |
| 246 | |
| 247 HRESULT STDMETHODCALLTYPE OnFolderChanging( IFileDialog *pfd, IShellItem *psiFolder) {return S_OK;} | |
| 248 | |
| 249 HRESULT STDMETHODCALLTYPE OnFolderChange( IFileDialog *pfd ) { | |
| 250 //pfd->GetFolder(); | |
| 251 return S_OK; | |
| 252 } | |
| 253 | |
| 254 HRESULT STDMETHODCALLTYPE OnSelectionChange( IFileDialog *pfd ) {return S_OK;} | |
| 255 | |
| 256 HRESULT STDMETHODCALLTYPE OnShareViolation( IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse) { return S_OK; } | |
| 257 | |
| 258 HRESULT STDMETHODCALLTYPE OnTypeChange( IFileDialog *pfd ) {return S_OK; } | |
| 259 | |
| 260 HRESULT STDMETHODCALLTYPE OnOverwrite( IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse) {return S_OK; } | |
| 261 | |
| 262 private: | |
| 263 const pfc::string m_tofind; | |
| 264 }; | |
| 265 | |
| 266 } | |
| 267 #endif | |
| 268 BOOL Vista_BrowseForFolder(HWND parent, const char * p_title, pfc::string_base & path) { | |
| 269 modal_dialog_scope modalScope(parent); | |
| 270 pfc::com_ptr_t<IFileOpenDialog> dlg; | |
| 271 if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); | |
| 272 | |
| 273 if (p_title != NULL) { | |
| 274 if (FAILED(dlg->SetTitle(dTEXT(p_title)))) return FALSE; | |
| 275 } | |
| 276 | |
| 277 if (FAILED(AddOptionsHelper(dlg, FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM))) return FALSE; | |
| 278 | |
| 279 if (!path.is_empty()) { | |
| 280 SetFolderHelper(dlg,path); | |
| 281 } | |
| 282 | |
| 283 if (FAILED( dlg->Show(parent) ) ) return FALSE; | |
| 284 | |
| 285 { | |
| 286 pfc::com_ptr_t<IShellItem> result; | |
| 287 if (FAILED(dlg->GetResult(result.receive_ptr()))) return FALSE; | |
| 288 | |
| 289 CoTaskMemObject<WCHAR*> nameBuf; | |
| 290 if (FAILED(result->GetDisplayName(SIGDN_FILESYSPATH,&nameBuf.m_ptr))) return FALSE; | |
| 291 | |
| 292 path = pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ); | |
| 293 } | |
| 294 return TRUE; | |
| 295 } | |
| 296 | |
| 297 | |
| 298 __inline HRESULT mySHLoadLibraryFromItem( | |
| 299 __in IShellItem *psiLibrary, | |
| 300 __in DWORD grfMode, | |
| 301 __in REFIID riid, | |
| 302 __deref_out void **ppv | |
| 303 ) | |
| 304 { | |
| 305 *ppv = NULL; | |
| 306 IShellLibrary *plib; | |
| 307 | |
| 308 HRESULT hr = CoCreateInstance( | |
| 309 CLSID_ShellLibrary, | |
| 310 NULL, | |
| 311 CLSCTX_INPROC_SERVER, | |
| 312 IID_PPV_ARGS(&plib)); | |
| 313 | |
| 314 if (SUCCEEDED(hr)) | |
| 315 { | |
| 316 hr = plib->LoadLibraryFromItem (psiLibrary, grfMode); | |
| 317 if (SUCCEEDED(hr)) | |
| 318 { | |
| 319 hr = plib->QueryInterface (riid, ppv); | |
| 320 } | |
| 321 plib->Release(); | |
| 322 } | |
| 323 return hr; | |
| 324 } | |
| 325 | |
| 326 // | |
| 327 // from shobjidl.h | |
| 328 // | |
| 329 __inline HRESULT mySHLoadLibraryFromKnownFolder( | |
| 330 __in REFKNOWNFOLDERID kfidLibrary, | |
| 331 __in DWORD grfMode, | |
| 332 __in REFIID riid, | |
| 333 __deref_out void **ppv) | |
| 334 { | |
| 335 *ppv = NULL; | |
| 336 IShellLibrary *plib; | |
| 337 HRESULT hr = CoCreateInstance( | |
| 338 CLSID_ShellLibrary, | |
| 339 NULL, | |
| 340 CLSCTX_INPROC_SERVER, | |
| 341 IID_PPV_ARGS(&plib)); | |
| 342 if (SUCCEEDED(hr)) | |
| 343 { | |
| 344 hr = plib->LoadLibraryFromKnownFolder(kfidLibrary, grfMode); | |
| 345 if (SUCCEEDED(hr)) | |
| 346 { | |
| 347 hr = plib->QueryInterface(riid, ppv); | |
| 348 } | |
| 349 plib->Release(); | |
| 350 } | |
| 351 return hr; | |
| 352 } | |
| 353 | |
| 354 puGetOpenFileNameMultiResult Vista_BrowseForFolderEx(HWND parent,const char * p_title, const char * initPath) { | |
| 355 try { | |
| 356 modal_dialog_scope modalScope(parent); | |
| 357 pfc::com_ptr_t<IFileOpenDialog> dlg; | |
| 358 if (FAILED(CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**) dlg.receive_ptr()))) throw pfc::exception_not_implemented(); | |
| 359 | |
| 360 if (p_title != NULL) { | |
| 361 EH << dlg->SetTitle(dTEXT(p_title)); | |
| 362 } | |
| 363 | |
| 364 EH << AddOptionsHelper(dlg, FOS_ALLOWMULTISELECT | FOS_PICKFOLDERS); | |
| 365 | |
| 366 if (initPath && *initPath) { | |
| 367 SetFolderHelper(dlg,initPath); | |
| 368 } | |
| 369 | |
| 370 EH << dlg->Show(parent); | |
| 371 | |
| 372 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 373 pfc::com_ptr_t<IShellItemArray> results; | |
| 374 EH << dlg->GetResults(results.receive_ptr()); | |
| 375 DWORD total; | |
| 376 EH << results->GetCount(&total); | |
| 377 CoTaskMemObject<WCHAR*> nameBuf; | |
| 378 for(DWORD itemWalk = 0; itemWalk < total; ++itemWalk) { | |
| 379 pfc::com_ptr_t<IShellItem> item; | |
| 380 EH << results->GetItemAt(itemWalk,item.receive_ptr()); | |
| 381 if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()))) { | |
| 382 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); | |
| 383 } else { | |
| 384 pfc::com_ptr_t<IShellLibrary> library; | |
| 385 if (SUCCEEDED(mySHLoadLibraryFromItem(item.get_ptr(), STGM_READ, IID_IShellLibrary, (void**)library.receive_ptr()))) { | |
| 386 pfc::com_ptr_t<IShellItemArray> subFolders; | |
| 387 EH << library->GetFolders(LFF_FORCEFILESYSTEM, IID_IShellItemArray, (void**)subFolders.receive_ptr()); | |
| 388 DWORD subTotal; | |
| 389 EH << subFolders->GetCount(&subTotal); | |
| 390 for(DWORD subWalk = 0; subWalk < subTotal; ++subWalk) { | |
| 391 pfc::com_ptr_t<IShellItem> subItem; | |
| 392 EH << subFolders->GetItemAt(subWalk,subItem.receive_ptr()); | |
| 393 EH << subItem->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()); | |
| 394 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); | |
| 395 } | |
| 396 } | |
| 397 } | |
| 398 } | |
| 399 if (result->GetCount() == 0) return NULL; | |
| 400 return result.detach(); | |
| 401 } catch(exception_com const &) { | |
| 402 return NULL; | |
| 403 } | |
| 404 } | |
| 405 | |
| 406 static bool GetLegacyKnownFolder(int & out, REFKNOWNFOLDERID id) { | |
| 407 if (id == FOLDERID_Music) { | |
| 408 out = CSIDL_MYMUSIC; | |
| 409 return true; | |
| 410 } else if (id == FOLDERID_Pictures) { | |
| 411 out = CSIDL_MYPICTURES; | |
| 412 return true; | |
| 413 } else if (id == FOLDERID_Videos) { | |
| 414 out = CSIDL_MYVIDEO; | |
| 415 return true; | |
| 416 } else if (id == FOLDERID_Documents) { | |
| 417 out = CSIDL_MYDOCUMENTS; | |
| 418 return true; | |
| 419 } else if (id == FOLDERID_Desktop) { | |
| 420 out = CSIDL_DESKTOP; | |
| 421 return true; | |
| 422 } else { | |
| 423 return false; | |
| 424 } | |
| 425 } | |
| 426 | |
| 427 puGetOpenFileNameMultiResult SHARED_EXPORT uEvalKnownFolder(REFKNOWNFOLDERID id) { | |
| 428 try { | |
| 429 pfc::com_ptr_t<IShellLibrary> library; | |
| 430 EH << mySHLoadLibraryFromKnownFolder(id, STGM_READ, IID_IShellLibrary, (void**)library.receive_ptr()); | |
| 431 | |
| 432 pfc::com_ptr_t<IShellItemArray> subFolders; | |
| 433 EH << library->GetFolders(LFF_FORCEFILESYSTEM, IID_IShellItemArray, (void**)subFolders.receive_ptr()); | |
| 434 | |
| 435 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 436 | |
| 437 DWORD subTotal; | |
| 438 EH << subFolders->GetCount(&subTotal); | |
| 439 CoTaskMemObject<WCHAR*> nameBuf; | |
| 440 for(DWORD subWalk = 0; subWalk < subTotal; ++subWalk) { | |
| 441 pfc::com_ptr_t<IShellItem> subItem; | |
| 442 EH << subFolders->GetItemAt(subWalk,subItem.receive_ptr()); | |
| 443 EH << subItem->GetDisplayName(SIGDN_FILESYSPATH,nameBuf.Receive()); | |
| 444 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); | |
| 445 } | |
| 446 if (result->get_count() == 0) return NULL; | |
| 447 return result.detach(); | |
| 448 } catch(exception_com const &) { | |
| 449 //failed | |
| 450 } | |
| 451 | |
| 452 | |
| 453 try { | |
| 454 CComPtr<IKnownFolderManager> mgr; CComPtr<IKnownFolder> folder; CoTaskMemObject<wchar_t*> path; | |
| 455 EH << CoCreateInstance(__uuidof(KnownFolderManager), nullptr, CLSCTX_ALL, IID_IKnownFolderManager, (void**)&mgr.p); | |
| 456 EH << mgr->GetFolder(id, &folder.p); | |
| 457 EH << folder->GetPath(0, &path.m_ptr); | |
| 458 | |
| 459 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 460 result->AddItem(pfc::stringcvt::string_utf8_from_os(path.m_ptr)); | |
| 461 return result.detach(); | |
| 462 } catch (exception_com const &) { | |
| 463 | |
| 464 } | |
| 465 | |
| 466 //FALLBACK | |
| 467 | |
| 468 | |
| 469 | |
| 470 { | |
| 471 int legacyID; | |
| 472 if (GetLegacyKnownFolder(legacyID, id)) { | |
| 473 try { | |
| 474 TCHAR path[MAX_PATH+16] = {}; | |
| 475 EH << SHGetFolderPath(NULL, legacyID, NULL, SHGFP_TYPE_CURRENT, path); | |
| 476 path[_countof(path)-1] = 0; | |
| 477 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 478 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( path ) ); | |
| 479 return result.detach(); | |
| 480 } catch(exception_com const &) { | |
| 481 //failed; | |
| 482 } | |
| 483 } | |
| 484 } | |
| 485 #if 0 // Vista code path - uninteresting, XP shit still needs to be supported, SHGetKnownFolderPath() does not exist on XP | |
| 486 try { | |
| 487 pfc::ptrholder_t<uGetOpenFileNameMultiResult_impl> result = new uGetOpenFileNameMultiResult_impl; | |
| 488 CoTaskMemObject<WCHAR*> nameBuf; | |
| 489 EH << SHGetKnownFolderPath(id, 0, NULL, nameBuf.Receive()); | |
| 490 result->AddItem(pfc::stringcvt::string_utf8_from_os_ex( nameBuf.m_ptr ) ); | |
| 491 return result.detach(); | |
| 492 } catch(exception_com const &) { | |
| 493 //failed | |
| 494 } | |
| 495 #endif | |
| 496 return NULL; //failure | |
| 497 } |
