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