shell32: Unix folder COM cleanup.
[wine] / dlls / shell32 / shelldispatch.c
1 /*
2  * IShellDispatch implementation
3  *
4  * Copyright 2010 Alexander Morozov for Etersoft
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 "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25
26 #define COBJMACROS
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "shlwapi.h"
34 #include "shlobj.h"
35 #include "shldisp.h"
36 #include "debughlp.h"
37
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41
42 typedef struct {
43     IShellDispatch IShellDispatch_iface;
44     LONG ref;
45     ITypeInfo *iTypeInfo;
46 } ShellDispatch;
47
48 typedef struct {
49     Folder3 Folder_iface;
50     LONG ref;
51     ITypeInfo *iTypeInfo;
52     VARIANT dir;
53 } FolderImpl;
54
55 typedef struct {
56     FolderItem FolderItem_iface;
57     LONG ref;
58     ITypeInfo *iTypeInfo;
59     VARIANT dir;
60 } FolderItemImpl;
61
62 static inline ShellDispatch *impl_from_IShellDispatch(IShellDispatch *iface)
63 {
64     return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch_iface);
65 }
66
67 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
68 {
69     return CONTAINING_RECORD(iface, FolderImpl, Folder_iface);
70 }
71
72 static inline FolderItemImpl *impl_from_FolderItem(FolderItem *iface)
73 {
74     return CONTAINING_RECORD(iface, FolderItemImpl, FolderItem_iface);
75 }
76
77 static HRESULT load_type_info(REFGUID guid, ITypeInfo **pptinfo)
78 {
79     ITypeLib *typelib;
80     HRESULT ret;
81
82     ret = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &typelib);
83     if (FAILED(ret))
84     {
85         ERR("LoadRegTypeLib failed: %08x\n", ret);
86         return ret;
87     }
88
89     ret = ITypeLib_GetTypeInfoOfGuid(typelib, guid, pptinfo);
90     ITypeLib_Release(typelib);
91     if (FAILED(ret))
92         ERR("failed to load ITypeInfo\n");
93
94     return ret;
95 }
96
97 static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem *iface,
98         REFIID riid, LPVOID *ppv)
99 {
100     FolderItemImpl *This = impl_from_FolderItem(iface);
101
102     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
103
104     if (!ppv) return E_INVALIDARG;
105
106     if (IsEqualIID(&IID_IUnknown, riid) ||
107         IsEqualIID(&IID_IDispatch, riid) ||
108         IsEqualIID(&IID_FolderItem, riid))
109         *ppv = This;
110     else
111     {
112         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
113         *ppv = NULL;
114         return E_NOINTERFACE;
115     }
116     IUnknown_AddRef((IUnknown*)*ppv);
117     return S_OK;
118 }
119
120 static ULONG WINAPI FolderItemImpl_AddRef(FolderItem *iface)
121 {
122     FolderItemImpl *This = impl_from_FolderItem(iface);
123     ULONG ref = InterlockedIncrement(&This->ref);
124
125     TRACE("(%p), new refcount=%i\n", iface, ref);
126
127     return ref;
128 }
129
130 static ULONG WINAPI FolderItemImpl_Release(FolderItem *iface)
131 {
132     FolderItemImpl *This = impl_from_FolderItem(iface);
133     ULONG ref = InterlockedDecrement(&This->ref);
134
135     TRACE("(%p), new refcount=%i\n", iface, ref);
136
137     if (!ref)
138     {
139         VariantClear(&This->dir);
140         ITypeInfo_Release(This->iTypeInfo);
141         HeapFree(GetProcessHeap(), 0, This);
142     }
143     return ref;
144 }
145
146 static HRESULT WINAPI FolderItemImpl_GetTypeInfoCount(FolderItem *iface,
147         UINT *pctinfo)
148 {
149     TRACE("(%p,%p)\n", iface, pctinfo);
150
151     *pctinfo = 1;
152     return S_OK;
153 }
154
155 static HRESULT WINAPI FolderItemImpl_GetTypeInfo(FolderItem *iface, UINT iTInfo,
156         LCID lcid, ITypeInfo **ppTInfo)
157 {
158     FolderItemImpl *This = impl_from_FolderItem(iface);
159
160     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
161
162     ITypeInfo_AddRef(This->iTypeInfo);
163     *ppTInfo = This->iTypeInfo;
164     return S_OK;
165 }
166
167 static HRESULT WINAPI FolderItemImpl_GetIDsOfNames(FolderItem *iface,
168         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
169         DISPID *rgDispId)
170 {
171     FolderItemImpl *This = impl_from_FolderItem(iface);
172
173     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
174             rgDispId);
175
176     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
177 }
178
179 static HRESULT WINAPI FolderItemImpl_Invoke(FolderItem *iface,
180         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
181         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
182         UINT *puArgErr)
183 {
184     FolderItemImpl *This = impl_from_FolderItem(iface);
185
186     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
187             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
188
189     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
190             pDispParams, pVarResult, pExcepInfo, puArgErr);
191 }
192
193 static HRESULT WINAPI FolderItemImpl_get_Application(FolderItem *iface,
194         IDispatch **ppid)
195 {
196     FIXME("(%p,%p)\n", iface, ppid);
197
198     *ppid = NULL;
199     return E_NOTIMPL;
200 }
201
202 static HRESULT WINAPI FolderItemImpl_get_Parent(FolderItem *iface,
203         IDispatch **ppid)
204 {
205     FIXME("(%p,%p)\n", iface, ppid);
206
207     *ppid = NULL;
208     return E_NOTIMPL;
209 }
210
211 static HRESULT WINAPI FolderItemImpl_get_Name(FolderItem *iface, BSTR *pbs)
212 {
213     FIXME("(%p,%p)\n", iface, pbs);
214
215     *pbs = NULL;
216     return E_NOTIMPL;
217 }
218
219 static HRESULT WINAPI FolderItemImpl_put_Name(FolderItem *iface, BSTR bs)
220 {
221     FIXME("(%p,%s)\n", iface, debugstr_w(bs));
222
223     return E_NOTIMPL;
224 }
225
226 static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem *iface, BSTR *pbs)
227 {
228     FolderItemImpl *This = impl_from_FolderItem(iface);
229     HRESULT ret = S_OK;
230     WCHAR *pathW;
231     int len;
232
233     TRACE("(%p,%p)\n", iface, pbs);
234
235     *pbs = NULL;
236     if (V_VT(&This->dir) == VT_I4)
237     {
238         pathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
239         if (!pathW) return E_OUTOFMEMORY;
240         ret = SHGetFolderPathW(NULL, V_I4(&This->dir), NULL, SHGFP_TYPE_CURRENT,
241                 pathW);
242         if (ret == S_OK)
243             *pbs = SysAllocString(pathW);
244         else if (ret == E_INVALIDARG)
245         {
246             FIXME("not implemented for %#x\n", V_I4(&This->dir));
247             ret = E_NOTIMPL;
248         }
249         HeapFree(GetProcessHeap(), 0, pathW);
250     }
251     else /* VT_BSTR */
252     {
253         pathW = V_BSTR(&This->dir);
254         len = lstrlenW(pathW);
255         *pbs = SysAllocStringLen(pathW, pathW[len - 1] == '\\' ? len - 1 : len);
256     }
257     if (ret == S_OK && !*pbs)
258         ret = E_OUTOFMEMORY;
259     return ret;
260 }
261
262 static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem *iface,
263         IDispatch **ppid)
264 {
265     FIXME("(%p,%p)\n", iface, ppid);
266
267     *ppid = NULL;
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem *iface,
272         IDispatch **ppid)
273 {
274     FIXME("(%p,%p)\n", iface, ppid);
275
276     *ppid = NULL;
277     return E_NOTIMPL;
278 }
279
280 static HRESULT WINAPI FolderItemImpl_get_IsLink(FolderItem *iface,
281         VARIANT_BOOL *pb)
282 {
283     FIXME("(%p,%p)\n", iface, pb);
284
285     return E_NOTIMPL;
286 }
287
288 static HRESULT WINAPI FolderItemImpl_get_IsFolder(FolderItem *iface,
289         VARIANT_BOOL *pb)
290 {
291     FIXME("(%p,%p)\n", iface, pb);
292
293     return E_NOTIMPL;
294 }
295
296 static HRESULT WINAPI FolderItemImpl_get_IsFileSystem(FolderItem *iface,
297         VARIANT_BOOL *pb)
298 {
299     FIXME("(%p,%p)\n", iface, pb);
300
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI FolderItemImpl_get_IsBrowsable(FolderItem *iface,
305         VARIANT_BOOL *pb)
306 {
307     FIXME("(%p,%p)\n", iface, pb);
308
309     return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI FolderItemImpl_get_ModifyDate(FolderItem *iface,
313         DATE *pdt)
314 {
315     FIXME("(%p,%p)\n", iface, pdt);
316
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI FolderItemImpl_put_ModifyDate(FolderItem *iface, DATE dt)
321 {
322     FIXME("(%p,%f)\n", iface, dt);
323
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI FolderItemImpl_get_Size(FolderItem *iface, LONG *pul)
328 {
329     FIXME("(%p,%p)\n", iface, pul);
330
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI FolderItemImpl_get_Type(FolderItem *iface, BSTR *pbs)
335 {
336     FIXME("(%p,%p)\n", iface, pbs);
337
338     *pbs = NULL;
339     return E_NOTIMPL;
340 }
341
342 static HRESULT WINAPI FolderItemImpl_Verbs(FolderItem *iface,
343         FolderItemVerbs **ppfic)
344 {
345     FIXME("(%p,%p)\n", iface, ppfic);
346
347     *ppfic = NULL;
348     return E_NOTIMPL;
349 }
350
351 static HRESULT WINAPI FolderItemImpl_InvokeVerb(FolderItem *iface,
352         VARIANT vVerb)
353 {
354     FIXME("(%p)\n", iface);
355
356     return E_NOTIMPL;
357 }
358
359 static const FolderItemVtbl FolderItemImpl_Vtbl = {
360     FolderItemImpl_QueryInterface,
361     FolderItemImpl_AddRef,
362     FolderItemImpl_Release,
363     FolderItemImpl_GetTypeInfoCount,
364     FolderItemImpl_GetTypeInfo,
365     FolderItemImpl_GetIDsOfNames,
366     FolderItemImpl_Invoke,
367     FolderItemImpl_get_Application,
368     FolderItemImpl_get_Parent,
369     FolderItemImpl_get_Name,
370     FolderItemImpl_put_Name,
371     FolderItemImpl_get_Path,
372     FolderItemImpl_get_GetLink,
373     FolderItemImpl_get_GetFolder,
374     FolderItemImpl_get_IsLink,
375     FolderItemImpl_get_IsFolder,
376     FolderItemImpl_get_IsFileSystem,
377     FolderItemImpl_get_IsBrowsable,
378     FolderItemImpl_get_ModifyDate,
379     FolderItemImpl_put_ModifyDate,
380     FolderItemImpl_get_Size,
381     FolderItemImpl_get_Type,
382     FolderItemImpl_Verbs,
383     FolderItemImpl_InvokeVerb
384 };
385
386 static HRESULT FolderItem_Constructor(VARIANT *dir, FolderItem **ppfi)
387 {
388     FolderItemImpl *This;
389     HRESULT ret;
390
391     *ppfi = NULL;
392
393     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderItemImpl));
394     if (!This) return E_OUTOFMEMORY;
395     This->FolderItem_iface.lpVtbl = &FolderItemImpl_Vtbl;
396     This->ref = 1;
397
398     ret = load_type_info(&IID_FolderItem, &This->iTypeInfo);
399     if (FAILED(ret))
400     {
401         HeapFree(GetProcessHeap(), 0, This);
402         return ret;
403     }
404
405     VariantInit(&This->dir);
406     ret = VariantCopy(&This->dir, dir);
407     if (FAILED(ret))
408     {
409         ITypeInfo_Release(This->iTypeInfo);
410         HeapFree(GetProcessHeap(), 0, This);
411         return E_OUTOFMEMORY;
412     }
413
414     *ppfi = (FolderItem*)This;
415     return ret;
416 }
417
418 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
419         LPVOID *ppv)
420 {
421     FolderImpl *This = impl_from_Folder(iface);
422
423     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
424
425     if (!ppv) return E_INVALIDARG;
426
427     if (IsEqualIID(&IID_IUnknown, riid) ||
428         IsEqualIID(&IID_IDispatch, riid) ||
429         IsEqualIID(&IID_Folder, riid) ||
430         IsEqualIID(&IID_Folder2, riid) ||
431         IsEqualIID(&IID_Folder3, riid))
432         *ppv = This;
433     else
434     {
435         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
436         *ppv = NULL;
437         return E_NOINTERFACE;
438     }
439     IUnknown_AddRef((IUnknown*)*ppv);
440     return S_OK;
441 }
442
443 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
444 {
445     FolderImpl *This = impl_from_Folder(iface);
446     ULONG ref = InterlockedIncrement(&This->ref);
447
448     TRACE("(%p), new refcount=%i\n", iface, ref);
449
450     return ref;
451 }
452
453 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
454 {
455     FolderImpl *This = impl_from_Folder(iface);
456     ULONG ref = InterlockedDecrement(&This->ref);
457
458     TRACE("(%p), new refcount=%i\n", iface, ref);
459
460     if (!ref)
461     {
462         VariantClear(&This->dir);
463         ITypeInfo_Release(This->iTypeInfo);
464         HeapFree(GetProcessHeap(), 0, This);
465     }
466     return ref;
467 }
468
469 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
470 {
471     TRACE("(%p,%p)\n", iface, pctinfo);
472
473     *pctinfo = 1;
474     return S_OK;
475 }
476
477 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
478         LCID lcid, ITypeInfo **ppTInfo)
479 {
480     FolderImpl *This = impl_from_Folder(iface);
481
482     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
483
484     ITypeInfo_AddRef(This->iTypeInfo);
485     *ppTInfo = This->iTypeInfo;
486     return S_OK;
487 }
488
489 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
490         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
491 {
492     FolderImpl *This = impl_from_Folder(iface);
493
494     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
495             rgDispId);
496
497     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames,
498             rgDispId);
499 }
500
501 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
502         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
503         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
504 {
505     FolderImpl *This = impl_from_Folder(iface);
506
507     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
508             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
509
510     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
511             pDispParams, pVarResult, pExcepInfo, puArgErr);
512 }
513
514 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs)
515 {
516     FolderImpl *This = impl_from_Folder(iface);
517     WCHAR *p;
518     int len;
519
520     TRACE("(%p,%p)\n", iface, pbs);
521
522     *pbs = NULL;
523
524     if (V_VT(&This->dir) == VT_I4)
525     {
526         FIXME("special folder constants are not supported\n");
527         return E_NOTIMPL;
528     }
529     p = PathFindFileNameW(V_BSTR(&This->dir));
530     len = lstrlenW(p);
531     *pbs = SysAllocStringLen(p, p[len - 1] == '\\' ? len - 1 : len);
532     return *pbs ? S_OK : E_OUTOFMEMORY;
533 }
534
535 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface,
536         IDispatch **ppid)
537 {
538     FIXME("(%p,%p)\n", iface, ppid);
539
540     *ppid = NULL;
541     return E_NOTIMPL;
542 }
543
544 static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid)
545 {
546     FIXME("(%p,%p)\n", iface, ppid);
547
548     *ppid = NULL;
549     return E_NOTIMPL;
550 }
551
552 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
553 {
554     FIXME("(%p,%p)\n", iface, ppsf);
555
556     *ppsf = NULL;
557     return E_NOTIMPL;
558 }
559
560 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
561 {
562     FIXME("(%p,%p)\n", iface, ppid);
563
564     *ppid = NULL;
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR bName,
569         FolderItem **ppid)
570 {
571     FIXME("(%p,%s,%p)\n", iface, debugstr_w(bName), ppid);
572
573     *ppid = NULL;
574     return E_NOTIMPL;
575 }
576
577 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR bName,
578         VARIANT vOptions)
579 {
580     FIXME("(%p,%s)\n", iface, debugstr_w(bName));
581
582     return E_NOTIMPL;
583 }
584
585 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT vItem,
586         VARIANT vOptions)
587 {
588     FIXME("(%p)\n", iface);
589
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT vItem,
594         VARIANT vOptions)
595 {
596     FIXME("(%p)\n", iface);
597
598     return E_NOTIMPL;
599 }
600
601 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT vItem,
602         int iColumn, BSTR *pbs)
603 {
604     FIXME("(%p,%d,%p)\n", iface, iColumn, pbs);
605
606     *pbs = NULL;
607     return E_NOTIMPL;
608 }
609
610 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **ppfi)
611 {
612     FolderImpl *This = impl_from_Folder(iface);
613
614     TRACE("(%p,%p)\n", iface, ppfi);
615
616     return FolderItem_Constructor(&This->dir, ppfi);
617 }
618
619 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
620 {
621     FIXME("(%p,%p)\n", iface, pul);
622
623     return E_NOTIMPL;
624 }
625
626 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
627 {
628     FIXME("(%p)\n", iface);
629
630     return E_NOTIMPL;
631 }
632
633 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
634         VARIANT_BOOL *pbHaveToShowWebViewBarricade)
635 {
636     FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
637
638     return E_NOTIMPL;
639 }
640
641 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
642 {
643     FIXME("(%p)\n", iface);
644
645     return E_NOTIMPL;
646 }
647
648 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
649         VARIANT_BOOL *pbShowWebViewBarricade)
650 {
651     FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
652
653     return E_NOTIMPL;
654 }
655
656 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
657         VARIANT_BOOL bShowWebViewBarricade)
658 {
659     FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
660
661     return E_NOTIMPL;
662 }
663
664 static const Folder3Vtbl FolderImpl_Vtbl = {
665     FolderImpl_QueryInterface,
666     FolderImpl_AddRef,
667     FolderImpl_Release,
668     FolderImpl_GetTypeInfoCount,
669     FolderImpl_GetTypeInfo,
670     FolderImpl_GetIDsOfNames,
671     FolderImpl_Invoke,
672     FolderImpl_get_Title,
673     FolderImpl_get_Application,
674     FolderImpl_get_Parent,
675     FolderImpl_get_ParentFolder,
676     FolderImpl_Items,
677     FolderImpl_ParseName,
678     FolderImpl_NewFolder,
679     FolderImpl_MoveHere,
680     FolderImpl_CopyHere,
681     FolderImpl_GetDetailsOf,
682     FolderImpl_get_Self,
683     FolderImpl_get_OfflineStatus,
684     FolderImpl_Synchronize,
685     FolderImpl_get_HaveToShowWebViewBarricade,
686     FolderImpl_DismissedWebViewBarricade,
687     FolderImpl_get_ShowWebViewBarricade,
688     FolderImpl_put_ShowWebViewBarricade
689 };
690
691 static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf)
692 {
693     FolderImpl *This;
694     HRESULT ret;
695
696     *ppsdf = NULL;
697
698     switch (V_VT(dir))
699     {
700         case VT_I4:
701             /* FIXME: add some checks */
702             break;
703         case VT_BSTR:
704             if (PathIsDirectoryW(V_BSTR(dir)) &&
705                 !PathIsRelativeW(V_BSTR(dir)) &&
706                 PathFileExistsW(V_BSTR(dir)))
707                 break;
708         default:
709             return S_FALSE;
710     }
711
712     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl));
713     if (!This) return E_OUTOFMEMORY;
714     This->Folder_iface.lpVtbl = &FolderImpl_Vtbl;
715     This->ref = 1;
716
717     ret = load_type_info(&IID_Folder3, &This->iTypeInfo);
718     if (FAILED(ret))
719     {
720         HeapFree(GetProcessHeap(), 0, This);
721         return ret;
722     }
723
724     VariantInit(&This->dir);
725     ret = VariantCopy(&This->dir, dir);
726     if (FAILED(ret))
727     {
728         ITypeInfo_Release(This->iTypeInfo);
729         HeapFree(GetProcessHeap(), 0, This);
730         return E_OUTOFMEMORY;
731     }
732
733     *ppsdf = (Folder*)This;
734     return ret;
735 }
736
737 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch *iface,
738         REFIID riid, LPVOID *ppv)
739 {
740     ShellDispatch *This = impl_from_IShellDispatch(iface);
741
742     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
743
744     if (!ppv) return E_INVALIDARG;
745
746     if (IsEqualIID(&IID_IUnknown, riid) ||
747         IsEqualIID(&IID_IDispatch, riid) ||
748         IsEqualIID(&IID_IShellDispatch, riid))
749         *ppv = This;
750     else
751     {
752         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
753         *ppv = NULL;
754         return E_NOINTERFACE;
755     }
756     IUnknown_AddRef((IUnknown*)*ppv);
757     return S_OK;
758 }
759
760 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch *iface)
761 {
762     ShellDispatch *This = impl_from_IShellDispatch(iface);
763     ULONG ref = InterlockedIncrement(&This->ref);
764
765     TRACE("(%p), new refcount=%i\n", iface, ref);
766
767     return ref;
768 }
769
770 static ULONG WINAPI ShellDispatch_Release(IShellDispatch *iface)
771 {
772     ShellDispatch *This = impl_from_IShellDispatch(iface);
773     ULONG ref = InterlockedDecrement(&This->ref);
774
775     TRACE("(%p), new refcount=%i\n", iface, ref);
776
777     if (!ref)
778     {
779         ITypeInfo_Release(This->iTypeInfo);
780         HeapFree(GetProcessHeap(), 0, This);
781     }
782     return ref;
783 }
784
785 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch *iface,
786         UINT *pctinfo)
787 {
788     TRACE("(%p,%p)\n", iface, pctinfo);
789
790     *pctinfo = 1;
791     return S_OK;
792 }
793
794 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch *iface,
795         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
796 {
797     ShellDispatch *This = impl_from_IShellDispatch(iface);
798
799     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
800
801     ITypeInfo_AddRef(This->iTypeInfo);
802     *ppTInfo = This->iTypeInfo;
803     return S_OK;
804 }
805
806 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch *iface,
807         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
808 {
809     ShellDispatch *This = impl_from_IShellDispatch(iface);
810
811     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
812             rgDispId);
813
814     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
815 }
816
817 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch *iface,
818         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
819         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
820         UINT *puArgErr)
821 {
822     ShellDispatch *This = impl_from_IShellDispatch(iface);
823
824     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
825             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
826
827     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
828             pDispParams, pVarResult, pExcepInfo, puArgErr);
829 }
830
831 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch *iface,
832         IDispatch **ppid)
833 {
834     FIXME("(%p,%p)\n", iface, ppid);
835
836     *ppid = NULL;
837     return E_NOTIMPL;
838 }
839
840 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch *iface,
841         IDispatch **ppid)
842 {
843     FIXME("(%p,%p)\n", iface, ppid);
844
845     *ppid = NULL;
846     return E_NOTIMPL;
847 }
848
849 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch *iface,
850         VARIANT vDir, Folder **ppsdf)
851 {
852     TRACE("(%p,%p)\n", iface, ppsdf);
853
854     return Folder_Constructor(&vDir, ppsdf);
855 }
856
857 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch *iface,
858         LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf)
859 {
860     FIXME("(%p,%x,%s,%x,%p)\n", iface, Hwnd, debugstr_w(Title), Options, ppsdf);
861
862     *ppsdf = NULL;
863     return E_NOTIMPL;
864 }
865
866 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch *iface,
867         IDispatch **ppid)
868 {
869     FIXME("(%p,%p)\n", iface, ppid);
870
871     *ppid = NULL;
872     return E_NOTIMPL;
873 }
874
875 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch *iface, VARIANT vDir)
876 {
877     FIXME("(%p)\n", iface);
878
879     return E_NOTIMPL;
880 }
881
882 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch *iface, VARIANT vDir)
883 {
884     FIXME("(%p)\n", iface);
885
886     return E_NOTIMPL;
887 }
888
889 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch *iface)
890 {
891     FIXME("(%p)\n", iface);
892
893     return E_NOTIMPL;
894 }
895
896 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch *iface)
897 {
898     FIXME("(%p)\n", iface);
899
900     return E_NOTIMPL;
901 }
902
903 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch *iface)
904 {
905     FIXME("(%p)\n", iface);
906
907     return E_NOTIMPL;
908 }
909
910 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch *iface)
911 {
912     FIXME("(%p)\n", iface);
913
914     return E_NOTIMPL;
915 }
916
917 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch *iface)
918 {
919     FIXME("(%p)\n", iface);
920
921     return E_NOTIMPL;
922 }
923
924 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch *iface)
925 {
926     FIXME("(%p)\n", iface);
927
928     return E_NOTIMPL;
929 }
930
931 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch *iface)
932 {
933     FIXME("(%p)\n", iface);
934
935     return E_NOTIMPL;
936 }
937
938 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch *iface)
939 {
940     FIXME("(%p)\n", iface);
941
942     return E_NOTIMPL;
943 }
944
945 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch *iface)
946 {
947     FIXME("(%p)\n", iface);
948
949     return E_NOTIMPL;
950 }
951
952 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch *iface)
953 {
954     FIXME("(%p)\n", iface);
955
956     return E_NOTIMPL;
957 }
958
959 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch *iface)
960 {
961     FIXME("(%p)\n", iface);
962
963     return E_NOTIMPL;
964 }
965
966 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch *iface)
967 {
968     FIXME("(%p)\n", iface);
969
970     return E_NOTIMPL;
971 }
972
973 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch *iface)
974 {
975     FIXME("(%p)\n", iface);
976
977     return E_NOTIMPL;
978 }
979
980 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch *iface)
981 {
982     FIXME("(%p)\n", iface);
983
984     return E_NOTIMPL;
985 }
986
987 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch *iface)
988 {
989     FIXME("(%p)\n", iface);
990
991     return E_NOTIMPL;
992 }
993
994 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch *iface,
995         BSTR szDir)
996 {
997     FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
998
999     return E_NOTIMPL;
1000 }
1001
1002 static const IShellDispatchVtbl ShellDispatch_Vtbl = {
1003     ShellDispatch_QueryInterface,
1004     ShellDispatch_AddRef,
1005     ShellDispatch_Release,
1006     ShellDispatch_GetTypeInfoCount,
1007     ShellDispatch_GetTypeInfo,
1008     ShellDispatch_GetIDsOfNames,
1009     ShellDispatch_Invoke,
1010     ShellDispatch_get_Application,
1011     ShellDispatch_get_Parent,
1012     ShellDispatch_NameSpace,
1013     ShellDispatch_BrowseForFolder,
1014     ShellDispatch_Windows,
1015     ShellDispatch_Open,
1016     ShellDispatch_Explore,
1017     ShellDispatch_MinimizeAll,
1018     ShellDispatch_UndoMinimizeALL,
1019     ShellDispatch_FileRun,
1020     ShellDispatch_CascadeWindows,
1021     ShellDispatch_TileVertically,
1022     ShellDispatch_TileHorizontally,
1023     ShellDispatch_ShutdownWindows,
1024     ShellDispatch_Suspend,
1025     ShellDispatch_EjectPC,
1026     ShellDispatch_SetTime,
1027     ShellDispatch_TrayProperties,
1028     ShellDispatch_Help,
1029     ShellDispatch_FindFiles,
1030     ShellDispatch_FindComputer,
1031     ShellDispatch_RefreshMenu,
1032     ShellDispatch_ControlPanelItem
1033 };
1034
1035 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *pUnkOuter, REFIID riid,
1036         LPVOID *ppv)
1037 {
1038     ShellDispatch *This;
1039     HRESULT ret;
1040
1041     TRACE("(%p,%s)\n", pUnkOuter, debugstr_guid(riid));
1042
1043     *ppv = NULL;
1044
1045     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
1046
1047     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellDispatch));
1048     if (!This) return E_OUTOFMEMORY;
1049     This->IShellDispatch_iface.lpVtbl = &ShellDispatch_Vtbl;
1050     This->ref = 1;
1051
1052     ret = load_type_info(&IID_IShellDispatch, &This->iTypeInfo);
1053     if (FAILED(ret))
1054     {
1055         HeapFree(GetProcessHeap(), 0, This);
1056         return ret;
1057     }
1058
1059     ret = ShellDispatch_QueryInterface(&This->IShellDispatch_iface, riid, ppv);
1060     ShellDispatch_Release(&This->IShellDispatch_iface);
1061     return ret;
1062 }