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