|
1
|
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 }
|