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