[COMDLG32] Sync with Wine Staging 2.16. CORE-13762
[reactos.git] / reactos / dll / win32 / comdlg32 / filedlgbrowser.c
1 /*
2 * Implementation of IShellBrowser for the File Open common dialog
3 *
4 * Copyright 1999 Francois Boisvert
5 * Copyright 1999, 2000 Juergen Schmied
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "cdlg.h"
23
24 typedef struct
25 {
26
27 IShellBrowser IShellBrowser_iface;
28 ICommDlgBrowser ICommDlgBrowser_iface;
29 IServiceProvider IServiceProvider_iface;
30 LONG ref; /* Reference counter */
31 HWND hwndOwner; /* Owner dialog of the interface */
32
33 } IShellBrowserImpl;
34
35 static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
36 {
37 return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
38 }
39
40 static inline IShellBrowserImpl *impl_from_ICommDlgBrowser( ICommDlgBrowser *iface )
41 {
42 return CONTAINING_RECORD(iface, IShellBrowserImpl, ICommDlgBrowser_iface);
43 }
44
45 static inline IShellBrowserImpl *impl_from_IServiceProvider( IServiceProvider *iface )
46 {
47 return CONTAINING_RECORD(iface, IShellBrowserImpl, IServiceProvider_iface);
48 }
49
50 /**************************************************************************
51 * vtable
52 */
53 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
54 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl;
55 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl;
56
57 /*
58 * Helper functions
59 */
60
61 #define add_flag(a) if (flags & a) {strcat(str, #a );strcat(str," ");}
62 static void COMDLG32_DumpSBSPFlags(UINT uflags)
63 {
64 if (TRACE_ON(commdlg))
65 {
66 unsigned int i;
67 static const struct {
68 DWORD mask;
69 const char *name;
70 } flags[] = {
71 #define FE(x) { x, #x}
72 /* SBSP_DEFBROWSER == 0 */
73 FE(SBSP_SAMEBROWSER),
74 FE(SBSP_NEWBROWSER),
75
76 /* SBSP_DEFMODE == 0 */
77 FE(SBSP_OPENMODE),
78 FE(SBSP_EXPLOREMODE),
79 FE(SBSP_HELPMODE),
80 FE(SBSP_NOTRANSFERHIST),
81
82 /* SBSP_ABSOLUTE == 0 */
83 FE(SBSP_RELATIVE),
84 FE(SBSP_PARENT),
85 FE(SBSP_NAVIGATEBACK),
86 FE(SBSP_NAVIGATEFORWARD),
87 FE(SBSP_ALLOW_AUTONAVIGATE),
88
89 FE(SBSP_NOAUTOSELECT),
90 FE(SBSP_WRITENOHISTORY),
91
92 FE(SBSP_REDIRECT),
93 FE(SBSP_INITIATEDBYHLINKFRAME),
94 };
95 #undef FE
96 TRACE("SBSP Flags: %08x =", uflags);
97 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
98 if (flags[i].mask & uflags)
99 TRACE("%s ", flags[i].name);
100 TRACE("\n");
101 }
102 }
103
104 static void COMDLG32_UpdateCurrentDir(const FileOpenDlgInfos *fodInfos)
105 {
106 LPSHELLFOLDER psfDesktop;
107 STRRET strret;
108 HRESULT res;
109
110 res = SHGetDesktopFolder(&psfDesktop);
111 if (FAILED(res))
112 return;
113
114 res = IShellFolder_GetDisplayNameOf(psfDesktop, fodInfos->ShellInfos.pidlAbsCurrent,
115 SHGDN_FORPARSING, &strret);
116 if (SUCCEEDED(res)) {
117 WCHAR wszCurrentDir[MAX_PATH];
118
119 res = StrRetToBufW(&strret, fodInfos->ShellInfos.pidlAbsCurrent, wszCurrentDir, MAX_PATH);
120 if (SUCCEEDED(res))
121 SetCurrentDirectoryW(wszCurrentDir);
122 }
123
124 IShellFolder_Release(psfDesktop);
125 }
126
127 /* copied from shell32 to avoid linking to it */
128 static BOOL COMDLG32_StrRetToStrNW (LPVOID dest, DWORD len, LPSTRRET src, LPCITEMIDLIST pidl)
129 {
130 TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest , len, src, pidl);
131
132 switch (src->uType)
133 {
134 case STRRET_WSTR:
135 lstrcpynW(dest, src->u.pOleStr, len);
136 COMDLG32_SHFree(src->u.pOleStr);
137 break;
138
139 case STRRET_CSTR:
140 if (len && !MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
141 ((LPWSTR)dest)[len-1] = 0;
142 break;
143
144 case STRRET_OFFSET:
145 if (pidl)
146 {
147 if (len && !MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset,
148 -1, dest, len ))
149 ((LPWSTR)dest)[len-1] = 0;
150 }
151 break;
152
153 default:
154 FIXME("unknown type!\n");
155 if (len)
156 { *(LPWSTR)dest = '\0';
157 }
158 return(FALSE);
159 }
160 return TRUE;
161 }
162
163 /*
164 * IShellBrowser
165 */
166
167 /**************************************************************************
168 * IShellBrowserImpl_Construct
169 */
170 IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
171 {
172 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndOwner);
173 IShellBrowserImpl *sb;
174
175 sb = COMDLG32_SHAlloc(sizeof(IShellBrowserImpl));
176
177 /* Initialisation of the member variables */
178 sb->ref=1;
179 sb->hwndOwner = hwndOwner;
180
181 /* Initialisation of the vTables */
182 sb->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
183 sb->ICommDlgBrowser_iface.lpVtbl = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
184 sb->IServiceProvider_iface.lpVtbl = &IShellBrowserImpl_IServiceProvider_Vtbl;
185 SHGetSpecialFolderLocation(hwndOwner, CSIDL_DESKTOP,
186 &fodInfos->ShellInfos.pidlAbsCurrent);
187
188 TRACE("%p\n", sb);
189
190 return &sb->IShellBrowser_iface;
191 }
192
193 /***************************************************************************
194 * IShellBrowserImpl_QueryInterface
195 */
196 static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppvObj)
197 {
198 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
199
200 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj);
201
202 *ppvObj = NULL;
203
204 if(IsEqualIID(riid, &IID_IUnknown))
205 *ppvObj = &This->IShellBrowser_iface;
206 else if(IsEqualIID(riid, &IID_IOleWindow))
207 *ppvObj = &This->IShellBrowser_iface;
208 else if(IsEqualIID(riid, &IID_IShellBrowser))
209 *ppvObj = &This->IShellBrowser_iface;
210 else if(IsEqualIID(riid, &IID_ICommDlgBrowser))
211 *ppvObj = &This->ICommDlgBrowser_iface;
212 else if(IsEqualIID(riid, &IID_IServiceProvider))
213 *ppvObj = &This->IServiceProvider_iface;
214
215 if(*ppvObj) {
216 IUnknown_AddRef((IUnknown*)*ppvObj);
217 return S_OK;
218 }
219
220 FIXME("unsupported interface, %s\n", debugstr_guid(riid));
221 return E_NOINTERFACE;
222 }
223
224 /**************************************************************************
225 * IShellBrowser::AddRef
226 */
227 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
228 {
229 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
230 ULONG ref = InterlockedIncrement(&This->ref);
231
232 TRACE("(%p,%u)\n", This, ref - 1);
233
234 return ref;
235 }
236
237 /**************************************************************************
238 * IShellBrowserImpl_Release
239 */
240 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
241 {
242 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
243 ULONG ref = InterlockedDecrement(&This->ref);
244
245 TRACE("(%p,%u)\n", This, ref + 1);
246
247 if (!ref)
248 {
249 COMDLG32_SHFree(This);
250 TRACE("-- destroyed\n");
251 }
252 return ref;
253 }
254
255 /*
256 * IOleWindow
257 */
258
259 /**************************************************************************
260 * IShellBrowserImpl_GetWindow (IOleWindow)
261 *
262 * Inherited from IOleWindow::GetWindow
263 *
264 * See Windows documentation for more details
265 *
266 * Note : We will never be window less in the File Open dialog
267 *
268 */
269 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
270 HWND * phwnd)
271 {
272 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
273
274 TRACE("(%p)\n", This);
275
276 if(!This->hwndOwner)
277 return E_FAIL;
278
279 *phwnd = This->hwndOwner;
280
281 return (*phwnd) ? S_OK : E_UNEXPECTED;
282
283 }
284
285 /**************************************************************************
286 * IShellBrowserImpl_ContextSensitiveHelp
287 */
288 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
289 BOOL fEnterMode)
290 {
291 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
292
293 TRACE("(%p)\n", This);
294
295 /* Feature not implemented */
296 return E_NOTIMPL;
297 }
298
299 /*
300 * IShellBrowser
301 */
302
303 /**************************************************************************
304 * IShellBrowserImpl_BrowseObject
305 *
306 * See Windows documentation on IShellBrowser::BrowseObject for more details
307 *
308 * This function will override user specified flags and will always
309 * use SBSP_DEFBROWSER and SBSP_DEFMODE.
310 */
311 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
312 LPCITEMIDLIST pidl,
313 UINT wFlags)
314 {
315 HRESULT hRes;
316 IShellFolder *psfTmp;
317 IShellView *psvTmp;
318 FileOpenDlgInfos *fodInfos;
319 LPITEMIDLIST pidlTmp;
320 HWND hwndView;
321 HWND hDlgWnd;
322 BOOL bViewHasFocus;
323 RECT rectView;
324
325 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
326
327 TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
328 COMDLG32_DumpSBSPFlags(wFlags);
329
330 fodInfos = get_filedlg_infoptr(This->hwndOwner);
331
332 /* Format the pidl according to its parameter's category */
333 if(wFlags & SBSP_RELATIVE)
334 {
335
336 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */
337 if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
338 pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
339 {
340 ERR("bind to object failed\n");
341 return hRes;
342 }
343 /* create an absolute pidl */
344 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl);
345 }
346 else if(wFlags & SBSP_PARENT)
347 {
348 /* Browse the parent folder (ignores the pidl) */
349 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
350 psfTmp = GetShellFolderFromPidl(pidlTmp);
351
352 }
353 else /* SBSP_ABSOLUTE is 0x0000 */
354 {
355 /* An absolute pidl (relative from the desktop) */
356 pidlTmp = COMDLG32_PIDL_ILClone(pidl);
357 psfTmp = GetShellFolderFromPidl(pidlTmp);
358 }
359
360 if(!psfTmp)
361 {
362 ERR("could not browse to folder\n");
363 return E_FAIL;
364 }
365
366 /* If the pidl to browse to is equal to the actual pidl ...
367 do nothing and pretend you did it*/
368 if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
369 {
370 IShellFolder_Release(psfTmp);
371 COMDLG32_SHFree(pidlTmp);
372 TRACE("keep current folder\n");
373 return NOERROR;
374 }
375
376 /* Release the current DataObject */
377 if (fodInfos->Shell.FOIDataObject)
378 {
379 IDataObject_Release(fodInfos->Shell.FOIDataObject);
380 fodInfos->Shell.FOIDataObject = NULL;
381 }
382
383 /* Create the associated view */
384 TRACE("create view object\n");
385 if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner,
386 &IID_IShellView, (LPVOID *)&psvTmp))) goto error;
387
388 /* Check if listview has focus */
389 bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus());
390
391 /* Get the foldersettings from the old view */
392 if(fodInfos->Shell.FOIShellView)
393 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings);
394
395 /* Release the old fodInfos->Shell.FOIShellView and update its value.
396 We have to update this early since ShellView_CreateViewWindow of native
397 shell32 calls OnStateChange and needs the correct view here.*/
398 if(fodInfos->Shell.FOIShellView)
399 {
400 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
401 IShellView_Release(fodInfos->Shell.FOIShellView);
402 }
403 fodInfos->Shell.FOIShellView = psvTmp;
404
405 /* Release old FOIShellFolder and update its value */
406 if (fodInfos->Shell.FOIShellFolder)
407 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
408 fodInfos->Shell.FOIShellFolder = psfTmp;
409
410 /* Release old pidlAbsCurrent and update its value */
411 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
412 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
413
414 COMDLG32_UpdateCurrentDir(fodInfos);
415
416 GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
417 MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);
418
419 /* Create the window */
420 TRACE("create view window\n");
421 if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
422 &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
423 &rectView, &hwndView))) goto error;
424
425 fodInfos->ShellInfos.hwndView = hwndView;
426
427 /* Set view window control id to 5002 */
428 SetWindowLongPtrW(hwndView, GWLP_ID, lst2);
429 SendMessageW( hwndView, WM_SETFONT, SendMessageW( GetParent(hwndView), WM_GETFONT, 0, 0 ), FALSE );
430
431 /* Select the new folder in the Look In combo box of the Open file dialog */
432 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent);
433
434 /* changes the tab order of the ListView to reflect the window's File Dialog */
435 hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN);
436 SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
437
438 /* Since we destroyed the old view if it had focus set focus to the newly created view */
439 if (bViewHasFocus)
440 SetFocus(fodInfos->ShellInfos.hwndView);
441
442 return hRes;
443 error:
444 ERR("Failed with error 0x%08x\n", hRes);
445 return hRes;
446 }
447
448 /**************************************************************************
449 * IShellBrowserImpl_EnableModelessSB
450 */
451 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
452 BOOL fEnable)
453
454 {
455 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
456
457 TRACE("(%p)\n", This);
458
459 /* Feature not implemented */
460 return E_NOTIMPL;
461 }
462
463 /**************************************************************************
464 * IShellBrowserImpl_GetControlWindow
465 */
466 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
467 UINT id,
468 HWND *lphwnd)
469
470 {
471 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
472
473 TRACE("(%p)\n", This);
474
475 /* Feature not implemented */
476 return E_NOTIMPL;
477 }
478
479 /**************************************************************************
480 * IShellBrowserImpl_GetViewStateStream
481 */
482 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
483 DWORD grfMode,
484 LPSTREAM *ppStrm)
485
486 {
487 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
488
489 FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm);
490
491 /* Feature not implemented */
492 return E_NOTIMPL;
493 }
494
495 /**************************************************************************
496 * IShellBrowserImpl_InsertMenusSB
497 */
498 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
499 HMENU hmenuShared,
500 LPOLEMENUGROUPWIDTHS lpMenuWidths)
501
502 {
503 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
504
505 TRACE("(%p)\n", This);
506
507 /* Feature not implemented */
508 return E_NOTIMPL;
509 }
510
511 /**************************************************************************
512 * IShellBrowserImpl_OnViewWindowActive
513 */
514 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
515 IShellView *ppshv)
516
517 {
518 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
519
520 TRACE("(%p)\n", This);
521
522 /* Feature not implemented */
523 return E_NOTIMPL;
524 }
525
526 /**************************************************************************
527 * IShellBrowserImpl_QueryActiveShellView
528 */
529 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
530 IShellView **ppshv)
531
532 {
533 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
534
535 FileOpenDlgInfos *fodInfos;
536
537 TRACE("(%p)\n", This);
538
539 fodInfos = get_filedlg_infoptr(This->hwndOwner);
540
541 if(!(*ppshv = fodInfos->Shell.FOIShellView))
542 {
543 return E_FAIL;
544 }
545 IShellView_AddRef(fodInfos->Shell.FOIShellView);
546 return NOERROR;
547 }
548
549 /**************************************************************************
550 * IShellBrowserImpl_RemoveMenusSB
551 */
552 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
553 HMENU hmenuShared)
554
555 {
556 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
557
558 TRACE("(%p)\n", This);
559
560 /* Feature not implemented */
561 return E_NOTIMPL;
562 }
563
564 /**************************************************************************
565 * IShellBrowserImpl_SendControlMsg
566 */
567 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
568 UINT id,
569 UINT uMsg,
570 WPARAM wParam,
571 LPARAM lParam,
572 LRESULT *pret)
573
574 {
575 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
576 LRESULT lres;
577
578 TRACE("(%p)->(0x%08x 0x%08x 0x%08lx 0x%08lx %p)\n", This, id, uMsg, wParam, lParam, pret);
579
580 switch (id)
581 {
582 case FCW_TOOLBAR:
583 lres = SendDlgItemMessageA( This->hwndOwner, IDC_TOOLBAR, uMsg, wParam, lParam);
584 break;
585 default:
586 FIXME("ctrl id: %x\n", id);
587 return E_NOTIMPL;
588 }
589 if (pret) *pret = lres;
590 return S_OK;
591 }
592
593 /**************************************************************************
594 * IShellBrowserImpl_SetMenuSB
595 */
596 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
597 HMENU hmenuShared,
598 HOLEMENU holemenuReserved,
599 HWND hwndActiveObject)
600
601 {
602 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
603
604 TRACE("(%p)\n", This);
605
606 /* Feature not implemented */
607 return E_NOTIMPL;
608 }
609
610 /**************************************************************************
611 * IShellBrowserImpl_SetStatusTextSB
612 */
613 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
614 LPCOLESTR lpszStatusText)
615
616 {
617 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
618
619 TRACE("(%p)\n", This);
620
621 /* Feature not implemented */
622 return E_NOTIMPL;
623 }
624
625 /**************************************************************************
626 * IShellBrowserImpl_SetToolbarItems
627 */
628 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
629 LPTBBUTTON lpButtons,
630 UINT nButtons,
631 UINT uFlags)
632
633 {
634 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
635
636 TRACE("(%p)\n", This);
637
638 /* Feature not implemented */
639 return E_NOTIMPL;
640 }
641
642 /**************************************************************************
643 * IShellBrowserImpl_TranslateAcceleratorSB
644 */
645 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
646 LPMSG lpmsg,
647 WORD wID)
648
649 {
650 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
651
652 TRACE("(%p)\n", This);
653
654 /* Feature not implemented */
655 return E_NOTIMPL;
656 }
657
658 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
659 {
660 /* IUnknown */
661 IShellBrowserImpl_QueryInterface,
662 IShellBrowserImpl_AddRef,
663 IShellBrowserImpl_Release,
664 /* IOleWindow */
665 IShellBrowserImpl_GetWindow,
666 IShellBrowserImpl_ContextSensitiveHelp,
667 /* IShellBrowser */
668 IShellBrowserImpl_InsertMenusSB,
669 IShellBrowserImpl_SetMenuSB,
670 IShellBrowserImpl_RemoveMenusSB,
671 IShellBrowserImpl_SetStatusTextSB,
672 IShellBrowserImpl_EnableModelessSB,
673 IShellBrowserImpl_TranslateAcceleratorSB,
674 IShellBrowserImpl_BrowseObject,
675 IShellBrowserImpl_GetViewStateStream,
676 IShellBrowserImpl_GetControlWindow,
677 IShellBrowserImpl_SendControlMsg,
678 IShellBrowserImpl_QueryActiveShellView,
679 IShellBrowserImpl_OnViewWindowActive,
680 IShellBrowserImpl_SetToolbarItems
681 };
682
683
684
685 /*
686 * ICommDlgBrowser
687 */
688
689 /***************************************************************************
690 * IShellBrowserImpl_ICommDlgBrowser_QueryInterface
691 */
692 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(
693 ICommDlgBrowser *iface,
694 REFIID riid,
695 LPVOID *ppvObj)
696 {
697 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
698
699 TRACE("(%p)\n", This);
700
701 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
702 }
703
704 /**************************************************************************
705 * IShellBrowserImpl_ICommDlgBrowser_AddRef
706 */
707 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
708 {
709 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
710
711 TRACE("(%p)\n", This);
712
713 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
714 }
715
716 /**************************************************************************
717 * IShellBrowserImpl_ICommDlgBrowser_Release
718 */
719 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
720 {
721 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
722
723 TRACE("(%p)\n", This);
724
725 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
726 }
727
728 /**************************************************************************
729 * IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
730 *
731 * Called when a user double-clicks in the view or presses the ENTER key
732 */
733 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
734 IShellView *ppshv)
735 {
736 LPITEMIDLIST pidl;
737 FileOpenDlgInfos *fodInfos;
738
739 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
740
741 TRACE("(%p)\n", This);
742
743 fodInfos = get_filedlg_infoptr(This->hwndOwner);
744
745 /* If the selected object is not a folder, send an IDOK command to parent window */
746 if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1)))
747 {
748 HRESULT hRes;
749
750 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
751 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
752 if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
753 {
754 hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE);
755 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
756 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
757 }
758 else
759 {
760 /* Tell the dialog that the user selected a file */
761 PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
762 hRes = S_OK;
763 }
764
765 /* Free memory used by pidl */
766 COMDLG32_SHFree(pidl);
767
768 return hRes;
769 }
770
771 return E_FAIL;
772 }
773
774 /**************************************************************************
775 * IShellBrowserImpl_OnSelChange
776 */
777 static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv)
778 {
779 FileOpenDlgInfos *fodInfos;
780
781 fodInfos = get_filedlg_infoptr(This->hwndOwner);
782 TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView);
783
784 /* release old selections */
785 if (fodInfos->Shell.FOIDataObject)
786 IDataObject_Release(fodInfos->Shell.FOIDataObject);
787
788 /* get a new DataObject from the ShellView */
789 if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION,
790 &IID_IDataObject, (void**)&fodInfos->Shell.FOIDataObject)))
791 return E_FAIL;
792
793 FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);
794
795 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
796 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
797 return S_OK;
798 }
799
800 /**************************************************************************
801 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange
802 */
803 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
804 IShellView *ppshv,
805 ULONG uChange)
806 {
807
808 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
809
810 TRACE("(%p shv=%p)\n", This, ppshv);
811
812 switch (uChange)
813 {
814 case CDBOSC_SETFOCUS:
815 /* FIXME: Reset the default button.
816 This should be taken care of by defdlg. If control
817 other than button receives focus the default button
818 should be restored. */
819 SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0);
820
821 break;
822 case CDBOSC_KILLFOCUS:
823 {
824 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(This->hwndOwner);
825 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
826 {
827 WCHAR szSave[16];
828 LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR));
829 SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave);
830 }
831 }
832 break;
833 case CDBOSC_SELCHANGE:
834 return IShellBrowserImpl_OnSelChange(This, ppshv);
835 case CDBOSC_RENAME:
836 /* nothing to do */
837 break;
838 }
839
840 return NOERROR;
841 }
842
843 /* send_includeitem_notification
844 *
845 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg
846 */
847 static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl)
848 {
849 LRESULT hook_result = 0;
850 FileOpenDlgInfos *fodInfos = get_filedlg_infoptr(hwndParentDlg);
851
852 if(!fodInfos) return 0;
853
854 if(fodInfos->DlgInfos.hwndCustomDlg)
855 {
856 TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl);
857 if(fodInfos->unicode)
858 {
859 OFNOTIFYEXW ofnNotify;
860 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
861 ofnNotify.pidl = (LPITEMIDLIST)pidl;
862 ofnNotify.hdr.hwndFrom = hwndParentDlg;
863 ofnNotify.hdr.idFrom = 0;
864 ofnNotify.hdr.code = CDN_INCLUDEITEM;
865 ofnNotify.lpOFN = fodInfos->ofnInfos;
866 hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
867 }
868 else
869 {
870 OFNOTIFYEXA ofnNotify;
871 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
872 ofnNotify.pidl = (LPITEMIDLIST)pidl;
873 ofnNotify.hdr.hwndFrom = hwndParentDlg;
874 ofnNotify.hdr.idFrom = 0;
875 ofnNotify.hdr.code = CDN_INCLUDEITEM;
876 ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos;
877 hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
878 }
879 }
880 TRACE("Retval: 0x%08lx\n", hook_result);
881 return hook_result;
882 }
883
884 /**************************************************************************
885 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject
886 */
887 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
888 IShellView * ppshv,
889 LPCITEMIDLIST pidl)
890 {
891 FileOpenDlgInfos *fodInfos;
892 ULONG ulAttr;
893 STRRET str;
894 WCHAR szPathW[MAX_PATH];
895
896 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
897
898 TRACE("(%p)\n", This);
899
900 fodInfos = get_filedlg_infoptr(This->hwndOwner);
901
902 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK;
903 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
904
905 if( (ulAttr & SFGAO_HIDDEN) || /* hidden */
906 !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
907 return S_FALSE;
908
909 /* always include directories and links */
910 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
911 return S_OK;
912
913 /* if the application takes care of including the item we are done */
914 if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY &&
915 send_includeitem_notification(This->hwndOwner, pidl))
916 return S_OK;
917
918 /* Check if there is a mask to apply if not */
919 if(!fodInfos->ShellInfos.lpstrCurrentFilter || !fodInfos->ShellInfos.lpstrCurrentFilter[0])
920 return S_OK;
921
922 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
923 {
924 if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl))
925 {
926 if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
927 return S_OK;
928 }
929 }
930 return S_FALSE;
931
932 }
933
934 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
935 {
936 /* IUnknown */
937 IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
938 IShellBrowserImpl_ICommDlgBrowser_AddRef,
939 IShellBrowserImpl_ICommDlgBrowser_Release,
940 /* ICommDlgBrowser */
941 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
942 IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
943 IShellBrowserImpl_ICommDlgBrowser_IncludeObject
944 };
945
946
947
948
949 /*
950 * IServiceProvider
951 */
952
953 /***************************************************************************
954 * IShellBrowserImpl_IServiceProvider_QueryInterface
955 */
956 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
957 IServiceProvider *iface,
958 REFIID riid,
959 LPVOID *ppvObj)
960 {
961 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
962
963 FIXME("(%p)\n", This);
964
965 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
966 }
967
968 /**************************************************************************
969 * IShellBrowserImpl_IServiceProvider_AddRef
970 */
971 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
972 {
973 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
974
975 FIXME("(%p)\n", This);
976
977 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
978 }
979
980 /**************************************************************************
981 * IShellBrowserImpl_IServiceProvider_Release
982 */
983 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
984 {
985 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
986
987 FIXME("(%p)\n", This);
988
989 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
990 }
991
992 /**************************************************************************
993 * IShellBrowserImpl_IServiceProvider_Release
994 *
995 * NOTES
996 * the w2k shellview asks for (guidService = SID_STopLevelBrowser,
997 * riid = IShellBrowser) to call SendControlMsg ().
998 *
999 * FIXME
1000 * this is a hack!
1001 */
1002
1003 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
1004 IServiceProvider * iface,
1005 REFGUID guidService,
1006 REFIID riid,
1007 void** ppv)
1008 {
1009 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1010
1011 FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) );
1012
1013 *ppv = NULL;
1014 if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
1015 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppv);
1016
1017 FIXME("(%p) unknown interface requested\n", This);
1018 return E_NOINTERFACE;
1019
1020 }
1021
1022 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1023 {
1024 /* IUnknown */
1025 IShellBrowserImpl_IServiceProvider_QueryInterface,
1026 IShellBrowserImpl_IServiceProvider_AddRef,
1027 IShellBrowserImpl_IServiceProvider_Release,
1028 /* IServiceProvider */
1029 IShellBrowserImpl_IServiceProvider_QueryService
1030 };