wined3d: Remove COM from the shader implementation.
[wine] / dlls / comdlg32 / itemdlg.c
1 /*
2  * Common Item Dialog
3  *
4  * Copyright 2010,2011 David Hedberg
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "winreg.h"
32 #include "shlwapi.h"
33
34 #include "commdlg.h"
35 #include "cdlg.h"
36
37 #include "wine/debug.h"
38 #include "wine/list.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
41
42 enum ITEMDLG_TYPE {
43     ITEMDLG_TYPE_OPEN,
44     ITEMDLG_TYPE_SAVE
45 };
46
47 typedef struct {
48     struct list entry;
49     IFileDialogEvents *pfde;
50     DWORD cookie;
51 } events_client;
52
53 typedef struct FileDialogImpl {
54     IFileDialog2 IFileDialog2_iface;
55     union {
56         IFileOpenDialog IFileOpenDialog_iface;
57         IFileSaveDialog IFileSaveDialog_iface;
58     } u;
59     enum ITEMDLG_TYPE dlg_type;
60     LONG ref;
61
62     FILEOPENDIALOGOPTIONS options;
63     COMDLG_FILTERSPEC *filterspecs;
64     UINT filterspec_count;
65     UINT filetypeindex;
66
67     struct list events_clients;
68     DWORD events_next_cookie;
69
70     IShellItemArray *psia_selection;
71     IShellItemArray *psia_results;
72     IShellItem *psi_defaultfolder;
73     IShellItem *psi_setfolder;
74     IShellItem *psi_folder;
75 } FileDialogImpl;
76
77 /**************************************************************************
78  * IFileDialog implementation
79  */
80 static inline FileDialogImpl *impl_from_IFileDialog2(IFileDialog2 *iface)
81 {
82     return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialog2_iface);
83 }
84
85 static HRESULT WINAPI IFileDialog2_fnQueryInterface(IFileDialog2 *iface,
86                                                     REFIID riid,
87                                                     void **ppvObject)
88 {
89     FileDialogImpl *This = impl_from_IFileDialog2(iface);
90     TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
91
92     *ppvObject = NULL;
93     if(IsEqualGUID(riid, &IID_IUnknown) ||
94        IsEqualGUID(riid, &IID_IFileDialog) ||
95        IsEqualGUID(riid, &IID_IFileDialog2))
96     {
97         *ppvObject = iface;
98     }
99     else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
100     {
101         *ppvObject = &This->u.IFileOpenDialog_iface;
102     }
103     else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
104     {
105         *ppvObject = &This->u.IFileSaveDialog_iface;
106     }
107     else
108         FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
109
110     if(*ppvObject)
111     {
112         IUnknown_AddRef((IUnknown*)*ppvObject);
113         return S_OK;
114     }
115
116     return E_NOINTERFACE;
117 }
118
119 static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
120 {
121     FileDialogImpl *This = impl_from_IFileDialog2(iface);
122     LONG ref = InterlockedIncrement(&This->ref);
123     TRACE("%p - ref %d\n", This, ref);
124
125     return ref;
126 }
127
128 static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
129 {
130     FileDialogImpl *This = impl_from_IFileDialog2(iface);
131     LONG ref = InterlockedDecrement(&This->ref);
132     TRACE("%p - ref %d\n", This, ref);
133
134     if(!ref)
135     {
136         UINT i;
137         for(i = 0; i < This->filterspec_count; i++)
138         {
139             LocalFree((void*)This->filterspecs[i].pszName);
140             LocalFree((void*)This->filterspecs[i].pszSpec);
141         }
142         HeapFree(GetProcessHeap(), 0, This->filterspecs);
143
144         if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
145         if(This->psi_setfolder)     IShellItem_Release(This->psi_setfolder);
146         if(This->psi_folder)        IShellItem_Release(This->psi_folder);
147         if(This->psia_selection)    IShellItemArray_Release(This->psia_selection);
148         if(This->psia_results)      IShellItemArray_Release(This->psia_results);
149
150         HeapFree(GetProcessHeap(), 0, This);
151     }
152
153     return ref;
154 }
155
156 static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
157 {
158     FileDialogImpl *This = impl_from_IFileDialog2(iface);
159     FIXME("stub - %p (%p)\n", This, hwndOwner);
160     return E_NOTIMPL;
161 }
162
163 static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
164                                                   const COMDLG_FILTERSPEC *rgFilterSpec)
165 {
166     FileDialogImpl *This = impl_from_IFileDialog2(iface);
167     UINT i;
168     TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
169
170     if(This->filterspecs)
171         return E_UNEXPECTED;
172
173     if(!rgFilterSpec)
174         return E_INVALIDARG;
175
176     if(!cFileTypes)
177         return S_OK;
178
179     This->filterspecs = HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC)*cFileTypes);
180     for(i = 0; i < cFileTypes; i++)
181     {
182         This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
183         This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
184     }
185     This->filterspec_count = cFileTypes;
186
187     return S_OK;
188 }
189
190 static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
191 {
192     FileDialogImpl *This = impl_from_IFileDialog2(iface);
193     TRACE("%p (%d)\n", This, iFileType);
194
195     if(!This->filterspecs)
196         return E_FAIL;
197
198     if(iFileType >= This->filterspec_count)
199         This->filetypeindex = This->filterspec_count - 1;
200     else
201         This->filetypeindex = iFileType;
202
203     return S_OK;
204 }
205
206 static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
207 {
208     FileDialogImpl *This = impl_from_IFileDialog2(iface);
209     TRACE("%p (%p)\n", This, piFileType);
210
211     if(!piFileType)
212         return E_INVALIDARG;
213
214     *piFileType = This->filetypeindex;
215
216     return S_OK;
217 }
218
219 static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
220 {
221     FileDialogImpl *This = impl_from_IFileDialog2(iface);
222     events_client *client;
223     TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
224
225     if(!pfde || !pdwCookie)
226         return E_INVALIDARG;
227
228     client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
229     client->pfde = pfde;
230     client->cookie = ++This->events_next_cookie;
231
232     IFileDialogEvents_AddRef(pfde);
233     *pdwCookie = client->cookie;
234
235     list_add_tail(&This->events_clients, &client->entry);
236
237     return S_OK;
238 }
239
240 static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
241 {
242     FileDialogImpl *This = impl_from_IFileDialog2(iface);
243     events_client *client, *found = NULL;
244     TRACE("%p (%d)\n", This, dwCookie);
245
246     LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
247     {
248         if(client->cookie == dwCookie)
249         {
250             found = client;
251             break;
252         }
253     }
254
255     if(found)
256     {
257         list_remove(&found->entry);
258         IFileDialogEvents_Release(found->pfde);
259         HeapFree(GetProcessHeap(), 0, found);
260         return S_OK;
261     }
262
263     return E_INVALIDARG;
264 }
265
266 static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
267 {
268     FileDialogImpl *This = impl_from_IFileDialog2(iface);
269     TRACE("%p (0x%x)\n", This, fos);
270
271     This->options = fos;
272
273     return S_OK;
274 }
275
276 static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
277 {
278     FileDialogImpl *This = impl_from_IFileDialog2(iface);
279     TRACE("%p (%p)\n", This, pfos);
280
281     if(!pfos)
282         return E_INVALIDARG;
283
284     *pfos = This->options;
285
286     return S_OK;
287 }
288
289 static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
290 {
291     FileDialogImpl *This = impl_from_IFileDialog2(iface);
292     TRACE("%p (%p)\n", This, psi);
293     if(This->psi_defaultfolder)
294         IShellItem_Release(This->psi_defaultfolder);
295
296     This->psi_defaultfolder = psi;
297
298     if(This->psi_defaultfolder)
299         IShellItem_AddRef(This->psi_defaultfolder);
300
301     return S_OK;
302 }
303
304 static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
305 {
306     FileDialogImpl *This = impl_from_IFileDialog2(iface);
307     TRACE("%p (%p)\n", This, psi);
308     if(This->psi_setfolder)
309         IShellItem_Release(This->psi_setfolder);
310
311     This->psi_setfolder = psi;
312
313     if(This->psi_setfolder)
314         IShellItem_AddRef(This->psi_setfolder);
315
316     return S_OK;
317 }
318
319 static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
320 {
321     FileDialogImpl *This = impl_from_IFileDialog2(iface);
322     TRACE("%p (%p)\n", This, ppsi);
323     if(!ppsi)
324         return E_INVALIDARG;
325
326     /* FIXME:
327        If the dialog is shown, return the current(ly selected) folder. */
328
329     *ppsi = NULL;
330     if(This->psi_folder)
331         *ppsi = This->psi_folder;
332     else if(This->psi_setfolder)
333         *ppsi = This->psi_setfolder;
334     else if(This->psi_defaultfolder)
335         *ppsi = This->psi_defaultfolder;
336
337     if(*ppsi)
338     {
339         IShellItem_AddRef(*ppsi);
340         return S_OK;
341     }
342
343     return E_FAIL;
344 }
345
346 static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
347 {
348     FileDialogImpl *This = impl_from_IFileDialog2(iface);
349     HRESULT hr;
350     TRACE("%p (%p)\n", This, ppsi);
351
352     if(!ppsi)
353         return E_INVALIDARG;
354
355     if(This->psia_selection)
356     {
357         /* FIXME: Check filename edit box */
358         hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
359         return hr;
360     }
361
362     return E_FAIL;
363 }
364
365 static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
366 {
367     FileDialogImpl *This = impl_from_IFileDialog2(iface);
368     FIXME("stub - %p (%p)\n", This, pszName);
369     return E_NOTIMPL;
370 }
371
372 static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
373 {
374     FileDialogImpl *This = impl_from_IFileDialog2(iface);
375     FIXME("stub - %p (%p)\n", This, pszName);
376     return E_NOTIMPL;
377 }
378
379 static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
380 {
381     FileDialogImpl *This = impl_from_IFileDialog2(iface);
382     FIXME("stub - %p (%p)\n", This, pszTitle);
383     return E_NOTIMPL;
384 }
385
386 static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
387 {
388     FileDialogImpl *This = impl_from_IFileDialog2(iface);
389     FIXME("stub - %p (%p)\n", This, pszText);
390     return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
394 {
395     FileDialogImpl *This = impl_from_IFileDialog2(iface);
396     FIXME("stub - %p (%p)\n", This, pszLabel);
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
401 {
402     FileDialogImpl *This = impl_from_IFileDialog2(iface);
403     HRESULT hr;
404     TRACE("%p (%p)\n", This, ppsi);
405
406     if(!ppsi)
407         return E_INVALIDARG;
408
409     if(This->psia_results)
410     {
411         UINT item_count;
412         hr = IShellItemArray_GetCount(This->psia_results, &item_count);
413         if(SUCCEEDED(hr))
414         {
415             if(item_count != 1)
416                 return E_FAIL;
417
418             /* Adds a reference. */
419             hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
420         }
421
422         return hr;
423     }
424
425     return E_UNEXPECTED;
426 }
427
428 static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
429 {
430     FileDialogImpl *This = impl_from_IFileDialog2(iface);
431     FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
436 {
437     FileDialogImpl *This = impl_from_IFileDialog2(iface);
438     FIXME("stub - %p (%s)\n", This, debugstr_w(pszDefaultExtension));
439     return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
443 {
444     FileDialogImpl *This = impl_from_IFileDialog2(iface);
445     FIXME("stub - %p (0x%08x)\n", This, hr);
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
450 {
451     FileDialogImpl *This = impl_from_IFileDialog2(iface);
452     FIXME("stub - %p (%s)\n", This, debugstr_guid(guid));
453     return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
457 {
458     FileDialogImpl *This = impl_from_IFileDialog2(iface);
459     FIXME("stub - %p\n", This);
460     return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
464 {
465     FileDialogImpl *This = impl_from_IFileDialog2(iface);
466     FIXME("stub - %p (%p)\n", This, pFilter);
467     return E_NOTIMPL;
468 }
469
470 static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
471 {
472     FileDialogImpl *This = impl_from_IFileDialog2(iface);
473     FIXME("stub - %p (%s)\n", This, debugstr_w(pszLabel));
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
478 {
479     FileDialogImpl *This = impl_from_IFileDialog2(iface);
480     FIXME("stub - %p (%p)\n", This, psi);
481     return E_NOTIMPL;
482 }
483
484 static const IFileDialog2Vtbl vt_IFileDialog2 = {
485     IFileDialog2_fnQueryInterface,
486     IFileDialog2_fnAddRef,
487     IFileDialog2_fnRelease,
488     IFileDialog2_fnShow,
489     IFileDialog2_fnSetFileTypes,
490     IFileDialog2_fnSetFileTypeIndex,
491     IFileDialog2_fnGetFileTypeIndex,
492     IFileDialog2_fnAdvise,
493     IFileDialog2_fnUnadvise,
494     IFileDialog2_fnSetOptions,
495     IFileDialog2_fnGetOptions,
496     IFileDialog2_fnSetDefaultFolder,
497     IFileDialog2_fnSetFolder,
498     IFileDialog2_fnGetFolder,
499     IFileDialog2_fnGetCurrentSelection,
500     IFileDialog2_fnSetFileName,
501     IFileDialog2_fnGetFileName,
502     IFileDialog2_fnSetTitle,
503     IFileDialog2_fnSetOkButtonLabel,
504     IFileDialog2_fnSetFileNameLabel,
505     IFileDialog2_fnGetResult,
506     IFileDialog2_fnAddPlace,
507     IFileDialog2_fnSetDefaultExtension,
508     IFileDialog2_fnClose,
509     IFileDialog2_fnSetClientGuid,
510     IFileDialog2_fnClearClientData,
511     IFileDialog2_fnSetFilter,
512     IFileDialog2_fnSetCancelButtonLabel,
513     IFileDialog2_fnSetNavigationRoot
514 };
515
516 /**************************************************************************
517  * IFileOpenDialog
518  */
519 static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
520 {
521     return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
522 }
523
524 static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
525                                                        REFIID riid, void **ppvObject)
526 {
527     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
528     return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
529 }
530
531 static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
532 {
533     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
534     return IFileDialog2_AddRef(&This->IFileDialog2_iface);
535 }
536
537 static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
538 {
539     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
540     return IFileDialog2_Release(&This->IFileDialog2_iface);
541 }
542
543 static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
544 {
545     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
546     return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
547 }
548
549 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
550                                                      const COMDLG_FILTERSPEC *rgFilterSpec)
551 {
552     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
553     return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
554 }
555
556 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
557 {
558     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
559     return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
560 }
561
562 static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
563 {
564     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
565     return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
566 }
567
568 static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
569                                                DWORD *pdwCookie)
570 {
571     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
572     return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
573 }
574
575 static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
576 {
577     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
578     return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
579 }
580
581 static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
582 {
583     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
584     return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
585 }
586
587 static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
588 {
589     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
590     return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
591 }
592
593 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
594 {
595     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
596     return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
597 }
598
599 static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
600 {
601     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
602     return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
603 }
604
605 static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
606 {
607     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
608     return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
609 }
610
611 static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
612 {
613     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
614     return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
615 }
616
617 static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
618 {
619     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
620     return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
621 }
622
623 static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
624 {
625     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
626     return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
627 }
628
629 static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
630 {
631     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
632     return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
633 }
634
635 static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
636 {
637     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
638     return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
639 }
640
641 static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
642 {
643     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
644     return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
645 }
646
647 static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
648 {
649     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
650     return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
651 }
652
653 static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
654 {
655     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
656     return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
657 }
658
659 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
660                                                             LPCWSTR pszDefaultExtension)
661 {
662     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
663     return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
664 }
665
666 static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
667 {
668     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
669     return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
670 }
671
672 static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
673 {
674     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
675     return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
676 }
677
678 static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
679 {
680     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
681     return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
682 }
683
684 static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
685 {
686     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
687     return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
688 }
689
690 static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
691 {
692     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
693     TRACE("%p (%p)\n", This, ppenum);
694
695     *ppenum = This->psia_results;
696
697     if(*ppenum)
698     {
699         IShellItemArray_AddRef(*ppenum);
700         return S_OK;
701     }
702
703     return E_FAIL;
704 }
705
706 static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
707 {
708     FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
709     TRACE("%p (%p)\n", This, ppsai);
710
711     if(This->psia_selection)
712     {
713         *ppsai = This->psia_selection;
714         IShellItemArray_AddRef(*ppsai);
715         return S_OK;
716     }
717
718     return E_FAIL;
719 }
720
721 static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
722     IFileOpenDialog_fnQueryInterface,
723     IFileOpenDialog_fnAddRef,
724     IFileOpenDialog_fnRelease,
725     IFileOpenDialog_fnShow,
726     IFileOpenDialog_fnSetFileTypes,
727     IFileOpenDialog_fnSetFileTypeIndex,
728     IFileOpenDialog_fnGetFileTypeIndex,
729     IFileOpenDialog_fnAdvise,
730     IFileOpenDialog_fnUnadvise,
731     IFileOpenDialog_fnSetOptions,
732     IFileOpenDialog_fnGetOptions,
733     IFileOpenDialog_fnSetDefaultFolder,
734     IFileOpenDialog_fnSetFolder,
735     IFileOpenDialog_fnGetFolder,
736     IFileOpenDialog_fnGetCurrentSelection,
737     IFileOpenDialog_fnSetFileName,
738     IFileOpenDialog_fnGetFileName,
739     IFileOpenDialog_fnSetTitle,
740     IFileOpenDialog_fnSetOkButtonLabel,
741     IFileOpenDialog_fnSetFileNameLabel,
742     IFileOpenDialog_fnGetResult,
743     IFileOpenDialog_fnAddPlace,
744     IFileOpenDialog_fnSetDefaultExtension,
745     IFileOpenDialog_fnClose,
746     IFileOpenDialog_fnSetClientGuid,
747     IFileOpenDialog_fnClearClientData,
748     IFileOpenDialog_fnSetFilter,
749     IFileOpenDialog_fnGetResults,
750     IFileOpenDialog_fnGetSelectedItems
751 };
752
753 /**************************************************************************
754  * IFileSaveDialog
755  */
756 static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
757 {
758     return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
759 }
760
761 static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
762                                                        REFIID riid,
763                                                        void **ppvObject)
764 {
765     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
766     return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
767 }
768
769 static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
770 {
771     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
772     return IFileDialog2_AddRef(&This->IFileDialog2_iface);
773 }
774
775 static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
776 {
777     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
778     return IFileDialog2_Release(&This->IFileDialog2_iface);
779 }
780
781 static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
782 {
783     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
784     return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
785 }
786
787 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
788                                                      const COMDLG_FILTERSPEC *rgFilterSpec)
789 {
790     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
791     return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
792 }
793
794 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
795 {
796     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
797     return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
798 }
799
800 static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
801 {
802     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
803     return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
804 }
805
806 static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
807                                                DWORD *pdwCookie)
808 {
809     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
810     return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
811 }
812
813 static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
814 {
815     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
816     return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
817 }
818
819 static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
820 {
821     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
822     return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
823 }
824
825 static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
826 {
827     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
828     return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
829 }
830
831 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
832 {
833     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
834     return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
835 }
836
837 static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
838 {
839     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
840     return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
841 }
842
843 static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
844 {
845     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
846     return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
847 }
848
849 static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
850 {
851     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
852     return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
853 }
854
855 static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
856 {
857     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
858     return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
859 }
860
861 static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
862 {
863     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
864     return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
865 }
866
867 static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
868 {
869     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
870     return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
871 }
872
873 static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
874 {
875     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
876     return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
877 }
878
879 static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
880 {
881     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
882     return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
883 }
884
885 static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
886 {
887     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
888     return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
889 }
890
891 static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
892 {
893     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
894     return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
895 }
896
897 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
898                                                             LPCWSTR pszDefaultExtension)
899 {
900     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
901     return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
902 }
903
904 static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
905 {
906     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
907     return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
908 }
909
910 static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
911 {
912     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
913     return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
914 }
915
916 static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
917 {
918     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
919     return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
920 }
921
922 static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
923 {
924     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
925     return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
926 }
927
928 static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
929 {
930     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
931     FIXME("stub - %p (%p)\n", This, psi);
932     return E_NOTIMPL;
933 }
934
935 static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
936 {
937     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
938     FIXME("stub - %p (%p)\n", This, pStore);
939     return E_NOTIMPL;
940 }
941
942 static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
943                                                                IPropertyDescriptionList *pList,
944                                                                BOOL fAppendDefault)
945 {
946     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
947     FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
948     return E_NOTIMPL;
949 }
950
951 static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
952 {
953     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
954     FIXME("stub - %p (%p)\n", This, ppStore);
955     return E_NOTIMPL;
956 }
957
958 static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
959                                                         IShellItem *psi,
960                                                         IPropertyStore *pStore,
961                                                         HWND hwnd,
962                                                         IFileOperationProgressSink *pSink)
963 {
964     FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
965     FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
966     return E_NOTIMPL;
967 }
968
969 static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
970     IFileSaveDialog_fnQueryInterface,
971     IFileSaveDialog_fnAddRef,
972     IFileSaveDialog_fnRelease,
973     IFileSaveDialog_fnShow,
974     IFileSaveDialog_fnSetFileTypes,
975     IFileSaveDialog_fnSetFileTypeIndex,
976     IFileSaveDialog_fnGetFileTypeIndex,
977     IFileSaveDialog_fnAdvise,
978     IFileSaveDialog_fnUnadvise,
979     IFileSaveDialog_fnSetOptions,
980     IFileSaveDialog_fnGetOptions,
981     IFileSaveDialog_fnSetDefaultFolder,
982     IFileSaveDialog_fnSetFolder,
983     IFileSaveDialog_fnGetFolder,
984     IFileSaveDialog_fnGetCurrentSelection,
985     IFileSaveDialog_fnSetFileName,
986     IFileSaveDialog_fnGetFileName,
987     IFileSaveDialog_fnSetTitle,
988     IFileSaveDialog_fnSetOkButtonLabel,
989     IFileSaveDialog_fnSetFileNameLabel,
990     IFileSaveDialog_fnGetResult,
991     IFileSaveDialog_fnAddPlace,
992     IFileSaveDialog_fnSetDefaultExtension,
993     IFileSaveDialog_fnClose,
994     IFileSaveDialog_fnSetClientGuid,
995     IFileSaveDialog_fnClearClientData,
996     IFileSaveDialog_fnSetFilter,
997     IFileSaveDialog_fnSetSaveAsItem,
998     IFileSaveDialog_fnSetProperties,
999     IFileSaveDialog_fnSetCollectedProperties,
1000     IFileSaveDialog_fnGetProperties,
1001     IFileSaveDialog_fnApplyProperties
1002 };
1003
1004 static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
1005 {
1006     FileDialogImpl *fdimpl;
1007     HRESULT hr;
1008     IShellFolder *psf;
1009     TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
1010
1011     if(!ppv)
1012         return E_POINTER;
1013     if(pUnkOuter)
1014         return CLASS_E_NOAGGREGATION;
1015
1016     fdimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(FileDialogImpl));
1017     if(!fdimpl)
1018         return E_OUTOFMEMORY;
1019
1020     fdimpl->ref = 1;
1021     fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
1022
1023     if(type == ITEMDLG_TYPE_OPEN)
1024     {
1025         fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
1026         fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
1027         fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
1028     }
1029     else
1030     {
1031         fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
1032         fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
1033         fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
1034     }
1035
1036     fdimpl->filterspecs = NULL;
1037     fdimpl->filterspec_count = 0;
1038     fdimpl->filetypeindex = 0;
1039
1040     fdimpl->psia_selection = fdimpl->psia_results = NULL;
1041     fdimpl->psi_setfolder = fdimpl->psi_folder = NULL;
1042
1043     list_init(&fdimpl->events_clients);
1044     fdimpl->events_next_cookie = 0;
1045
1046     /* FIXME: The default folder setting should be restored for the
1047      * application if it was previously set. */
1048     SHGetDesktopFolder(&psf);
1049     SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
1050     IShellFolder_Release(psf);
1051
1052     hr = IUnknown_QueryInterface((IUnknown*)fdimpl, riid, ppv);
1053     IUnknown_Release((IUnknown*)fdimpl);
1054     return hr;
1055 }
1056
1057 HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
1058 {
1059     return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
1060 }
1061
1062 HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
1063 {
1064     return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);
1065 }