2 * Implementation of IShellBrowser for the File Open common dialog
9 #include "filedlgbrowser.h"
12 #include "wine/obj_dataobject.h"
13 #include "debugtools.h"
15 #include "wine/undocshell.h"
17 DEFAULT_DEBUG_CHANNEL(commdlg)
19 #define SETDefFormatEtc(fe,cf,med) \
22 (fe).dwAspect = DVASPECT_CONTENT; \
29 /**************************************************************************
32 static ICOM_VTABLE(IShellBrowser) IShellBrowserImpl_Vtbl =
35 IShellBrowserImpl_QueryInterface,
36 IShellBrowserImpl_AddRef,
37 IShellBrowserImpl_Release,
39 IShellBrowserImpl_GetWindow,
40 IShellBrowserImpl_ContextSensitiveHelp,
42 IShellBrowserImpl_InsertMenusSB,
43 IShellBrowserImpl_SetMenuSB,
44 IShellBrowserImpl_RemoveMenusSB,
45 IShellBrowserImpl_SetStatusTextSB,
46 IShellBrowserImpl_EnableModelessSB,
47 IShellBrowserImpl_TranslateAcceleratorSB,
48 IShellBrowserImpl_BrowseObject,
49 IShellBrowserImpl_GetViewStateStream,
50 IShellBrowserImpl_GetControlWindow,
51 IShellBrowserImpl_SendControlMsg,
52 IShellBrowserImpl_QueryActiveShellView,
53 IShellBrowserImpl_OnViewWindowActive,
54 IShellBrowserImpl_SetToolbarItems
57 static ICOM_VTABLE(ICommDlgBrowser) IShellBrowserImpl_ICommDlgBrowser_Vtbl =
60 IShellBrowserImpl_ICommDlgBrowser_QueryInterface,
61 IShellBrowserImpl_ICommDlgBrowser_AddRef,
62 IShellBrowserImpl_ICommDlgBrowser_Release,
64 IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand,
65 IShellBrowserImpl_ICommDlgBrowser_OnStateChange,
66 IShellBrowserImpl_ICommDlgBrowser_IncludeObject
70 /**************************************************************************
74 HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, IShellView *ppshv);
75 //LPITEMIDLIST GetSelectedPidl(IShellView *ppshv);
77 /**************************************************************************
80 extern const char *FileOpenDlgInfosStr;
82 extern HRESULT GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST pidl,DWORD dwFlags,LPSTR lpstrFileName);
83 extern HRESULT GetFileName(HWND hwnd, LPITEMIDLIST pidl, LPSTR lpstrFileName);
84 extern IShellFolder* GetShellFolderFromPidl(LPITEMIDLIST pidlAbs);
85 extern LPITEMIDLIST GetParentPidl(LPITEMIDLIST pidl);
86 extern LPITEMIDLIST GetPidlFromName(IShellFolder *psf,LPCSTR lpcstrFileName);
88 extern BOOL FILEDLG95_SHELL_FillIncludedItemList(HWND hwnd,
89 LPITEMIDLIST pidlCurrentFolder,
92 extern int FILEDLG95_LOOKIN_SelectItem(HWND hwnd,LPITEMIDLIST pidl);
93 extern BOOL FILEDLG95_OnOpen(HWND hwnd);
96 /**************************************************************************
97 * IShellBrowserImpl_Construct
99 IShellBrowser * IShellBrowserImpl_Construct(HWND hwndOwner)
101 IShellBrowserImpl *sb;
102 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(hwndOwner,FileOpenDlgInfosStr);
104 sb=(IShellBrowserImpl*)SHAlloc(sizeof(IShellBrowserImpl));
106 /* Initialisation of the member variables */
108 sb->hwndOwner = hwndOwner;
110 /* Initialisation of the vTables */
111 sb->lpVtbl = &IShellBrowserImpl_Vtbl;
112 sb->lpVtbl2 = &IShellBrowserImpl_ICommDlgBrowser_Vtbl;
114 COMDLG32_SHGetSpecialFolderLocation(hwndOwner,
116 &fodInfos->ShellInfos.pidlAbsCurrent);
120 return (IShellBrowser *) sb;
123 /**************************************************************************
126 * The INTERFACE of the IShellBrowser object
134 /***************************************************************************
135 * IShellBrowserImpl_QueryInterface
137 HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
141 ICOM_THIS(IShellBrowserImpl, iface);
143 TRACE("(%p)\n", This);
147 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
150 else if(IsEqualIID(riid, &IID_IOleWindow)) /*IOleWindow*/
151 { *ppvObj = (IOleWindow*)This;
154 else if(IsEqualIID(riid, &IID_IShellBrowser)) /*IShellBrowser*/
155 { *ppvObj = (IShellBrowser*)This;
158 else if(IsEqualIID(riid, &IID_ICommDlgBrowser)) /*ICommDlgBrowser*/
159 { *ppvObj = (ICommDlgBrowser*) &(This->lpVtbl2);
163 { IUnknown_AddRef( (IShellBrowser*) *ppvObj);
166 return E_NOINTERFACE;
169 /**************************************************************************
170 * IShellBrowser::AddRef
172 ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
174 ICOM_THIS(IShellBrowserImpl, iface);
176 TRACE("(%p)\n", This);
178 return ++(This->ref);
181 /**************************************************************************
182 * IShellBrowserImpl_Release
184 ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
186 ICOM_THIS(IShellBrowserImpl, iface);
188 TRACE("(%p)\n", This);
192 COMDLG32_SHFree(This);
202 /**************************************************************************
203 * IShellBrowserImpl_GetWindow (IOleWindow)
205 * Inherited from IOleWindow::GetWindow
207 * See Windows documentation for more details
209 * Note : We will never be window less in the File Open dialog
212 HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser * iface,
215 ICOM_THIS(IShellBrowserImpl, iface);
217 TRACE("(%p)\n", This);
222 *phwnd = This->hwndOwner;
224 return (*phwnd) ? S_OK : E_UNEXPECTED;
228 /**************************************************************************
229 * IShellBrowserImpl_ContextSensitiveHelp
231 HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser * iface,
234 ICOM_THIS(IShellBrowserImpl, iface);
236 TRACE("(%p)\n", This);
238 /* Feature not implemented */
246 /**************************************************************************
247 * IShellBrowserImpl_BrowseObject
249 * See Windows documentation on IShellBrowser::BrowseObject for more details
251 * This function will override user specified flags and will always
252 * use SBSP_DEFBROWSER and SBSP_DEFMODE.
254 HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
259 IShellFolder *psfTmp;
261 FileOpenDlgInfos *fodInfos;
262 LPITEMIDLIST pidlTmp;
264 ICOM_THIS(IShellBrowserImpl, iface);
266 TRACE("(%p)\n", This);
268 fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
270 /* Format the pidl according to its parameter's category */
271 if(wFlags & SBSP_RELATIVE)
274 /* SBSP_RELATIVE A relative pidl (relative from the current folder) */
275 hRes = IShellFolder_BindToObject(fodInfos->Shell.FOIShellFolder,
284 /* create an absolute pidl */
285 pidlTmp = COMDLG32_PIDL_ILCombine(fodInfos->ShellInfos.pidlAbsCurrent,
289 else if(wFlags & SBSP_PARENT)
291 /* Browse the parent folder (ignores the pidl) */
293 pidlTmp = GetParentPidl(fodInfos->ShellInfos.pidlAbsCurrent);
294 psfTmp = GetShellFolderFromPidl(pidlTmp);
299 /* An absolute pidl (relative from the desktop) */
300 pidlTmp = COMDLG32_PIDL_ILClone((LPITEMIDLIST)pidl);
301 psfTmp = GetShellFolderFromPidl(pidlTmp);
305 /* Retrieve the IShellFolder interface of the pidl specified folder */
309 /* Release the current fodInfos->Shell.FOIShellFolder and update its value */
310 IShellFolder_Release(fodInfos->Shell.FOIShellFolder);
311 fodInfos->Shell.FOIShellFolder = psfTmp;
313 /* Create the associated view */
314 if(SUCCEEDED(hRes = IShellFolder_CreateViewObject(psfTmp,
315 fodInfos->ShellInfos.hwndOwner,
320 /* Get the foldersettings from the old view */
321 if(fodInfos->Shell.FOIShellView)
323 IShellView_GetCurrentInfo(fodInfos->Shell.FOIShellView,
324 &fodInfos->ShellInfos.folderSettings);
327 /* Create the window */
328 if(SUCCEEDED(hRes = IShellView_CreateViewWindow(psvTmp,
330 &fodInfos->ShellInfos.folderSettings,
331 fodInfos->Shell.FOIShellBrowser,
332 &fodInfos->ShellInfos.rectView,
335 /* Fit the created view in the appropriate RECT */
337 fodInfos->ShellInfos.rectView.left,
338 fodInfos->ShellInfos.rectView.top,
339 fodInfos->ShellInfos.rectView.right-fodInfos->ShellInfos.rectView.left,
340 fodInfos->ShellInfos.rectView.bottom-fodInfos->ShellInfos.rectView.top,
343 /* Select the new folder in the Look In combo box of the Open file dialog */
345 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,pidlTmp);
347 /* Release old pidlAbsCurrent memory and update its value */
348 COMDLG32_SHFree((LPVOID)fodInfos->ShellInfos.pidlAbsCurrent);
349 fodInfos->ShellInfos.pidlAbsCurrent = pidlTmp;
351 /* Release the current fodInfos->Shell.FOIShellView and update its value */
352 if(fodInfos->Shell.FOIShellView)
354 IShellView_DestroyViewWindow(fodInfos->Shell.FOIShellView);
355 IShellView_Release(fodInfos->Shell.FOIShellView);
358 ShowWindow(fodInfos->ShellInfos.hwndView,SW_HIDE);
360 fodInfos->Shell.FOIShellView = psvTmp;
362 fodInfos->ShellInfos.hwndView = hwndView;
368 FILEDLG95_LOOKIN_SelectItem(fodInfos->DlgInfos.hwndLookInCB,fodInfos->ShellInfos.pidlAbsCurrent);
372 /**************************************************************************
373 * IShellBrowserImpl_EnableModelessSB
375 HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
379 ICOM_THIS(IShellBrowserImpl, iface);
381 TRACE("(%p)\n", This);
383 /* Feature not implemented */
387 /**************************************************************************
388 * IShellBrowserImpl_GetControlWindow
390 HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
395 ICOM_THIS(IShellBrowserImpl, iface);
397 TRACE("(%p)\n", This);
399 /* Feature not implemented */
402 /**************************************************************************
403 * IShellBrowserImpl_GetViewStateStream
405 HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
410 ICOM_THIS(IShellBrowserImpl, iface);
412 TRACE("(%p)\n", This);
414 /* Feature not implemented */
417 /**************************************************************************
418 * IShellBrowserImpl_InsertMenusSB
420 HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
422 LPOLEMENUGROUPWIDTHS lpMenuWidths)
425 ICOM_THIS(IShellBrowserImpl, iface);
427 TRACE("(%p)\n", This);
429 /* Feature not implemented */
432 /**************************************************************************
433 * IShellBrowserImpl_OnViewWindowActive
435 HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
439 ICOM_THIS(IShellBrowserImpl, iface);
441 TRACE("(%p)\n", This);
443 /* Feature not implemented */
446 /**************************************************************************
447 * IShellBrowserImpl_QueryActiveShellView
449 HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
453 ICOM_THIS(IShellBrowserImpl, iface);
455 FileOpenDlgInfos *fodInfos;
457 TRACE("(%p)\n", This);
459 fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
461 if(!(*ppshv = fodInfos->Shell.FOIShellView))
465 IShellView_AddRef(fodInfos->Shell.FOIShellView);
468 /**************************************************************************
469 * IShellBrowserImpl_RemoveMenusSB
471 HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
475 ICOM_THIS(IShellBrowserImpl, iface);
477 TRACE("(%p)\n", This);
479 /* Feature not implemented */
482 /**************************************************************************
483 * IShellBrowserImpl_SendControlMsg
485 HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
493 ICOM_THIS(IShellBrowserImpl, iface);
495 TRACE("(%p)\n", This);
497 /* Feature not implemented */
500 /**************************************************************************
501 * IShellBrowserImpl_SetMenuSB
503 HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
505 HOLEMENU holemenuReserved,
506 HWND hwndActiveObject)
509 ICOM_THIS(IShellBrowserImpl, iface);
511 TRACE("(%p)\n", This);
513 /* Feature not implemented */
516 /**************************************************************************
517 * IShellBrowserImpl_SetStatusTextSB
519 HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
520 LPCOLESTR lpszStatusText)
523 ICOM_THIS(IShellBrowserImpl, iface);
525 TRACE("(%p)\n", This);
527 /* Feature not implemented */
530 /**************************************************************************
531 * IShellBrowserImpl_SetToolbarItems
533 HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
534 LPTBBUTTON lpButtons,
539 ICOM_THIS(IShellBrowserImpl, iface);
541 TRACE("(%p)\n", This);
543 /* Feature not implemented */
546 /**************************************************************************
547 * IShellBrowserImpl_TranslateAcceleratorSB
549 HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
554 ICOM_THIS(IShellBrowserImpl, iface);
556 TRACE("(%p)\n", This);
558 /* Feature not implemented */
566 /***************************************************************************
567 * IShellBrowserImpl_ICommDlgBrowser_QueryInterface
569 HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_QueryInterface(ICommDlgBrowser *iface,
573 _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);
575 TRACE("(%p)\n", This);
577 return IShellBrowserImpl_QueryInterface(This,riid,ppvObj);
580 /**************************************************************************
581 * IShellBrowserImpl_ICommDlgBrowser_AddRef
583 ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_AddRef(ICommDlgBrowser * iface)
585 _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);
587 TRACE("(%p)\n", This);
589 return IShellBrowserImpl_AddRef(This);
592 /**************************************************************************
593 * IShellBrowserImpl_ICommDlgBrowser_Release
595 ULONG WINAPI IShellBrowserImpl_ICommDlgBrowser_Release(ICommDlgBrowser * iface)
597 _ICOM_THIS_FromICommDlgBrowser(IShellBrowser,iface);
599 TRACE("(%p)\n", This);
601 return IShellBrowserImpl_Release(This);
603 /**************************************************************************
604 * IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
606 * Called when a user double-clicks in the view or presses the ENTER key
608 HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(ICommDlgBrowser *iface,
612 FileOpenDlgInfos *fodInfos;
614 _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);
616 TRACE("(%p)\n", This);
618 fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
620 /* If the selected object is not a folder, send a IDOK command to parent window */
621 if((pidl = GetSelectedPidl(ppshv)))
625 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
626 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
628 hRes = IShellBrowser_BrowseObject((IShellBrowser *)This,pidl,SBSP_RELATIVE);
629 /* Tell the dialog that the user selected a file */
632 hRes = FILEDLG95_OnOpen(This->hwndOwner);
635 /* Free memory used by pidl */
636 COMDLG32_SHFree((LPVOID)pidl);
644 /**************************************************************************
645 * IShellBrowserImpl_ICommDlgBrowser_OnStateChange
647 HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_OnStateChange(ICommDlgBrowser *iface,
652 _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);
654 TRACE("(%p)\n", This);
658 case CDBOSC_SETFOCUS:
660 case CDBOSC_KILLFOCUS:
662 FileOpenDlgInfos *fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
663 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
664 SetDlgItemTextA(fodInfos->ShellInfos.hwndOwner,IDOK,"&Save");
667 case CDBOSC_SELCHANGE:
668 return IShellBrowserImpl_ICommDlgBrowser_OnSelChange(iface,ppshv);
675 /**************************************************************************
676 * IShellBrowserImpl_ICommDlgBrowser_IncludeObject
678 HRESULT WINAPI IShellBrowserImpl_ICommDlgBrowser_IncludeObject(ICommDlgBrowser *iface,
682 FileOpenDlgInfos *fodInfos;
685 WCHAR szPathW[MAX_PATH];
687 _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);
689 TRACE("(%p)\n", This);
691 fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
693 ulAttr = SFGAO_HIDDEN | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR | SFGAO_LINK;
694 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
697 if( (ulAttr & SFGAO_HIDDEN) /* hidden */
698 | !(ulAttr & (SFGAO_FILESYSTEM | SFGAO_FILESYSANCESTOR))) /* special folder */
700 /* always include directorys and links */
701 if(ulAttr & (SFGAO_FOLDER | SFGAO_LINK))
703 /* Check if there is a mask to apply if not */
704 if(!fodInfos->ShellInfos.lpstrCurrentFilter ||
705 !lstrlenW(fodInfos->ShellInfos.lpstrCurrentFilter))
708 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(fodInfos->Shell.FOIShellFolder, pidl, SHGDN_FORPARSING, &str)))
709 { if (SUCCEEDED(COMDLG32_StrRetToBufW(&str, pidl,szPathW, MAX_PATH)))
711 if (COMDLG32_PathMatchSpecW(szPathW, fodInfos->ShellInfos.lpstrCurrentFilter))
719 /**************************************************************************
720 * IShellBrowserImpl_ICommDlgBrowser_OnSelChange
722 HRESULT IShellBrowserImpl_ICommDlgBrowser_OnSelChange(ICommDlgBrowser *iface, IShellView *ppshv)
725 FileOpenDlgInfos *fodInfos;
726 _ICOM_THIS_FromICommDlgBrowser(IShellBrowserImpl,iface);
728 fodInfos = (FileOpenDlgInfos *) GetPropA(This->hwndOwner,FileOpenDlgInfosStr);
729 TRACE("(%p)\n", This);
731 if((pidl = GetSelectedPidl(ppshv)))
733 HRESULT hRes = E_FAIL;
734 char lpstrFileName[MAX_PATH];
736 ULONG ulAttr = SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
737 IShellFolder_GetAttributesOf(fodInfos->Shell.FOIShellFolder, 1, &pidl, &ulAttr);
740 if(SUCCEEDED(hRes = GetName(fodInfos->Shell.FOIShellFolder,pidl,SHGDN_NORMAL,lpstrFileName)))
741 SetWindowTextA(fodInfos->DlgInfos.hwndFileName,lpstrFileName);
742 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
743 SetDlgItemTextA(fodInfos->ShellInfos.hwndOwner,IDOK,"&Save");
746 SetDlgItemTextA(fodInfos->ShellInfos.hwndOwner,IDOK,"&Open");
748 fodInfos->DlgInfos.dwDlgProp |= FODPROP_USEVIEW;
750 COMDLG32_SHFree((LPVOID)pidl);
753 if(fodInfos->DlgInfos.dwDlgProp & FODPROP_SAVEDLG)
754 SetDlgItemTextA(fodInfos->ShellInfos.hwndOwner,IDOK,"&Save");
756 fodInfos->DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
760 /***********************************************************************
763 * Return the pidl of the first selected item in the view
765 LPITEMIDLIST GetSelectedPidl(IShellView *ppshv)
768 IDataObject *doSelected;
769 LPITEMIDLIST pidlSelected = NULL;
771 TRACE("sv=%p\n", ppshv);
773 /* Get an IDataObject from the view */
774 if(SUCCEEDED(IShellView_GetItemObject(ppshv,
777 (LPVOID *)&doSelected)))
782 /* Set the FORMATETC structure*/
783 SETDefFormatEtc(formatetc,
784 RegisterClipboardFormatA(CFSTR_SHELLIDLIST),
787 /* Get the pidl from IDataObject */
788 if(SUCCEEDED(IDataObject_GetData(doSelected,&formatetc,&medium)))
790 LPIDA cida = GlobalLock(medium.u.hGlobal);
791 TRACE("cida=%p\n", cida);
792 pidlSelected = COMDLG32_PIDL_ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[1]]));
794 if(medium.pUnkForRelease)
795 IUnknown_Release(medium.pUnkForRelease);
798 GlobalUnlock(medium.u.hGlobal);
799 GlobalFree(medium.u.hGlobal);
802 IDataObject_Release(doSelected);