Sync with trunk revision 63128.
[reactos.git] / 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 IShellBrowserImpl *sb;
173 FileOpenDlgInfos *fodInfos = GetPropA(hwndOwner,FileOpenDlgInfosStr);
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,
197 REFIID riid,
198 LPVOID *ppvObj)
199 {
200 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
201
202 TRACE("(%p)\n\t%s\n", This, debugstr_guid(riid));
203
204 *ppvObj = NULL;
205
206 if(IsEqualIID(riid, &IID_IUnknown))
207 *ppvObj = &This->IShellBrowser_iface;
208 else if(IsEqualIID(riid, &IID_IOleWindow))
209 *ppvObj = &This->IShellBrowser_iface;
210 else if(IsEqualIID(riid, &IID_IShellBrowser))
211 *ppvObj = &This->IShellBrowser_iface;
212 else if(IsEqualIID(riid, &IID_ICommDlgBrowser))
213 *ppvObj = &This->ICommDlgBrowser_iface;
214 else if(IsEqualIID(riid, &IID_IServiceProvider))
215 *ppvObj = &This->IServiceProvider_iface;
216
217 if(*ppvObj) {
218 IUnknown_AddRef((IUnknown*)*ppvObj);
219 return S_OK;
220 }
221
222 FIXME("Unknown interface requested\n");
223 return E_NOINTERFACE;
224 }
225
226 /**************************************************************************
227 * IShellBrowser::AddRef
228 */
229 static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
230 {
231 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
232 ULONG ref = InterlockedIncrement(&This->ref);
233
234 TRACE("(%p,%u)\n", This, ref - 1);
235
236 return ref;
237 }
238
239 /**************************************************************************
240 * IShellBrowserImpl_Release
241 */
242 static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
243 {
244 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
245 ULONG ref = InterlockedDecrement(&This->ref);
246
247 TRACE("(%p,%u)\n", This, ref + 1);
248
249 if (!ref)
250 {
251 COMDLG32_SHFree(This);
252 TRACE("-- destroyed\n");
253 return 0;
254 }
255 return ref;
256 }
257
258 /*
259 * IOleWindow
260 */
261
262 /**************************************************************************
263 * IShellBrowserImpl_GetWindow (IOleWindow)
264 *
265 * Inherited from IOleWindow::GetWindow
266 *
267 * See Windows documentation for more details
268 *
269 * Note : We will never be window less in the File Open dialog
270 *
271 */
272 static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
273 HWND * phwnd)
274 {
275 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
276
277 TRACE("(%p)\n", This);
278
279 if(!This->hwndOwner)
280 return E_FAIL;
281
282 *phwnd = This->hwndOwner;
283
284 return (*phwnd) ? S_OK : E_UNEXPECTED;
285
286 }
287
288 /**************************************************************************
289 * IShellBrowserImpl_ContextSensitiveHelp
290 */
291 static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
292 BOOL fEnterMode)
293 {
294 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
295
296 TRACE("(%p)\n", This);
297
298 /* Feature not implemented */
299 return E_NOTIMPL;
300 }
301
302 /*
303 * IShellBrowser
304 */
305
306 /**************************************************************************
307 * IShellBrowserImpl_BrowseObject
308 *
309 * See Windows documentation on IShellBrowser::BrowseObject for more details
310 *
311 * This function will override user specified flags and will always
312 * use SBSP_DEFBROWSER and SBSP_DEFMODE.
313 */
314 static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
315 LPCITEMIDLIST pidl,
316 UINT wFlags)
317 {
318 HRESULT hRes;
319 IShellFolder *psfTmp;
320 IShellView *psvTmp;
321 FileOpenDlgInfos *fodInfos;
322 LPITEMIDLIST pidlTmp;
323 HWND hwndView;
324 HWND hDlgWnd;
325 BOOL bViewHasFocus;
326 RECT rectView;
327
328 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
329
330 TRACE("(%p)(pidl=%p,flags=0x%08x)\n", This, pidl, wFlags);
331 COMDLG32_DumpSBSPFlags(wFlags);
332
333 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
334
335 /* Format the pidl according to its parameter's category */
336 if(wFlags & SBSP_RELATIVE)
337 {
338
339 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */
340 if(FAILED(hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
341 pidl, NULL, &IID_IShellFolder, (LPVOID *)&psfTmp)))
342 {
343 ERR("bind to object failed\n");
344 return hRes;
345 }
346 /* create an absolute pidl */
347 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent, pidl);
348 }
349 else if(wFlags & SBSP_PARENT)
350 {
351 /* Browse the parent folder (ignores the pidl) */
352 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
353 psfTmp = GetShellFolderFromPidl(pidlTmp);
354
355 }
356 else /* SBSP_ABSOLUTE is 0x0000 */
357 {
358 /* An absolute pidl (relative from the desktop) */
359 pidlTmp = COMDLG32_PIDL_ILClone(pidl);
360 psfTmp = GetShellFolderFromPidl(pidlTmp);
361 }
362
363 if(!psfTmp)
364 {
365 ERR("could not browse to folder\n");
366 return E_FAIL;
367 }
368
369 /* If the pidl to browse to is equal to the actual pidl ...
370 do nothing and pretend you did it*/
371 if(COMDLG32_PIDL_ILIsEqual(pidlTmp,fodInfos->ShellInfos.pidlAbsCurrent))
372 {
373 IShellFolder_Release(psfTmp);
374 COMDLG32_SHFree(pidlTmp);
375 TRACE("keep current folder\n");
376 return NOERROR;
377 }
378
379 /* Release the current DataObject */
380 if (fodInfos->Shell.FOIDataObject)
381 {
382 IDataObject_Release(fodInfos->Shell.FOIDataObject);
383 fodInfos->Shell.FOIDataObject = NULL;
384 }
385
386 /* Create the associated view */
387 TRACE("create view object\n");
388 if(FAILED(hRes = IShellFolder_CreateViewObject(psfTmp, fodInfos->ShellInfos.hwndOwner,
389 &IID_IShellView, (LPVOID *)&psvTmp))) goto error;
390
391 /* Check if listview has focus */
392 bViewHasFocus = IsChild(fodInfos->ShellInfos.hwndView,GetFocus());
393
394 /* Get the foldersettings from the old view */
395 if(fodInfos->Shell.FOIShellView)
396 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView, &fodInfos->ShellInfos.folderSettings);
397
398 /* Release the old fodInfos->Shell.FOIShellView and update its value.
399 We have to update this early since ShellView_CreateViewWindow of native
400 shell32 calls OnStateChange and needs the correct view here.*/
401 if(fodInfos->Shell.FOIShellView)
402 {
403 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
404 IShellView_Release(fodInfos->Shell.FOIShellView);
405 }
406 fodInfos->Shell.FOIShellView = psvTmp;
407
408 /* Release old FOIShellFolder and update its value */
409 if (fodInfos->Shell.FOIShellFolder)
410 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
411 fodInfos->Shell.FOIShellFolder = psfTmp;
412
413 /* Release old pidlAbsCurrent and update its value */
414 COMDLG32_SHFree(fodInfos->ShellInfos.pidlAbsCurrent);
415 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
416
417 COMDLG32_UpdateCurrentDir(fodInfos);
418
419 GetWindowRect(GetDlgItem(This->hwndOwner, IDC_SHELLSTATIC), &rectView);
420 MapWindowPoints(0, This->hwndOwner, (LPPOINT)&rectView, 2);
421
422 /* Create the window */
423 TRACE("create view window\n");
424 if(FAILED(hRes = IShellView_CreateViewWindow(psvTmp, NULL,
425 &fodInfos->ShellInfos.folderSettings, fodInfos->Shell.FOIShellBrowser,
426 &rectView, &hwndView))) goto error;
427
428 fodInfos->ShellInfos.hwndView = hwndView;
429
430 /* Set view window control id to 5002 */
431 SetWindowLongPtrW(hwndView, GWLP_ID, lst2);
432 SendMessageW( hwndView, WM_SETFONT, SendMessageW( GetParent(hwndView), WM_GETFONT, 0, 0 ), FALSE );
433
434 /* Select the new folder in the Look In combo box of the Open file dialog */
435 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent);
436
437 /* changes the tab order of the ListView to reflect the window's File Dialog */
438 hDlgWnd = GetDlgItem(GetParent(hwndView), IDC_LOOKIN);
439 SetWindowPos(hwndView, hDlgWnd, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
440
441 /* Since we destroyed the old view if it had focus set focus to the newly created view */
442 if (bViewHasFocus)
443 SetFocus(fodInfos->ShellInfos.hwndView);
444
445 return hRes;
446 error:
447 ERR("Failed with error 0x%08x\n", hRes);
448 return hRes;
449 }
450
451 /**************************************************************************
452 * IShellBrowserImpl_EnableModelessSB
453 */
454 static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
455 BOOL fEnable)
456
457 {
458 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
459
460 TRACE("(%p)\n", This);
461
462 /* Feature not implemented */
463 return E_NOTIMPL;
464 }
465
466 /**************************************************************************
467 * IShellBrowserImpl_GetControlWindow
468 */
469 static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
470 UINT id,
471 HWND *lphwnd)
472
473 {
474 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
475
476 TRACE("(%p)\n", This);
477
478 /* Feature not implemented */
479 return E_NOTIMPL;
480 }
481
482 /**************************************************************************
483 * IShellBrowserImpl_GetViewStateStream
484 */
485 static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
486 DWORD grfMode,
487 LPSTREAM *ppStrm)
488
489 {
490 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
491
492 FIXME("(%p 0x%08x %p)\n", This, grfMode, ppStrm);
493
494 /* Feature not implemented */
495 return E_NOTIMPL;
496 }
497
498 /**************************************************************************
499 * IShellBrowserImpl_InsertMenusSB
500 */
501 static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
502 HMENU hmenuShared,
503 LPOLEMENUGROUPWIDTHS lpMenuWidths)
504
505 {
506 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
507
508 TRACE("(%p)\n", This);
509
510 /* Feature not implemented */
511 return E_NOTIMPL;
512 }
513
514 /**************************************************************************
515 * IShellBrowserImpl_OnViewWindowActive
516 */
517 static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
518 IShellView *ppshv)
519
520 {
521 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
522
523 TRACE("(%p)\n", This);
524
525 /* Feature not implemented */
526 return E_NOTIMPL;
527 }
528
529 /**************************************************************************
530 * IShellBrowserImpl_QueryActiveShellView
531 */
532 static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
533 IShellView **ppshv)
534
535 {
536 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
537
538 FileOpenDlgInfos *fodInfos;
539
540 TRACE("(%p)\n", This);
541
542 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
543
544 if(!(*ppshv = fodInfos->Shell.FOIShellView))
545 {
546 return E_FAIL;
547 }
548 IShellView_AddRef(fodInfos->Shell.FOIShellView);
549 return NOERROR;
550 }
551
552 /**************************************************************************
553 * IShellBrowserImpl_RemoveMenusSB
554 */
555 static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
556 HMENU hmenuShared)
557
558 {
559 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
560
561 TRACE("(%p)\n", This);
562
563 /* Feature not implemented */
564 return E_NOTIMPL;
565 }
566
567 /**************************************************************************
568 * IShellBrowserImpl_SendControlMsg
569 */
570 static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
571 UINT id,
572 UINT uMsg,
573 WPARAM wParam,
574 LPARAM lParam,
575 LRESULT *pret)
576
577 {
578 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
579 LRESULT lres;
580
581 TRACE("(%p)->(0x%08x 0x%08x 0x%08lx 0x%08lx %p)\n", This, id, uMsg, wParam, lParam, pret);
582
583 switch (id)
584 {
585 case FCW_TOOLBAR:
586 lres = SendDlgItemMessageA( This->hwndOwner, IDC_TOOLBAR, uMsg, wParam, lParam);
587 break;
588 default:
589 FIXME("ctrl id: %x\n", id);
590 return E_NOTIMPL;
591 }
592 if (pret) *pret = lres;
593 return S_OK;
594 }
595
596 /**************************************************************************
597 * IShellBrowserImpl_SetMenuSB
598 */
599 static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
600 HMENU hmenuShared,
601 HOLEMENU holemenuReserved,
602 HWND hwndActiveObject)
603
604 {
605 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
606
607 TRACE("(%p)\n", This);
608
609 /* Feature not implemented */
610 return E_NOTIMPL;
611 }
612
613 /**************************************************************************
614 * IShellBrowserImpl_SetStatusTextSB
615 */
616 static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
617 LPCOLESTR lpszStatusText)
618
619 {
620 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
621
622 TRACE("(%p)\n", This);
623
624 /* Feature not implemented */
625 return E_NOTIMPL;
626 }
627
628 /**************************************************************************
629 * IShellBrowserImpl_SetToolbarItems
630 */
631 static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
632 LPTBBUTTON lpButtons,
633 UINT nButtons,
634 UINT uFlags)
635
636 {
637 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
638
639 TRACE("(%p)\n", This);
640
641 /* Feature not implemented */
642 return E_NOTIMPL;
643 }
644
645 /**************************************************************************
646 * IShellBrowserImpl_TranslateAcceleratorSB
647 */
648 static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
649 LPMSG lpmsg,
650 WORD wID)
651
652 {
653 IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
654
655 TRACE("(%p)\n", This);
656
657 /* Feature not implemented */
658 return E_NOTIMPL;
659 }
660
661 static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
662 {
663 /* IUnknown */
664 IShellBrowserImpl_QueryInterface,
665 IShellBrowserImpl_AddRef,
666 IShellBrowserImpl_Release,
667 /* IOleWindow */
668 IShellBrowserImpl_GetWindow,
669 IShellBrowserImpl_ContextSensitiveHelp,
670 /* IShellBrowser */
671 IShellBrowserImpl_InsertMenusSB,
672 IShellBrowserImpl_SetMenuSB,
673 IShellBrowserImpl_RemoveMenusSB,
674 IShellBrowserImpl_SetStatusTextSB,
675 IShellBrowserImpl_EnableModelessSB,
676 IShellBrowserImpl_TranslateAcceleratorSB,
677 IShellBrowserImpl_BrowseObject,
678 IShellBrowserImpl_GetViewStateStream,
679 IShellBrowserImpl_GetControlWindow,
680 IShellBrowserImpl_SendControlMsg,
681 IShellBrowserImpl_QueryActiveShellView,
682 IShellBrowserImpl_OnViewWindowActive,
683 IShellBrowserImpl_SetToolbarItems
684 };
685
686
687
688 /*
689 * ICommDlgBrowser
690 */
691
692 /***************************************************************************
693 * IShellBrowserImpl_ICommDlgBrowser_QueryInterface
694 */
695 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(
696 ICommDlgBrowser *iface,
697 REFIID riid,
698 LPVOID *ppvObj)
699 {
700 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
701
702 TRACE("(%p)\n", This);
703
704 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
705 }
706
707 /**************************************************************************
708 * IShellBrowserImpl_ICommDlgBrowser_AddRef
709 */
710 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
711 {
712 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
713
714 TRACE("(%p)\n", This);
715
716 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
717 }
718
719 /**************************************************************************
720 * IShellBrowserImpl_ICommDlgBrowser_Release
721 */
722 static ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
723 {
724 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
725
726 TRACE("(%p)\n", This);
727
728 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
729 }
730
731 /**************************************************************************
732 * IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
733 *
734 * Called when a user double-clicks in the view or presses the ENTER key
735 */
736 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
737 IShellView *ppshv)
738 {
739 LPITEMIDLIST pidl;
740 FileOpenDlgInfos *fodInfos;
741
742 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
743
744 TRACE("(%p)\n", This);
745
746 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
747
748 /* If the selected object is not a folder, send an IDOK command to parent window */
749 if((pidl = GetPidlFromDataObject(fodInfos->Shell.FOIDataObject, 1)))
750 {
751 HRESULT hRes;
752
753 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
754 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, (LPCITEMIDLIST *)&pidl, &ulAttr);
755 if (ulAttr & (SFGAO_FOLDER | SFGAO_HASSUBFOLDER) )
756 {
757 hRes = IShellBrowser_BrowseObject(&This->IShellBrowser_iface,pidl,SBSP_RELATIVE);
758 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
759 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_FOLDERCHANGE);
760 }
761 else
762 {
763 /* Tell the dialog that the user selected a file */
764 PostMessageA(This->hwndOwner, WM_COMMAND, IDOK, 0L);
765 hRes = S_OK;
766 }
767
768 /* Free memory used by pidl */
769 COMDLG32_SHFree(pidl);
770
771 return hRes;
772 }
773
774 return E_FAIL;
775 }
776
777 /**************************************************************************
778 * IShellBrowserImpl_OnSelChange
779 */
780 static HRESULT IShellBrowserImpl_OnSelChange(IShellBrowserImpl *This, const IShellView *ppshv)
781 {
782 FileOpenDlgInfos *fodInfos;
783
784 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
785 TRACE("(%p do=%p view=%p)\n", This, fodInfos->Shell.FOIDataObject, fodInfos->Shell.FOIShellView);
786
787 /* release old selections */
788 if (fodInfos->Shell.FOIDataObject)
789 IDataObject_Release(fodInfos->Shell.FOIDataObject);
790
791 /* get a new DataObject from the ShellView */
792 if(FAILED(IShellView_GetItemObject(fodInfos->Shell.FOIShellView, SVGIO_SELECTION,
793 &IID_IDataObject, (void**)&fodInfos->Shell.FOIDataObject)))
794 return E_FAIL;
795
796 FILEDLG95_FILENAME_FillFromSelection(This->hwndOwner);
797
798 if(fodInfos->ofnInfos->Flags & OFN_EXPLORER)
799 SendCustomDlgNotificationMessage(This->hwndOwner, CDN_SELCHANGE);
800 return S_OK;
801 }
802
803 /**************************************************************************
804 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange
805 */
806 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
807 IShellView *ppshv,
808 ULONG uChange)
809 {
810
811 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
812
813 TRACE("(%p shv=%p)\n", This, ppshv);
814
815 switch (uChange)
816 {
817 case CDBOSC_SETFOCUS:
818 /* FIXME: Reset the default button.
819 This should be taken care of by defdlg. If control
820 other than button receives focus the default button
821 should be restored. */
822 SendMessageA(This->hwndOwner, DM_SETDEFID, IDOK, 0);
823
824 break;
825 case CDBOSC_KILLFOCUS:
826 {
827 FileOpenDlgInfos *fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
828 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
829 {
830 WCHAR szSave[16];
831 LoadStringW(COMDLG32_hInstance, IDS_SAVE_BUTTON, szSave, sizeof(szSave)/sizeof(WCHAR));
832 SetDlgItemTextW(fodInfos->ShellInfos.hwndOwner, IDOK, szSave);
833 }
834 }
835 break;
836 case CDBOSC_SELCHANGE:
837 return IShellBrowserImpl_OnSelChange(This, ppshv);
838 case CDBOSC_RENAME:
839 /* nothing to do */
840 break;
841 }
842
843 return NOERROR;
844 }
845
846 /* send_includeitem_notification
847 *
848 * Sends a CDN_INCLUDEITEM notification for "pidl" to hwndParentDlg
849 */
850 static LRESULT send_includeitem_notification(HWND hwndParentDlg, LPCITEMIDLIST pidl)
851 {
852 LRESULT hook_result = 0;
853 FileOpenDlgInfos *fodInfos = GetPropA(hwndParentDlg, FileOpenDlgInfosStr);
854
855 if(!fodInfos) return 0;
856
857 if(fodInfos->DlgInfos.hwndCustomDlg)
858 {
859 TRACE("call notify CDN_INCLUDEITEM for pidl=%p\n", pidl);
860 if(fodInfos->unicode)
861 {
862 OFNOTIFYEXW ofnNotify;
863 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
864 ofnNotify.pidl = (LPITEMIDLIST)pidl;
865 ofnNotify.hdr.hwndFrom = hwndParentDlg;
866 ofnNotify.hdr.idFrom = 0;
867 ofnNotify.hdr.code = CDN_INCLUDEITEM;
868 ofnNotify.lpOFN = fodInfos->ofnInfos;
869 hook_result = SendMessageW(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
870 }
871 else
872 {
873 OFNOTIFYEXA ofnNotify;
874 ofnNotify.psf = fodInfos->Shell.FOIShellFolder;
875 ofnNotify.pidl = (LPITEMIDLIST)pidl;
876 ofnNotify.hdr.hwndFrom = hwndParentDlg;
877 ofnNotify.hdr.idFrom = 0;
878 ofnNotify.hdr.code = CDN_INCLUDEITEM;
879 ofnNotify.lpOFN = (LPOPENFILENAMEA)fodInfos->ofnInfos;
880 hook_result = SendMessageA(fodInfos->DlgInfos.hwndCustomDlg, WM_NOTIFY, 0, (LPARAM)&ofnNotify);
881 }
882 }
883 TRACE("Retval: 0x%08lx\n", hook_result);
884 return hook_result;
885 }
886
887 /**************************************************************************
888 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject
889 */
890 static HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
891 IShellView * ppshv,
892 LPCITEMIDLIST pidl)
893 {
894 FileOpenDlgInfos *fodInfos;
895 ULONG ulAttr;
896 STRRET str;
897 WCHAR szPathW[MAX_PATH];
898
899 IShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
900
901 TRACE("(%p)\n", This);
902
903 fodInfos = GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
904
905 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK;
906 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
907
908 if( (ulAttr & SFGAO_HIDDEN) || /* hidden */
909 !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
910 return S_FALSE;
911
912 /* always include directories and links */
913 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
914 return S_OK;
915
916 /* if the application takes care of including the item we are done */
917 if(fodInfos->ofnInfos->Flags & OFN_ENABLEINCLUDENOTIFY &&
918 send_includeitem_notification(This->hwndOwner, pidl))
919 return S_OK;
920
921 /* Check if there is a mask to apply if not */
922 if(!fodInfos->ShellInfos.lpstrCurrentFilter || !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter))
923 return S_OK;
924
925 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &str)))
926 {
927 if (COMDLG32_StrRetToStrNW(szPathW, MAX_PATH, &str, pidl))
928 {
929 if (PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
930 return S_OK;
931 }
932 }
933 return S_FALSE;
934
935 }
936
937 static const ICommDlgBrowserVtbl IShellBrowserImpl_ICommDlgBrowser_Vtbl =
938 {
939 /* IUnknown */
940 IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
941 IShellBrowserImpl_ICommDlgBrowser_AddRef,
942 IShellBrowserImpl_ICommDlgBrowser_Release,
943 /* ICommDlgBrowser */
944 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
945 IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
946 IShellBrowserImpl_ICommDlgBrowser_IncludeObject
947 };
948
949
950
951
952 /*
953 * IServiceProvider
954 */
955
956 /***************************************************************************
957 * IShellBrowserImpl_IServiceProvider_QueryInterface
958 */
959 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryInterface(
960 IServiceProvider *iface,
961 REFIID riid,
962 LPVOID *ppvObj)
963 {
964 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
965
966 FIXME("(%p)\n", This);
967
968 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppvObj);
969 }
970
971 /**************************************************************************
972 * IShellBrowserImpl_IServiceProvider_AddRef
973 */
974 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_AddRef(IServiceProvider * iface)
975 {
976 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
977
978 FIXME("(%p)\n", This);
979
980 return IShellBrowserImpl_AddRef(&This->IShellBrowser_iface);
981 }
982
983 /**************************************************************************
984 * IShellBrowserImpl_IServiceProvider_Release
985 */
986 static ULONG WINAPI IShellBrowserImpl_IServiceProvider_Release(IServiceProvider * iface)
987 {
988 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
989
990 FIXME("(%p)\n", This);
991
992 return IShellBrowserImpl_Release(&This->IShellBrowser_iface);
993 }
994
995 /**************************************************************************
996 * IShellBrowserImpl_IServiceProvider_Release
997 *
998 * NOTES
999 * the w2k shellview asks for (guidService = SID_STopLevelBrowser,
1000 * riid = IShellBrowser) to call SendControlMsg ().
1001 *
1002 * FIXME
1003 * this is a hack!
1004 */
1005
1006 static HRESULT WINAPI IShellBrowserImpl_IServiceProvider_QueryService(
1007 IServiceProvider * iface,
1008 REFGUID guidService,
1009 REFIID riid,
1010 void** ppv)
1011 {
1012 IShellBrowserImpl *This = impl_from_IServiceProvider(iface);
1013
1014 FIXME("(%p)\n\t%s\n\t%s\n", This,debugstr_guid(guidService), debugstr_guid(riid) );
1015
1016 *ppv = NULL;
1017 if(guidService && IsEqualIID(guidService, &SID_STopLevelBrowser))
1018 return IShellBrowserImpl_QueryInterface(&This->IShellBrowser_iface,riid,ppv);
1019
1020 FIXME("(%p) unknown interface requested\n", This);
1021 return E_NOINTERFACE;
1022
1023 }
1024
1025 static const IServiceProviderVtbl IShellBrowserImpl_IServiceProvider_Vtbl =
1026 {
1027 /* IUnknown */
1028 IShellBrowserImpl_IServiceProvider_QueryInterface,
1029 IShellBrowserImpl_IServiceProvider_AddRef,
1030 IShellBrowserImpl_IServiceProvider_Release,
1031 /* IServiceProvider */
1032 IShellBrowserImpl_IServiceProvider_QueryService
1033 };