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