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