comctl32/tests: Some tests for TVM_GETNEXTITEM and item toggle.
[wine/multimedia.git] / dlls / comdlg32 / itemdlg.c
blob51767a75d89c923bf941ca6ce3ff8fd391182e15
1 /*
2 * Common Item Dialog
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
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
34 #include "commdlg.h"
35 #include "cdlg.h"
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);
47 enum ITEMDLG_TYPE {
48 ITEMDLG_TYPE_OPEN,
49 ITEMDLG_TYPE_SAVE
52 typedef struct {
53 struct list entry;
54 IFileDialogEvents *pfde;
55 DWORD cookie;
56 } events_client;
58 typedef struct FileDialogImpl {
59 IFileDialog2 IFileDialog2_iface;
60 union {
61 IFileOpenDialog IFileOpenDialog_iface;
62 IFileSaveDialog IFileSaveDialog_iface;
63 } u;
64 enum ITEMDLG_TYPE dlg_type;
65 IExplorerBrowserEvents IExplorerBrowserEvents_iface;
66 IServiceProvider IServiceProvider_iface;
67 ICommDlgBrowser3 ICommDlgBrowser3_iface;
68 LONG ref;
70 FILEOPENDIALOGOPTIONS options;
71 COMDLG_FILTERSPEC *filterspecs;
72 UINT filterspec_count;
73 UINT filetypeindex;
75 struct list events_clients;
76 DWORD events_next_cookie;
78 IShellItemArray *psia_selection;
79 IShellItemArray *psia_results;
80 IShellItem *psi_defaultfolder;
81 IShellItem *psi_setfolder;
82 IShellItem *psi_folder;
84 HWND dlg_hwnd;
85 IExplorerBrowser *peb;
86 DWORD ebevents_cookie;
88 LPWSTR set_filename;
89 LPWSTR custom_title;
90 LPWSTR custom_okbutton;
91 LPWSTR custom_cancelbutton;
92 LPWSTR custom_filenamelabel;
93 } FileDialogImpl;
95 /**************************************************************************
96 * Helper functions.
98 static UINT get_file_name(FileDialogImpl *This, LPWSTR *str)
100 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
101 UINT len;
103 if(!hwnd_edit)
105 if(This->set_filename)
107 len = lstrlenW(This->set_filename);
108 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
109 lstrcpyW(*str, This->set_filename);
110 return len;
112 return FALSE;
115 len = SendMessageW(hwnd_edit, WM_GETTEXTLENGTH, 0, 0);
116 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
117 if(!*str)
118 return FALSE;
120 SendMessageW(hwnd_edit, WM_GETTEXT, len+1, (LPARAM)*str);
121 return len;
124 static BOOL set_file_name(FileDialogImpl *This, LPCWSTR str)
126 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
128 if(This->set_filename)
129 LocalFree(This->set_filename);
131 This->set_filename = StrDupW(str);
133 return SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str);
136 static void fill_filename_from_selection(FileDialogImpl *This)
138 IShellItem *psi;
139 LPWSTR *names;
140 HRESULT hr;
141 UINT item_count, valid_count;
142 UINT len_total, i;
144 if(!This->psia_selection)
145 return;
147 hr = IShellItemArray_GetCount(This->psia_selection, &item_count);
148 if(FAILED(hr) || !item_count)
149 return;
151 names = HeapAlloc(GetProcessHeap(), 0, item_count*sizeof(LPWSTR));
153 /* Get names of the selected items */
154 valid_count = 0; len_total = 0;
155 for(i = 0; i < item_count; i++)
157 hr = IShellItemArray_GetItemAt(This->psia_selection, i, &psi);
158 if(SUCCEEDED(hr))
160 UINT attr;
162 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &attr);
163 if(SUCCEEDED(hr) && (attr & SFGAO_FOLDER))
164 continue; /* FIXME: FOS_PICKFOLDERS */
166 hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &names[valid_count]);
167 if(SUCCEEDED(hr))
169 len_total += lstrlenW(names[valid_count]) + 3;
170 valid_count++;
172 IShellItem_Release(psi);
176 if(valid_count == 1)
178 set_file_name(This, names[0]);
179 CoTaskMemFree(names[0]);
181 else if(valid_count > 1)
183 LPWSTR string = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len_total);
184 LPWSTR cur_point = string;
186 for(i = 0; i < valid_count; i++)
188 LPWSTR file = names[i];
189 *cur_point++ = '\"';
190 lstrcpyW(cur_point, file);
191 cur_point += lstrlenW(file);
192 *cur_point++ = '\"';
193 *cur_point++ = ' ';
194 CoTaskMemFree(file);
196 *(cur_point-1) = '\0';
198 set_file_name(This, string);
199 HeapFree(GetProcessHeap(), 0, string);
202 HeapFree(GetProcessHeap(), 0, names);
203 return;
206 static HRESULT on_default_action(FileDialogImpl *This)
208 IShellFolder *psf_parent, *psf_desktop;
209 LPITEMIDLIST *pidla;
210 LPITEMIDLIST current_folder;
211 LPWSTR fn_iter, files, tmp_files;
212 UINT file_count = 0, len, i;
213 int open_action;
214 HRESULT hr, ret = E_FAIL;
216 len = get_file_name(This, &tmp_files);
217 if(len)
219 UINT size_used;
220 file_count = COMDLG32_SplitFileNames(tmp_files, len, &files, &size_used);
222 if(!file_count) return E_FAIL;
224 hr = SHGetIDListFromObject((IUnknown*)This->psi_folder, &current_folder);
225 if(FAILED(hr))
227 ERR("Failed to get pidl for current directory.\n");
228 return hr;
231 TRACE("Acting on %d file(s).\n", file_count);
233 pidla = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST) * file_count);
234 open_action = ONOPEN_OPEN;
235 fn_iter = files;
237 for(i = 0; i < file_count && open_action == ONOPEN_OPEN; i++)
239 WCHAR canon_filename[MAX_PATH];
240 psf_parent = NULL;
242 COMDLG32_GetCanonicalPath(current_folder, fn_iter, canon_filename);
244 if( (This->options & FOS_NOVALIDATE) &&
245 !(This->options & FOS_FILEMUSTEXIST) )
246 open_action = ONOPEN_OPEN;
247 else
248 open_action = ONOPEN_BROWSE;
250 open_action = FILEDLG95_ValidatePathAction(canon_filename, &psf_parent, This->dlg_hwnd,
251 This->options, (This->dlg_type == ITEMDLG_TYPE_SAVE),
252 open_action);
254 pidla[i] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename);
256 if(psf_parent && !(open_action == ONOPEN_BROWSE))
257 IShellItem_Release(psf_parent);
259 fn_iter += (WCHAR)lstrlenW(fn_iter) + 1;
262 HeapFree(GetProcessHeap(), 0, files);
263 ILFree(current_folder);
265 if((This->options & FOS_PICKFOLDERS) && open_action == ONOPEN_BROWSE)
266 open_action = ONOPEN_OPEN; /* FIXME: Multiple folders? */
268 switch(open_action)
270 case ONOPEN_SEARCH:
271 FIXME("Filtering not implemented.\n");
272 break;
274 case ONOPEN_BROWSE:
275 hr = IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psf_parent, SBSP_DEFBROWSER);
276 if(FAILED(hr))
277 ERR("Failed to browse to directory: %08x\n", hr);
279 IShellItem_Release(psf_parent);
280 break;
282 case ONOPEN_OPEN:
283 hr = SHGetDesktopFolder(&psf_desktop);
284 if(SUCCEEDED(hr))
286 if(This->psia_results)
287 IShellItemArray_Release(This->psia_results);
289 hr = SHCreateShellItemArray(NULL, psf_desktop, file_count, (PCUITEMID_CHILD_ARRAY)pidla,
290 &This->psia_results);
292 if(SUCCEEDED(hr))
293 ret = S_OK;
295 IShellFolder_Release(psf_desktop);
297 break;
299 default:
300 ERR("Failed.\n");
301 break;
304 /* Clean up */
305 for(i = 0; i < file_count; i++)
306 ILFree(pidla[i]);
307 HeapFree(GetProcessHeap(), 0, pidla);
309 /* Success closes the dialog */
310 return ret;
313 /**************************************************************************
314 * Control functions.
316 static void ctrl_resize(HWND hctrl, UINT min_width, UINT max_width)
318 LPWSTR text;
319 UINT len, final_width;
320 SIZE size;
321 RECT rc;
322 HDC hdc;
324 TRACE("\n");
326 len = SendMessageW(hctrl, WM_GETTEXTLENGTH, 0, 0);
327 text = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
328 if(!text) return;
329 SendMessageW(hctrl, WM_GETTEXT, len+1, (LPARAM)text);
331 hdc = GetDC(hctrl);
332 GetTextExtentPoint32W(hdc, text, lstrlenW(text), &size);
333 ReleaseDC(hctrl, hdc);
335 GetWindowRect(hctrl, &rc);
336 final_width = min(max(size.cx, min_width) + 4, max_width);
337 SetWindowPos(hctrl, NULL, 0, 0, final_width, rc.bottom - rc.top,
338 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
340 HeapFree(GetProcessHeap(), 0, text);
343 /**************************************************************************
344 * Window related functions.
346 static SIZE update_layout(FileDialogImpl *This)
348 HDWP hdwp;
349 HWND hwnd;
350 RECT dialog_rc;
351 RECT cancel_rc, open_rc;
352 RECT filetype_rc, filename_rc, filenamelabel_rc;
353 RECT toolbar_rc, ebrowser_rc;
354 int missing_width, missing_height;
355 static const UINT vspacing = 4, hspacing = 4;
356 SIZE ret;
358 GetClientRect(This->dlg_hwnd, &dialog_rc);
360 missing_width = max(0, 320 - dialog_rc.right);
361 missing_height = max(0, 200 - dialog_rc.bottom);
363 if(missing_width || missing_height)
365 TRACE("Missing (%d, %d)\n", missing_width, missing_height);
366 ret.cx = missing_width;
367 ret.cy = missing_height;
368 return ret;
371 /****
372 * Calculate the size of the dialog and all the parts.
375 /* Cancel button */
376 hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL);
377 if(hwnd)
379 int cancel_width, cancel_height;
380 GetWindowRect(hwnd, &cancel_rc);
381 cancel_width = cancel_rc.right - cancel_rc.left;
382 cancel_height = cancel_rc.bottom - cancel_rc.top;
384 cancel_rc.left = dialog_rc.right - cancel_width - hspacing;
385 cancel_rc.top = dialog_rc.bottom - cancel_height - vspacing;
386 cancel_rc.right = cancel_rc.left + cancel_width;
387 cancel_rc.bottom = cancel_rc.top + cancel_height;
390 /* Open/Save button */
391 hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
392 if(hwnd)
394 int open_width, open_height;
395 GetWindowRect(hwnd, &open_rc);
396 open_width = open_rc.right - open_rc.left;
397 open_height = open_rc.bottom - open_rc.top;
399 open_rc.left = cancel_rc.left - open_width - hspacing;
400 open_rc.top = cancel_rc.top;
401 open_rc.right = open_rc.left + open_width;
402 open_rc.bottom = open_rc.top + open_height;
405 /* The filetype combobox. */
406 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
407 if(hwnd)
409 int filetype_width, filetype_height;
410 GetWindowRect(hwnd, &filetype_rc);
412 filetype_width = filetype_rc.right - filetype_rc.left;
413 filetype_height = filetype_rc.bottom - filetype_rc.top;
415 filetype_rc.right = cancel_rc.right;
417 filetype_rc.left = filetype_rc.right - filetype_width;
418 filetype_rc.top = cancel_rc.top - filetype_height - vspacing;
419 filetype_rc.bottom = filetype_rc.top + filetype_height;
421 if(!This->filterspec_count)
422 filetype_rc.left = filetype_rc.right;
425 /* Filename label. */
426 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC);
427 if(hwnd)
429 int filetypelabel_width, filetypelabel_height;
430 GetWindowRect(hwnd, &filenamelabel_rc);
432 filetypelabel_width = filenamelabel_rc.right - filenamelabel_rc.left;
433 filetypelabel_height = filenamelabel_rc.bottom - filenamelabel_rc.top;
435 filenamelabel_rc.left = 160; /* FIXME */
436 filenamelabel_rc.top = filetype_rc.top;
437 filenamelabel_rc.right = filenamelabel_rc.left + filetypelabel_width;
438 filenamelabel_rc.bottom = filenamelabel_rc.top + filetypelabel_height;
441 /* Filename edit box. */
442 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
443 if(hwnd)
445 int filename_width, filename_height;
446 GetWindowRect(hwnd, &filename_rc);
448 filename_width = filetype_rc.left - filenamelabel_rc.right - hspacing*2;
449 filename_height = filename_rc.bottom - filename_rc.top;
451 filename_rc.left = filenamelabel_rc.right + hspacing;
452 filename_rc.top = filetype_rc.top;
453 filename_rc.right = filename_rc.left + filename_width;
454 filename_rc.bottom = filename_rc.top + filename_height;
457 hwnd = GetDlgItem(This->dlg_hwnd, IDC_NAV_TOOLBAR);
458 if(hwnd)
460 GetWindowRect(hwnd, &toolbar_rc);
461 MapWindowPoints(NULL, This->dlg_hwnd, (POINT*)&toolbar_rc, 2);
464 /* The ExplorerBrowser control. */
465 ebrowser_rc.left = dialog_rc.left + vspacing;
466 ebrowser_rc.top = toolbar_rc.bottom + vspacing;
467 ebrowser_rc.right = dialog_rc.right - hspacing;
468 ebrowser_rc.bottom = filename_rc.top - hspacing;
470 /****
471 * Move everything to the right place.
474 /* FIXME: The Save Dialog uses a slightly different layout. */
475 hdwp = BeginDeferWindowPos(6);
477 if(hdwp && This->peb)
478 IExplorerBrowser_SetRect(This->peb, &hdwp, ebrowser_rc);
480 /* The default controls */
481 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE)) )
482 DeferWindowPos(hdwp, hwnd, NULL, filetype_rc.left, filetype_rc.top, 0, 0,
483 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
485 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
486 DeferWindowPos(hdwp, hwnd, NULL, filename_rc.left, filename_rc.top,
487 filename_rc.right - filename_rc.left, filename_rc.bottom - filename_rc.top,
488 SWP_NOZORDER | SWP_NOACTIVATE);
490 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)) )
491 DeferWindowPos(hdwp, hwnd, NULL, filenamelabel_rc.left, filenamelabel_rc.top, 0, 0,
492 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
494 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDOK)) )
495 DeferWindowPos(hdwp, hwnd, NULL, open_rc.left, open_rc.top, 0, 0,
496 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
498 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL)) )
499 DeferWindowPos(hdwp, hwnd, NULL, cancel_rc.left, cancel_rc.top, 0, 0,
500 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
502 if(hdwp)
503 EndDeferWindowPos(hdwp);
504 else
505 ERR("Failed to position dialog controls.\n");
507 ret.cx = 0; ret.cy = 0;
508 return ret;
511 static HRESULT init_explorerbrowser(FileDialogImpl *This)
513 IShellItem *psi_folder;
514 FOLDERSETTINGS fos;
515 RECT rc = {0};
516 HRESULT hr;
518 /* Create ExplorerBrowser instance */
519 OleInitialize(NULL);
521 hr = CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
522 &IID_IExplorerBrowser, (void**)&This->peb);
523 if(FAILED(hr))
525 ERR("Failed to instantiate ExplorerBrowser control.\n");
526 return hr;
529 IExplorerBrowser_SetOptions(This->peb, EBO_SHOWFRAMES);
531 hr = IExplorerBrowser_Initialize(This->peb, This->dlg_hwnd, &rc, NULL);
532 if(FAILED(hr))
534 ERR("Failed to initialize the ExplorerBrowser control.\n");
535 IExplorerBrowser_Release(This->peb);
536 This->peb = NULL;
537 return hr;
539 hr = IExplorerBrowser_Advise(This->peb, &This->IExplorerBrowserEvents_iface, &This->ebevents_cookie);
540 if(FAILED(hr))
541 ERR("Advise (ExplorerBrowser) failed.\n");
543 /* Get previous options? */
544 fos.ViewMode = fos.fFlags = 0;
545 if(!(This->options & FOS_ALLOWMULTISELECT))
546 fos.fFlags |= FWF_SINGLESEL;
548 IExplorerBrowser_SetFolderSettings(This->peb, &fos);
550 hr = IUnknown_SetSite((IUnknown*)This->peb, (IUnknown*)This);
551 if(FAILED(hr))
552 ERR("SetSite (ExplorerBrowser) failed.\n");
554 /* Browse somewhere */
555 psi_folder = This->psi_setfolder ? This->psi_setfolder : This->psi_defaultfolder;
556 IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psi_folder, SBSP_DEFBROWSER);
558 return S_OK;
561 static void init_toolbar(FileDialogImpl *This, HWND hwnd)
563 HWND htoolbar;
564 TBADDBITMAP tbab;
565 TBBUTTON button[2];
567 htoolbar = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE,
568 0, 0, 0, 0,
569 hwnd, (HMENU)IDC_NAV_TOOLBAR, NULL, NULL);
571 tbab.hInst = HINST_COMMCTRL;
572 tbab.nID = IDB_HIST_LARGE_COLOR;
573 SendMessageW(htoolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
575 button[0].iBitmap = HIST_BACK;
576 button[0].idCommand = IDC_NAVBACK;
577 button[0].fsState = TBSTATE_ENABLED;
578 button[0].fsStyle = BTNS_BUTTON;
579 button[0].dwData = 0;
580 button[0].iString = 0;
582 button[1].iBitmap = HIST_FORWARD;
583 button[1].idCommand = IDC_NAVFORWARD;
584 button[1].fsState = TBSTATE_ENABLED;
585 button[1].fsStyle = BTNS_BUTTON;
586 button[1].dwData = 0;
587 button[1].iString = 0;
589 SendMessageW(htoolbar, TB_ADDBUTTONSW, 2, (LPARAM)&button);
590 SendMessageW(htoolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(24,24));
591 SendMessageW(htoolbar, TB_AUTOSIZE, 0, 0);
594 static void update_control_text(FileDialogImpl *This)
596 HWND hitem;
597 if(This->custom_title)
598 SetWindowTextW(This->dlg_hwnd, This->custom_title);
600 if(This->custom_okbutton &&
601 (hitem = GetDlgItem(This->dlg_hwnd, IDOK)))
603 SetWindowTextW(hitem, This->custom_okbutton);
604 ctrl_resize(hitem, 50, 250);
607 if(This->custom_cancelbutton &&
608 (hitem = GetDlgItem(This->dlg_hwnd, IDCANCEL)))
610 SetWindowTextW(hitem, This->custom_cancelbutton);
611 ctrl_resize(hitem, 50, 250);
614 if(This->custom_filenamelabel &&
615 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)))
617 SetWindowTextW(hitem, This->custom_filenamelabel);
618 ctrl_resize(hitem, 50, 250);
622 static LRESULT on_wm_initdialog(HWND hwnd, LPARAM lParam)
624 FileDialogImpl *This = (FileDialogImpl*)lParam;
625 HWND hitem;
627 TRACE("(%p, %p)\n", This, hwnd);
629 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
630 This->dlg_hwnd = hwnd;
632 hitem = GetDlgItem(This->dlg_hwnd, pshHelp);
633 if(hitem) ShowWindow(hitem, SW_HIDE);
635 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPESTATIC);
636 if(hitem) ShowWindow(hitem, SW_HIDE);
638 /* Fill filetypes combobox, or hide it. */
639 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
640 if(This->filterspec_count)
642 UINT i;
643 for(i = 0; i < This->filterspec_count; i++)
644 SendMessageW(hitem, CB_ADDSTRING, 0, (LPARAM)This->filterspecs[i].pszName);
646 SendMessageW(hitem, CB_SETCURSEL, This->filetypeindex, 0);
648 else
649 ShowWindow(hitem, SW_HIDE);
651 if(This->set_filename &&
652 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
653 SendMessageW(hitem, WM_SETTEXT, 0, (LPARAM)This->set_filename);
655 init_explorerbrowser(This);
656 init_toolbar(This, hwnd);
657 update_control_text(This);
658 update_layout(This);
660 return TRUE;
663 static LRESULT on_wm_size(FileDialogImpl *This)
665 update_layout(This);
666 return FALSE;
669 static LRESULT on_wm_getminmaxinfo(FileDialogImpl *This, LPARAM lparam)
671 MINMAXINFO *mmi = (MINMAXINFO*)lparam;
672 TRACE("%p (%p)\n", This, mmi);
674 /* FIXME */
675 mmi->ptMinTrackSize.x = 640;
676 mmi->ptMinTrackSize.y = 480;
678 return FALSE;
681 static LRESULT on_wm_destroy(FileDialogImpl *This)
683 TRACE("%p\n", This);
685 if(This->peb)
687 IExplorerBrowser_Destroy(This->peb);
688 IExplorerBrowser_Release(This->peb);
689 This->peb = NULL;
692 This->dlg_hwnd = NULL;
694 return TRUE;
697 static LRESULT on_idok(FileDialogImpl *This)
699 TRACE("%p\n", This);
701 if(SUCCEEDED(on_default_action(This)))
702 EndDialog(This->dlg_hwnd, S_OK);
704 return FALSE;
707 static LRESULT on_idcancel(FileDialogImpl *This)
709 TRACE("%p\n", This);
711 EndDialog(This->dlg_hwnd, HRESULT_FROM_WIN32(ERROR_CANCELLED));
713 return FALSE;
716 static LRESULT on_browse_back(FileDialogImpl *This)
718 TRACE("%p\n", This);
719 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEBACK);
720 return FALSE;
723 static LRESULT on_browse_forward(FileDialogImpl *This)
725 TRACE("%p\n", This);
726 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEFORWARD);
727 return FALSE;
730 static LRESULT on_command_filetype(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
732 if(HIWORD(wparam) == CBN_SELCHANGE)
734 IShellView *psv;
735 HRESULT hr;
737 This->filetypeindex = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
738 TRACE("File type selection changed to %d.\n", This->filetypeindex);
740 hr = IExplorerBrowser_GetCurrentView(This->peb, &IID_IShellView, (void**)&psv);
741 if(SUCCEEDED(hr))
743 IShellView_Refresh(psv);
744 IShellView_Release(psv);
748 return FALSE;
751 static LRESULT on_wm_command(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
753 switch(LOWORD(wparam))
755 case IDOK: return on_idok(This);
756 case IDCANCEL: return on_idcancel(This);
757 case IDC_NAVBACK: return on_browse_back(This);
758 case IDC_NAVFORWARD: return on_browse_forward(This);
759 case IDC_FILETYPE: return on_command_filetype(This, wparam, lparam);
760 default: TRACE("Unknown command.\n");
762 return FALSE;
765 static LRESULT CALLBACK itemdlg_dlgproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
767 FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
769 switch(umessage)
771 case WM_INITDIALOG: return on_wm_initdialog(hwnd, lparam);
772 case WM_COMMAND: return on_wm_command(This, wparam, lparam);
773 case WM_SIZE: return on_wm_size(This);
774 case WM_GETMINMAXINFO: return on_wm_getminmaxinfo(This, lparam);
775 case WM_DESTROY: return on_wm_destroy(This);
778 return FALSE;
781 static HRESULT create_dialog(FileDialogImpl *This, HWND parent)
783 INT_PTR res;
785 SetLastError(0);
786 res = DialogBoxParamW(COMDLG32_hInstance,
787 MAKEINTRESOURCEW(NEWFILEOPENV3ORD),
788 parent, itemdlg_dlgproc, (LPARAM)This);
789 This->dlg_hwnd = NULL;
790 if(res == -1)
792 ERR("Failed to show dialog (LastError: %d)\n", GetLastError());
793 return E_FAIL;
796 TRACE("Returning 0x%08x\n", (HRESULT)res);
797 return (HRESULT)res;
800 /**************************************************************************
801 * IFileDialog implementation
803 static inline FileDialogImpl *impl_from_IFileDialog2(IFileDialog2 *iface)
805 return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialog2_iface);
808 static HRESULT WINAPI IFileDialog2_fnQueryInterface(IFileDialog2 *iface,
809 REFIID riid,
810 void **ppvObject)
812 FileDialogImpl *This = impl_from_IFileDialog2(iface);
813 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
815 *ppvObject = NULL;
816 if(IsEqualGUID(riid, &IID_IUnknown) ||
817 IsEqualGUID(riid, &IID_IFileDialog) ||
818 IsEqualGUID(riid, &IID_IFileDialog2))
820 *ppvObject = iface;
822 else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
824 *ppvObject = &This->u.IFileOpenDialog_iface;
826 else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
828 *ppvObject = &This->u.IFileSaveDialog_iface;
830 else if(IsEqualGUID(riid, &IID_IExplorerBrowserEvents))
832 *ppvObject = &This->IExplorerBrowserEvents_iface;
834 else if(IsEqualGUID(riid, &IID_IServiceProvider))
836 *ppvObject = &This->IServiceProvider_iface;
838 else if(IsEqualGUID(&IID_ICommDlgBrowser3, riid) ||
839 IsEqualGUID(&IID_ICommDlgBrowser2, riid) ||
840 IsEqualGUID(&IID_ICommDlgBrowser, riid))
842 *ppvObject = &This->ICommDlgBrowser3_iface;
844 else
845 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
847 if(*ppvObject)
849 IUnknown_AddRef((IUnknown*)*ppvObject);
850 return S_OK;
853 return E_NOINTERFACE;
856 static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
858 FileDialogImpl *This = impl_from_IFileDialog2(iface);
859 LONG ref = InterlockedIncrement(&This->ref);
860 TRACE("%p - ref %d\n", This, ref);
862 return ref;
865 static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
867 FileDialogImpl *This = impl_from_IFileDialog2(iface);
868 LONG ref = InterlockedDecrement(&This->ref);
869 TRACE("%p - ref %d\n", This, ref);
871 if(!ref)
873 UINT i;
874 for(i = 0; i < This->filterspec_count; i++)
876 LocalFree((void*)This->filterspecs[i].pszName);
877 LocalFree((void*)This->filterspecs[i].pszSpec);
879 HeapFree(GetProcessHeap(), 0, This->filterspecs);
881 if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
882 if(This->psi_setfolder) IShellItem_Release(This->psi_setfolder);
883 if(This->psi_folder) IShellItem_Release(This->psi_folder);
884 if(This->psia_selection) IShellItemArray_Release(This->psia_selection);
885 if(This->psia_results) IShellItemArray_Release(This->psia_results);
887 LocalFree(This->set_filename);
888 LocalFree(This->custom_title);
889 LocalFree(This->custom_okbutton);
890 LocalFree(This->custom_cancelbutton);
891 LocalFree(This->custom_filenamelabel);
893 HeapFree(GetProcessHeap(), 0, This);
896 return ref;
899 static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
901 FileDialogImpl *This = impl_from_IFileDialog2(iface);
902 TRACE("%p (%p)\n", iface, hwndOwner);
904 return create_dialog(This, hwndOwner);
907 static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
908 const COMDLG_FILTERSPEC *rgFilterSpec)
910 FileDialogImpl *This = impl_from_IFileDialog2(iface);
911 UINT i;
912 TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
914 if(This->filterspecs)
915 return E_UNEXPECTED;
917 if(!rgFilterSpec)
918 return E_INVALIDARG;
920 if(!cFileTypes)
921 return S_OK;
923 This->filterspecs = HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC)*cFileTypes);
924 for(i = 0; i < cFileTypes; i++)
926 This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
927 This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
929 This->filterspec_count = cFileTypes;
931 return S_OK;
934 static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
936 FileDialogImpl *This = impl_from_IFileDialog2(iface);
937 TRACE("%p (%d)\n", This, iFileType);
939 if(!This->filterspecs)
940 return E_FAIL;
942 if(iFileType >= This->filterspec_count)
943 This->filetypeindex = This->filterspec_count - 1;
944 else
945 This->filetypeindex = iFileType;
947 return S_OK;
950 static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
952 FileDialogImpl *This = impl_from_IFileDialog2(iface);
953 TRACE("%p (%p)\n", This, piFileType);
955 if(!piFileType)
956 return E_INVALIDARG;
958 *piFileType = This->filetypeindex;
960 return S_OK;
963 static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
965 FileDialogImpl *This = impl_from_IFileDialog2(iface);
966 events_client *client;
967 TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
969 if(!pfde || !pdwCookie)
970 return E_INVALIDARG;
972 client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
973 client->pfde = pfde;
974 client->cookie = ++This->events_next_cookie;
976 IFileDialogEvents_AddRef(pfde);
977 *pdwCookie = client->cookie;
979 list_add_tail(&This->events_clients, &client->entry);
981 return S_OK;
984 static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
986 FileDialogImpl *This = impl_from_IFileDialog2(iface);
987 events_client *client, *found = NULL;
988 TRACE("%p (%d)\n", This, dwCookie);
990 LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
992 if(client->cookie == dwCookie)
994 found = client;
995 break;
999 if(found)
1001 list_remove(&found->entry);
1002 IFileDialogEvents_Release(found->pfde);
1003 HeapFree(GetProcessHeap(), 0, found);
1004 return S_OK;
1007 return E_INVALIDARG;
1010 static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
1012 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1013 TRACE("%p (0x%x)\n", This, fos);
1015 This->options = fos;
1017 return S_OK;
1020 static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
1022 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1023 TRACE("%p (%p)\n", This, pfos);
1025 if(!pfos)
1026 return E_INVALIDARG;
1028 *pfos = This->options;
1030 return S_OK;
1033 static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
1035 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1036 TRACE("%p (%p)\n", This, psi);
1037 if(This->psi_defaultfolder)
1038 IShellItem_Release(This->psi_defaultfolder);
1040 This->psi_defaultfolder = psi;
1042 if(This->psi_defaultfolder)
1043 IShellItem_AddRef(This->psi_defaultfolder);
1045 return S_OK;
1048 static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
1050 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1051 TRACE("%p (%p)\n", This, psi);
1052 if(This->psi_setfolder)
1053 IShellItem_Release(This->psi_setfolder);
1055 This->psi_setfolder = psi;
1057 if(This->psi_setfolder)
1058 IShellItem_AddRef(This->psi_setfolder);
1060 return S_OK;
1063 static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
1065 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1066 TRACE("%p (%p)\n", This, ppsi);
1067 if(!ppsi)
1068 return E_INVALIDARG;
1070 /* FIXME:
1071 If the dialog is shown, return the current(ly selected) folder. */
1073 *ppsi = NULL;
1074 if(This->psi_folder)
1075 *ppsi = This->psi_folder;
1076 else if(This->psi_setfolder)
1077 *ppsi = This->psi_setfolder;
1078 else if(This->psi_defaultfolder)
1079 *ppsi = This->psi_defaultfolder;
1081 if(*ppsi)
1083 IShellItem_AddRef(*ppsi);
1084 return S_OK;
1087 return E_FAIL;
1090 static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
1092 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1093 HRESULT hr;
1094 TRACE("%p (%p)\n", This, ppsi);
1096 if(!ppsi)
1097 return E_INVALIDARG;
1099 if(This->psia_selection)
1101 /* FIXME: Check filename edit box */
1102 hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
1103 return hr;
1106 return E_FAIL;
1109 static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
1111 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1112 TRACE("%p (%p)\n", iface, pszName);
1114 set_file_name(This, pszName);
1116 return S_OK;
1119 static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
1121 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1122 TRACE("%p (%p)\n", iface, pszName);
1124 if(!pszName)
1125 return E_INVALIDARG;
1127 *pszName = NULL;
1128 if(get_file_name(This, pszName))
1129 return S_OK;
1130 else
1131 return E_FAIL;
1134 static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
1136 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1137 TRACE("%p (%p)\n", This, pszTitle);
1139 LocalFree(This->custom_title);
1140 This->custom_title = StrDupW(pszTitle);
1141 update_control_text(This);
1143 return S_OK;
1146 static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
1148 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1149 TRACE("%p (%p)\n", This, pszText);
1151 LocalFree(This->custom_okbutton);
1152 This->custom_okbutton = StrDupW(pszText);
1153 update_control_text(This);
1154 update_layout(This);
1156 return S_OK;
1159 static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
1161 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1162 TRACE("%p (%p)\n", This, pszLabel);
1164 LocalFree(This->custom_filenamelabel);
1165 This->custom_filenamelabel = StrDupW(pszLabel);
1166 update_control_text(This);
1167 update_layout(This);
1169 return S_OK;
1172 static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
1174 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1175 HRESULT hr;
1176 TRACE("%p (%p)\n", This, ppsi);
1178 if(!ppsi)
1179 return E_INVALIDARG;
1181 if(This->psia_results)
1183 UINT item_count;
1184 hr = IShellItemArray_GetCount(This->psia_results, &item_count);
1185 if(SUCCEEDED(hr))
1187 if(item_count != 1)
1188 return E_FAIL;
1190 /* Adds a reference. */
1191 hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
1194 return hr;
1197 return E_UNEXPECTED;
1200 static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
1202 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1203 FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
1204 return E_NOTIMPL;
1207 static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
1209 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1210 FIXME("stub - %p (%s)\n", This, debugstr_w(pszDefaultExtension));
1211 return E_NOTIMPL;
1214 static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
1216 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1217 TRACE("%p (0x%08x)\n", This, hr);
1219 if(This->dlg_hwnd)
1220 EndDialog(This->dlg_hwnd, hr);
1222 return S_OK;
1225 static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
1227 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1228 FIXME("stub - %p (%s)\n", This, debugstr_guid(guid));
1229 return E_NOTIMPL;
1232 static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
1234 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1235 FIXME("stub - %p\n", This);
1236 return E_NOTIMPL;
1239 static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
1241 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1242 FIXME("stub - %p (%p)\n", This, pFilter);
1243 return E_NOTIMPL;
1246 static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
1248 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1249 TRACE("%p (%p)\n", This, pszLabel);
1251 LocalFree(This->custom_cancelbutton);
1252 This->custom_cancelbutton = StrDupW(pszLabel);
1253 update_control_text(This);
1254 update_layout(This);
1256 return S_OK;
1259 static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
1261 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1262 FIXME("stub - %p (%p)\n", This, psi);
1263 return E_NOTIMPL;
1266 static const IFileDialog2Vtbl vt_IFileDialog2 = {
1267 IFileDialog2_fnQueryInterface,
1268 IFileDialog2_fnAddRef,
1269 IFileDialog2_fnRelease,
1270 IFileDialog2_fnShow,
1271 IFileDialog2_fnSetFileTypes,
1272 IFileDialog2_fnSetFileTypeIndex,
1273 IFileDialog2_fnGetFileTypeIndex,
1274 IFileDialog2_fnAdvise,
1275 IFileDialog2_fnUnadvise,
1276 IFileDialog2_fnSetOptions,
1277 IFileDialog2_fnGetOptions,
1278 IFileDialog2_fnSetDefaultFolder,
1279 IFileDialog2_fnSetFolder,
1280 IFileDialog2_fnGetFolder,
1281 IFileDialog2_fnGetCurrentSelection,
1282 IFileDialog2_fnSetFileName,
1283 IFileDialog2_fnGetFileName,
1284 IFileDialog2_fnSetTitle,
1285 IFileDialog2_fnSetOkButtonLabel,
1286 IFileDialog2_fnSetFileNameLabel,
1287 IFileDialog2_fnGetResult,
1288 IFileDialog2_fnAddPlace,
1289 IFileDialog2_fnSetDefaultExtension,
1290 IFileDialog2_fnClose,
1291 IFileDialog2_fnSetClientGuid,
1292 IFileDialog2_fnClearClientData,
1293 IFileDialog2_fnSetFilter,
1294 IFileDialog2_fnSetCancelButtonLabel,
1295 IFileDialog2_fnSetNavigationRoot
1298 /**************************************************************************
1299 * IFileOpenDialog
1301 static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
1303 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
1306 static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
1307 REFIID riid, void **ppvObject)
1309 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1310 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1313 static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
1315 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1316 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1319 static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
1321 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1322 return IFileDialog2_Release(&This->IFileDialog2_iface);
1325 static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
1327 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1328 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
1331 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
1332 const COMDLG_FILTERSPEC *rgFilterSpec)
1334 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1335 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
1338 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
1340 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1341 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
1344 static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
1346 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1347 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
1350 static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
1351 DWORD *pdwCookie)
1353 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1354 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
1357 static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
1359 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1360 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
1363 static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
1365 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1366 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
1369 static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
1371 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1372 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
1375 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
1377 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1378 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
1381 static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
1383 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1384 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
1387 static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
1389 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1390 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
1393 static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
1395 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1396 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
1399 static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
1401 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1402 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
1405 static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
1407 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1408 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
1411 static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
1413 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1414 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
1417 static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
1419 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1420 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
1423 static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
1425 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1426 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
1429 static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
1431 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1432 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
1435 static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
1437 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1438 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
1441 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
1442 LPCWSTR pszDefaultExtension)
1444 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1445 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
1448 static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
1450 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1451 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
1454 static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
1456 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1457 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
1460 static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
1462 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1463 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
1466 static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
1468 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1469 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
1472 static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
1474 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1475 TRACE("%p (%p)\n", This, ppenum);
1477 *ppenum = This->psia_results;
1479 if(*ppenum)
1481 IShellItemArray_AddRef(*ppenum);
1482 return S_OK;
1485 return E_FAIL;
1488 static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
1490 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
1491 TRACE("%p (%p)\n", This, ppsai);
1493 if(This->psia_selection)
1495 *ppsai = This->psia_selection;
1496 IShellItemArray_AddRef(*ppsai);
1497 return S_OK;
1500 return E_FAIL;
1503 static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
1504 IFileOpenDialog_fnQueryInterface,
1505 IFileOpenDialog_fnAddRef,
1506 IFileOpenDialog_fnRelease,
1507 IFileOpenDialog_fnShow,
1508 IFileOpenDialog_fnSetFileTypes,
1509 IFileOpenDialog_fnSetFileTypeIndex,
1510 IFileOpenDialog_fnGetFileTypeIndex,
1511 IFileOpenDialog_fnAdvise,
1512 IFileOpenDialog_fnUnadvise,
1513 IFileOpenDialog_fnSetOptions,
1514 IFileOpenDialog_fnGetOptions,
1515 IFileOpenDialog_fnSetDefaultFolder,
1516 IFileOpenDialog_fnSetFolder,
1517 IFileOpenDialog_fnGetFolder,
1518 IFileOpenDialog_fnGetCurrentSelection,
1519 IFileOpenDialog_fnSetFileName,
1520 IFileOpenDialog_fnGetFileName,
1521 IFileOpenDialog_fnSetTitle,
1522 IFileOpenDialog_fnSetOkButtonLabel,
1523 IFileOpenDialog_fnSetFileNameLabel,
1524 IFileOpenDialog_fnGetResult,
1525 IFileOpenDialog_fnAddPlace,
1526 IFileOpenDialog_fnSetDefaultExtension,
1527 IFileOpenDialog_fnClose,
1528 IFileOpenDialog_fnSetClientGuid,
1529 IFileOpenDialog_fnClearClientData,
1530 IFileOpenDialog_fnSetFilter,
1531 IFileOpenDialog_fnGetResults,
1532 IFileOpenDialog_fnGetSelectedItems
1535 /**************************************************************************
1536 * IFileSaveDialog
1538 static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
1540 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
1543 static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
1544 REFIID riid,
1545 void **ppvObject)
1547 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1548 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1551 static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
1553 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1554 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1557 static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
1559 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1560 return IFileDialog2_Release(&This->IFileDialog2_iface);
1563 static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
1565 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1566 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
1569 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
1570 const COMDLG_FILTERSPEC *rgFilterSpec)
1572 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1573 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
1576 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
1578 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1579 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
1582 static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
1584 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1585 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
1588 static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
1589 DWORD *pdwCookie)
1591 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1592 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
1595 static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
1597 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1598 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
1601 static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
1603 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1604 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
1607 static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
1609 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1610 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
1613 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
1615 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1616 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
1619 static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
1621 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1622 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
1625 static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
1627 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1628 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
1631 static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
1633 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1634 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
1637 static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
1639 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1640 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
1643 static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
1645 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1646 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
1649 static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
1651 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1652 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
1655 static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
1657 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1658 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
1661 static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
1663 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1664 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
1667 static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
1669 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1670 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
1673 static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
1675 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1676 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
1679 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
1680 LPCWSTR pszDefaultExtension)
1682 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1683 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
1686 static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
1688 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1689 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
1692 static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
1694 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1695 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
1698 static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
1700 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1701 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
1704 static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
1706 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1707 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
1710 static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
1712 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1713 FIXME("stub - %p (%p)\n", This, psi);
1714 return E_NOTIMPL;
1717 static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
1719 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1720 FIXME("stub - %p (%p)\n", This, pStore);
1721 return E_NOTIMPL;
1724 static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
1725 IPropertyDescriptionList *pList,
1726 BOOL fAppendDefault)
1728 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1729 FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
1730 return E_NOTIMPL;
1733 static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
1735 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1736 FIXME("stub - %p (%p)\n", This, ppStore);
1737 return E_NOTIMPL;
1740 static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
1741 IShellItem *psi,
1742 IPropertyStore *pStore,
1743 HWND hwnd,
1744 IFileOperationProgressSink *pSink)
1746 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
1747 FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
1748 return E_NOTIMPL;
1751 static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
1752 IFileSaveDialog_fnQueryInterface,
1753 IFileSaveDialog_fnAddRef,
1754 IFileSaveDialog_fnRelease,
1755 IFileSaveDialog_fnShow,
1756 IFileSaveDialog_fnSetFileTypes,
1757 IFileSaveDialog_fnSetFileTypeIndex,
1758 IFileSaveDialog_fnGetFileTypeIndex,
1759 IFileSaveDialog_fnAdvise,
1760 IFileSaveDialog_fnUnadvise,
1761 IFileSaveDialog_fnSetOptions,
1762 IFileSaveDialog_fnGetOptions,
1763 IFileSaveDialog_fnSetDefaultFolder,
1764 IFileSaveDialog_fnSetFolder,
1765 IFileSaveDialog_fnGetFolder,
1766 IFileSaveDialog_fnGetCurrentSelection,
1767 IFileSaveDialog_fnSetFileName,
1768 IFileSaveDialog_fnGetFileName,
1769 IFileSaveDialog_fnSetTitle,
1770 IFileSaveDialog_fnSetOkButtonLabel,
1771 IFileSaveDialog_fnSetFileNameLabel,
1772 IFileSaveDialog_fnGetResult,
1773 IFileSaveDialog_fnAddPlace,
1774 IFileSaveDialog_fnSetDefaultExtension,
1775 IFileSaveDialog_fnClose,
1776 IFileSaveDialog_fnSetClientGuid,
1777 IFileSaveDialog_fnClearClientData,
1778 IFileSaveDialog_fnSetFilter,
1779 IFileSaveDialog_fnSetSaveAsItem,
1780 IFileSaveDialog_fnSetProperties,
1781 IFileSaveDialog_fnSetCollectedProperties,
1782 IFileSaveDialog_fnGetProperties,
1783 IFileSaveDialog_fnApplyProperties
1786 /**************************************************************************
1787 * IExplorerBrowserEvents implementation
1789 static inline FileDialogImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
1791 return CONTAINING_RECORD(iface, FileDialogImpl, IExplorerBrowserEvents_iface);
1794 static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
1795 REFIID riid, void **ppvObject)
1797 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1798 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1800 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1803 static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
1805 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1806 TRACE("%p\n", This);
1807 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1810 static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
1812 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1813 TRACE("%p\n", This);
1814 return IFileDialog2_Release(&This->IFileDialog2_iface);
1817 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
1818 PCIDLIST_ABSOLUTE pidlFolder)
1820 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1821 TRACE("%p (%p)\n", This, pidlFolder);
1822 return S_OK;
1825 static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
1826 IShellView *psv)
1828 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1829 TRACE("%p (%p)\n", This, psv);
1830 return S_OK;
1833 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
1834 PCIDLIST_ABSOLUTE pidlFolder)
1836 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1837 HRESULT hr;
1838 TRACE("%p (%p)\n", This, pidlFolder);
1840 if(This->psi_folder)
1841 IShellItem_Release(This->psi_folder);
1843 hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&This->psi_folder);
1844 if(FAILED(hr))
1846 ERR("Failed to get the current folder.\n");
1847 This->psi_folder = NULL;
1850 return S_OK;
1853 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
1854 PCIDLIST_ABSOLUTE pidlFolder)
1856 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
1857 TRACE("%p (%p)\n", This, pidlFolder);
1858 return S_OK;
1861 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents = {
1862 IExplorerBrowserEvents_fnQueryInterface,
1863 IExplorerBrowserEvents_fnAddRef,
1864 IExplorerBrowserEvents_fnRelease,
1865 IExplorerBrowserEvents_fnOnNavigationPending,
1866 IExplorerBrowserEvents_fnOnViewCreated,
1867 IExplorerBrowserEvents_fnOnNavigationComplete,
1868 IExplorerBrowserEvents_fnOnNavigationFailed
1871 /**************************************************************************
1872 * IServiceProvider implementation
1874 static inline FileDialogImpl *impl_from_IServiceProvider(IServiceProvider *iface)
1876 return CONTAINING_RECORD(iface, FileDialogImpl, IServiceProvider_iface);
1879 static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface,
1880 REFIID riid, void **ppvObject)
1882 FileDialogImpl *This = impl_from_IServiceProvider(iface);
1883 TRACE("%p\n", This);
1884 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1887 static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
1889 FileDialogImpl *This = impl_from_IServiceProvider(iface);
1890 TRACE("%p\n", This);
1891 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1894 static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
1896 FileDialogImpl *This = impl_from_IServiceProvider(iface);
1897 TRACE("%p\n", This);
1898 return IFileDialog2_Release(&This->IFileDialog2_iface);
1901 static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
1902 REFGUID guidService,
1903 REFIID riid, void **ppv)
1905 FileDialogImpl *This = impl_from_IServiceProvider(iface);
1906 HRESULT hr = E_FAIL;
1907 TRACE("%p (%s, %s, %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1909 *ppv = NULL;
1910 if(IsEqualGUID(guidService, &SID_STopLevelBrowser) && This->peb)
1911 hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv);
1912 else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame))
1913 hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv);
1914 else
1915 FIXME("Interface %s requested from unknown service %s\n",
1916 debugstr_guid(riid), debugstr_guid(guidService));
1918 if(SUCCEEDED(hr) && *ppv)
1920 IUnknown_AddRef((IUnknown*)*ppv);
1921 return S_OK;
1924 return E_FAIL;
1927 static const IServiceProviderVtbl vt_IServiceProvider = {
1928 IServiceProvider_fnQueryInterface,
1929 IServiceProvider_fnAddRef,
1930 IServiceProvider_fnRelease,
1931 IServiceProvider_fnQueryService
1934 /**************************************************************************
1935 * ICommDlgBrowser3 implementation
1937 static inline FileDialogImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
1939 return CONTAINING_RECORD(iface, FileDialogImpl, ICommDlgBrowser3_iface);
1942 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
1943 REFIID riid, void **ppvObject)
1945 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
1946 TRACE("%p\n", This);
1947 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
1950 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
1952 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
1953 TRACE("%p\n", This);
1954 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
1957 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
1959 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
1960 TRACE("%p\n", This);
1961 return IFileDialog2_Release(&This->IFileDialog2_iface);
1964 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
1965 IShellView *shv)
1967 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
1968 HRESULT hr;
1969 TRACE("%p (%p)\n", This, shv);
1971 hr = on_default_action(This);
1973 if(SUCCEEDED(hr))
1974 EndDialog(This->dlg_hwnd, S_OK);
1976 return S_OK;
1979 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
1980 IShellView *shv, ULONG uChange )
1982 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
1983 IDataObject *new_selection;
1984 HRESULT hr;
1985 TRACE("%p (%p, %x)\n", This, shv, uChange);
1987 switch(uChange)
1989 case CDBOSC_SELCHANGE:
1990 if(This->psia_selection)
1992 IShellItemArray_Release(This->psia_selection);
1993 This->psia_selection = NULL;
1996 hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&new_selection);
1997 if(SUCCEEDED(hr))
1999 hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
2000 (void**)&This->psia_selection);
2001 if(SUCCEEDED(hr))
2002 fill_filename_from_selection(This);
2004 IDataObject_Release(new_selection);
2006 break;
2007 default:
2008 TRACE("Unhandled state change\n");
2010 return S_OK;
2013 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
2014 IShellView *shv, LPCITEMIDLIST pidl)
2016 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2017 IShellItem *psi;
2018 LPWSTR filename;
2019 LPITEMIDLIST parent_pidl;
2020 HRESULT hr;
2021 ULONG attr;
2022 TRACE("%p (%p, %p)\n", This, shv, pidl);
2024 if(!This->filterspec_count)
2025 return S_OK;
2027 hr = SHGetIDListFromObject((IUnknown*)shv, &parent_pidl);
2028 if(SUCCEEDED(hr))
2030 LPITEMIDLIST full_pidl = ILCombine(parent_pidl, pidl);
2031 hr = SHCreateItemFromIDList(full_pidl, &IID_IShellItem, (void**)&psi);
2032 ILFree(parent_pidl);
2033 ILFree(full_pidl);
2035 if(FAILED(hr))
2037 ERR("Failed to get shellitem (%08x).\n", hr);
2038 return S_OK;
2041 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER|SFGAO_LINK, &attr);
2042 if(FAILED(hr) || (attr & (SFGAO_FOLDER | SFGAO_LINK)))
2044 IShellItem_Release(psi);
2045 return S_OK;
2048 hr = S_OK;
2049 if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename)))
2051 if(!PathMatchSpecW(filename, This->filterspecs[This->filetypeindex].pszSpec))
2052 hr = S_FALSE;
2053 CoTaskMemFree(filename);
2056 IShellItem_Release(psi);
2057 return hr;
2060 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
2061 IShellView *ppshv, DWORD dwNotifyType)
2063 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2064 FIXME("Stub: %p (%p, 0x%x)\n", This, ppshv, dwNotifyType);
2065 return E_NOTIMPL;
2068 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
2069 IShellView *pshv,
2070 LPWSTR pszText, int cchMax)
2072 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2073 FIXME("Stub: %p (%p, %p, %d)\n", This, pshv, pszText, cchMax);
2074 return E_NOTIMPL;
2077 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, DWORD *pdwFlags)
2079 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2080 FIXME("Stub: %p (%p)\n", This, pdwFlags);
2081 return E_NOTIMPL;
2084 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
2085 IShellView *pshv, int iColumn)
2087 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2088 FIXME("Stub: %p (%p, %d)\n", This, pshv, iColumn);
2089 return E_NOTIMPL;
2092 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
2093 LPWSTR pszFileSpec, int cchFileSpec)
2095 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2096 FIXME("Stub: %p (%p, %d)\n", This, pszFileSpec, cchFileSpec);
2097 return E_NOTIMPL;
2100 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
2101 IShellView *pshv)
2103 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2104 FIXME("Stub: %p (%p)\n", This, pshv);
2105 return E_NOTIMPL;
2108 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
2109 ICommDlgBrowser3_fnQueryInterface,
2110 ICommDlgBrowser3_fnAddRef,
2111 ICommDlgBrowser3_fnRelease,
2112 ICommDlgBrowser3_fnOnDefaultCommand,
2113 ICommDlgBrowser3_fnOnStateChange,
2114 ICommDlgBrowser3_fnIncludeObject,
2115 ICommDlgBrowser3_fnNotify,
2116 ICommDlgBrowser3_fnGetDefaultMenuText,
2117 ICommDlgBrowser3_fnGetViewFlags,
2118 ICommDlgBrowser3_fnOnColumnClicked,
2119 ICommDlgBrowser3_fnGetCurrentFilter,
2120 ICommDlgBrowser3_fnOnPreviewCreated
2123 static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
2125 FileDialogImpl *fdimpl;
2126 HRESULT hr;
2127 IShellFolder *psf;
2128 TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
2130 if(!ppv)
2131 return E_POINTER;
2132 if(pUnkOuter)
2133 return CLASS_E_NOAGGREGATION;
2135 fdimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(FileDialogImpl));
2136 if(!fdimpl)
2137 return E_OUTOFMEMORY;
2139 fdimpl->ref = 1;
2140 fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
2141 fdimpl->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
2142 fdimpl->IServiceProvider_iface.lpVtbl = &vt_IServiceProvider;
2143 fdimpl->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
2145 if(type == ITEMDLG_TYPE_OPEN)
2147 fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
2148 fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
2149 fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
2150 fdimpl->custom_title = fdimpl->custom_okbutton = NULL;
2152 else
2154 WCHAR buf[16];
2155 fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
2156 fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
2157 fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
2159 LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, sizeof(buf)/sizeof(WCHAR));
2160 fdimpl->custom_title = StrDupW(buf);
2161 fdimpl->custom_okbutton = StrDupW(buf);
2164 fdimpl->filterspecs = NULL;
2165 fdimpl->filterspec_count = 0;
2166 fdimpl->filetypeindex = 0;
2168 fdimpl->psia_selection = fdimpl->psia_results = NULL;
2169 fdimpl->psi_setfolder = fdimpl->psi_folder = NULL;
2171 list_init(&fdimpl->events_clients);
2172 fdimpl->events_next_cookie = 0;
2174 fdimpl->dlg_hwnd = NULL;
2175 fdimpl->peb = NULL;
2177 fdimpl->set_filename = NULL;
2178 fdimpl->custom_cancelbutton = fdimpl->custom_filenamelabel = NULL;
2180 /* FIXME: The default folder setting should be restored for the
2181 * application if it was previously set. */
2182 SHGetDesktopFolder(&psf);
2183 SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
2184 IShellFolder_Release(psf);
2186 hr = IUnknown_QueryInterface((IUnknown*)fdimpl, riid, ppv);
2187 IUnknown_Release((IUnknown*)fdimpl);
2188 return hr;
2191 HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2193 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
2196 HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2198 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);