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