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