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