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