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