wininet: Keep handles invalid but reserved in InternetCloseHandle.
[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 static inline ShellDispatch *impl_from_IShellDispatch(IShellDispatch *iface)
56 {
57     return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch_iface);
58 }
59
60 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
61 {
62     return CONTAINING_RECORD(iface, FolderImpl, Folder_iface);
63 }
64
65 static HRESULT load_type_info(REFGUID guid, ITypeInfo **pptinfo)
66 {
67     ITypeLib *typelib;
68     HRESULT ret;
69
70     ret = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &typelib);
71     if (FAILED(ret))
72     {
73         ERR("LoadRegTypeLib failed: %08x\n", ret);
74         return ret;
75     }
76
77     ret = ITypeLib_GetTypeInfoOfGuid(typelib, guid, pptinfo);
78     ITypeLib_Release(typelib);
79     if (FAILED(ret))
80         ERR("failed to load ITypeInfo\n");
81
82     return ret;
83 }
84
85 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
86         LPVOID *ppv)
87 {
88     FolderImpl *This = impl_from_Folder(iface);
89
90     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
91
92     if (!ppv) return E_INVALIDARG;
93
94     if (IsEqualIID(&IID_IUnknown, riid) ||
95         IsEqualIID(&IID_IDispatch, riid) ||
96         IsEqualIID(&IID_Folder, riid) ||
97         IsEqualIID(&IID_Folder2, riid) ||
98         IsEqualIID(&IID_Folder3, riid))
99         *ppv = This;
100     else
101     {
102         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
103         *ppv = NULL;
104         return E_NOINTERFACE;
105     }
106     IUnknown_AddRef((IUnknown*)*ppv);
107     return S_OK;
108 }
109
110 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
111 {
112     FolderImpl *This = impl_from_Folder(iface);
113     ULONG ref = InterlockedIncrement(&This->ref);
114
115     TRACE("(%p), new refcount=%i\n", iface, ref);
116
117     return ref;
118 }
119
120 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
121 {
122     FolderImpl *This = impl_from_Folder(iface);
123     ULONG ref = InterlockedDecrement(&This->ref);
124
125     TRACE("(%p), new refcount=%i\n", iface, ref);
126
127     if (!ref)
128     {
129         VariantClear(&This->dir);
130         ITypeInfo_Release(This->iTypeInfo);
131         HeapFree(GetProcessHeap(), 0, This);
132     }
133     return ref;
134 }
135
136 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
137 {
138     TRACE("(%p,%p)\n", iface, pctinfo);
139
140     *pctinfo = 1;
141     return S_OK;
142 }
143
144 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
145         LCID lcid, ITypeInfo **ppTInfo)
146 {
147     FolderImpl *This = impl_from_Folder(iface);
148
149     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
150
151     ITypeInfo_AddRef(This->iTypeInfo);
152     *ppTInfo = This->iTypeInfo;
153     return S_OK;
154 }
155
156 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
157         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
158 {
159     FolderImpl *This = impl_from_Folder(iface);
160
161     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
162             rgDispId);
163
164     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames,
165             rgDispId);
166 }
167
168 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
169         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
170         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
171 {
172     FolderImpl *This = impl_from_Folder(iface);
173
174     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
175             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
176
177     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
178             pDispParams, pVarResult, pExcepInfo, puArgErr);
179 }
180
181 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs)
182 {
183     FolderImpl *This = impl_from_Folder(iface);
184     WCHAR *p;
185     int len;
186
187     TRACE("(%p,%p)\n", iface, pbs);
188
189     *pbs = NULL;
190
191     if (V_VT(&This->dir) == VT_I4)
192     {
193         FIXME("special folder constants are not supported\n");
194         return E_NOTIMPL;
195     }
196     p = PathFindFileNameW(V_BSTR(&This->dir));
197     len = lstrlenW(p);
198     *pbs = SysAllocStringLen(p, p[len - 1] == '\\' ? len - 1 : len);
199     return *pbs ? S_OK : E_OUTOFMEMORY;
200 }
201
202 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *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 FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid)
212 {
213     FIXME("(%p,%p)\n", iface, ppid);
214
215     *ppid = NULL;
216     return E_NOTIMPL;
217 }
218
219 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
220 {
221     FIXME("(%p,%p)\n", iface, ppsf);
222
223     *ppsf = NULL;
224     return E_NOTIMPL;
225 }
226
227 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
228 {
229     FIXME("(%p,%p)\n", iface, ppid);
230
231     *ppid = NULL;
232     return E_NOTIMPL;
233 }
234
235 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR bName,
236         FolderItem **ppid)
237 {
238     FIXME("(%p,%s,%p)\n", iface, debugstr_w(bName), ppid);
239
240     *ppid = NULL;
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR bName,
245         VARIANT vOptions)
246 {
247     FIXME("(%p,%s)\n", iface, debugstr_w(bName));
248
249     return E_NOTIMPL;
250 }
251
252 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT vItem,
253         VARIANT vOptions)
254 {
255     FIXME("(%p)\n", iface);
256
257     return E_NOTIMPL;
258 }
259
260 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT vItem,
261         VARIANT vOptions)
262 {
263     FIXME("(%p)\n", iface);
264
265     return E_NOTIMPL;
266 }
267
268 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT vItem,
269         int iColumn, BSTR *pbs)
270 {
271     FIXME("(%p,%d,%p)\n", iface, iColumn, pbs);
272
273     *pbs = NULL;
274     return E_NOTIMPL;
275 }
276
277 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **ppfi)
278 {
279     FIXME("(%p,%p)\n", iface, ppfi);
280
281     *ppfi = NULL;
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
286 {
287     FIXME("(%p,%p)\n", iface, pul);
288
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
293 {
294     FIXME("(%p)\n", iface);
295
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
300         VARIANT_BOOL *pbHaveToShowWebViewBarricade)
301 {
302     FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
303
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
308 {
309     FIXME("(%p)\n", iface);
310
311     return E_NOTIMPL;
312 }
313
314 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
315         VARIANT_BOOL *pbShowWebViewBarricade)
316 {
317     FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
318
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
323         VARIANT_BOOL bShowWebViewBarricade)
324 {
325     FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
326
327     return E_NOTIMPL;
328 }
329
330 static const Folder3Vtbl FolderImpl_Vtbl = {
331     FolderImpl_QueryInterface,
332     FolderImpl_AddRef,
333     FolderImpl_Release,
334     FolderImpl_GetTypeInfoCount,
335     FolderImpl_GetTypeInfo,
336     FolderImpl_GetIDsOfNames,
337     FolderImpl_Invoke,
338     FolderImpl_get_Title,
339     FolderImpl_get_Application,
340     FolderImpl_get_Parent,
341     FolderImpl_get_ParentFolder,
342     FolderImpl_Items,
343     FolderImpl_ParseName,
344     FolderImpl_NewFolder,
345     FolderImpl_MoveHere,
346     FolderImpl_CopyHere,
347     FolderImpl_GetDetailsOf,
348     FolderImpl_get_Self,
349     FolderImpl_get_OfflineStatus,
350     FolderImpl_Synchronize,
351     FolderImpl_get_HaveToShowWebViewBarricade,
352     FolderImpl_DismissedWebViewBarricade,
353     FolderImpl_get_ShowWebViewBarricade,
354     FolderImpl_put_ShowWebViewBarricade
355 };
356
357 static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf)
358 {
359     FolderImpl *This;
360     HRESULT ret;
361
362     *ppsdf = NULL;
363
364     switch (V_VT(dir))
365     {
366         case VT_I4:
367             /* FIXME: add some checks */
368             break;
369         case VT_BSTR:
370             if (PathIsDirectoryW(V_BSTR(dir)) &&
371                 !PathIsRelativeW(V_BSTR(dir)) &&
372                 PathFileExistsW(V_BSTR(dir)))
373                 break;
374         default:
375             return S_FALSE;
376     }
377
378     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl));
379     if (!This) return E_OUTOFMEMORY;
380     This->Folder_iface.lpVtbl = &FolderImpl_Vtbl;
381     This->ref = 1;
382
383     ret = load_type_info(&IID_Folder3, &This->iTypeInfo);
384     if (FAILED(ret))
385     {
386         HeapFree(GetProcessHeap(), 0, This);
387         return ret;
388     }
389
390     VariantInit(&This->dir);
391     ret = VariantCopy(&This->dir, dir);
392     if (FAILED(ret))
393     {
394         HeapFree(GetProcessHeap(), 0, This);
395         return E_OUTOFMEMORY;
396     }
397
398     *ppsdf = (Folder*)This;
399     return ret;
400 }
401
402 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch *iface,
403         REFIID riid, LPVOID *ppv)
404 {
405     ShellDispatch *This = impl_from_IShellDispatch(iface);
406
407     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
408
409     if (!ppv) return E_INVALIDARG;
410
411     if (IsEqualIID(&IID_IUnknown, riid) ||
412         IsEqualIID(&IID_IDispatch, riid) ||
413         IsEqualIID(&IID_IShellDispatch, riid))
414         *ppv = This;
415     else
416     {
417         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
418         *ppv = NULL;
419         return E_NOINTERFACE;
420     }
421     IUnknown_AddRef((IUnknown*)*ppv);
422     return S_OK;
423 }
424
425 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch *iface)
426 {
427     ShellDispatch *This = impl_from_IShellDispatch(iface);
428     ULONG ref = InterlockedIncrement(&This->ref);
429
430     TRACE("(%p), new refcount=%i\n", iface, ref);
431
432     return ref;
433 }
434
435 static ULONG WINAPI ShellDispatch_Release(IShellDispatch *iface)
436 {
437     ShellDispatch *This = impl_from_IShellDispatch(iface);
438     ULONG ref = InterlockedDecrement(&This->ref);
439
440     TRACE("(%p), new refcount=%i\n", iface, ref);
441
442     if (!ref)
443     {
444         ITypeInfo_Release(This->iTypeInfo);
445         HeapFree(GetProcessHeap(), 0, This);
446     }
447     return ref;
448 }
449
450 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch *iface,
451         UINT *pctinfo)
452 {
453     TRACE("(%p,%p)\n", iface, pctinfo);
454
455     *pctinfo = 1;
456     return S_OK;
457 }
458
459 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch *iface,
460         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
461 {
462     ShellDispatch *This = impl_from_IShellDispatch(iface);
463
464     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
465
466     ITypeInfo_AddRef(This->iTypeInfo);
467     *ppTInfo = This->iTypeInfo;
468     return S_OK;
469 }
470
471 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch *iface,
472         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
473 {
474     ShellDispatch *This = impl_from_IShellDispatch(iface);
475
476     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
477             rgDispId);
478
479     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
480 }
481
482 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch *iface,
483         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
484         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
485         UINT *puArgErr)
486 {
487     ShellDispatch *This = impl_from_IShellDispatch(iface);
488
489     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
490             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
491
492     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
493             pDispParams, pVarResult, pExcepInfo, puArgErr);
494 }
495
496 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch *iface,
497         IDispatch **ppid)
498 {
499     FIXME("(%p,%p)\n", iface, ppid);
500
501     *ppid = NULL;
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch *iface,
506         IDispatch **ppid)
507 {
508     FIXME("(%p,%p)\n", iface, ppid);
509
510     *ppid = NULL;
511     return E_NOTIMPL;
512 }
513
514 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch *iface,
515         VARIANT vDir, Folder **ppsdf)
516 {
517     TRACE("(%p,%p)\n", iface, ppsdf);
518
519     return Folder_Constructor(&vDir, ppsdf);
520 }
521
522 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch *iface,
523         LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf)
524 {
525     FIXME("(%p,%x,%s,%x,%p)\n", iface, Hwnd, debugstr_w(Title), Options, ppsdf);
526
527     *ppsdf = NULL;
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch *iface,
532         IDispatch **ppid)
533 {
534     FIXME("(%p,%p)\n", iface, ppid);
535
536     *ppid = NULL;
537     return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch *iface, VARIANT vDir)
541 {
542     FIXME("(%p)\n", iface);
543
544     return E_NOTIMPL;
545 }
546
547 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch *iface, VARIANT vDir)
548 {
549     FIXME("(%p)\n", iface);
550
551     return E_NOTIMPL;
552 }
553
554 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch *iface)
555 {
556     FIXME("(%p)\n", iface);
557
558     return E_NOTIMPL;
559 }
560
561 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch *iface)
562 {
563     FIXME("(%p)\n", iface);
564
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch *iface)
569 {
570     FIXME("(%p)\n", iface);
571
572     return E_NOTIMPL;
573 }
574
575 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch *iface)
576 {
577     FIXME("(%p)\n", iface);
578
579     return E_NOTIMPL;
580 }
581
582 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch *iface)
583 {
584     FIXME("(%p)\n", iface);
585
586     return E_NOTIMPL;
587 }
588
589 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch *iface)
590 {
591     FIXME("(%p)\n", iface);
592
593     return E_NOTIMPL;
594 }
595
596 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch *iface)
597 {
598     FIXME("(%p)\n", iface);
599
600     return E_NOTIMPL;
601 }
602
603 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch *iface)
604 {
605     FIXME("(%p)\n", iface);
606
607     return E_NOTIMPL;
608 }
609
610 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch *iface)
611 {
612     FIXME("(%p)\n", iface);
613
614     return E_NOTIMPL;
615 }
616
617 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch *iface)
618 {
619     FIXME("(%p)\n", iface);
620
621     return E_NOTIMPL;
622 }
623
624 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch *iface)
625 {
626     FIXME("(%p)\n", iface);
627
628     return E_NOTIMPL;
629 }
630
631 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch *iface)
632 {
633     FIXME("(%p)\n", iface);
634
635     return E_NOTIMPL;
636 }
637
638 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch *iface)
639 {
640     FIXME("(%p)\n", iface);
641
642     return E_NOTIMPL;
643 }
644
645 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch *iface)
646 {
647     FIXME("(%p)\n", iface);
648
649     return E_NOTIMPL;
650 }
651
652 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch *iface)
653 {
654     FIXME("(%p)\n", iface);
655
656     return E_NOTIMPL;
657 }
658
659 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch *iface,
660         BSTR szDir)
661 {
662     FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
663
664     return E_NOTIMPL;
665 }
666
667 static const IShellDispatchVtbl ShellDispatch_Vtbl = {
668     ShellDispatch_QueryInterface,
669     ShellDispatch_AddRef,
670     ShellDispatch_Release,
671     ShellDispatch_GetTypeInfoCount,
672     ShellDispatch_GetTypeInfo,
673     ShellDispatch_GetIDsOfNames,
674     ShellDispatch_Invoke,
675     ShellDispatch_get_Application,
676     ShellDispatch_get_Parent,
677     ShellDispatch_NameSpace,
678     ShellDispatch_BrowseForFolder,
679     ShellDispatch_Windows,
680     ShellDispatch_Open,
681     ShellDispatch_Explore,
682     ShellDispatch_MinimizeAll,
683     ShellDispatch_UndoMinimizeALL,
684     ShellDispatch_FileRun,
685     ShellDispatch_CascadeWindows,
686     ShellDispatch_TileVertically,
687     ShellDispatch_TileHorizontally,
688     ShellDispatch_ShutdownWindows,
689     ShellDispatch_Suspend,
690     ShellDispatch_EjectPC,
691     ShellDispatch_SetTime,
692     ShellDispatch_TrayProperties,
693     ShellDispatch_Help,
694     ShellDispatch_FindFiles,
695     ShellDispatch_FindComputer,
696     ShellDispatch_RefreshMenu,
697     ShellDispatch_ControlPanelItem
698 };
699
700 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *pUnkOuter, REFIID riid,
701         LPVOID *ppv)
702 {
703     ShellDispatch *This;
704     HRESULT ret;
705
706     TRACE("(%p,%s)\n", pUnkOuter, debugstr_guid(riid));
707
708     *ppv = NULL;
709
710     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
711
712     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellDispatch));
713     if (!This) return E_OUTOFMEMORY;
714     This->IShellDispatch_iface.lpVtbl = &ShellDispatch_Vtbl;
715     This->ref = 1;
716
717     ret = load_type_info(&IID_IShellDispatch, &This->iTypeInfo);
718     if (FAILED(ret))
719     {
720         HeapFree(GetProcessHeap(), 0, This);
721         return ret;
722     }
723
724     ret = ShellDispatch_QueryInterface(&This->IShellDispatch_iface, riid, ppv);
725     ShellDispatch_Release(&This->IShellDispatch_iface);
726     return ret;
727 }