xref: /reactos/dll/win32/comdlg32/filedlgbrowser.c (revision c2c66aff)
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 };
1031