4 * Copyright 2010,2011 David Hedberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
36 #include "filedlgbrowser.h"
38 #include "wine/debug.h"
39 #include "wine/list.h"
41 #define IDC_NAV_TOOLBAR 200
42 #define IDC_NAVBACK 201
43 #define IDC_NAVFORWARD 202
45 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
54 IFileDialogEvents *pfde;
58 typedef struct FileDialogImpl {
59 IFileDialog2 IFileDialog2_iface;
61 IFileOpenDialog IFileOpenDialog_iface;
62 IFileSaveDialog IFileSaveDialog_iface;
64 enum ITEMDLG_TYPE dlg_type;
65 IExplorerBrowserEvents IExplorerBrowserEvents_iface;
66 IServiceProvider IServiceProvider_iface;
67 ICommDlgBrowser3 ICommDlgBrowser3_iface;
68 IOleWindow IOleWindow_iface;
71 FILEOPENDIALOGOPTIONS options;
72 COMDLG_FILTERSPEC *filterspecs;
73 UINT filterspec_count;
76 struct list events_clients;
77 DWORD events_next_cookie;
79 IShellItemArray *psia_selection;
80 IShellItemArray *psia_results;
81 IShellItem *psi_defaultfolder;
82 IShellItem *psi_setfolder;
83 IShellItem *psi_folder;
86 IExplorerBrowser *peb;
87 DWORD ebevents_cookie;
92 LPWSTR custom_okbutton;
93 LPWSTR custom_cancelbutton;
94 LPWSTR custom_filenamelabel;
97 /**************************************************************************
100 static HRESULT events_OnFileOk(FileDialogImpl *This)
102 events_client *cursor;
106 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
108 TRACE("Notifying %p\n", cursor);
109 hr = IFileDialogEvents_OnFileOk(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
110 if(FAILED(hr) && hr != E_NOTIMPL)
120 static HRESULT events_OnFolderChanging(FileDialogImpl *This, IShellItem *folder)
122 events_client *cursor;
124 TRACE("%p (%p)\n", This, folder);
126 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
128 TRACE("Notifying %p\n", cursor);
129 hr = IFileDialogEvents_OnFolderChanging(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface, folder);
130 if(FAILED(hr) && hr != E_NOTIMPL)
140 static void events_OnFolderChange(FileDialogImpl *This)
142 events_client *cursor;
145 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
147 TRACE("Notifying %p\n", cursor);
148 IFileDialogEvents_OnFolderChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
152 static void events_OnSelectionChange(FileDialogImpl *This)
154 events_client *cursor;
157 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
159 TRACE("Notifying %p\n", cursor);
160 IFileDialogEvents_OnSelectionChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
164 /**************************************************************************
167 static UINT get_file_name(FileDialogImpl *This, LPWSTR *str)
169 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
174 if(This->set_filename)
176 len = lstrlenW(This->set_filename);
177 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
178 lstrcpyW(*str, This->set_filename);
184 len = SendMessageW(hwnd_edit, WM_GETTEXTLENGTH, 0, 0);
185 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
189 SendMessageW(hwnd_edit, WM_GETTEXT, len+1, (LPARAM)*str);
193 static BOOL set_file_name(FileDialogImpl *This, LPCWSTR str)
195 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
197 if(This->set_filename)
198 LocalFree(This->set_filename);
200 This->set_filename = StrDupW(str);
202 return SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str);
205 static void fill_filename_from_selection(FileDialogImpl *This)
210 UINT item_count, valid_count;
213 if(!This->psia_selection)
216 hr = IShellItemArray_GetCount(This->psia_selection, &item_count);
217 if(FAILED(hr) || !item_count)
220 names = HeapAlloc(GetProcessHeap(), 0, item_count*sizeof(LPWSTR));
222 /* Get names of the selected items */
223 valid_count = 0; len_total = 0;
224 for(i = 0; i < item_count; i++)
226 hr = IShellItemArray_GetItemAt(This->psia_selection, i, &psi);
231 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &attr);
232 if(SUCCEEDED(hr) && (attr & SFGAO_FOLDER))
233 continue; /* FIXME: FOS_PICKFOLDERS */
235 hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &names[valid_count]);
238 len_total += lstrlenW(names[valid_count]) + 3;
241 IShellItem_Release(psi);
247 set_file_name(This, names[0]);
248 CoTaskMemFree(names[0]);
250 else if(valid_count > 1)
252 LPWSTR string = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len_total);
253 LPWSTR cur_point = string;
255 for(i = 0; i < valid_count; i++)
257 LPWSTR file = names[i];
259 lstrcpyW(cur_point, file);
260 cur_point += lstrlenW(file);
265 *(cur_point-1) = '\0';
267 set_file_name(This, string);
268 HeapFree(GetProcessHeap(), 0, string);
271 HeapFree(GetProcessHeap(), 0, names);
275 static LPWSTR get_first_ext_from_spec(LPWSTR buf, LPCWSTR spec)
280 if( (endpos = StrChrW(buf, ';')) )
283 ext = PathFindExtensionW(buf);
284 if(StrChrW(ext, '*'))
290 static HRESULT on_default_action(FileDialogImpl *This)
292 IShellFolder *psf_parent, *psf_desktop;
294 LPITEMIDLIST current_folder;
295 LPWSTR fn_iter, files, tmp_files;
296 UINT file_count = 0, len, i;
298 HRESULT hr, ret = E_FAIL;
300 len = get_file_name(This, &tmp_files);
304 file_count = COMDLG32_SplitFileNames(tmp_files, len, &files, &size_used);
306 if(!file_count) return E_FAIL;
308 hr = SHGetIDListFromObject((IUnknown*)This->psi_folder, ¤t_folder);
311 ERR("Failed to get pidl for current directory.\n");
315 TRACE("Acting on %d file(s).\n", file_count);
317 pidla = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST) * file_count);
318 open_action = ONOPEN_OPEN;
321 for(i = 0; i < file_count && open_action == ONOPEN_OPEN; i++)
323 WCHAR canon_filename[MAX_PATH];
326 COMDLG32_GetCanonicalPath(current_folder, fn_iter, canon_filename);
328 if( (This->options & FOS_NOVALIDATE) &&
329 !(This->options & FOS_FILEMUSTEXIST) )
330 open_action = ONOPEN_OPEN;
332 open_action = ONOPEN_BROWSE;
334 open_action = FILEDLG95_ValidatePathAction(canon_filename, &psf_parent, This->dlg_hwnd,
335 This->options & ~FOS_FILEMUSTEXIST,
336 (This->dlg_type == ITEMDLG_TYPE_SAVE),
339 /* Add the proper extension */
340 if(open_action == ONOPEN_OPEN)
342 static const WCHAR dotW[] = {'.',0};
344 if(This->dlg_type == ITEMDLG_TYPE_SAVE)
346 WCHAR extbuf[MAX_PATH], *newext = NULL;
348 if(This->filterspec_count)
350 newext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
352 else if(This->default_ext)
354 lstrcpyW(extbuf, dotW);
355 lstrcatW(extbuf, This->default_ext);
361 WCHAR *ext = PathFindExtensionW(canon_filename);
362 if(lstrcmpW(ext, newext))
363 lstrcatW(canon_filename, newext);
368 if( !(This->options & FOS_NOVALIDATE) && (This->options & FOS_FILEMUSTEXIST) &&
369 !PathFileExistsW(canon_filename))
371 if(This->default_ext)
373 lstrcatW(canon_filename, dotW);
374 lstrcatW(canon_filename, This->default_ext);
376 if(!PathFileExistsW(canon_filename))
378 FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
379 open_action = ONOPEN_BROWSE;
384 FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
385 open_action = ONOPEN_BROWSE;
391 pidla[i] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename);
393 if(psf_parent && !(open_action == ONOPEN_BROWSE))
394 IShellItem_Release(psf_parent);
396 fn_iter += (WCHAR)lstrlenW(fn_iter) + 1;
399 HeapFree(GetProcessHeap(), 0, files);
400 ILFree(current_folder);
402 if((This->options & FOS_PICKFOLDERS) && open_action == ONOPEN_BROWSE)
403 open_action = ONOPEN_OPEN; /* FIXME: Multiple folders? */
408 FIXME("Filtering not implemented.\n");
412 hr = IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psf_parent, SBSP_DEFBROWSER);
414 ERR("Failed to browse to directory: %08x\n", hr);
416 IShellItem_Release(psf_parent);
420 if(events_OnFileOk(This) != S_OK)
423 hr = SHGetDesktopFolder(&psf_desktop);
426 if(This->psia_results)
427 IShellItemArray_Release(This->psia_results);
429 hr = SHCreateShellItemArray(NULL, psf_desktop, file_count, (PCUITEMID_CHILD_ARRAY)pidla,
430 &This->psia_results);
434 IShellFolder_Release(psf_desktop);
444 for(i = 0; i < file_count; i++)
446 HeapFree(GetProcessHeap(), 0, pidla);
448 /* Success closes the dialog */
452 /**************************************************************************
455 static void ctrl_resize(HWND hctrl, UINT min_width, UINT max_width)
458 UINT len, final_width;
465 len = SendMessageW(hctrl, WM_GETTEXTLENGTH, 0, 0);
466 text = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
468 SendMessageW(hctrl, WM_GETTEXT, len+1, (LPARAM)text);
471 GetTextExtentPoint32W(hdc, text, lstrlenW(text), &size);
472 ReleaseDC(hctrl, hdc);
474 GetWindowRect(hctrl, &rc);
475 final_width = min(max(size.cx, min_width) + 4, max_width);
476 SetWindowPos(hctrl, NULL, 0, 0, final_width, rc.bottom - rc.top,
477 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
479 HeapFree(GetProcessHeap(), 0, text);
482 /**************************************************************************
483 * Window related functions.
485 static SIZE update_layout(FileDialogImpl *This)
490 RECT cancel_rc, open_rc;
491 RECT filetype_rc, filename_rc, filenamelabel_rc;
492 RECT toolbar_rc, ebrowser_rc;
493 int missing_width, missing_height;
494 static const UINT vspacing = 4, hspacing = 4;
497 GetClientRect(This->dlg_hwnd, &dialog_rc);
499 missing_width = max(0, 320 - dialog_rc.right);
500 missing_height = max(0, 200 - dialog_rc.bottom);
502 if(missing_width || missing_height)
504 TRACE("Missing (%d, %d)\n", missing_width, missing_height);
505 ret.cx = missing_width;
506 ret.cy = missing_height;
511 * Calculate the size of the dialog and all the parts.
515 hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL);
518 int cancel_width, cancel_height;
519 GetWindowRect(hwnd, &cancel_rc);
520 cancel_width = cancel_rc.right - cancel_rc.left;
521 cancel_height = cancel_rc.bottom - cancel_rc.top;
523 cancel_rc.left = dialog_rc.right - cancel_width - hspacing;
524 cancel_rc.top = dialog_rc.bottom - cancel_height - vspacing;
525 cancel_rc.right = cancel_rc.left + cancel_width;
526 cancel_rc.bottom = cancel_rc.top + cancel_height;
529 /* Open/Save button */
530 hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
533 int open_width, open_height;
534 GetWindowRect(hwnd, &open_rc);
535 open_width = open_rc.right - open_rc.left;
536 open_height = open_rc.bottom - open_rc.top;
538 open_rc.left = cancel_rc.left - open_width - hspacing;
539 open_rc.top = cancel_rc.top;
540 open_rc.right = open_rc.left + open_width;
541 open_rc.bottom = open_rc.top + open_height;
544 /* The filetype combobox. */
545 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
548 int filetype_width, filetype_height;
549 GetWindowRect(hwnd, &filetype_rc);
551 filetype_width = filetype_rc.right - filetype_rc.left;
552 filetype_height = filetype_rc.bottom - filetype_rc.top;
554 filetype_rc.right = cancel_rc.right;
556 filetype_rc.left = filetype_rc.right - filetype_width;
557 filetype_rc.top = cancel_rc.top - filetype_height - vspacing;
558 filetype_rc.bottom = filetype_rc.top + filetype_height;
560 if(!This->filterspec_count)
561 filetype_rc.left = filetype_rc.right;
564 /* Filename label. */
565 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC);
568 int filetypelabel_width, filetypelabel_height;
569 GetWindowRect(hwnd, &filenamelabel_rc);
571 filetypelabel_width = filenamelabel_rc.right - filenamelabel_rc.left;
572 filetypelabel_height = filenamelabel_rc.bottom - filenamelabel_rc.top;
574 filenamelabel_rc.left = 160; /* FIXME */
575 filenamelabel_rc.top = filetype_rc.top;
576 filenamelabel_rc.right = filenamelabel_rc.left + filetypelabel_width;
577 filenamelabel_rc.bottom = filenamelabel_rc.top + filetypelabel_height;
580 /* Filename edit box. */
581 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
584 int filename_width, filename_height;
585 GetWindowRect(hwnd, &filename_rc);
587 filename_width = filetype_rc.left - filenamelabel_rc.right - hspacing*2;
588 filename_height = filename_rc.bottom - filename_rc.top;
590 filename_rc.left = filenamelabel_rc.right + hspacing;
591 filename_rc.top = filetype_rc.top;
592 filename_rc.right = filename_rc.left + filename_width;
593 filename_rc.bottom = filename_rc.top + filename_height;
596 hwnd = GetDlgItem(This->dlg_hwnd, IDC_NAV_TOOLBAR);
599 GetWindowRect(hwnd, &toolbar_rc);
600 MapWindowPoints(NULL, This->dlg_hwnd, (POINT*)&toolbar_rc, 2);
603 /* The ExplorerBrowser control. */
604 ebrowser_rc.left = dialog_rc.left + vspacing;
605 ebrowser_rc.top = toolbar_rc.bottom + vspacing;
606 ebrowser_rc.right = dialog_rc.right - hspacing;
607 ebrowser_rc.bottom = filename_rc.top - hspacing;
610 * Move everything to the right place.
613 /* FIXME: The Save Dialog uses a slightly different layout. */
614 hdwp = BeginDeferWindowPos(6);
616 if(hdwp && This->peb)
617 IExplorerBrowser_SetRect(This->peb, &hdwp, ebrowser_rc);
619 /* The default controls */
620 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE)) )
621 DeferWindowPos(hdwp, hwnd, NULL, filetype_rc.left, filetype_rc.top, 0, 0,
622 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
624 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
625 DeferWindowPos(hdwp, hwnd, NULL, filename_rc.left, filename_rc.top,
626 filename_rc.right - filename_rc.left, filename_rc.bottom - filename_rc.top,
627 SWP_NOZORDER | SWP_NOACTIVATE);
629 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)) )
630 DeferWindowPos(hdwp, hwnd, NULL, filenamelabel_rc.left, filenamelabel_rc.top, 0, 0,
631 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
633 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDOK)) )
634 DeferWindowPos(hdwp, hwnd, NULL, open_rc.left, open_rc.top, 0, 0,
635 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
637 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL)) )
638 DeferWindowPos(hdwp, hwnd, NULL, cancel_rc.left, cancel_rc.top, 0, 0,
639 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
642 EndDeferWindowPos(hdwp);
644 ERR("Failed to position dialog controls.\n");
646 ret.cx = 0; ret.cy = 0;
650 static HRESULT init_explorerbrowser(FileDialogImpl *This)
652 IShellItem *psi_folder;
657 /* Create ExplorerBrowser instance */
660 hr = CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
661 &IID_IExplorerBrowser, (void**)&This->peb);
664 ERR("Failed to instantiate ExplorerBrowser control.\n");
668 IExplorerBrowser_SetOptions(This->peb, EBO_SHOWFRAMES);
670 hr = IExplorerBrowser_Initialize(This->peb, This->dlg_hwnd, &rc, NULL);
673 ERR("Failed to initialize the ExplorerBrowser control.\n");
674 IExplorerBrowser_Release(This->peb);
678 hr = IExplorerBrowser_Advise(This->peb, &This->IExplorerBrowserEvents_iface, &This->ebevents_cookie);
680 ERR("Advise (ExplorerBrowser) failed.\n");
682 /* Get previous options? */
683 fos.ViewMode = fos.fFlags = 0;
684 if(!(This->options & FOS_ALLOWMULTISELECT))
685 fos.fFlags |= FWF_SINGLESEL;
687 IExplorerBrowser_SetFolderSettings(This->peb, &fos);
689 hr = IUnknown_SetSite((IUnknown*)This->peb, (IUnknown*)This);
691 ERR("SetSite (ExplorerBrowser) failed.\n");
693 /* Browse somewhere */
694 psi_folder = This->psi_setfolder ? This->psi_setfolder : This->psi_defaultfolder;
695 IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psi_folder, SBSP_DEFBROWSER);
700 static void init_toolbar(FileDialogImpl *This, HWND hwnd)
706 htoolbar = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE,
708 hwnd, (HMENU)IDC_NAV_TOOLBAR, NULL, NULL);
710 tbab.hInst = HINST_COMMCTRL;
711 tbab.nID = IDB_HIST_LARGE_COLOR;
712 SendMessageW(htoolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
714 button[0].iBitmap = HIST_BACK;
715 button[0].idCommand = IDC_NAVBACK;
716 button[0].fsState = TBSTATE_ENABLED;
717 button[0].fsStyle = BTNS_BUTTON;
718 button[0].dwData = 0;
719 button[0].iString = 0;
721 button[1].iBitmap = HIST_FORWARD;
722 button[1].idCommand = IDC_NAVFORWARD;
723 button[1].fsState = TBSTATE_ENABLED;
724 button[1].fsStyle = BTNS_BUTTON;
725 button[1].dwData = 0;
726 button[1].iString = 0;
728 SendMessageW(htoolbar, TB_ADDBUTTONSW, 2, (LPARAM)&button);
729 SendMessageW(htoolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(24,24));
730 SendMessageW(htoolbar, TB_AUTOSIZE, 0, 0);
733 static void update_control_text(FileDialogImpl *This)
736 if(This->custom_title)
737 SetWindowTextW(This->dlg_hwnd, This->custom_title);
739 if(This->custom_okbutton &&
740 (hitem = GetDlgItem(This->dlg_hwnd, IDOK)))
742 SetWindowTextW(hitem, This->custom_okbutton);
743 ctrl_resize(hitem, 50, 250);
746 if(This->custom_cancelbutton &&
747 (hitem = GetDlgItem(This->dlg_hwnd, IDCANCEL)))
749 SetWindowTextW(hitem, This->custom_cancelbutton);
750 ctrl_resize(hitem, 50, 250);
753 if(This->custom_filenamelabel &&
754 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)))
756 SetWindowTextW(hitem, This->custom_filenamelabel);
757 ctrl_resize(hitem, 50, 250);
761 static LRESULT on_wm_initdialog(HWND hwnd, LPARAM lParam)
763 FileDialogImpl *This = (FileDialogImpl*)lParam;
766 TRACE("(%p, %p)\n", This, hwnd);
768 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
769 This->dlg_hwnd = hwnd;
771 hitem = GetDlgItem(This->dlg_hwnd, pshHelp);
772 if(hitem) ShowWindow(hitem, SW_HIDE);
774 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPESTATIC);
775 if(hitem) ShowWindow(hitem, SW_HIDE);
777 /* Fill filetypes combobox, or hide it. */
778 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
779 if(This->filterspec_count)
782 for(i = 0; i < This->filterspec_count; i++)
783 SendMessageW(hitem, CB_ADDSTRING, 0, (LPARAM)This->filterspecs[i].pszName);
785 SendMessageW(hitem, CB_SETCURSEL, This->filetypeindex, 0);
788 ShowWindow(hitem, SW_HIDE);
790 if(This->set_filename &&
791 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
792 SendMessageW(hitem, WM_SETTEXT, 0, (LPARAM)This->set_filename);
794 init_explorerbrowser(This);
795 init_toolbar(This, hwnd);
796 update_control_text(This);
802 static LRESULT on_wm_size(FileDialogImpl *This)
808 static LRESULT on_wm_getminmaxinfo(FileDialogImpl *This, LPARAM lparam)
810 MINMAXINFO *mmi = (MINMAXINFO*)lparam;
811 TRACE("%p (%p)\n", This, mmi);
814 mmi->ptMinTrackSize.x = 640;
815 mmi->ptMinTrackSize.y = 480;
820 static LRESULT on_wm_destroy(FileDialogImpl *This)
826 IExplorerBrowser_Destroy(This->peb);
827 IExplorerBrowser_Release(This->peb);
831 This->dlg_hwnd = NULL;
836 static LRESULT on_idok(FileDialogImpl *This)
840 if(SUCCEEDED(on_default_action(This)))
841 EndDialog(This->dlg_hwnd, S_OK);
846 static LRESULT on_idcancel(FileDialogImpl *This)
850 EndDialog(This->dlg_hwnd, HRESULT_FROM_WIN32(ERROR_CANCELLED));
855 static LRESULT on_browse_back(FileDialogImpl *This)
858 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEBACK);
862 static LRESULT on_browse_forward(FileDialogImpl *This)
865 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEFORWARD);
869 static LRESULT on_command_filetype(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
871 if(HIWORD(wparam) == CBN_SELCHANGE)
876 UINT prev_index = This->filetypeindex;
878 This->filetypeindex = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
879 TRACE("File type selection changed to %d.\n", This->filetypeindex);
881 if(prev_index == This->filetypeindex)
884 hr = IExplorerBrowser_GetCurrentView(This->peb, &IID_IShellView, (void**)&psv);
887 IShellView_Refresh(psv);
888 IShellView_Release(psv);
891 if(This->dlg_type == ITEMDLG_TYPE_SAVE && get_file_name(This, &filename))
893 WCHAR buf[MAX_PATH], extbuf[MAX_PATH], *ext;
895 ext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
898 lstrcpyW(buf, filename);
900 if(PathMatchSpecW(buf, This->filterspecs[prev_index].pszSpec))
901 PathRemoveExtensionW(buf);
904 set_file_name(This, buf);
906 CoTaskMemFree(filename);
913 static LRESULT on_wm_command(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
915 switch(LOWORD(wparam))
917 case IDOK: return on_idok(This);
918 case IDCANCEL: return on_idcancel(This);
919 case IDC_NAVBACK: return on_browse_back(This);
920 case IDC_NAVFORWARD: return on_browse_forward(This);
921 case IDC_FILETYPE: return on_command_filetype(This, wparam, lparam);
922 default: TRACE("Unknown command.\n");
927 static LRESULT CALLBACK itemdlg_dlgproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
929 FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
933 case WM_INITDIALOG: return on_wm_initdialog(hwnd, lparam);
934 case WM_COMMAND: return on_wm_command(This, wparam, lparam);
935 case WM_SIZE: return on_wm_size(This);
936 case WM_GETMINMAXINFO: return on_wm_getminmaxinfo(This, lparam);
937 case WM_DESTROY: return on_wm_destroy(This);
943 static HRESULT create_dialog(FileDialogImpl *This, HWND parent)
948 res = DialogBoxParamW(COMDLG32_hInstance,
949 MAKEINTRESOURCEW(NEWFILEOPENV3ORD),
950 parent, itemdlg_dlgproc, (LPARAM)This);
951 This->dlg_hwnd = NULL;
954 ERR("Failed to show dialog (LastError: %d)\n", GetLastError());
958 TRACE("Returning 0x%08x\n", (HRESULT)res);
962 /**************************************************************************
963 * IFileDialog implementation
965 static inline FileDialogImpl *impl_from_IFileDialog2(IFileDialog2 *iface)
967 return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialog2_iface);
970 static HRESULT WINAPI IFileDialog2_fnQueryInterface(IFileDialog2 *iface,
974 FileDialogImpl *This = impl_from_IFileDialog2(iface);
975 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
978 if(IsEqualGUID(riid, &IID_IUnknown) ||
979 IsEqualGUID(riid, &IID_IFileDialog) ||
980 IsEqualGUID(riid, &IID_IFileDialog2))
984 else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
986 *ppvObject = &This->u.IFileOpenDialog_iface;
988 else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
990 *ppvObject = &This->u.IFileSaveDialog_iface;
992 else if(IsEqualGUID(riid, &IID_IExplorerBrowserEvents))
994 *ppvObject = &This->IExplorerBrowserEvents_iface;
996 else if(IsEqualGUID(riid, &IID_IServiceProvider))
998 *ppvObject = &This->IServiceProvider_iface;
1000 else if(IsEqualGUID(&IID_ICommDlgBrowser3, riid) ||
1001 IsEqualGUID(&IID_ICommDlgBrowser2, riid) ||
1002 IsEqualGUID(&IID_ICommDlgBrowser, riid))
1004 *ppvObject = &This->ICommDlgBrowser3_iface;
1006 else if(IsEqualGUID(&IID_IOleWindow, riid))
1008 *ppvObject = &This->IOleWindow_iface;
1011 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
1015 IUnknown_AddRef((IUnknown*)*ppvObject);
1019 return E_NOINTERFACE;
1022 static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
1024 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1025 LONG ref = InterlockedIncrement(&This->ref);
1026 TRACE("%p - ref %d\n", This, ref);
1031 static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
1033 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1034 LONG ref = InterlockedDecrement(&This->ref);
1035 TRACE("%p - ref %d\n", This, ref);
1040 for(i = 0; i < This->filterspec_count; i++)
1042 LocalFree((void*)This->filterspecs[i].pszName);
1043 LocalFree((void*)This->filterspecs[i].pszSpec);
1045 HeapFree(GetProcessHeap(), 0, This->filterspecs);
1047 if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
1048 if(This->psi_setfolder) IShellItem_Release(This->psi_setfolder);
1049 if(This->psi_folder) IShellItem_Release(This->psi_folder);
1050 if(This->psia_selection) IShellItemArray_Release(This->psia_selection);
1051 if(This->psia_results) IShellItemArray_Release(This->psia_results);
1053 LocalFree(This->set_filename);
1054 LocalFree(This->default_ext);
1055 LocalFree(This->custom_title);
1056 LocalFree(This->custom_okbutton);
1057 LocalFree(This->custom_cancelbutton);
1058 LocalFree(This->custom_filenamelabel);
1060 HeapFree(GetProcessHeap(), 0, This);
1066 static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
1068 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1069 TRACE("%p (%p)\n", iface, hwndOwner);
1071 return create_dialog(This, hwndOwner);
1074 static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
1075 const COMDLG_FILTERSPEC *rgFilterSpec)
1077 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1079 TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
1081 if(This->filterspecs)
1082 return E_UNEXPECTED;
1085 return E_INVALIDARG;
1090 This->filterspecs = HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC)*cFileTypes);
1091 for(i = 0; i < cFileTypes; i++)
1093 This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
1094 This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
1096 This->filterspec_count = cFileTypes;
1101 static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
1103 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1104 TRACE("%p (%d)\n", This, iFileType);
1106 if(!This->filterspecs)
1109 if(iFileType >= This->filterspec_count)
1110 This->filetypeindex = This->filterspec_count - 1;
1112 This->filetypeindex = iFileType;
1117 static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
1119 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1120 TRACE("%p (%p)\n", This, piFileType);
1123 return E_INVALIDARG;
1125 *piFileType = This->filetypeindex;
1130 static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
1132 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1133 events_client *client;
1134 TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
1136 if(!pfde || !pdwCookie)
1137 return E_INVALIDARG;
1139 client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
1140 client->pfde = pfde;
1141 client->cookie = ++This->events_next_cookie;
1143 IFileDialogEvents_AddRef(pfde);
1144 *pdwCookie = client->cookie;
1146 list_add_tail(&This->events_clients, &client->entry);
1151 static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
1153 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1154 events_client *client, *found = NULL;
1155 TRACE("%p (%d)\n", This, dwCookie);
1157 LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
1159 if(client->cookie == dwCookie)
1168 list_remove(&found->entry);
1169 IFileDialogEvents_Release(found->pfde);
1170 HeapFree(GetProcessHeap(), 0, found);
1174 return E_INVALIDARG;
1177 static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
1179 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1180 TRACE("%p (0x%x)\n", This, fos);
1182 This->options = fos;
1187 static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
1189 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1190 TRACE("%p (%p)\n", This, pfos);
1193 return E_INVALIDARG;
1195 *pfos = This->options;
1200 static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
1202 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1203 TRACE("%p (%p)\n", This, psi);
1204 if(This->psi_defaultfolder)
1205 IShellItem_Release(This->psi_defaultfolder);
1207 This->psi_defaultfolder = psi;
1209 if(This->psi_defaultfolder)
1210 IShellItem_AddRef(This->psi_defaultfolder);
1215 static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
1217 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1218 TRACE("%p (%p)\n", This, psi);
1219 if(This->psi_setfolder)
1220 IShellItem_Release(This->psi_setfolder);
1222 This->psi_setfolder = psi;
1224 if(This->psi_setfolder)
1225 IShellItem_AddRef(This->psi_setfolder);
1230 static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
1232 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1233 TRACE("%p (%p)\n", This, ppsi);
1235 return E_INVALIDARG;
1238 If the dialog is shown, return the current(ly selected) folder. */
1241 if(This->psi_folder)
1242 *ppsi = This->psi_folder;
1243 else if(This->psi_setfolder)
1244 *ppsi = This->psi_setfolder;
1245 else if(This->psi_defaultfolder)
1246 *ppsi = This->psi_defaultfolder;
1250 IShellItem_AddRef(*ppsi);
1257 static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
1259 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1261 TRACE("%p (%p)\n", This, ppsi);
1264 return E_INVALIDARG;
1266 if(This->psia_selection)
1268 /* FIXME: Check filename edit box */
1269 hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
1276 static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
1278 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1279 TRACE("%p (%s)\n", iface, debugstr_w(pszName));
1281 set_file_name(This, pszName);
1286 static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
1288 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1289 TRACE("%p (%p)\n", iface, pszName);
1292 return E_INVALIDARG;
1295 if(get_file_name(This, pszName))
1301 static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
1303 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1304 TRACE("%p (%s)\n", This, debugstr_w(pszTitle));
1306 LocalFree(This->custom_title);
1307 This->custom_title = StrDupW(pszTitle);
1308 update_control_text(This);
1313 static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
1315 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1316 TRACE("%p (%s)\n", This, debugstr_w(pszText));
1318 LocalFree(This->custom_okbutton);
1319 This->custom_okbutton = StrDupW(pszText);
1320 update_control_text(This);
1321 update_layout(This);
1326 static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
1328 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1329 TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
1331 LocalFree(This->custom_filenamelabel);
1332 This->custom_filenamelabel = StrDupW(pszLabel);
1333 update_control_text(This);
1334 update_layout(This);
1339 static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
1341 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1343 TRACE("%p (%p)\n", This, ppsi);
1346 return E_INVALIDARG;
1348 if(This->psia_results)
1351 hr = IShellItemArray_GetCount(This->psia_results, &item_count);
1357 /* Adds a reference. */
1358 hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
1364 return E_UNEXPECTED;
1367 static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
1369 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1370 FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
1374 static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
1376 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1377 TRACE("%p (%s)\n", This, debugstr_w(pszDefaultExtension));
1379 LocalFree(This->default_ext);
1380 This->default_ext = StrDupW(pszDefaultExtension);
1385 static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
1387 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1388 TRACE("%p (0x%08x)\n", This, hr);
1391 EndDialog(This->dlg_hwnd, hr);
1396 static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
1398 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1399 FIXME("stub - %p (%s)\n", This, debugstr_guid(guid));
1403 static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
1405 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1406 FIXME("stub - %p\n", This);
1410 static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
1412 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1413 FIXME("stub - %p (%p)\n", This, pFilter);
1417 static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
1419 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1420 TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
1422 LocalFree(This->custom_cancelbutton);
1423 This->custom_cancelbutton = StrDupW(pszLabel);
1424 update_control_text(This);
1425 update_layout(This);
1430 static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
1432 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1433 FIXME("stub - %p (%p)\n", This, psi);
1437 static const IFileDialog2Vtbl vt_IFileDialog2 = {
1438 IFileDialog2_fnQueryInterface,
1439 IFileDialog2_fnAddRef,
1440 IFileDialog2_fnRelease,
1441 IFileDialog2_fnShow,
1442 IFileDialog2_fnSetFileTypes,
1443 IFileDialog2_fnSetFileTypeIndex,
1444 IFileDialog2_fnGetFileTypeIndex,
1445 IFileDialog2_fnAdvise,
1446 IFileDialog2_fnUnadvise,
1447 IFileDialog2_fnSetOptions,
1448 IFileDialog2_fnGetOptions,
1449 IFileDialog2_fnSetDefaultFolder,
1450 IFileDialog2_fnSetFolder,
1451 IFileDialog2_fnGetFolder,
1452 IFileDialog2_fnGetCurrentSelection,
1453 IFileDialog2_fnSetFileName,
1454 IFileDialog2_fnGetFileName,
1455 IFileDialog2_fnSetTitle,
1456 IFileDialog2_fnSetOkButtonLabel,
1457 IFileDialog2_fnSetFileNameLabel,
1458 IFileDialog2_fnGetResult,
1459 IFileDialog2_fnAddPlace,
1460 IFileDialog2_fnSetDefaultExtension,
1461 IFileDialog2_fnClose,
1462 IFileDialog2_fnSetClientGuid,
1463 IFileDialog2_fnClearClientData,
1464 IFileDialog2_fnSetFilter,
1465 IFileDialog2_fnSetCancelButtonLabel,
1466 IFileDialog2_fnSetNavigationRoot
1469 /**************************************************************************
1472 static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
1474 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
1477 static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
1478 REFIID riid, void **ppvObject)
1480 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1481 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1484 static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
1486 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1487 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1490 static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
1492 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1493 return IFileDialog2_Release(&This->IFileDialog2_iface);
1496 static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
1498 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1499 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
1502 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
1503 const COMDLG_FILTERSPEC *rgFilterSpec)
1505 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1506 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
1509 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
1511 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1512 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
1515 static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
1517 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1518 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
1521 static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
1524 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1525 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
1528 static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
1530 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1531 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
1534 static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
1536 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1537 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
1540 static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
1542 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1543 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
1546 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
1548 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1549 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
1552 static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
1554 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1555 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
1558 static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
1560 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1561 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
1564 static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
1566 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1567 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
1570 static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
1572 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1573 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
1576 static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
1578 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1579 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
1582 static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
1584 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1585 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
1588 static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
1590 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1591 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
1594 static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
1596 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1597 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
1600 static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
1602 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1603 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
1606 static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
1608 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1609 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
1612 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
1613 LPCWSTR pszDefaultExtension)
1615 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1616 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
1619 static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
1621 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1622 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
1625 static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
1627 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1628 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
1631 static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
1633 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1634 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
1637 static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
1639 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1640 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
1643 static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
1645 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1646 TRACE("%p (%p)\n", This, ppenum);
1648 *ppenum = This->psia_results;
1652 IShellItemArray_AddRef(*ppenum);
1659 static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
1661 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1662 TRACE("%p (%p)\n", This, ppsai);
1664 if(This->psia_selection)
1666 *ppsai = This->psia_selection;
1667 IShellItemArray_AddRef(*ppsai);
1674 static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
1675 IFileOpenDialog_fnQueryInterface,
1676 IFileOpenDialog_fnAddRef,
1677 IFileOpenDialog_fnRelease,
1678 IFileOpenDialog_fnShow,
1679 IFileOpenDialog_fnSetFileTypes,
1680 IFileOpenDialog_fnSetFileTypeIndex,
1681 IFileOpenDialog_fnGetFileTypeIndex,
1682 IFileOpenDialog_fnAdvise,
1683 IFileOpenDialog_fnUnadvise,
1684 IFileOpenDialog_fnSetOptions,
1685 IFileOpenDialog_fnGetOptions,
1686 IFileOpenDialog_fnSetDefaultFolder,
1687 IFileOpenDialog_fnSetFolder,
1688 IFileOpenDialog_fnGetFolder,
1689 IFileOpenDialog_fnGetCurrentSelection,
1690 IFileOpenDialog_fnSetFileName,
1691 IFileOpenDialog_fnGetFileName,
1692 IFileOpenDialog_fnSetTitle,
1693 IFileOpenDialog_fnSetOkButtonLabel,
1694 IFileOpenDialog_fnSetFileNameLabel,
1695 IFileOpenDialog_fnGetResult,
1696 IFileOpenDialog_fnAddPlace,
1697 IFileOpenDialog_fnSetDefaultExtension,
1698 IFileOpenDialog_fnClose,
1699 IFileOpenDialog_fnSetClientGuid,
1700 IFileOpenDialog_fnClearClientData,
1701 IFileOpenDialog_fnSetFilter,
1702 IFileOpenDialog_fnGetResults,
1703 IFileOpenDialog_fnGetSelectedItems
1706 /**************************************************************************
1709 static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
1711 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
1714 static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
1718 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1719 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1722 static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
1724 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1725 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1728 static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
1730 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1731 return IFileDialog2_Release(&This->IFileDialog2_iface);
1734 static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
1736 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1737 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
1740 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
1741 const COMDLG_FILTERSPEC *rgFilterSpec)
1743 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1744 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
1747 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
1749 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1750 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
1753 static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
1755 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1756 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
1759 static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
1762 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1763 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
1766 static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
1768 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1769 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
1772 static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
1774 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1775 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
1778 static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
1780 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1781 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
1784 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
1786 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1787 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
1790 static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
1792 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1793 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
1796 static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
1798 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1799 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
1802 static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
1804 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1805 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
1808 static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
1810 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1811 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
1814 static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
1816 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1817 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
1820 static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
1822 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1823 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
1826 static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
1828 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1829 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
1832 static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
1834 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1835 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
1838 static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
1840 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1841 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
1844 static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
1846 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1847 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
1850 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
1851 LPCWSTR pszDefaultExtension)
1853 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1854 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
1857 static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
1859 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1860 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
1863 static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
1865 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1866 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
1869 static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
1871 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1872 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
1875 static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
1877 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1878 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
1881 static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
1883 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1884 FIXME("stub - %p (%p)\n", This, psi);
1888 static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
1890 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1891 FIXME("stub - %p (%p)\n", This, pStore);
1895 static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
1896 IPropertyDescriptionList *pList,
1897 BOOL fAppendDefault)
1899 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1900 FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
1904 static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
1906 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1907 FIXME("stub - %p (%p)\n", This, ppStore);
1911 static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
1913 IPropertyStore *pStore,
1915 IFileOperationProgressSink *pSink)
1917 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1918 FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
1922 static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
1923 IFileSaveDialog_fnQueryInterface,
1924 IFileSaveDialog_fnAddRef,
1925 IFileSaveDialog_fnRelease,
1926 IFileSaveDialog_fnShow,
1927 IFileSaveDialog_fnSetFileTypes,
1928 IFileSaveDialog_fnSetFileTypeIndex,
1929 IFileSaveDialog_fnGetFileTypeIndex,
1930 IFileSaveDialog_fnAdvise,
1931 IFileSaveDialog_fnUnadvise,
1932 IFileSaveDialog_fnSetOptions,
1933 IFileSaveDialog_fnGetOptions,
1934 IFileSaveDialog_fnSetDefaultFolder,
1935 IFileSaveDialog_fnSetFolder,
1936 IFileSaveDialog_fnGetFolder,
1937 IFileSaveDialog_fnGetCurrentSelection,
1938 IFileSaveDialog_fnSetFileName,
1939 IFileSaveDialog_fnGetFileName,
1940 IFileSaveDialog_fnSetTitle,
1941 IFileSaveDialog_fnSetOkButtonLabel,
1942 IFileSaveDialog_fnSetFileNameLabel,
1943 IFileSaveDialog_fnGetResult,
1944 IFileSaveDialog_fnAddPlace,
1945 IFileSaveDialog_fnSetDefaultExtension,
1946 IFileSaveDialog_fnClose,
1947 IFileSaveDialog_fnSetClientGuid,
1948 IFileSaveDialog_fnClearClientData,
1949 IFileSaveDialog_fnSetFilter,
1950 IFileSaveDialog_fnSetSaveAsItem,
1951 IFileSaveDialog_fnSetProperties,
1952 IFileSaveDialog_fnSetCollectedProperties,
1953 IFileSaveDialog_fnGetProperties,
1954 IFileSaveDialog_fnApplyProperties
1957 /**************************************************************************
1958 * IExplorerBrowserEvents implementation
1960 static inline FileDialogImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
1962 return CONTAINING_RECORD(iface, FileDialogImpl, IExplorerBrowserEvents_iface);
1965 static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
1966 REFIID riid, void **ppvObject)
1968 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1969 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1971 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1974 static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
1976 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1977 TRACE("%p\n", This);
1978 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1981 static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
1983 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1984 TRACE("%p\n", This);
1985 return IFileDialog2_Release(&This->IFileDialog2_iface);
1988 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
1989 PCIDLIST_ABSOLUTE pidlFolder)
1991 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1994 TRACE("%p (%p)\n", This, pidlFolder);
1996 hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&psi);
1999 hr = events_OnFolderChanging(This, psi);
2000 IShellItem_Release(psi);
2002 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
2009 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder);
2014 static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
2017 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2018 TRACE("%p (%p)\n", This, psv);
2022 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
2023 PCIDLIST_ABSOLUTE pidlFolder)
2025 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2027 TRACE("%p (%p)\n", This, pidlFolder);
2029 if(This->psi_folder)
2030 IShellItem_Release(This->psi_folder);
2032 hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&This->psi_folder);
2035 ERR("Failed to get the current folder.\n");
2036 This->psi_folder = NULL;
2039 events_OnFolderChange(This);
2044 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
2045 PCIDLIST_ABSOLUTE pidlFolder)
2047 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2048 TRACE("%p (%p)\n", This, pidlFolder);
2052 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents = {
2053 IExplorerBrowserEvents_fnQueryInterface,
2054 IExplorerBrowserEvents_fnAddRef,
2055 IExplorerBrowserEvents_fnRelease,
2056 IExplorerBrowserEvents_fnOnNavigationPending,
2057 IExplorerBrowserEvents_fnOnViewCreated,
2058 IExplorerBrowserEvents_fnOnNavigationComplete,
2059 IExplorerBrowserEvents_fnOnNavigationFailed
2062 /**************************************************************************
2063 * IServiceProvider implementation
2065 static inline FileDialogImpl *impl_from_IServiceProvider(IServiceProvider *iface)
2067 return CONTAINING_RECORD(iface, FileDialogImpl, IServiceProvider_iface);
2070 static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface,
2071 REFIID riid, void **ppvObject)
2073 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2074 TRACE("%p\n", This);
2075 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2078 static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
2080 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2081 TRACE("%p\n", This);
2082 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2085 static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
2087 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2088 TRACE("%p\n", This);
2089 return IFileDialog2_Release(&This->IFileDialog2_iface);
2092 static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
2093 REFGUID guidService,
2094 REFIID riid, void **ppv)
2096 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2097 HRESULT hr = E_FAIL;
2098 TRACE("%p (%s, %s, %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
2101 if(IsEqualGUID(guidService, &SID_STopLevelBrowser) && This->peb)
2102 hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv);
2103 else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame))
2104 hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv);
2106 FIXME("Interface %s requested from unknown service %s\n",
2107 debugstr_guid(riid), debugstr_guid(guidService));
2112 static const IServiceProviderVtbl vt_IServiceProvider = {
2113 IServiceProvider_fnQueryInterface,
2114 IServiceProvider_fnAddRef,
2115 IServiceProvider_fnRelease,
2116 IServiceProvider_fnQueryService
2119 /**************************************************************************
2120 * ICommDlgBrowser3 implementation
2122 static inline FileDialogImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
2124 return CONTAINING_RECORD(iface, FileDialogImpl, ICommDlgBrowser3_iface);
2127 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
2128 REFIID riid, void **ppvObject)
2130 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2131 TRACE("%p\n", This);
2132 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2135 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
2137 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2138 TRACE("%p\n", This);
2139 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2142 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
2144 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2145 TRACE("%p\n", This);
2146 return IFileDialog2_Release(&This->IFileDialog2_iface);
2149 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
2152 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2154 TRACE("%p (%p)\n", This, shv);
2156 hr = on_default_action(This);
2159 EndDialog(This->dlg_hwnd, S_OK);
2164 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
2165 IShellView *shv, ULONG uChange )
2167 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2168 IDataObject *new_selection;
2170 TRACE("%p (%p, %x)\n", This, shv, uChange);
2174 case CDBOSC_SELCHANGE:
2175 if(This->psia_selection)
2177 IShellItemArray_Release(This->psia_selection);
2178 This->psia_selection = NULL;
2181 hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&new_selection);
2184 hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
2185 (void**)&This->psia_selection);
2188 fill_filename_from_selection(This);
2189 events_OnSelectionChange(This);
2192 IDataObject_Release(new_selection);
2196 TRACE("Unhandled state change\n");
2201 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
2202 IShellView *shv, LPCITEMIDLIST pidl)
2204 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2207 LPITEMIDLIST parent_pidl;
2210 TRACE("%p (%p, %p)\n", This, shv, pidl);
2212 if(!This->filterspec_count)
2215 hr = SHGetIDListFromObject((IUnknown*)shv, &parent_pidl);
2218 LPITEMIDLIST full_pidl = ILCombine(parent_pidl, pidl);
2219 hr = SHCreateItemFromIDList(full_pidl, &IID_IShellItem, (void**)&psi);
2220 ILFree(parent_pidl);
2225 ERR("Failed to get shellitem (%08x).\n", hr);
2229 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER|SFGAO_LINK, &attr);
2230 if(FAILED(hr) || (attr & (SFGAO_FOLDER | SFGAO_LINK)))
2232 IShellItem_Release(psi);
2237 if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename)))
2239 if(!PathMatchSpecW(filename, This->filterspecs[This->filetypeindex].pszSpec))
2241 CoTaskMemFree(filename);
2244 IShellItem_Release(psi);
2248 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
2249 IShellView *ppshv, DWORD dwNotifyType)
2251 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2252 FIXME("Stub: %p (%p, 0x%x)\n", This, ppshv, dwNotifyType);
2256 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
2258 LPWSTR pszText, int cchMax)
2260 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2261 FIXME("Stub: %p (%p, %p, %d)\n", This, pshv, pszText, cchMax);
2265 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, DWORD *pdwFlags)
2267 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2268 FIXME("Stub: %p (%p)\n", This, pdwFlags);
2272 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
2273 IShellView *pshv, int iColumn)
2275 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2276 FIXME("Stub: %p (%p, %d)\n", This, pshv, iColumn);
2280 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
2281 LPWSTR pszFileSpec, int cchFileSpec)
2283 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2284 FIXME("Stub: %p (%p, %d)\n", This, pszFileSpec, cchFileSpec);
2288 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
2291 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2292 FIXME("Stub: %p (%p)\n", This, pshv);
2296 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
2297 ICommDlgBrowser3_fnQueryInterface,
2298 ICommDlgBrowser3_fnAddRef,
2299 ICommDlgBrowser3_fnRelease,
2300 ICommDlgBrowser3_fnOnDefaultCommand,
2301 ICommDlgBrowser3_fnOnStateChange,
2302 ICommDlgBrowser3_fnIncludeObject,
2303 ICommDlgBrowser3_fnNotify,
2304 ICommDlgBrowser3_fnGetDefaultMenuText,
2305 ICommDlgBrowser3_fnGetViewFlags,
2306 ICommDlgBrowser3_fnOnColumnClicked,
2307 ICommDlgBrowser3_fnGetCurrentFilter,
2308 ICommDlgBrowser3_fnOnPreviewCreated
2311 /**************************************************************************
2312 * IOleWindow implementation
2314 static inline FileDialogImpl *impl_from_IOleWindow(IOleWindow *iface)
2316 return CONTAINING_RECORD(iface, FileDialogImpl, IOleWindow_iface);
2319 static HRESULT WINAPI IOleWindow_fnQueryInterface(IOleWindow *iface, REFIID riid, void **ppvObject)
2321 FileDialogImpl *This = impl_from_IOleWindow(iface);
2322 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2325 static ULONG WINAPI IOleWindow_fnAddRef(IOleWindow *iface)
2327 FileDialogImpl *This = impl_from_IOleWindow(iface);
2328 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2331 static ULONG WINAPI IOleWindow_fnRelease(IOleWindow *iface)
2333 FileDialogImpl *This = impl_from_IOleWindow(iface);
2334 return IFileDialog2_Release(&This->IFileDialog2_iface);
2337 static HRESULT WINAPI IOleWindow_fnContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMOde)
2339 FileDialogImpl *This = impl_from_IOleWindow(iface);
2340 FIXME("Stub: %p (%d)\n", This, fEnterMOde);
2344 static HRESULT WINAPI IOleWindow_fnGetWindow(IOleWindow *iface, HWND *phwnd)
2346 FileDialogImpl *This = impl_from_IOleWindow(iface);
2347 TRACE("%p (%p)\n", This, phwnd);
2348 *phwnd = This->dlg_hwnd;
2352 static const IOleWindowVtbl vt_IOleWindow = {
2353 IOleWindow_fnQueryInterface,
2354 IOleWindow_fnAddRef,
2355 IOleWindow_fnRelease,
2356 IOleWindow_fnGetWindow,
2357 IOleWindow_fnContextSensitiveHelp
2360 static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
2362 FileDialogImpl *fdimpl;
2365 TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
2370 return CLASS_E_NOAGGREGATION;
2372 fdimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(FileDialogImpl));
2374 return E_OUTOFMEMORY;
2377 fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
2378 fdimpl->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
2379 fdimpl->IServiceProvider_iface.lpVtbl = &vt_IServiceProvider;
2380 fdimpl->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
2381 fdimpl->IOleWindow_iface.lpVtbl = &vt_IOleWindow;
2383 if(type == ITEMDLG_TYPE_OPEN)
2385 fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
2386 fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
2387 fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
2388 fdimpl->custom_title = fdimpl->custom_okbutton = NULL;
2393 fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
2394 fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
2395 fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
2397 LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, sizeof(buf)/sizeof(WCHAR));
2398 fdimpl->custom_title = StrDupW(buf);
2399 fdimpl->custom_okbutton = StrDupW(buf);
2402 fdimpl->filterspecs = NULL;
2403 fdimpl->filterspec_count = 0;
2404 fdimpl->filetypeindex = 0;
2406 fdimpl->psia_selection = fdimpl->psia_results = NULL;
2407 fdimpl->psi_setfolder = fdimpl->psi_folder = NULL;
2409 list_init(&fdimpl->events_clients);
2410 fdimpl->events_next_cookie = 0;
2412 fdimpl->dlg_hwnd = NULL;
2415 fdimpl->set_filename = NULL;
2416 fdimpl->default_ext = NULL;
2417 fdimpl->custom_cancelbutton = fdimpl->custom_filenamelabel = NULL;
2419 /* FIXME: The default folder setting should be restored for the
2420 * application if it was previously set. */
2421 SHGetDesktopFolder(&psf);
2422 SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
2423 IShellFolder_Release(psf);
2425 hr = IUnknown_QueryInterface((IUnknown*)fdimpl, riid, ppv);
2426 IUnknown_Release((IUnknown*)fdimpl);
2430 HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2432 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
2435 HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2437 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);