server: Use server_get_file_info for all info classes not implemented on client side.
[wine.git] / dlls / shell32 / shelldispatch.c
blobc6d1dab7f62e38686f21dd829cd3d23f64cdc37a
1 /*
2 * IShellDispatch implementation
4 * Copyright 2010 Alexander Morozov for Etersoft
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
26 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winsvc.h"
32 #include "shlwapi.h"
33 #include "shlobj.h"
34 #include "shldisp.h"
35 #include "debughlp.h"
37 #include "shell32_main.h"
38 #include "pidl.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(shell);
44 static ITypeLib *typelib;
45 static const IID * const tid_ids[] =
47 &IID_NULL,
48 &IID_IShellDispatch6,
49 &IID_IShellFolderViewDual3,
50 &IID_Folder3,
51 &IID_FolderItem2,
52 &IID_FolderItems3,
53 &IID_FolderItemVerb,
54 &IID_FolderItemVerbs
56 static ITypeInfo *typeinfos[LAST_tid];
58 typedef struct {
59 IShellDispatch6 IShellDispatch6_iface;
60 LONG ref;
61 } ShellDispatch;
63 typedef struct {
64 Folder3 Folder3_iface;
65 LONG ref;
66 IDispatch *application;
67 IShellFolder2 *folder;
68 PIDLIST_ABSOLUTE pidl;
69 BSTR path;
70 } FolderImpl;
72 typedef struct {
73 FolderItems3 FolderItems3_iface;
74 LONG ref;
75 FolderImpl *folder;
76 BSTR *item_names;
77 LONG item_count;
78 } FolderItemsImpl;
80 typedef struct {
81 FolderItem2 FolderItem2_iface;
82 LONG ref;
83 FolderImpl *folder;
84 WCHAR *path; /* if NULL, folder path is used */
85 DWORD attributes;
86 } FolderItemImpl;
88 typedef struct {
89 FolderItemVerbs FolderItemVerbs_iface;
90 LONG ref;
92 IContextMenu *contextmenu;
93 HMENU hMenu;
94 LONG count;
95 } FolderItemVerbsImpl;
97 typedef struct {
98 FolderItemVerb FolderItemVerb_iface;
99 LONG ref;
101 IContextMenu *contextmenu;
102 BSTR name;
103 } FolderItemVerbImpl;
105 static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface)
107 return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch6_iface);
110 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
112 return CONTAINING_RECORD(iface, FolderImpl, Folder3_iface);
115 static inline FolderItemsImpl *impl_from_FolderItems(FolderItems3 *iface)
117 return CONTAINING_RECORD(iface, FolderItemsImpl, FolderItems3_iface);
120 static inline FolderItemImpl *impl_from_FolderItem(FolderItem2 *iface)
122 return CONTAINING_RECORD(iface, FolderItemImpl, FolderItem2_iface);
125 static inline FolderItemVerbsImpl *impl_from_FolderItemVerbs(FolderItemVerbs *iface)
127 return CONTAINING_RECORD(iface, FolderItemVerbsImpl, FolderItemVerbs_iface);
130 static inline FolderItemVerbImpl *impl_from_FolderItemVerb(FolderItemVerb *iface)
132 return CONTAINING_RECORD(iface, FolderItemVerbImpl, FolderItemVerb_iface);
135 static HRESULT load_typelib(void)
137 ITypeLib *tl;
138 HRESULT hr;
140 hr = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
141 if (FAILED(hr)) {
142 ERR("LoadRegTypeLib failed: %08x\n", hr);
143 return hr;
146 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
147 ITypeLib_Release(tl);
148 return hr;
151 void release_typelib(void)
153 unsigned i;
155 if (!typelib)
156 return;
158 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
159 if (typeinfos[i])
160 ITypeInfo_Release(typeinfos[i]);
162 ITypeLib_Release(typelib);
165 HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
167 HRESULT hr;
169 if (!typelib)
170 hr = load_typelib();
171 if (!typelib)
172 return hr;
174 if (!typeinfos[tid])
176 ITypeInfo *ti;
178 hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
179 if (FAILED(hr))
181 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hr);
182 return hr;
185 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
186 ITypeInfo_Release(ti);
189 *typeinfo = typeinfos[tid];
190 return S_OK;
193 /* FolderItemVerb */
194 static HRESULT WINAPI FolderItemVerbImpl_QueryInterface(FolderItemVerb *iface,
195 REFIID riid, void **ppv)
197 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
199 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
201 if (IsEqualIID(&IID_IUnknown, riid) ||
202 IsEqualIID(&IID_IDispatch, riid) ||
203 IsEqualIID(&IID_FolderItemVerb, riid))
204 *ppv = &This->FolderItemVerb_iface;
205 else
207 WARN("not implemented for %s\n", debugstr_guid(riid));
208 *ppv = NULL;
209 return E_NOINTERFACE;
212 IUnknown_AddRef((IUnknown*)*ppv);
213 return S_OK;
216 static ULONG WINAPI FolderItemVerbImpl_AddRef(FolderItemVerb *iface)
218 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
219 ULONG ref = InterlockedIncrement(&This->ref);
221 TRACE("(%p), new refcount=%i\n", iface, ref);
223 return ref;
226 static ULONG WINAPI FolderItemVerbImpl_Release(FolderItemVerb *iface)
228 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
229 ULONG ref = InterlockedDecrement(&This->ref);
231 TRACE("(%p), new refcount=%i\n", iface, ref);
233 if (!ref)
235 IContextMenu_Release(This->contextmenu);
236 SysFreeString(This->name);
237 heap_free(This);
240 return ref;
243 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfoCount(FolderItemVerb *iface, UINT *pctinfo)
245 TRACE("(%p,%p)\n", iface, pctinfo);
246 *pctinfo = 1;
247 return S_OK;
250 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfo(FolderItemVerb *iface, UINT iTInfo,
251 LCID lcid, ITypeInfo **ppTInfo)
253 HRESULT hr;
255 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
257 hr = get_typeinfo(FolderItemVerb_tid, ppTInfo);
258 if (SUCCEEDED(hr))
259 ITypeInfo_AddRef(*ppTInfo);
260 return hr;
263 static HRESULT WINAPI FolderItemVerbImpl_GetIDsOfNames(FolderItemVerb *iface,
264 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
266 ITypeInfo *ti;
267 HRESULT hr;
269 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
270 rgDispId);
272 hr = get_typeinfo(FolderItemVerb_tid, &ti);
273 if (SUCCEEDED(hr))
274 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
275 return hr;
278 static HRESULT WINAPI FolderItemVerbImpl_Invoke(FolderItemVerb *iface,
279 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
280 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
281 UINT *puArgErr)
283 ITypeInfo *ti;
284 HRESULT hr;
286 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
287 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
289 hr = get_typeinfo(FolderItemVerb_tid, &ti);
290 if (SUCCEEDED(hr))
291 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
292 return hr;
295 static HRESULT WINAPI FolderItemVerbImpl_get_Application(FolderItemVerb *iface, IDispatch **disp)
297 TRACE("(%p, %p)\n", iface, disp);
299 if (disp)
300 *disp = NULL;
301 return E_NOTIMPL;
304 static HRESULT WINAPI FolderItemVerbImpl_get_Parent(FolderItemVerb *iface, IDispatch **disp)
306 TRACE("(%p, %p)\n", iface, disp);
308 if (disp)
309 *disp = NULL;
310 return E_NOTIMPL;
313 static HRESULT WINAPI FolderItemVerbImpl_get_Name(FolderItemVerb *iface, BSTR *name)
315 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
317 TRACE("(%p, %p)\n", iface, name);
319 *name = SysAllocString(This->name);
320 return *name ? S_OK : E_OUTOFMEMORY;
323 static HRESULT WINAPI FolderItemVerbImpl_DoIt(FolderItemVerb *iface)
325 FIXME("(%p)\n", iface);
326 return E_NOTIMPL;
329 static FolderItemVerbVtbl folderitemverbvtbl = {
330 FolderItemVerbImpl_QueryInterface,
331 FolderItemVerbImpl_AddRef,
332 FolderItemVerbImpl_Release,
333 FolderItemVerbImpl_GetTypeInfoCount,
334 FolderItemVerbImpl_GetTypeInfo,
335 FolderItemVerbImpl_GetIDsOfNames,
336 FolderItemVerbImpl_Invoke,
337 FolderItemVerbImpl_get_Application,
338 FolderItemVerbImpl_get_Parent,
339 FolderItemVerbImpl_get_Name,
340 FolderItemVerbImpl_DoIt
343 static HRESULT FolderItemVerb_Constructor(IContextMenu *contextmenu, BSTR name, FolderItemVerb **verb)
345 FolderItemVerbImpl *This;
347 TRACE("%p, %s\n", contextmenu, debugstr_w(name));
349 This = heap_alloc(sizeof(*This));
350 if (!This)
351 return E_OUTOFMEMORY;
353 This->FolderItemVerb_iface.lpVtbl = &folderitemverbvtbl;
354 This->ref = 1;
355 This->contextmenu = contextmenu;
356 IContextMenu_AddRef(contextmenu);
357 This->name = name;
359 *verb = &This->FolderItemVerb_iface;
360 return S_OK;
363 /* FolderItemVerbs */
364 static HRESULT WINAPI FolderItemVerbsImpl_QueryInterface(FolderItemVerbs *iface,
365 REFIID riid, void **ppv)
367 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
369 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
371 if (IsEqualIID(&IID_IUnknown, riid) ||
372 IsEqualIID(&IID_IDispatch, riid) ||
373 IsEqualIID(&IID_FolderItemVerbs, riid))
374 *ppv = &This->FolderItemVerbs_iface;
375 else
377 WARN("not implemented for %s\n", debugstr_guid(riid));
378 *ppv = NULL;
379 return E_NOINTERFACE;
382 IUnknown_AddRef((IUnknown*)*ppv);
383 return S_OK;
386 static ULONG WINAPI FolderItemVerbsImpl_AddRef(FolderItemVerbs *iface)
388 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
389 ULONG ref = InterlockedIncrement(&This->ref);
391 TRACE("(%p), new refcount=%i\n", iface, ref);
393 return ref;
396 static ULONG WINAPI FolderItemVerbsImpl_Release(FolderItemVerbs *iface)
398 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
399 ULONG ref = InterlockedDecrement(&This->ref);
401 TRACE("(%p), new refcount=%i\n", iface, ref);
403 if (!ref)
405 IContextMenu_Release(This->contextmenu);
406 DestroyMenu(This->hMenu);
407 heap_free(This);
410 return ref;
413 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfoCount(FolderItemVerbs *iface, UINT *pctinfo)
415 TRACE("(%p,%p)\n", iface, pctinfo);
416 *pctinfo = 1;
417 return S_OK;
420 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfo(FolderItemVerbs *iface, UINT iTInfo,
421 LCID lcid, ITypeInfo **ppTInfo)
423 HRESULT hr;
425 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
427 hr = get_typeinfo(FolderItemVerbs_tid, ppTInfo);
428 if (SUCCEEDED(hr))
429 ITypeInfo_AddRef(*ppTInfo);
430 return hr;
433 static HRESULT WINAPI FolderItemVerbsImpl_GetIDsOfNames(FolderItemVerbs *iface,
434 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
436 ITypeInfo *ti;
437 HRESULT hr;
439 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
440 rgDispId);
442 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
443 if (SUCCEEDED(hr))
444 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
445 return hr;
448 static HRESULT WINAPI FolderItemVerbsImpl_Invoke(FolderItemVerbs *iface,
449 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
450 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
451 UINT *puArgErr)
453 ITypeInfo *ti;
454 HRESULT hr;
456 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
457 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
459 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
460 if (SUCCEEDED(hr))
461 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
462 return hr;
465 static HRESULT WINAPI FolderItemVerbsImpl_get_Count(FolderItemVerbs *iface, LONG *count)
467 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
469 TRACE("(%p, %p)\n", iface, count);
471 if (!count)
472 return E_INVALIDARG;
474 *count = This->count;
475 return S_OK;
478 static HRESULT WINAPI FolderItemVerbsImpl_get_Application(FolderItemVerbs *iface, IDispatch **disp)
480 TRACE("(%p, %p)\n", iface, disp);
482 if (disp)
483 *disp = NULL;
484 return E_NOTIMPL;
487 static HRESULT WINAPI FolderItemVerbsImpl_get_Parent(FolderItemVerbs *iface, IDispatch **disp)
489 TRACE("(%p, %p)\n", iface, disp);
491 if (disp)
492 *disp = NULL;
493 return E_NOTIMPL;
496 static HRESULT WINAPI FolderItemVerbsImpl_Item(FolderItemVerbs *iface, VARIANT index, FolderItemVerb **verb)
498 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
499 MENUITEMINFOW info;
500 HRESULT hr;
501 VARIANT v;
502 BSTR name;
504 TRACE("(%p, %s, %p)\n", iface, debugstr_variant(&index), verb);
506 if (!verb)
507 return E_INVALIDARG;
509 *verb = NULL;
511 VariantInit(&v);
512 VariantCopyInd(&v, &index);
514 hr = VariantChangeType(&v, &v, 0, VT_I4);
515 if (FAILED(hr))
517 FIXME("failed to coerce to VT_I4, %s\n", debugstr_variant(&v));
518 return hr;
521 if (V_I4(&v) > This->count)
522 return S_OK;
524 if (V_I4(&v) == This->count)
525 name = SysAllocStringLen(NULL, 0);
526 else
528 /* get item name */
529 memset(&info, 0, sizeof(info));
530 info.cbSize = sizeof(info);
531 info.fMask = MIIM_STRING;
532 if (!GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info))
533 return E_FAIL;
535 name = SysAllocStringLen(NULL, info.cch);
536 if (name)
538 info.dwTypeData = name;
539 info.cch++;
540 GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info);
544 if (!name)
545 return E_OUTOFMEMORY;
547 return FolderItemVerb_Constructor(This->contextmenu, name, verb);
550 static HRESULT WINAPI FolderItemVerbsImpl__NewEnum(FolderItemVerbs *iface, IUnknown **ret)
552 FIXME("(%p, %p)\n", iface, ret);
553 return E_NOTIMPL;
556 static FolderItemVerbsVtbl folderitemverbsvtbl = {
557 FolderItemVerbsImpl_QueryInterface,
558 FolderItemVerbsImpl_AddRef,
559 FolderItemVerbsImpl_Release,
560 FolderItemVerbsImpl_GetTypeInfoCount,
561 FolderItemVerbsImpl_GetTypeInfo,
562 FolderItemVerbsImpl_GetIDsOfNames,
563 FolderItemVerbsImpl_Invoke,
564 FolderItemVerbsImpl_get_Count,
565 FolderItemVerbsImpl_get_Application,
566 FolderItemVerbsImpl_get_Parent,
567 FolderItemVerbsImpl_Item,
568 FolderItemVerbsImpl__NewEnum
571 static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs)
573 FolderItemVerbsImpl *This;
574 IShellFolder *folder;
575 LPCITEMIDLIST child;
576 LPITEMIDLIST pidl;
577 HRESULT hr;
579 *verbs = NULL;
581 This = heap_alloc(sizeof(*This));
582 if (!This)
583 return E_OUTOFMEMORY;
585 This->FolderItemVerbs_iface.lpVtbl = &folderitemverbsvtbl;
586 This->ref = 1;
588 /* build context menu for this path */
589 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
590 if (FAILED(hr))
591 goto failed;
593 hr = SHBindToParent(pidl, &IID_IShellFolder, (void**)&folder, &child);
594 CoTaskMemFree(pidl);
595 if (FAILED(hr))
596 goto failed;
598 hr = IShellFolder_GetUIObjectOf(folder, NULL, 1, &child, &IID_IContextMenu, NULL, (void**)&This->contextmenu);
599 IShellFolder_Release(folder);
600 if (FAILED(hr))
601 goto failed;
603 This->hMenu = CreatePopupMenu();
604 hr = IContextMenu_QueryContextMenu(This->contextmenu, This->hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
605 if (FAILED(hr))
607 FolderItemVerbs_Release(&This->FolderItemVerbs_iface);
608 return hr;
611 This->count = GetMenuItemCount(This->hMenu);
612 *verbs = &This->FolderItemVerbs_iface;
613 return S_OK;
615 failed:
616 heap_free(This);
617 return hr;
620 static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface,
621 REFIID riid, LPVOID *ppv)
623 FolderItemImpl *This = impl_from_FolderItem(iface);
625 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
627 if (!ppv) return E_INVALIDARG;
629 if (IsEqualIID(&IID_IUnknown, riid) ||
630 IsEqualIID(&IID_IDispatch, riid) ||
631 IsEqualIID(&IID_FolderItem, riid) ||
632 IsEqualIID(&IID_FolderItem2, riid))
633 *ppv = &This->FolderItem2_iface;
634 else
636 WARN("not implemented for %s\n", debugstr_guid(riid));
637 *ppv = NULL;
638 return E_NOINTERFACE;
640 IUnknown_AddRef((IUnknown*)*ppv);
641 return S_OK;
644 static ULONG WINAPI FolderItemImpl_AddRef(FolderItem2 *iface)
646 FolderItemImpl *This = impl_from_FolderItem(iface);
647 ULONG ref = InterlockedIncrement(&This->ref);
649 TRACE("(%p), new refcount=%i\n", iface, ref);
651 return ref;
654 static ULONG WINAPI FolderItemImpl_Release(FolderItem2 *iface)
656 FolderItemImpl *This = impl_from_FolderItem(iface);
657 ULONG ref = InterlockedDecrement(&This->ref);
659 TRACE("(%p), new refcount=%i\n", iface, ref);
661 if (!ref)
663 Folder3_Release(&This->folder->Folder3_iface);
664 heap_free(This->path);
665 heap_free(This);
667 return ref;
670 static HRESULT WINAPI FolderItemImpl_GetTypeInfoCount(FolderItem2 *iface,
671 UINT *pctinfo)
673 TRACE("(%p,%p)\n", iface, pctinfo);
675 *pctinfo = 1;
676 return S_OK;
679 static HRESULT WINAPI FolderItemImpl_GetTypeInfo(FolderItem2 *iface, UINT iTInfo,
680 LCID lcid, ITypeInfo **ppTInfo)
682 HRESULT hr;
684 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
686 hr = get_typeinfo(FolderItem2_tid, ppTInfo);
687 if (SUCCEEDED(hr))
688 ITypeInfo_AddRef(*ppTInfo);
689 return hr;
692 static HRESULT WINAPI FolderItemImpl_GetIDsOfNames(FolderItem2 *iface,
693 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
694 DISPID *rgDispId)
696 ITypeInfo *ti;
697 HRESULT hr;
699 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
700 rgDispId);
702 hr = get_typeinfo(FolderItem2_tid, &ti);
703 if (SUCCEEDED(hr))
704 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
705 return hr;
708 static HRESULT WINAPI FolderItemImpl_Invoke(FolderItem2 *iface,
709 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
710 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
711 UINT *puArgErr)
713 FolderItemImpl *This = impl_from_FolderItem(iface);
714 ITypeInfo *ti;
715 HRESULT hr;
717 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
718 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
720 hr = get_typeinfo(FolderItem2_tid, &ti);
721 if (SUCCEEDED(hr))
722 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
723 return hr;
726 static HRESULT WINAPI FolderItemImpl_get_Application(FolderItem2 *iface, IDispatch **disp)
728 FolderItemImpl *This = impl_from_FolderItem(iface);
730 TRACE("(%p,%p)\n", iface, disp);
732 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
735 static HRESULT WINAPI FolderItemImpl_get_Parent(FolderItem2 *iface, IDispatch **disp)
737 FolderItemImpl *This = impl_from_FolderItem(iface);
739 TRACE("(%p,%p)\n", iface, disp);
741 if (disp)
743 *disp = (IDispatch *)&This->folder->Folder3_iface;
744 IDispatch_AddRef(*disp);
747 return S_OK;
750 static HRESULT WINAPI FolderItemImpl_get_Name(FolderItem2 *iface, BSTR *name)
752 FolderItemImpl *This = impl_from_FolderItem(iface);
753 LPCITEMIDLIST last_part;
754 IShellFolder2 *parent;
755 HRESULT hr = S_OK;
756 LPITEMIDLIST pidl;
757 STRRET strret;
759 TRACE("(%p,%p)\n", iface, name);
761 *name = NULL;
763 if (This->path)
764 hr = SHParseDisplayName(This->path, NULL, &pidl, 0, NULL);
765 else
766 pidl = This->folder->pidl;
768 if (FAILED(hr))
769 return S_FALSE;
771 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
772 if (hr == S_OK)
773 hr = IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_INFOLDER, &strret);
775 IShellFolder2_Release(parent);
777 if (hr == S_OK)
778 hr = StrRetToBSTR(&strret, last_part, name);
780 if (This->path)
781 ILFree(pidl);
783 return hr;
786 static HRESULT WINAPI FolderItemImpl_put_Name(FolderItem2 *iface, BSTR bs)
788 FIXME("(%p,%s)\n", iface, debugstr_w(bs));
790 return E_NOTIMPL;
793 static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path)
795 FolderItemImpl *This = impl_from_FolderItem(iface);
797 TRACE("(%p,%p)\n", iface, path);
799 *path = SysAllocString(This->path ? This->path : This->folder->path);
800 return *path ? S_OK : E_OUTOFMEMORY;
803 static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface,
804 IDispatch **ppid)
806 FIXME("(%p,%p)\n", iface, ppid);
808 *ppid = NULL;
809 return E_NOTIMPL;
812 static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface,
813 IDispatch **ppid)
815 FIXME("(%p,%p)\n", iface, ppid);
817 *ppid = NULL;
818 return E_NOTIMPL;
821 static HRESULT WINAPI FolderItemImpl_get_IsLink(FolderItem2 *iface, VARIANT_BOOL *b)
823 FolderItemImpl *This = impl_from_FolderItem(iface);
825 TRACE("(%p,%p)\n", iface, b);
827 *b = This->attributes & SFGAO_LINK ? VARIANT_TRUE : VARIANT_FALSE;
829 return S_OK;
832 static HRESULT WINAPI FolderItemImpl_get_IsFolder(FolderItem2 *iface, VARIANT_BOOL *b)
834 FolderItemImpl *This = impl_from_FolderItem(iface);
836 TRACE("(%p,%p)\n", iface, b);
838 *b = This->attributes & SFGAO_FOLDER ? VARIANT_TRUE : VARIANT_FALSE;
840 return S_OK;
843 static HRESULT WINAPI FolderItemImpl_get_IsFileSystem(FolderItem2 *iface, VARIANT_BOOL *b)
845 FolderItemImpl *This = impl_from_FolderItem(iface);
847 TRACE("(%p,%p)\n", iface, b);
849 *b = This->attributes & SFGAO_FILESYSTEM ? VARIANT_TRUE : VARIANT_FALSE;
851 return S_OK;
854 static HRESULT WINAPI FolderItemImpl_get_IsBrowsable(FolderItem2 *iface, VARIANT_BOOL *b)
856 FolderItemImpl *This = impl_from_FolderItem(iface);
858 TRACE("(%p,%p)\n", iface, b);
860 *b = This->attributes & SFGAO_BROWSABLE ? VARIANT_TRUE : VARIANT_FALSE;
862 return S_OK;
865 static HRESULT WINAPI FolderItemImpl_get_ModifyDate(FolderItem2 *iface,
866 DATE *pdt)
868 FIXME("(%p,%p)\n", iface, pdt);
870 return E_NOTIMPL;
873 static HRESULT WINAPI FolderItemImpl_put_ModifyDate(FolderItem2 *iface, DATE dt)
875 FIXME("(%p,%f)\n", iface, dt);
877 return E_NOTIMPL;
880 static HRESULT WINAPI FolderItemImpl_get_Size(FolderItem2 *iface, LONG *pul)
882 FIXME("(%p,%p)\n", iface, pul);
884 return E_NOTIMPL;
887 static HRESULT WINAPI FolderItemImpl_get_Type(FolderItem2 *iface, BSTR *pbs)
889 FIXME("(%p,%p)\n", iface, pbs);
891 *pbs = NULL;
892 return E_NOTIMPL;
895 static HRESULT WINAPI FolderItemImpl_Verbs(FolderItem2 *iface, FolderItemVerbs **verbs)
897 FolderItemImpl *This = impl_from_FolderItem(iface);
899 TRACE("(%p, %p)\n", iface, verbs);
901 if (!verbs)
902 return E_INVALIDARG;
904 return FolderItemVerbs_Constructor(This->path ? This->path : This->folder->path, verbs);
907 static HRESULT WINAPI FolderItemImpl_InvokeVerb(FolderItem2 *iface,
908 VARIANT vVerb)
910 FIXME("(%p)\n", iface);
912 return E_NOTIMPL;
915 static HRESULT WINAPI FolderItemImpl_InvokeVerbEx(FolderItem2 *iface, VARIANT verb, VARIANT args)
917 FIXME("(%p): stub\n", iface);
919 return E_NOTIMPL;
922 static HRESULT WINAPI FolderItemImpl_ExtendedProperty(FolderItem2 *iface, BSTR propname, VARIANT *ret)
924 FIXME("(%p)->(%s %p): stub\n", iface, debugstr_w(propname), ret);
926 return E_NOTIMPL;
929 static const FolderItem2Vtbl FolderItemImpl_Vtbl = {
930 FolderItemImpl_QueryInterface,
931 FolderItemImpl_AddRef,
932 FolderItemImpl_Release,
933 FolderItemImpl_GetTypeInfoCount,
934 FolderItemImpl_GetTypeInfo,
935 FolderItemImpl_GetIDsOfNames,
936 FolderItemImpl_Invoke,
937 FolderItemImpl_get_Application,
938 FolderItemImpl_get_Parent,
939 FolderItemImpl_get_Name,
940 FolderItemImpl_put_Name,
941 FolderItemImpl_get_Path,
942 FolderItemImpl_get_GetLink,
943 FolderItemImpl_get_GetFolder,
944 FolderItemImpl_get_IsLink,
945 FolderItemImpl_get_IsFolder,
946 FolderItemImpl_get_IsFileSystem,
947 FolderItemImpl_get_IsBrowsable,
948 FolderItemImpl_get_ModifyDate,
949 FolderItemImpl_put_ModifyDate,
950 FolderItemImpl_get_Size,
951 FolderItemImpl_get_Type,
952 FolderItemImpl_Verbs,
953 FolderItemImpl_InvokeVerb,
954 FolderItemImpl_InvokeVerbEx,
955 FolderItemImpl_ExtendedProperty
958 static HRESULT FolderItem_Constructor(FolderImpl *folder, const WCHAR *path, FolderItem **item)
960 PIDLIST_ABSOLUTE pidl;
961 FolderItemImpl *This;
963 TRACE("%s\n", debugstr_w(path));
965 *item = NULL;
967 This = heap_alloc_zero(sizeof(*This));
968 if (!This)
969 return E_OUTOFMEMORY;
971 This->FolderItem2_iface.lpVtbl = &FolderItemImpl_Vtbl;
972 This->ref = 1;
973 if (path)
974 This->path = strdupW(path);
976 This->folder = folder;
977 Folder3_AddRef(&folder->Folder3_iface);
979 if (SHParseDisplayName(This->path, NULL, &pidl, ~0u, &This->attributes) == S_OK)
980 ILFree(pidl);
982 *item = (FolderItem *)&This->FolderItem2_iface;
983 return S_OK;
986 static HRESULT WINAPI FolderItemsImpl_QueryInterface(FolderItems3 *iface,
987 REFIID riid, LPVOID *ppv)
989 FolderItemsImpl *This = impl_from_FolderItems(iface);
991 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
993 if (!ppv) return E_INVALIDARG;
995 if (IsEqualIID(&IID_IUnknown, riid) ||
996 IsEqualIID(&IID_IDispatch, riid) ||
997 IsEqualIID(&IID_FolderItems, riid) ||
998 IsEqualIID(&IID_FolderItems2, riid) ||
999 IsEqualIID(&IID_FolderItems3, riid))
1000 *ppv = &This->FolderItems3_iface;
1001 else
1003 WARN("not implemented for %s\n", debugstr_guid(riid));
1004 *ppv = NULL;
1005 return E_NOINTERFACE;
1007 IUnknown_AddRef((IUnknown*)*ppv);
1008 return S_OK;
1011 static ULONG WINAPI FolderItemsImpl_AddRef(FolderItems3 *iface)
1013 FolderItemsImpl *This = impl_from_FolderItems(iface);
1014 ULONG ref = InterlockedIncrement(&This->ref);
1016 TRACE("(%p), new refcount=%i\n", iface, ref);
1018 return ref;
1021 static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
1023 FolderItemsImpl *This = impl_from_FolderItems(iface);
1024 ULONG ref = InterlockedDecrement(&This->ref);
1025 LONG i;
1027 TRACE("(%p), new refcount=%i\n", iface, ref);
1029 if (!ref)
1031 Folder3_Release(&This->folder->Folder3_iface);
1032 for (i = 0; i < This->item_count; i++)
1033 SysFreeString(This->item_names[i]);
1034 heap_free(This->item_names);
1035 heap_free(This);
1037 return ref;
1040 static HRESULT WINAPI FolderItemsImpl_GetTypeInfoCount(FolderItems3 *iface,
1041 UINT *count)
1043 TRACE("(%p,%p)\n", iface, count);
1045 *count = 1;
1046 return S_OK;
1049 static HRESULT WINAPI FolderItemsImpl_GetTypeInfo(FolderItems3 *iface,
1050 UINT type, LCID lcid, ITypeInfo **ppti)
1052 HRESULT hr;
1054 TRACE("(%p,%u,%d,%p)\n", iface, type, lcid, ppti);
1056 hr = get_typeinfo(FolderItems3_tid, ppti);
1057 if (SUCCEEDED(hr))
1058 ITypeInfo_AddRef(*ppti);
1059 return hr;
1062 static HRESULT WINAPI FolderItemsImpl_GetIDsOfNames(FolderItems3 *iface,
1063 REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid)
1065 ITypeInfo *ti;
1066 HRESULT hr;
1068 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), names, count, lcid, dispid);
1070 hr = get_typeinfo(FolderItems3_tid, &ti);
1071 if (SUCCEEDED(hr))
1072 hr = ITypeInfo_GetIDsOfNames(ti, names, count, dispid);
1073 return hr;
1076 static HRESULT WINAPI FolderItemsImpl_Invoke(FolderItems3 *iface,
1077 DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params,
1078 VARIANT *result, EXCEPINFO *ei, UINT *err)
1080 FolderItemsImpl *This = impl_from_FolderItems(iface);
1081 ITypeInfo *ti;
1082 HRESULT hr;
1084 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispid, shdebugstr_guid(riid), lcid, flags, params, result, ei, err);
1086 hr = get_typeinfo(FolderItems3_tid, &ti);
1087 if (SUCCEEDED(hr))
1088 hr = ITypeInfo_Invoke(ti, This, dispid, flags, params, result, ei, err);
1089 return hr;
1092 static BOOL shellfolder_exists(const WCHAR *path)
1094 PIDLIST_ABSOLUTE pidl = NULL;
1095 HRESULT hr;
1097 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
1098 ILFree(pidl);
1100 return SUCCEEDED(hr);
1103 static HRESULT WINAPI FolderItemsImpl_get_Count(FolderItems3 *iface, LONG *count)
1105 FolderItemsImpl *This = impl_from_FolderItems(iface);
1107 TRACE("(%p,%p)\n", iface, count);
1109 *count = shellfolder_exists(This->folder->path) ? This->item_count : 0;
1110 return S_OK;
1113 static HRESULT WINAPI FolderItemsImpl_get_Application(FolderItems3 *iface, IDispatch **disp)
1115 FolderItemsImpl *This = impl_from_FolderItems(iface);
1117 TRACE("(%p,%p)\n", iface, disp);
1119 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
1122 static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch **ppid)
1124 TRACE("(%p,%p)\n", iface, ppid);
1126 if (ppid)
1127 *ppid = NULL;
1129 return E_NOTIMPL;
1132 static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT var, FolderItem **item)
1134 FolderItemsImpl *This = impl_from_FolderItems(iface);
1135 BSTR display_name = NULL;
1136 VARIANT index;
1137 HRESULT hr;
1139 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&var), item);
1141 *item = NULL;
1143 if (!shellfolder_exists(This->folder->path))
1144 return S_FALSE;
1146 VariantInit(&index);
1147 if (FAILED(hr = VariantCopyInd(&index, &var)))
1148 return hr;
1150 switch (V_VT(&index))
1152 case VT_I2:
1153 VariantChangeType(&index, &index, 0, VT_I4);
1154 /* fall through */
1156 case VT_I4:
1157 if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
1158 return S_FALSE;
1160 display_name = SysAllocString(This->item_names[V_I4(&index)]);
1161 break;
1163 case VT_BSTR:
1165 LPITEMIDLIST pidl;
1166 STRRET strret;
1168 if (!V_BSTR(&index))
1169 return S_FALSE;
1171 hr = IShellFolder2_ParseDisplayName(This->folder->folder, NULL, NULL, V_BSTR(&index), NULL, &pidl, NULL);
1172 VariantClear(&index);
1173 if (FAILED(hr))
1174 return S_FALSE;
1176 if (IShellFolder2_GetDisplayNameOf(This->folder->folder, pidl, SHGDN_FORPARSING, &strret) == S_OK)
1177 StrRetToBSTR(&strret, pidl, &display_name);
1178 ILFree(pidl);
1179 break;
1181 case VT_ERROR:
1182 break;
1184 default:
1185 FIXME("Index type %#x not handled.\n", V_VT(&index));
1186 VariantClear(&index);
1187 /* fall through */
1188 case VT_EMPTY:
1189 return E_NOTIMPL;
1192 hr = FolderItem_Constructor(This->folder, display_name, item);
1193 SysFreeString(display_name);
1194 return hr;
1197 static HRESULT WINAPI FolderItemsImpl__NewEnum(FolderItems3 *iface, IUnknown **ppunk)
1199 FIXME("(%p,%p)\n", iface, ppunk);
1201 if (!ppunk)
1202 return E_INVALIDARG;
1204 *ppunk = NULL;
1205 return E_NOTIMPL;
1208 static HRESULT WINAPI FolderItemsImpl_InvokeVerbEx(FolderItems3 *iface, VARIANT verb, VARIANT args)
1210 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&verb), debugstr_variant(&args));
1212 return E_NOTIMPL;
1215 static HRESULT WINAPI FolderItemsImpl_Filter(FolderItems3 *iface, LONG flags, BSTR spec)
1217 FIXME("(%p,%d,%s)\n", iface, flags, wine_dbgstr_w(spec));
1219 return E_NOTIMPL;
1222 static HRESULT WINAPI FolderItemsImpl_get_Verbs(FolderItems3 *iface, FolderItemVerbs **ppfic)
1224 FIXME("(%p,%p)\n", iface, ppfic);
1226 if (!ppfic)
1227 return E_INVALIDARG;
1229 *ppfic = NULL;
1230 return E_NOTIMPL;
1233 static const FolderItems3Vtbl FolderItemsImpl_Vtbl = {
1234 FolderItemsImpl_QueryInterface,
1235 FolderItemsImpl_AddRef,
1236 FolderItemsImpl_Release,
1237 FolderItemsImpl_GetTypeInfoCount,
1238 FolderItemsImpl_GetTypeInfo,
1239 FolderItemsImpl_GetIDsOfNames,
1240 FolderItemsImpl_Invoke,
1241 FolderItemsImpl_get_Count,
1242 FolderItemsImpl_get_Application,
1243 FolderItemsImpl_get_Parent,
1244 FolderItemsImpl_Item,
1245 FolderItemsImpl__NewEnum,
1246 FolderItemsImpl_InvokeVerbEx,
1247 FolderItemsImpl_Filter,
1248 FolderItemsImpl_get_Verbs
1251 static void idlist_sort(LPITEMIDLIST *idlist, unsigned int l, unsigned int r, IShellFolder2 *folder)
1253 unsigned int m;
1255 if (l == r)
1256 return;
1258 if (r < l)
1260 idlist_sort(idlist, r, l, folder);
1261 return;
1264 m = (l + r) / 2;
1265 idlist_sort(idlist, l, m, folder);
1266 idlist_sort(idlist, m + 1, r, folder);
1268 /* join the two sides */
1269 while (l <= m && m < r)
1271 if ((short)IShellFolder2_CompareIDs(folder, 0, idlist[l], idlist[m + 1]) > 0)
1273 LPITEMIDLIST t = idlist[m + 1];
1274 memmove(&idlist[l + 1], &idlist[l], (m - l + 1) * sizeof(idlist[l]));
1275 idlist[l] = t;
1277 m++;
1279 l++;
1283 static HRESULT FolderItems_Constructor(FolderImpl *folder, FolderItems **ret)
1285 IEnumIDList *enumidlist;
1286 FolderItemsImpl *This;
1287 LPITEMIDLIST pidl;
1288 unsigned int i;
1289 HRESULT hr;
1291 TRACE("(%s,%p)\n", debugstr_w(folder->path), ret);
1293 *ret = NULL;
1295 This = heap_alloc_zero(sizeof(*This));
1296 if (!This)
1297 return E_OUTOFMEMORY;
1299 This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
1300 This->ref = 1;
1301 This->folder = folder;
1302 Folder3_AddRef(&folder->Folder3_iface);
1304 enumidlist = NULL;
1305 if (FAILED(hr = IShellFolder2_EnumObjects(folder->folder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1306 &enumidlist)))
1308 goto failed;
1311 while (IEnumIDList_Next(enumidlist, 1, &pidl, NULL) == S_OK)
1313 This->item_count++;
1314 ILFree(pidl);
1317 if (This->item_count)
1319 LPITEMIDLIST *pidls;
1320 ULONG fetched;
1322 pidls = heap_alloc(This->item_count * sizeof(*pidls));
1323 This->item_names = heap_alloc_zero(This->item_count * sizeof(*This->item_names));
1325 if (!pidls || !This->item_names)
1327 heap_free(pidls);
1328 heap_free(This->item_names);
1329 hr = E_OUTOFMEMORY;
1330 goto failed;
1333 IEnumIDList_Reset(enumidlist);
1334 if (IEnumIDList_Next(enumidlist, This->item_count, pidls, &fetched) == S_OK)
1335 idlist_sort(pidls, 0, This->item_count - 1, folder->folder);
1337 for (i = 0; i < This->item_count; i++)
1339 STRRET strret;
1341 if (IShellFolder2_GetDisplayNameOf(folder->folder, pidls[i], SHGDN_FORPARSING, &strret) == S_OK)
1342 StrRetToBSTR(&strret, pidls[i], &This->item_names[i]);
1344 ILFree(pidls[i]);
1346 heap_free(pidls);
1348 IEnumIDList_Release(enumidlist);
1350 *ret = (FolderItems *)&This->FolderItems3_iface;
1351 return S_OK;
1353 failed:
1354 if (enumidlist)
1355 IEnumIDList_Release(enumidlist);
1356 return hr;
1359 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
1360 LPVOID *ppv)
1362 FolderImpl *This = impl_from_Folder(iface);
1364 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1366 if (!ppv) return E_INVALIDARG;
1368 if (IsEqualIID(&IID_IUnknown, riid) ||
1369 IsEqualIID(&IID_IDispatch, riid) ||
1370 IsEqualIID(&IID_Folder, riid) ||
1371 IsEqualIID(&IID_Folder2, riid) ||
1372 IsEqualIID(&IID_Folder3, riid))
1373 *ppv = &This->Folder3_iface;
1374 else
1376 WARN("not implemented for %s\n", debugstr_guid(riid));
1377 *ppv = NULL;
1378 return E_NOINTERFACE;
1380 IUnknown_AddRef((IUnknown*)*ppv);
1381 return S_OK;
1384 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
1386 FolderImpl *This = impl_from_Folder(iface);
1387 ULONG ref = InterlockedIncrement(&This->ref);
1389 TRACE("(%p), new refcount=%i\n", iface, ref);
1391 return ref;
1394 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
1396 FolderImpl *This = impl_from_Folder(iface);
1397 ULONG ref = InterlockedDecrement(&This->ref);
1399 TRACE("(%p), new refcount=%i\n", iface, ref);
1401 if (!ref)
1403 ILFree(This->pidl);
1404 SysFreeString(This->path);
1405 IShellFolder2_Release(This->folder);
1406 IDispatch_Release(This->application);
1407 heap_free(This);
1409 return ref;
1412 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
1414 TRACE("(%p,%p)\n", iface, pctinfo);
1416 *pctinfo = 1;
1417 return S_OK;
1420 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
1421 LCID lcid, ITypeInfo **ppTInfo)
1423 HRESULT hr;
1425 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
1427 hr = get_typeinfo(Folder3_tid, ppTInfo);
1428 if (SUCCEEDED(hr))
1429 ITypeInfo_AddRef(*ppTInfo);
1431 return hr;
1434 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
1435 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1437 ITypeInfo *ti;
1438 HRESULT hr;
1440 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1441 rgDispId);
1443 hr = get_typeinfo(Folder3_tid, &ti);
1444 if (SUCCEEDED(hr))
1445 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1446 return hr;
1449 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
1450 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1451 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1453 FolderImpl *This = impl_from_Folder(iface);
1454 ITypeInfo *ti;
1455 HRESULT hr;
1457 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1458 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1460 hr = get_typeinfo(Folder3_tid, &ti);
1461 if (SUCCEEDED(hr))
1462 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1463 return hr;
1466 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *title)
1468 FolderImpl *This = impl_from_Folder(iface);
1469 PCUITEMID_CHILD last_part;
1470 IShellFolder2 *parent;
1471 SHELLDETAILS sd;
1472 HRESULT hr;
1474 TRACE("(%p,%p)\n", iface, title);
1476 *title = NULL;
1478 if (FAILED(hr = SHBindToParent(This->pidl, &IID_IShellFolder2, (void **)&parent, &last_part)))
1479 return hr;
1481 hr = IShellFolder2_GetDetailsOf(parent, last_part, 0, &sd);
1482 IShellFolder2_Release(parent);
1483 if (FAILED(hr))
1484 return hr;
1486 return StrRetToBSTR(&sd.str, last_part, title);
1489 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
1491 FolderImpl *This = impl_from_Folder(iface);
1493 TRACE("(%p,%p)\n", iface, disp);
1495 if (!disp)
1496 return E_INVALIDARG;
1498 *disp = This->application;
1499 IDispatch_AddRef(*disp);
1501 return S_OK;
1504 static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **disp)
1506 TRACE("(%p,%p)\n", iface, disp);
1508 if (disp)
1509 *disp = NULL;
1510 return E_NOTIMPL;
1513 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
1515 FIXME("(%p,%p)\n", iface, ppsf);
1517 *ppsf = NULL;
1518 return E_NOTIMPL;
1521 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
1523 FolderImpl *This = impl_from_Folder(iface);
1525 TRACE("(%p,%p)\n", iface, ppid);
1527 return FolderItems_Constructor(This, ppid);
1530 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
1532 FolderImpl *This = impl_from_Folder(iface);
1533 LPITEMIDLIST pidl;
1534 STRRET strret;
1535 HRESULT hr;
1536 BSTR path;
1538 TRACE("(%p,%s,%p)\n", iface, debugstr_w(name), item);
1540 *item = NULL;
1542 if (FAILED(IShellFolder2_ParseDisplayName(This->folder, NULL, NULL, name, NULL, &pidl, NULL)))
1543 return S_FALSE;
1545 if ((hr = IShellFolder2_GetDisplayNameOf(This->folder, pidl, SHGDN_FORPARSING, &strret)) == S_OK)
1546 hr = StrRetToBSTR(&strret, pidl, &path);
1548 ILFree(pidl);
1549 if (hr != S_OK)
1550 return S_FALSE;
1552 hr = FolderItem_Constructor(This, path, item);
1553 SysFreeString(path);
1554 return hr;
1557 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR name, VARIANT options)
1559 FIXME("(%p,%s,%s)\n", iface, debugstr_w(name), debugstr_variant(&options));
1561 return E_NOTIMPL;
1564 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT item, VARIANT options)
1566 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1568 return E_NOTIMPL;
1571 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT item, VARIANT options)
1573 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1575 return E_NOTIMPL;
1578 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT item, int column, BSTR *str)
1580 FIXME("(%p,%s,%d,%p)\n", iface, debugstr_variant(&item), column, str);
1582 *str = NULL;
1583 return E_NOTIMPL;
1586 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **item)
1588 FolderImpl *This = impl_from_Folder(iface);
1590 TRACE("(%p,%p)\n", iface, item);
1592 return FolderItem_Constructor(This, NULL, item);
1595 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
1597 FIXME("(%p,%p)\n", iface, pul);
1599 return E_NOTIMPL;
1602 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
1604 FIXME("(%p)\n", iface);
1606 return E_NOTIMPL;
1609 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
1610 VARIANT_BOOL *pbHaveToShowWebViewBarricade)
1612 FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
1614 return E_NOTIMPL;
1617 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
1619 FIXME("(%p)\n", iface);
1621 return E_NOTIMPL;
1624 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
1625 VARIANT_BOOL *pbShowWebViewBarricade)
1627 FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
1629 return E_NOTIMPL;
1632 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
1633 VARIANT_BOOL bShowWebViewBarricade)
1635 FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
1637 return E_NOTIMPL;
1640 static const Folder3Vtbl FolderImpl_Vtbl = {
1641 FolderImpl_QueryInterface,
1642 FolderImpl_AddRef,
1643 FolderImpl_Release,
1644 FolderImpl_GetTypeInfoCount,
1645 FolderImpl_GetTypeInfo,
1646 FolderImpl_GetIDsOfNames,
1647 FolderImpl_Invoke,
1648 FolderImpl_get_Title,
1649 FolderImpl_get_Application,
1650 FolderImpl_get_Parent,
1651 FolderImpl_get_ParentFolder,
1652 FolderImpl_Items,
1653 FolderImpl_ParseName,
1654 FolderImpl_NewFolder,
1655 FolderImpl_MoveHere,
1656 FolderImpl_CopyHere,
1657 FolderImpl_GetDetailsOf,
1658 FolderImpl_get_Self,
1659 FolderImpl_get_OfflineStatus,
1660 FolderImpl_Synchronize,
1661 FolderImpl_get_HaveToShowWebViewBarricade,
1662 FolderImpl_DismissedWebViewBarricade,
1663 FolderImpl_get_ShowWebViewBarricade,
1664 FolderImpl_put_ShowWebViewBarricade
1667 static HRESULT Folder_Constructor(IShellFolder2 *folder, LPITEMIDLIST pidl, Folder **ret)
1669 PCUITEMID_CHILD last_part;
1670 IShellFolder2 *parent;
1671 FolderImpl *This;
1672 STRRET strret;
1673 HRESULT hr;
1675 *ret = NULL;
1677 This = heap_alloc(sizeof(*This));
1678 if (!This)
1679 return E_OUTOFMEMORY;
1681 This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
1682 This->ref = 1;
1683 This->folder = folder;
1684 This->pidl = ILClone(pidl);
1686 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
1687 IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_FORPARSING, &strret);
1688 StrRetToBSTR(&strret, last_part, &This->path);
1689 IShellFolder2_Release(parent);
1691 IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
1693 *ret = (Folder *)&This->Folder3_iface;
1694 return hr;
1697 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch6 *iface,
1698 REFIID riid, LPVOID *ppv)
1700 ShellDispatch *This = impl_from_IShellDispatch6(iface);
1702 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1704 if (!ppv) return E_INVALIDARG;
1706 if (IsEqualIID(&IID_IUnknown, riid) ||
1707 IsEqualIID(&IID_IDispatch, riid) ||
1708 IsEqualIID(&IID_IShellDispatch, riid) ||
1709 IsEqualIID(&IID_IShellDispatch2, riid) ||
1710 IsEqualIID(&IID_IShellDispatch3, riid) ||
1711 IsEqualIID(&IID_IShellDispatch4, riid) ||
1712 IsEqualIID(&IID_IShellDispatch5, riid) ||
1713 IsEqualIID(&IID_IShellDispatch6, riid))
1714 *ppv = &This->IShellDispatch6_iface;
1715 else
1717 WARN("not implemented for %s\n", debugstr_guid(riid));
1718 *ppv = NULL;
1719 return E_NOINTERFACE;
1722 IShellDispatch6_AddRef(iface);
1723 return S_OK;
1726 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch6 *iface)
1728 ShellDispatch *This = impl_from_IShellDispatch6(iface);
1729 ULONG ref = InterlockedIncrement(&This->ref);
1731 TRACE("(%p), new refcount=%i\n", iface, ref);
1733 return ref;
1736 static ULONG WINAPI ShellDispatch_Release(IShellDispatch6 *iface)
1738 ShellDispatch *This = impl_from_IShellDispatch6(iface);
1739 ULONG ref = InterlockedDecrement(&This->ref);
1741 TRACE("(%p), new refcount=%i\n", iface, ref);
1743 if (!ref)
1744 heap_free(This);
1746 return ref;
1749 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch6 *iface,
1750 UINT *pctinfo)
1752 TRACE("(%p,%p)\n", iface, pctinfo);
1754 *pctinfo = 1;
1755 return S_OK;
1758 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch6 *iface,
1759 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1761 HRESULT hr;
1763 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
1765 hr = get_typeinfo(IShellDispatch6_tid, ppTInfo);
1766 if (SUCCEEDED(hr))
1767 ITypeInfo_AddRef(*ppTInfo);
1768 return hr;
1771 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch6 *iface,
1772 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1774 ITypeInfo *ti;
1775 HRESULT hr;
1777 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1778 rgDispId);
1780 hr = get_typeinfo(IShellDispatch6_tid, &ti);
1781 if (SUCCEEDED(hr))
1782 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1783 return hr;
1786 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch6 *iface,
1787 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
1788 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1789 UINT *puArgErr)
1791 ShellDispatch *This = impl_from_IShellDispatch6(iface);
1792 ITypeInfo *ti;
1793 HRESULT hr;
1795 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1796 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1798 hr = get_typeinfo(IShellDispatch6_tid, &ti);
1799 if (SUCCEEDED(hr))
1800 hr = ITypeInfo_Invoke(ti, &This->IShellDispatch6_iface, dispIdMember, wFlags, pDispParams,
1801 pVarResult, pExcepInfo, puArgErr);
1802 return hr;
1805 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch6 *iface, IDispatch **disp)
1807 TRACE("(%p,%p)\n", iface, disp);
1809 if (!disp)
1810 return E_INVALIDARG;
1812 *disp = (IDispatch *)iface;
1813 IDispatch_AddRef(*disp);
1814 return S_OK;
1817 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch6 *iface, IDispatch **disp)
1819 TRACE("(%p,%p)\n", iface, disp);
1821 if (disp)
1823 *disp = (IDispatch *)iface;
1824 IDispatch_AddRef(*disp);
1827 return S_OK;
1830 static HRESULT create_folder_for_pidl(LPITEMIDLIST pidl, Folder **ret)
1832 IShellFolder2 *folder;
1833 IShellFolder *desktop;
1834 HRESULT hr;
1836 *ret = NULL;
1838 if (FAILED(hr = SHGetDesktopFolder(&desktop)))
1839 return hr;
1841 if (_ILIsDesktop(pidl))
1842 hr = IShellFolder_QueryInterface(desktop, &IID_IShellFolder2, (void **)&folder);
1843 else
1844 hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder2, (void **)&folder);
1846 IShellFolder_Release(desktop);
1848 if (FAILED(hr))
1849 return S_FALSE;
1851 return Folder_Constructor(folder, pidl, ret);
1854 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch6 *iface,
1855 VARIANT dir, Folder **ret)
1857 LPITEMIDLIST pidl;
1858 HRESULT hr;
1860 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&dir), ret);
1862 *ret = NULL;
1864 switch (V_VT(&dir))
1866 case VT_I2:
1867 if (FAILED(hr = VariantChangeType(&dir, &dir, 0, VT_I4)))
1868 return hr;
1870 /* fallthrough */
1871 case VT_I4:
1872 if (FAILED(hr = SHGetFolderLocation(NULL, V_I4(&dir), NULL, 0, &pidl)))
1873 return S_FALSE;
1875 break;
1876 case VT_BSTR:
1877 if (FAILED(hr = SHParseDisplayName(V_BSTR(&dir), NULL, &pidl, 0, NULL)))
1878 return S_FALSE;
1880 break;
1881 default:
1882 WARN("Ignoring directory value %s\n", debugstr_variant(&dir));
1883 return S_FALSE;
1886 hr = create_folder_for_pidl(pidl, ret);
1887 ILFree(pidl);
1889 return hr;
1892 static BOOL is_optional_argument(const VARIANT *arg)
1894 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
1897 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch6 *iface,
1898 LONG hwnd, BSTR title, LONG options, VARIANT rootfolder, Folder **folder)
1900 PIDLIST_ABSOLUTE selection;
1901 BROWSEINFOW bi = { 0 };
1902 HRESULT hr;
1904 TRACE("(%p,%x,%s,%x,%s,%p)\n", iface, hwnd, debugstr_w(title), options, debugstr_variant(&rootfolder), folder);
1906 *folder = NULL;
1908 if (!is_optional_argument(&rootfolder))
1909 FIXME("root folder is ignored\n");
1911 bi.hwndOwner = LongToHandle(hwnd);
1912 bi.lpszTitle = title;
1913 bi.ulFlags = options;
1915 selection = SHBrowseForFolderW(&bi);
1916 if (selection)
1918 hr = create_folder_for_pidl(selection, folder);
1919 ILFree(selection);
1921 else
1922 hr = S_FALSE;
1924 return hr;
1927 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch6 *iface,
1928 IDispatch **ppid)
1930 FIXME("(%p,%p)\n", iface, ppid);
1932 *ppid = NULL;
1933 return E_NOTIMPL;
1936 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch6 *iface, VARIANT dir)
1938 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
1940 return E_NOTIMPL;
1943 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch6 *iface, VARIANT dir)
1945 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
1947 return E_NOTIMPL;
1950 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch6 *iface)
1952 FIXME("(%p)\n", iface);
1954 return E_NOTIMPL;
1957 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch6 *iface)
1959 FIXME("(%p)\n", iface);
1961 return E_NOTIMPL;
1964 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch6 *iface)
1966 FIXME("(%p)\n", iface);
1968 return E_NOTIMPL;
1971 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch6 *iface)
1973 FIXME("(%p)\n", iface);
1975 return E_NOTIMPL;
1978 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch6 *iface)
1980 FIXME("(%p)\n", iface);
1982 return E_NOTIMPL;
1985 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch6 *iface)
1987 FIXME("(%p)\n", iface);
1989 return E_NOTIMPL;
1992 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch6 *iface)
1994 FIXME("(%p)\n", iface);
1996 return E_NOTIMPL;
1999 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch6 *iface)
2001 FIXME("(%p)\n", iface);
2003 return E_NOTIMPL;
2006 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch6 *iface)
2008 FIXME("(%p)\n", iface);
2010 return E_NOTIMPL;
2013 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch6 *iface)
2015 FIXME("(%p)\n", iface);
2017 return E_NOTIMPL;
2020 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch6 *iface)
2022 FIXME("(%p)\n", iface);
2024 return E_NOTIMPL;
2027 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch6 *iface)
2029 FIXME("(%p)\n", iface);
2031 return E_NOTIMPL;
2034 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch6 *iface)
2036 FIXME("(%p)\n", iface);
2038 return E_NOTIMPL;
2041 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch6 *iface)
2043 FIXME("(%p)\n", iface);
2045 return E_NOTIMPL;
2048 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch6 *iface)
2050 FIXME("(%p)\n", iface);
2052 return E_NOTIMPL;
2055 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch6 *iface,
2056 BSTR szDir)
2058 FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
2060 return E_NOTIMPL;
2063 static HRESULT WINAPI ShellDispatch_IsRestricted(IShellDispatch6 *iface, BSTR group, BSTR restriction, LONG *value)
2065 FIXME("(%s, %s, %p): stub\n", debugstr_w(group), debugstr_w(restriction), value);
2066 return E_NOTIMPL;
2069 static HRESULT WINAPI ShellDispatch_ShellExecute(IShellDispatch6 *iface,
2070 BSTR file, VARIANT v_args, VARIANT v_dir, VARIANT v_op, VARIANT v_show)
2072 VARIANT args_str, dir_str, op_str, show_int;
2073 WCHAR *args = NULL, *dir = NULL, *op = NULL;
2074 INT show = 0;
2075 HINSTANCE ret;
2077 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file), debugstr_variant(&v_args),
2078 debugstr_variant(&v_dir), debugstr_variant(&v_op), debugstr_variant(&v_show));
2080 VariantInit(&args_str);
2081 VariantChangeType(&args_str, &v_args, 0, VT_BSTR);
2082 if (V_VT(&args_str) == VT_BSTR)
2083 args = V_BSTR(&args_str);
2085 VariantInit(&dir_str);
2086 VariantChangeType(&dir_str, &v_dir, 0, VT_BSTR);
2087 if (V_VT(&dir_str) == VT_BSTR)
2088 dir = V_BSTR(&dir_str);
2090 VariantInit(&op_str);
2091 VariantChangeType(&op_str, &v_op, 0, VT_BSTR);
2092 if (V_VT(&op_str) == VT_BSTR)
2093 op = V_BSTR(&op_str);
2095 VariantInit(&show_int);
2096 VariantChangeType(&show_int, &v_show, 0, VT_I4);
2097 if (V_VT(&show_int) == VT_I4)
2098 show = V_I4(&show_int);
2100 ret = ShellExecuteW(NULL, op, file, args, dir, show);
2102 VariantClear(&args_str);
2103 VariantClear(&dir_str);
2104 VariantClear(&op_str);
2105 VariantClear(&show_int);
2107 return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE;
2110 static HRESULT WINAPI ShellDispatch_FindPrinter(IShellDispatch6 *iface, BSTR name, BSTR location, BSTR model)
2112 FIXME("(%s, %s, %s): stub\n", debugstr_w(name), debugstr_w(location), debugstr_w(model));
2113 return E_NOTIMPL;
2116 static HRESULT WINAPI ShellDispatch_GetSystemInformation(IShellDispatch6 *iface, BSTR name, VARIANT *ret)
2118 FIXME("(%s, %p): stub\n", debugstr_w(name), ret);
2119 return E_NOTIMPL;
2122 static HRESULT WINAPI ShellDispatch_ServiceStart(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2124 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2125 return E_NOTIMPL;
2128 static HRESULT WINAPI ShellDispatch_ServiceStop(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2130 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2131 return E_NOTIMPL;
2134 static HRESULT WINAPI ShellDispatch_IsServiceRunning(IShellDispatch6 *iface, BSTR name, VARIANT *running)
2136 SERVICE_STATUS_PROCESS status;
2137 SC_HANDLE scm, service;
2138 DWORD dummy;
2140 TRACE("(%s, %p)\n", debugstr_w(name), running);
2142 V_VT(running) = VT_BOOL;
2143 V_BOOL(running) = VARIANT_FALSE;
2145 scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
2146 if (!scm)
2148 ERR("failed to connect to service manager\n");
2149 return S_OK;
2152 service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS);
2153 if (!service)
2155 ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError());
2156 CloseServiceHandle(scm);
2157 return S_OK;
2160 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status,
2161 sizeof(SERVICE_STATUS_PROCESS), &dummy))
2163 TRACE("failed to query service status (%u)\n", GetLastError());
2164 CloseServiceHandle(service);
2165 CloseServiceHandle(scm);
2166 return S_OK;
2169 if (status.dwCurrentState == SERVICE_RUNNING)
2170 V_BOOL(running) = VARIANT_TRUE;
2172 CloseServiceHandle(service);
2173 CloseServiceHandle(scm);
2175 return S_OK;
2178 static HRESULT WINAPI ShellDispatch_CanStartStopService(IShellDispatch6 *iface, BSTR service, VARIANT *ret)
2180 FIXME("(%s, %p): stub\n", debugstr_w(service), ret);
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI ShellDispatch_ShowBrowserBar(IShellDispatch6 *iface, BSTR clsid, VARIANT show, VARIANT *ret)
2186 FIXME("(%s, %s, %p): stub\n", debugstr_w(clsid), debugstr_variant(&show), ret);
2187 return E_NOTIMPL;
2190 static HRESULT WINAPI ShellDispatch_AddToRecent(IShellDispatch6 *iface, VARIANT file, BSTR category)
2192 FIXME("(%s, %s): stub\n", debugstr_variant(&file), debugstr_w(category));
2193 return E_NOTIMPL;
2196 static HRESULT WINAPI ShellDispatch_WindowsSecurity(IShellDispatch6 *iface)
2198 FIXME("stub\n");
2199 return E_NOTIMPL;
2202 static HRESULT WINAPI ShellDispatch_ToggleDesktop(IShellDispatch6 *iface)
2204 FIXME("stub\n");
2205 return E_NOTIMPL;
2208 static HRESULT WINAPI ShellDispatch_ExplorerPolicy(IShellDispatch6 *iface, BSTR policy, VARIANT *value)
2210 FIXME("(%s, %p): stub\n", debugstr_w(policy), value);
2211 return E_NOTIMPL;
2214 static HRESULT WINAPI ShellDispatch_GetSetting(IShellDispatch6 *iface, LONG setting, VARIANT_BOOL *result)
2216 FIXME("(%d %p): stub\n", setting, result);
2217 return E_NOTIMPL;
2220 static HRESULT WINAPI ShellDispatch_WindowSwitcher(IShellDispatch6 *iface)
2222 FIXME("stub\n");
2223 return E_NOTIMPL;
2226 static HRESULT WINAPI ShellDispatch_SearchCommand(IShellDispatch6 *iface)
2228 FIXME("stub\n");
2229 return E_NOTIMPL;
2232 static const IShellDispatch6Vtbl ShellDispatchVtbl = {
2233 ShellDispatch_QueryInterface,
2234 ShellDispatch_AddRef,
2235 ShellDispatch_Release,
2236 ShellDispatch_GetTypeInfoCount,
2237 ShellDispatch_GetTypeInfo,
2238 ShellDispatch_GetIDsOfNames,
2239 ShellDispatch_Invoke,
2240 ShellDispatch_get_Application,
2241 ShellDispatch_get_Parent,
2242 ShellDispatch_NameSpace,
2243 ShellDispatch_BrowseForFolder,
2244 ShellDispatch_Windows,
2245 ShellDispatch_Open,
2246 ShellDispatch_Explore,
2247 ShellDispatch_MinimizeAll,
2248 ShellDispatch_UndoMinimizeALL,
2249 ShellDispatch_FileRun,
2250 ShellDispatch_CascadeWindows,
2251 ShellDispatch_TileVertically,
2252 ShellDispatch_TileHorizontally,
2253 ShellDispatch_ShutdownWindows,
2254 ShellDispatch_Suspend,
2255 ShellDispatch_EjectPC,
2256 ShellDispatch_SetTime,
2257 ShellDispatch_TrayProperties,
2258 ShellDispatch_Help,
2259 ShellDispatch_FindFiles,
2260 ShellDispatch_FindComputer,
2261 ShellDispatch_RefreshMenu,
2262 ShellDispatch_ControlPanelItem,
2263 ShellDispatch_IsRestricted,
2264 ShellDispatch_ShellExecute,
2265 ShellDispatch_FindPrinter,
2266 ShellDispatch_GetSystemInformation,
2267 ShellDispatch_ServiceStart,
2268 ShellDispatch_ServiceStop,
2269 ShellDispatch_IsServiceRunning,
2270 ShellDispatch_CanStartStopService,
2271 ShellDispatch_ShowBrowserBar,
2272 ShellDispatch_AddToRecent,
2273 ShellDispatch_WindowsSecurity,
2274 ShellDispatch_ToggleDesktop,
2275 ShellDispatch_ExplorerPolicy,
2276 ShellDispatch_GetSetting,
2277 ShellDispatch_WindowSwitcher,
2278 ShellDispatch_SearchCommand
2281 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *outer, REFIID riid, void **ppv)
2283 ShellDispatch *This;
2284 HRESULT ret;
2286 TRACE("(%p, %s)\n", outer, debugstr_guid(riid));
2288 *ppv = NULL;
2290 if (outer) return CLASS_E_NOAGGREGATION;
2292 This = heap_alloc(sizeof(*This));
2293 if (!This) return E_OUTOFMEMORY;
2294 This->IShellDispatch6_iface.lpVtbl = &ShellDispatchVtbl;
2295 This->ref = 1;
2297 ret = IShellDispatch6_QueryInterface(&This->IShellDispatch6_iface, riid, ppv);
2298 IShellDispatch6_Release(&This->IShellDispatch6_iface);
2299 return ret;