mshtml: Added IHTMLWindow2::focus implementation.
[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         ITypeInfo_Release(This->iTypeInfo);
395         HeapFree(GetProcessHeap(), 0, This);
396         return E_OUTOFMEMORY;
397     }
398
399     *ppsdf = (Folder*)This;
400     return ret;
401 }
402
403 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch *iface,
404         REFIID riid, LPVOID *ppv)
405 {
406     ShellDispatch *This = impl_from_IShellDispatch(iface);
407
408     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
409
410     if (!ppv) return E_INVALIDARG;
411
412     if (IsEqualIID(&IID_IUnknown, riid) ||
413         IsEqualIID(&IID_IDispatch, riid) ||
414         IsEqualIID(&IID_IShellDispatch, riid))
415         *ppv = This;
416     else
417     {
418         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
419         *ppv = NULL;
420         return E_NOINTERFACE;
421     }
422     IUnknown_AddRef((IUnknown*)*ppv);
423     return S_OK;
424 }
425
426 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch *iface)
427 {
428     ShellDispatch *This = impl_from_IShellDispatch(iface);
429     ULONG ref = InterlockedIncrement(&This->ref);
430
431     TRACE("(%p), new refcount=%i\n", iface, ref);
432
433     return ref;
434 }
435
436 static ULONG WINAPI ShellDispatch_Release(IShellDispatch *iface)
437 {
438     ShellDispatch *This = impl_from_IShellDispatch(iface);
439     ULONG ref = InterlockedDecrement(&This->ref);
440
441     TRACE("(%p), new refcount=%i\n", iface, ref);
442
443     if (!ref)
444     {
445         ITypeInfo_Release(This->iTypeInfo);
446         HeapFree(GetProcessHeap(), 0, This);
447     }
448     return ref;
449 }
450
451 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch *iface,
452         UINT *pctinfo)
453 {
454     TRACE("(%p,%p)\n", iface, pctinfo);
455
456     *pctinfo = 1;
457     return S_OK;
458 }
459
460 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch *iface,
461         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
462 {
463     ShellDispatch *This = impl_from_IShellDispatch(iface);
464
465     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
466
467     ITypeInfo_AddRef(This->iTypeInfo);
468     *ppTInfo = This->iTypeInfo;
469     return S_OK;
470 }
471
472 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch *iface,
473         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
474 {
475     ShellDispatch *This = impl_from_IShellDispatch(iface);
476
477     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
478             rgDispId);
479
480     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
481 }
482
483 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch *iface,
484         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
485         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
486         UINT *puArgErr)
487 {
488     ShellDispatch *This = impl_from_IShellDispatch(iface);
489
490     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
491             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
492
493     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
494             pDispParams, pVarResult, pExcepInfo, puArgErr);
495 }
496
497 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch *iface,
498         IDispatch **ppid)
499 {
500     FIXME("(%p,%p)\n", iface, ppid);
501
502     *ppid = NULL;
503     return E_NOTIMPL;
504 }
505
506 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch *iface,
507         IDispatch **ppid)
508 {
509     FIXME("(%p,%p)\n", iface, ppid);
510
511     *ppid = NULL;
512     return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch *iface,
516         VARIANT vDir, Folder **ppsdf)
517 {
518     TRACE("(%p,%p)\n", iface, ppsdf);
519
520     return Folder_Constructor(&vDir, ppsdf);
521 }
522
523 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch *iface,
524         LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf)
525 {
526     FIXME("(%p,%x,%s,%x,%p)\n", iface, Hwnd, debugstr_w(Title), Options, ppsdf);
527
528     *ppsdf = NULL;
529     return E_NOTIMPL;
530 }
531
532 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch *iface,
533         IDispatch **ppid)
534 {
535     FIXME("(%p,%p)\n", iface, ppid);
536
537     *ppid = NULL;
538     return E_NOTIMPL;
539 }
540
541 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch *iface, VARIANT vDir)
542 {
543     FIXME("(%p)\n", iface);
544
545     return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch *iface, VARIANT vDir)
549 {
550     FIXME("(%p)\n", iface);
551
552     return E_NOTIMPL;
553 }
554
555 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch *iface)
556 {
557     FIXME("(%p)\n", iface);
558
559     return E_NOTIMPL;
560 }
561
562 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch *iface)
563 {
564     FIXME("(%p)\n", iface);
565
566     return E_NOTIMPL;
567 }
568
569 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch *iface)
570 {
571     FIXME("(%p)\n", iface);
572
573     return E_NOTIMPL;
574 }
575
576 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch *iface)
577 {
578     FIXME("(%p)\n", iface);
579
580     return E_NOTIMPL;
581 }
582
583 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch *iface)
584 {
585     FIXME("(%p)\n", iface);
586
587     return E_NOTIMPL;
588 }
589
590 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch *iface)
591 {
592     FIXME("(%p)\n", iface);
593
594     return E_NOTIMPL;
595 }
596
597 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch *iface)
598 {
599     FIXME("(%p)\n", iface);
600
601     return E_NOTIMPL;
602 }
603
604 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch *iface)
605 {
606     FIXME("(%p)\n", iface);
607
608     return E_NOTIMPL;
609 }
610
611 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch *iface)
612 {
613     FIXME("(%p)\n", iface);
614
615     return E_NOTIMPL;
616 }
617
618 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch *iface)
619 {
620     FIXME("(%p)\n", iface);
621
622     return E_NOTIMPL;
623 }
624
625 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch *iface)
626 {
627     FIXME("(%p)\n", iface);
628
629     return E_NOTIMPL;
630 }
631
632 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch *iface)
633 {
634     FIXME("(%p)\n", iface);
635
636     return E_NOTIMPL;
637 }
638
639 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch *iface)
640 {
641     FIXME("(%p)\n", iface);
642
643     return E_NOTIMPL;
644 }
645
646 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch *iface)
647 {
648     FIXME("(%p)\n", iface);
649
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch *iface)
654 {
655     FIXME("(%p)\n", iface);
656
657     return E_NOTIMPL;
658 }
659
660 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch *iface,
661         BSTR szDir)
662 {
663     FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
664
665     return E_NOTIMPL;
666 }
667
668 static const IShellDispatchVtbl ShellDispatch_Vtbl = {
669     ShellDispatch_QueryInterface,
670     ShellDispatch_AddRef,
671     ShellDispatch_Release,
672     ShellDispatch_GetTypeInfoCount,
673     ShellDispatch_GetTypeInfo,
674     ShellDispatch_GetIDsOfNames,
675     ShellDispatch_Invoke,
676     ShellDispatch_get_Application,
677     ShellDispatch_get_Parent,
678     ShellDispatch_NameSpace,
679     ShellDispatch_BrowseForFolder,
680     ShellDispatch_Windows,
681     ShellDispatch_Open,
682     ShellDispatch_Explore,
683     ShellDispatch_MinimizeAll,
684     ShellDispatch_UndoMinimizeALL,
685     ShellDispatch_FileRun,
686     ShellDispatch_CascadeWindows,
687     ShellDispatch_TileVertically,
688     ShellDispatch_TileHorizontally,
689     ShellDispatch_ShutdownWindows,
690     ShellDispatch_Suspend,
691     ShellDispatch_EjectPC,
692     ShellDispatch_SetTime,
693     ShellDispatch_TrayProperties,
694     ShellDispatch_Help,
695     ShellDispatch_FindFiles,
696     ShellDispatch_FindComputer,
697     ShellDispatch_RefreshMenu,
698     ShellDispatch_ControlPanelItem
699 };
700
701 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *pUnkOuter, REFIID riid,
702         LPVOID *ppv)
703 {
704     ShellDispatch *This;
705     HRESULT ret;
706
707     TRACE("(%p,%s)\n", pUnkOuter, debugstr_guid(riid));
708
709     *ppv = NULL;
710
711     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
712
713     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellDispatch));
714     if (!This) return E_OUTOFMEMORY;
715     This->IShellDispatch_iface.lpVtbl = &ShellDispatch_Vtbl;
716     This->ref = 1;
717
718     ret = load_type_info(&IID_IShellDispatch, &This->iTypeInfo);
719     if (FAILED(ret))
720     {
721         HeapFree(GetProcessHeap(), 0, This);
722         return ret;
723     }
724
725     ret = ShellDispatch_QueryInterface(&This->IShellDispatch_iface, riid, ppv);
726     ShellDispatch_Release(&This->IShellDispatch_iface);
727     return ret;
728 }