mf/topoloader: Move node connection responsibility to connection function.
[wine/zf.git] / dlls / shell32 / shelldispatch.c
blobb0eefa59999f999c361080df77b2a4926a438e8c
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,
55 &IID_IShellLinkDual2
57 static ITypeInfo *typeinfos[LAST_tid];
59 typedef struct {
60 IShellDispatch6 IShellDispatch6_iface;
61 LONG ref;
62 } ShellDispatch;
64 typedef struct {
65 Folder3 Folder3_iface;
66 LONG ref;
67 IDispatch *application;
68 IShellFolder2 *folder;
69 PIDLIST_ABSOLUTE pidl;
70 BSTR path;
71 } FolderImpl;
73 typedef struct {
74 FolderItems3 FolderItems3_iface;
75 LONG ref;
76 FolderImpl *folder;
77 BSTR *item_names;
78 LONG item_count;
79 } FolderItemsImpl;
81 typedef struct {
82 FolderItem2 FolderItem2_iface;
83 LONG ref;
84 FolderImpl *folder;
85 WCHAR *path; /* if NULL, folder path is used */
86 DWORD attributes;
87 } FolderItemImpl;
89 typedef struct {
90 FolderItemVerbs FolderItemVerbs_iface;
91 LONG ref;
93 IContextMenu *contextmenu;
94 HMENU hMenu;
95 LONG count;
96 } FolderItemVerbsImpl;
98 typedef struct {
99 FolderItemVerb FolderItemVerb_iface;
100 LONG ref;
102 IContextMenu *contextmenu;
103 BSTR name;
104 } FolderItemVerbImpl;
106 typedef struct {
107 IShellLinkDual2 IShellLinkDual2_iface;
108 LONG ref;
110 IShellLinkW *shell_link;
111 } ShellLinkObjectImpl;
113 static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface)
115 return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch6_iface);
118 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
120 return CONTAINING_RECORD(iface, FolderImpl, Folder3_iface);
123 static inline FolderItemsImpl *impl_from_FolderItems(FolderItems3 *iface)
125 return CONTAINING_RECORD(iface, FolderItemsImpl, FolderItems3_iface);
128 static inline FolderItemImpl *impl_from_FolderItem(FolderItem2 *iface)
130 return CONTAINING_RECORD(iface, FolderItemImpl, FolderItem2_iface);
133 static inline FolderItemVerbsImpl *impl_from_FolderItemVerbs(FolderItemVerbs *iface)
135 return CONTAINING_RECORD(iface, FolderItemVerbsImpl, FolderItemVerbs_iface);
138 static inline FolderItemVerbImpl *impl_from_FolderItemVerb(FolderItemVerb *iface)
140 return CONTAINING_RECORD(iface, FolderItemVerbImpl, FolderItemVerb_iface);
143 static inline ShellLinkObjectImpl *impl_from_IShellLinkDual(IShellLinkDual2 *iface)
145 return CONTAINING_RECORD(iface, ShellLinkObjectImpl, IShellLinkDual2_iface);
148 static HRESULT load_typelib(void)
150 ITypeLib *tl;
151 HRESULT hr;
153 hr = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
154 if (FAILED(hr)) {
155 ERR("LoadRegTypeLib failed: %08x\n", hr);
156 return hr;
159 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
160 ITypeLib_Release(tl);
161 return hr;
164 void release_typelib(void)
166 unsigned i;
168 if (!typelib)
169 return;
171 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
172 if (typeinfos[i])
173 ITypeInfo_Release(typeinfos[i]);
175 ITypeLib_Release(typelib);
178 HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
180 HRESULT hr;
182 if (!typelib)
183 hr = load_typelib();
184 if (!typelib)
185 return hr;
187 if (!typeinfos[tid])
189 ITypeInfo *ti;
191 hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
192 if (FAILED(hr))
194 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hr);
195 return hr;
198 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
199 ITypeInfo_Release(ti);
202 *typeinfo = typeinfos[tid];
203 return S_OK;
206 /* FolderItemVerb */
207 static HRESULT WINAPI FolderItemVerbImpl_QueryInterface(FolderItemVerb *iface,
208 REFIID riid, void **ppv)
210 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
212 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
214 if (IsEqualIID(&IID_IUnknown, riid) ||
215 IsEqualIID(&IID_IDispatch, riid) ||
216 IsEqualIID(&IID_FolderItemVerb, riid))
217 *ppv = &This->FolderItemVerb_iface;
218 else
220 WARN("not implemented for %s\n", debugstr_guid(riid));
221 *ppv = NULL;
222 return E_NOINTERFACE;
225 IUnknown_AddRef((IUnknown*)*ppv);
226 return S_OK;
229 static ULONG WINAPI FolderItemVerbImpl_AddRef(FolderItemVerb *iface)
231 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
232 ULONG ref = InterlockedIncrement(&This->ref);
234 TRACE("(%p), new refcount=%i\n", iface, ref);
236 return ref;
239 static ULONG WINAPI FolderItemVerbImpl_Release(FolderItemVerb *iface)
241 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
242 ULONG ref = InterlockedDecrement(&This->ref);
244 TRACE("(%p), new refcount=%i\n", iface, ref);
246 if (!ref)
248 IContextMenu_Release(This->contextmenu);
249 SysFreeString(This->name);
250 heap_free(This);
253 return ref;
256 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfoCount(FolderItemVerb *iface, UINT *pctinfo)
258 TRACE("(%p,%p)\n", iface, pctinfo);
259 *pctinfo = 1;
260 return S_OK;
263 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfo(FolderItemVerb *iface, UINT iTInfo,
264 LCID lcid, ITypeInfo **ppTInfo)
266 HRESULT hr;
268 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
270 hr = get_typeinfo(FolderItemVerb_tid, ppTInfo);
271 if (SUCCEEDED(hr))
272 ITypeInfo_AddRef(*ppTInfo);
273 return hr;
276 static HRESULT WINAPI FolderItemVerbImpl_GetIDsOfNames(FolderItemVerb *iface,
277 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
279 ITypeInfo *ti;
280 HRESULT hr;
282 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
283 rgDispId);
285 hr = get_typeinfo(FolderItemVerb_tid, &ti);
286 if (SUCCEEDED(hr))
287 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
288 return hr;
291 static HRESULT WINAPI FolderItemVerbImpl_Invoke(FolderItemVerb *iface,
292 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
293 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
294 UINT *puArgErr)
296 ITypeInfo *ti;
297 HRESULT hr;
299 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
300 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
302 hr = get_typeinfo(FolderItemVerb_tid, &ti);
303 if (SUCCEEDED(hr))
304 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
305 return hr;
308 static HRESULT WINAPI FolderItemVerbImpl_get_Application(FolderItemVerb *iface, IDispatch **disp)
310 TRACE("(%p, %p)\n", iface, disp);
312 if (disp)
313 *disp = NULL;
314 return E_NOTIMPL;
317 static HRESULT WINAPI FolderItemVerbImpl_get_Parent(FolderItemVerb *iface, IDispatch **disp)
319 TRACE("(%p, %p)\n", iface, disp);
321 if (disp)
322 *disp = NULL;
323 return E_NOTIMPL;
326 static HRESULT WINAPI FolderItemVerbImpl_get_Name(FolderItemVerb *iface, BSTR *name)
328 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
330 TRACE("(%p, %p)\n", iface, name);
332 *name = SysAllocString(This->name);
333 return *name ? S_OK : E_OUTOFMEMORY;
336 static HRESULT WINAPI FolderItemVerbImpl_DoIt(FolderItemVerb *iface)
338 FIXME("(%p)\n", iface);
339 return E_NOTIMPL;
342 static FolderItemVerbVtbl folderitemverbvtbl = {
343 FolderItemVerbImpl_QueryInterface,
344 FolderItemVerbImpl_AddRef,
345 FolderItemVerbImpl_Release,
346 FolderItemVerbImpl_GetTypeInfoCount,
347 FolderItemVerbImpl_GetTypeInfo,
348 FolderItemVerbImpl_GetIDsOfNames,
349 FolderItemVerbImpl_Invoke,
350 FolderItemVerbImpl_get_Application,
351 FolderItemVerbImpl_get_Parent,
352 FolderItemVerbImpl_get_Name,
353 FolderItemVerbImpl_DoIt
356 static HRESULT FolderItemVerb_Constructor(IContextMenu *contextmenu, BSTR name, FolderItemVerb **verb)
358 FolderItemVerbImpl *This;
360 TRACE("%p, %s\n", contextmenu, debugstr_w(name));
362 This = heap_alloc(sizeof(*This));
363 if (!This)
364 return E_OUTOFMEMORY;
366 This->FolderItemVerb_iface.lpVtbl = &folderitemverbvtbl;
367 This->ref = 1;
368 This->contextmenu = contextmenu;
369 IContextMenu_AddRef(contextmenu);
370 This->name = name;
372 *verb = &This->FolderItemVerb_iface;
373 return S_OK;
376 /* FolderItemVerbs */
377 static HRESULT WINAPI FolderItemVerbsImpl_QueryInterface(FolderItemVerbs *iface,
378 REFIID riid, void **ppv)
380 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
382 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
384 if (IsEqualIID(&IID_IUnknown, riid) ||
385 IsEqualIID(&IID_IDispatch, riid) ||
386 IsEqualIID(&IID_FolderItemVerbs, riid))
387 *ppv = &This->FolderItemVerbs_iface;
388 else
390 WARN("not implemented for %s\n", debugstr_guid(riid));
391 *ppv = NULL;
392 return E_NOINTERFACE;
395 IUnknown_AddRef((IUnknown*)*ppv);
396 return S_OK;
399 static ULONG WINAPI FolderItemVerbsImpl_AddRef(FolderItemVerbs *iface)
401 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
402 ULONG ref = InterlockedIncrement(&This->ref);
404 TRACE("(%p), new refcount=%i\n", iface, ref);
406 return ref;
409 static ULONG WINAPI FolderItemVerbsImpl_Release(FolderItemVerbs *iface)
411 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
412 ULONG ref = InterlockedDecrement(&This->ref);
414 TRACE("(%p), new refcount=%i\n", iface, ref);
416 if (!ref)
418 IContextMenu_Release(This->contextmenu);
419 DestroyMenu(This->hMenu);
420 heap_free(This);
423 return ref;
426 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfoCount(FolderItemVerbs *iface, UINT *pctinfo)
428 TRACE("(%p,%p)\n", iface, pctinfo);
429 *pctinfo = 1;
430 return S_OK;
433 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfo(FolderItemVerbs *iface, UINT iTInfo,
434 LCID lcid, ITypeInfo **ppTInfo)
436 HRESULT hr;
438 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
440 hr = get_typeinfo(FolderItemVerbs_tid, ppTInfo);
441 if (SUCCEEDED(hr))
442 ITypeInfo_AddRef(*ppTInfo);
443 return hr;
446 static HRESULT WINAPI FolderItemVerbsImpl_GetIDsOfNames(FolderItemVerbs *iface,
447 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
449 ITypeInfo *ti;
450 HRESULT hr;
452 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
453 rgDispId);
455 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
456 if (SUCCEEDED(hr))
457 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
458 return hr;
461 static HRESULT WINAPI FolderItemVerbsImpl_Invoke(FolderItemVerbs *iface,
462 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
463 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
464 UINT *puArgErr)
466 ITypeInfo *ti;
467 HRESULT hr;
469 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
470 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
472 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
473 if (SUCCEEDED(hr))
474 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
475 return hr;
478 static HRESULT WINAPI FolderItemVerbsImpl_get_Count(FolderItemVerbs *iface, LONG *count)
480 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
482 TRACE("(%p, %p)\n", iface, count);
484 if (!count)
485 return E_INVALIDARG;
487 *count = This->count;
488 return S_OK;
491 static HRESULT WINAPI FolderItemVerbsImpl_get_Application(FolderItemVerbs *iface, IDispatch **disp)
493 TRACE("(%p, %p)\n", iface, disp);
495 if (disp)
496 *disp = NULL;
497 return E_NOTIMPL;
500 static HRESULT WINAPI FolderItemVerbsImpl_get_Parent(FolderItemVerbs *iface, IDispatch **disp)
502 TRACE("(%p, %p)\n", iface, disp);
504 if (disp)
505 *disp = NULL;
506 return E_NOTIMPL;
509 static HRESULT WINAPI FolderItemVerbsImpl_Item(FolderItemVerbs *iface, VARIANT index, FolderItemVerb **verb)
511 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
512 MENUITEMINFOW info;
513 HRESULT hr;
514 VARIANT v;
515 BSTR name;
517 TRACE("(%p, %s, %p)\n", iface, debugstr_variant(&index), verb);
519 if (!verb)
520 return E_INVALIDARG;
522 *verb = NULL;
524 VariantInit(&v);
525 VariantCopyInd(&v, &index);
527 hr = VariantChangeType(&v, &v, 0, VT_I4);
528 if (FAILED(hr))
530 FIXME("failed to coerce to VT_I4, %s\n", debugstr_variant(&v));
531 return hr;
534 if (V_I4(&v) > This->count)
535 return S_OK;
537 if (V_I4(&v) == This->count)
538 name = SysAllocStringLen(NULL, 0);
539 else
541 /* get item name */
542 memset(&info, 0, sizeof(info));
543 info.cbSize = sizeof(info);
544 info.fMask = MIIM_STRING;
545 if (!GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info))
546 return E_FAIL;
548 name = SysAllocStringLen(NULL, info.cch);
549 if (name)
551 info.dwTypeData = name;
552 info.cch++;
553 GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info);
557 if (!name)
558 return E_OUTOFMEMORY;
560 return FolderItemVerb_Constructor(This->contextmenu, name, verb);
563 static HRESULT WINAPI FolderItemVerbsImpl__NewEnum(FolderItemVerbs *iface, IUnknown **ret)
565 FIXME("(%p, %p)\n", iface, ret);
566 return E_NOTIMPL;
569 static FolderItemVerbsVtbl folderitemverbsvtbl = {
570 FolderItemVerbsImpl_QueryInterface,
571 FolderItemVerbsImpl_AddRef,
572 FolderItemVerbsImpl_Release,
573 FolderItemVerbsImpl_GetTypeInfoCount,
574 FolderItemVerbsImpl_GetTypeInfo,
575 FolderItemVerbsImpl_GetIDsOfNames,
576 FolderItemVerbsImpl_Invoke,
577 FolderItemVerbsImpl_get_Count,
578 FolderItemVerbsImpl_get_Application,
579 FolderItemVerbsImpl_get_Parent,
580 FolderItemVerbsImpl_Item,
581 FolderItemVerbsImpl__NewEnum
584 static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs)
586 FolderItemVerbsImpl *This;
587 IShellFolder *folder;
588 LPCITEMIDLIST child;
589 LPITEMIDLIST pidl;
590 HRESULT hr;
592 *verbs = NULL;
594 This = heap_alloc(sizeof(*This));
595 if (!This)
596 return E_OUTOFMEMORY;
598 This->FolderItemVerbs_iface.lpVtbl = &folderitemverbsvtbl;
599 This->ref = 1;
601 /* build context menu for this path */
602 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
603 if (FAILED(hr))
604 goto failed;
606 hr = SHBindToParent(pidl, &IID_IShellFolder, (void**)&folder, &child);
607 CoTaskMemFree(pidl);
608 if (FAILED(hr))
609 goto failed;
611 hr = IShellFolder_GetUIObjectOf(folder, NULL, 1, &child, &IID_IContextMenu, NULL, (void**)&This->contextmenu);
612 IShellFolder_Release(folder);
613 if (FAILED(hr))
614 goto failed;
616 This->hMenu = CreatePopupMenu();
617 hr = IContextMenu_QueryContextMenu(This->contextmenu, This->hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
618 if (FAILED(hr))
620 FolderItemVerbs_Release(&This->FolderItemVerbs_iface);
621 return hr;
624 This->count = GetMenuItemCount(This->hMenu);
625 *verbs = &This->FolderItemVerbs_iface;
626 return S_OK;
628 failed:
629 heap_free(This);
630 return hr;
633 static HRESULT WINAPI ShellLinkObject_QueryInterface(IShellLinkDual2 *iface, REFIID riid,
634 LPVOID *ppv)
636 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
638 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
640 if (!ppv) return E_INVALIDARG;
642 if (IsEqualIID(&IID_IUnknown, riid) ||
643 IsEqualIID(&IID_IDispatch, riid) ||
644 IsEqualIID(&IID_IShellLinkDual, riid) ||
645 IsEqualIID(&IID_IShellLinkDual2, riid))
646 *ppv = &This->IShellLinkDual2_iface;
647 else
649 WARN("not implemented for %s\n", debugstr_guid(riid));
650 *ppv = NULL;
651 return E_NOINTERFACE;
653 IUnknown_AddRef((IUnknown*)*ppv);
654 return S_OK;
657 static ULONG WINAPI ShellLinkObject_AddRef(IShellLinkDual2 *iface)
659 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
660 ULONG ref = InterlockedIncrement(&This->ref);
662 TRACE("(%p), new refcount=%i\n", iface, ref);
664 return ref;
667 static ULONG WINAPI ShellLinkObject_Release(IShellLinkDual2 *iface)
669 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
670 ULONG ref = InterlockedDecrement(&This->ref);
672 TRACE("(%p), new refcount=%i\n", iface, ref);
674 if (!ref)
676 if (This->shell_link) IShellLinkW_Release(This->shell_link);
677 heap_free(This);
679 return ref;
682 static HRESULT WINAPI ShellLinkObject_GetTypeInfoCount(IShellLinkDual2 *iface, UINT *pctinfo)
684 TRACE("(%p,%p)\n", iface, pctinfo);
686 *pctinfo = 1;
687 return S_OK;
690 static HRESULT WINAPI ShellLinkObject_GetTypeInfo(IShellLinkDual2 *iface, UINT iTInfo,
691 LCID lcid, ITypeInfo **ppTInfo)
693 HRESULT hr;
695 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
697 hr = get_typeinfo(IShellLinkDual2_tid, ppTInfo);
698 if (SUCCEEDED(hr))
699 ITypeInfo_AddRef(*ppTInfo);
701 return hr;
704 static HRESULT WINAPI ShellLinkObject_GetIDsOfNames(IShellLinkDual2 *iface, REFIID riid,
705 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
707 ITypeInfo *ti;
708 HRESULT hr;
710 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
711 rgDispId);
713 hr = get_typeinfo(IShellLinkDual2_tid, &ti);
714 if (SUCCEEDED(hr))
715 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
716 return hr;
719 static HRESULT WINAPI ShellLinkObject_Invoke(IShellLinkDual2 *iface, DISPID dispIdMember,
720 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
721 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
723 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
724 ITypeInfo *ti;
725 HRESULT hr;
727 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
728 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
730 hr = get_typeinfo(IShellLinkDual2_tid, &ti);
731 if (SUCCEEDED(hr))
732 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
733 return hr;
736 static HRESULT WINAPI ShellLinkObject_get_Path(IShellLinkDual2 *iface, BSTR *pbs)
738 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
739 WCHAR path[MAX_PATH];
740 HRESULT hr;
742 TRACE("(%p, %p)\n", iface, pbs);
744 *pbs = NULL;
746 hr = IShellLinkW_GetPath(This->shell_link, path, MAX_PATH, NULL, 0);
747 if (hr != S_OK)
748 return hr;
750 *pbs = SysAllocString(path);
751 return hr;
754 static HRESULT WINAPI ShellLinkObject_put_Path(IShellLinkDual2 *iface, BSTR bs)
756 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
758 return E_NOTIMPL;
761 static HRESULT WINAPI ShellLinkObject_get_Description(IShellLinkDual2 *iface, BSTR *pbs)
763 FIXME("(%p, %p)\n", iface, pbs);
765 return E_NOTIMPL;
768 static HRESULT WINAPI ShellLinkObject_put_Description(IShellLinkDual2 *iface, BSTR bs)
770 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
772 return E_NOTIMPL;
775 static HRESULT WINAPI ShellLinkObject_get_WorkingDirectory(IShellLinkDual2 *iface, BSTR *pbs)
777 FIXME("(%p, %p)\n", iface, pbs);
779 return E_NOTIMPL;
782 static HRESULT WINAPI ShellLinkObject_put_WorkingDirectory(IShellLinkDual2 *iface, BSTR bs)
784 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
786 return E_NOTIMPL;
789 static HRESULT WINAPI ShellLinkObject_get_Arguments(IShellLinkDual2 *iface, BSTR *pbs)
791 FIXME("(%p, %p)\n", iface, pbs);
793 return E_NOTIMPL;
796 static HRESULT WINAPI ShellLinkObject_put_Arguments(IShellLinkDual2 *iface, BSTR bs)
798 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
800 return E_NOTIMPL;
803 static HRESULT WINAPI ShellLinkObject_get_Hotkey(IShellLinkDual2 *iface, int *piHK)
805 FIXME("(%p, %p)\n", iface, piHK);
807 return E_NOTIMPL;
810 static HRESULT WINAPI ShellLinkObject_put_Hotkey(IShellLinkDual2 *iface, int iHK)
812 FIXME("(%p, %d)\n", iface, iHK);
814 return E_NOTIMPL;
817 static HRESULT WINAPI ShellLinkObject_get_ShowCommand(IShellLinkDual2 *iface, int *piShowCommand)
819 FIXME("(%p, %p)\n", iface, piShowCommand);
821 return E_NOTIMPL;
824 static HRESULT WINAPI ShellLinkObject_put_ShowCommand(IShellLinkDual2 *iface, int iShowCommand)
826 FIXME("(%p, %d)\n", iface, iShowCommand);
828 return E_NOTIMPL;
831 static HRESULT WINAPI ShellLinkObject_Resolve(IShellLinkDual2 *iface, int fFlags)
833 FIXME("(%p, %d)\n", iface, fFlags);
835 return E_NOTIMPL;
838 static HRESULT WINAPI ShellLinkObject_GetIconLocation(IShellLinkDual2 *iface, BSTR *pbs,
839 int *piIcon)
841 FIXME("(%p, %p, %p)\n", iface, pbs, piIcon);
843 return E_NOTIMPL;
846 static HRESULT WINAPI ShellLinkObject_SetIconLocation(IShellLinkDual2 *iface, BSTR bs,
847 int iIcon)
849 FIXME("(%p, %s, %d)\n", iface, debugstr_w(bs), iIcon);
851 return E_NOTIMPL;
854 static HRESULT WINAPI ShellLinkObject_Save(IShellLinkDual2 *iface, VARIANT vWhere)
856 FIXME("(%p, %s)\n", iface, debugstr_variant(&vWhere));
858 return E_NOTIMPL;
861 static HRESULT WINAPI ShellLinkObject_get_Target(IShellLinkDual2 *iface, FolderItem **ppfi)
863 FIXME("(%p, %p)\n", iface, ppfi);
865 return E_NOTIMPL;
868 static const IShellLinkDual2Vtbl ShellLinkObjectVtbl = {
869 ShellLinkObject_QueryInterface,
870 ShellLinkObject_AddRef,
871 ShellLinkObject_Release,
872 ShellLinkObject_GetTypeInfoCount,
873 ShellLinkObject_GetTypeInfo,
874 ShellLinkObject_GetIDsOfNames,
875 ShellLinkObject_Invoke,
876 ShellLinkObject_get_Path,
877 ShellLinkObject_put_Path,
878 ShellLinkObject_get_Description,
879 ShellLinkObject_put_Description,
880 ShellLinkObject_get_WorkingDirectory,
881 ShellLinkObject_put_WorkingDirectory,
882 ShellLinkObject_get_Arguments,
883 ShellLinkObject_put_Arguments,
884 ShellLinkObject_get_Hotkey,
885 ShellLinkObject_put_Hotkey,
886 ShellLinkObject_get_ShowCommand,
887 ShellLinkObject_put_ShowCommand,
888 ShellLinkObject_Resolve,
889 ShellLinkObject_GetIconLocation,
890 ShellLinkObject_SetIconLocation,
891 ShellLinkObject_Save,
892 ShellLinkObject_get_Target,
895 static HRESULT ShellLinkObject_Constructor(FolderItemImpl *item, IShellLinkDual2 **link)
897 HRESULT hr;
898 IPersistFile *persist_file = NULL;
899 ShellLinkObjectImpl *This;
901 TRACE("(%p, %p)\n", item, link);
903 *link = NULL;
905 This = heap_alloc(sizeof(*This));
906 if (!This) return E_OUTOFMEMORY;
907 This->IShellLinkDual2_iface.lpVtbl = &ShellLinkObjectVtbl;
908 This->ref = 1;
910 This->shell_link = NULL;
911 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
912 &IID_IShellLinkW, (LPVOID*)&This->shell_link);
913 if (FAILED(hr))
915 heap_free(This);
916 return hr;
919 hr = IShellLinkW_QueryInterface(This->shell_link, &IID_IPersistFile,
920 (LPVOID*)&persist_file);
921 if (FAILED(hr))
923 IShellLinkW_Release(This->shell_link);
924 heap_free(This);
925 return hr;
928 hr = IPersistFile_Load(persist_file, item->path, STGM_READ);
929 IPersistFile_Release(persist_file);
930 if (FAILED(hr))
932 IShellLinkW_Release(This->shell_link);
933 heap_free(This);
934 return hr;
937 *link = &This->IShellLinkDual2_iface;
938 return S_OK;
941 static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface,
942 REFIID riid, LPVOID *ppv)
944 FolderItemImpl *This = impl_from_FolderItem(iface);
946 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
948 if (!ppv) return E_INVALIDARG;
950 if (IsEqualIID(&IID_IUnknown, riid) ||
951 IsEqualIID(&IID_IDispatch, riid) ||
952 IsEqualIID(&IID_FolderItem, riid) ||
953 IsEqualIID(&IID_FolderItem2, riid))
954 *ppv = &This->FolderItem2_iface;
955 else
957 WARN("not implemented for %s\n", debugstr_guid(riid));
958 *ppv = NULL;
959 return E_NOINTERFACE;
961 IUnknown_AddRef((IUnknown*)*ppv);
962 return S_OK;
965 static ULONG WINAPI FolderItemImpl_AddRef(FolderItem2 *iface)
967 FolderItemImpl *This = impl_from_FolderItem(iface);
968 ULONG ref = InterlockedIncrement(&This->ref);
970 TRACE("(%p), new refcount=%i\n", iface, ref);
972 return ref;
975 static ULONG WINAPI FolderItemImpl_Release(FolderItem2 *iface)
977 FolderItemImpl *This = impl_from_FolderItem(iface);
978 ULONG ref = InterlockedDecrement(&This->ref);
980 TRACE("(%p), new refcount=%i\n", iface, ref);
982 if (!ref)
984 Folder3_Release(&This->folder->Folder3_iface);
985 heap_free(This->path);
986 heap_free(This);
988 return ref;
991 static HRESULT WINAPI FolderItemImpl_GetTypeInfoCount(FolderItem2 *iface,
992 UINT *pctinfo)
994 TRACE("(%p,%p)\n", iface, pctinfo);
996 *pctinfo = 1;
997 return S_OK;
1000 static HRESULT WINAPI FolderItemImpl_GetTypeInfo(FolderItem2 *iface, UINT iTInfo,
1001 LCID lcid, ITypeInfo **ppTInfo)
1003 HRESULT hr;
1005 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
1007 hr = get_typeinfo(FolderItem2_tid, ppTInfo);
1008 if (SUCCEEDED(hr))
1009 ITypeInfo_AddRef(*ppTInfo);
1010 return hr;
1013 static HRESULT WINAPI FolderItemImpl_GetIDsOfNames(FolderItem2 *iface,
1014 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
1015 DISPID *rgDispId)
1017 ITypeInfo *ti;
1018 HRESULT hr;
1020 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1021 rgDispId);
1023 hr = get_typeinfo(FolderItem2_tid, &ti);
1024 if (SUCCEEDED(hr))
1025 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1026 return hr;
1029 static HRESULT WINAPI FolderItemImpl_Invoke(FolderItem2 *iface,
1030 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
1031 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1032 UINT *puArgErr)
1034 FolderItemImpl *This = impl_from_FolderItem(iface);
1035 ITypeInfo *ti;
1036 HRESULT hr;
1038 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1039 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1041 hr = get_typeinfo(FolderItem2_tid, &ti);
1042 if (SUCCEEDED(hr))
1043 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1044 return hr;
1047 static HRESULT WINAPI FolderItemImpl_get_Application(FolderItem2 *iface, IDispatch **disp)
1049 FolderItemImpl *This = impl_from_FolderItem(iface);
1051 TRACE("(%p,%p)\n", iface, disp);
1053 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
1056 static HRESULT WINAPI FolderItemImpl_get_Parent(FolderItem2 *iface, IDispatch **disp)
1058 FolderItemImpl *This = impl_from_FolderItem(iface);
1060 TRACE("(%p,%p)\n", iface, disp);
1062 if (disp)
1064 *disp = (IDispatch *)&This->folder->Folder3_iface;
1065 IDispatch_AddRef(*disp);
1068 return S_OK;
1071 static HRESULT WINAPI FolderItemImpl_get_Name(FolderItem2 *iface, BSTR *name)
1073 FolderItemImpl *This = impl_from_FolderItem(iface);
1074 LPCITEMIDLIST last_part;
1075 IShellFolder2 *parent;
1076 HRESULT hr = S_OK;
1077 LPITEMIDLIST pidl;
1078 STRRET strret;
1080 TRACE("(%p,%p)\n", iface, name);
1082 *name = NULL;
1084 if (This->path)
1085 hr = SHParseDisplayName(This->path, NULL, &pidl, 0, NULL);
1086 else
1087 pidl = This->folder->pidl;
1089 if (FAILED(hr))
1090 return S_FALSE;
1092 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
1093 if (hr == S_OK)
1094 hr = IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_INFOLDER, &strret);
1096 IShellFolder2_Release(parent);
1098 if (hr == S_OK)
1099 hr = StrRetToBSTR(&strret, last_part, name);
1101 if (This->path)
1102 ILFree(pidl);
1104 return hr;
1107 static HRESULT WINAPI FolderItemImpl_put_Name(FolderItem2 *iface, BSTR bs)
1109 FIXME("(%p,%s)\n", iface, debugstr_w(bs));
1111 return E_NOTIMPL;
1114 static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path)
1116 FolderItemImpl *This = impl_from_FolderItem(iface);
1118 TRACE("(%p,%p)\n", iface, path);
1120 *path = SysAllocString(This->path ? This->path : This->folder->path);
1121 return *path ? S_OK : E_OUTOFMEMORY;
1124 static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface,
1125 IDispatch **ppid)
1127 IShellLinkDual2 *link;
1128 HRESULT hr;
1129 FolderItemImpl *This = impl_from_FolderItem(iface);
1131 TRACE("(%p,%p)\n", iface, ppid);
1133 *ppid = NULL;
1135 if (!(This->attributes & SFGAO_LINK))
1136 return E_NOTIMPL;
1138 hr = ShellLinkObject_Constructor(This, &link);
1139 if (hr != S_OK)
1140 return hr;
1142 *ppid = (IDispatch*)link;
1143 return S_OK;
1146 static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface,
1147 IDispatch **ppid)
1149 FIXME("(%p,%p)\n", iface, ppid);
1151 *ppid = NULL;
1152 return E_NOTIMPL;
1155 static HRESULT WINAPI FolderItemImpl_get_IsLink(FolderItem2 *iface, VARIANT_BOOL *b)
1157 FolderItemImpl *This = impl_from_FolderItem(iface);
1159 TRACE("(%p,%p)\n", iface, b);
1161 *b = This->attributes & SFGAO_LINK ? VARIANT_TRUE : VARIANT_FALSE;
1163 return S_OK;
1166 static HRESULT WINAPI FolderItemImpl_get_IsFolder(FolderItem2 *iface, VARIANT_BOOL *b)
1168 FolderItemImpl *This = impl_from_FolderItem(iface);
1170 TRACE("(%p,%p)\n", iface, b);
1172 *b = This->attributes & SFGAO_FOLDER ? VARIANT_TRUE : VARIANT_FALSE;
1174 return S_OK;
1177 static HRESULT WINAPI FolderItemImpl_get_IsFileSystem(FolderItem2 *iface, VARIANT_BOOL *b)
1179 FolderItemImpl *This = impl_from_FolderItem(iface);
1181 TRACE("(%p,%p)\n", iface, b);
1183 *b = This->attributes & SFGAO_FILESYSTEM ? VARIANT_TRUE : VARIANT_FALSE;
1185 return S_OK;
1188 static HRESULT WINAPI FolderItemImpl_get_IsBrowsable(FolderItem2 *iface, VARIANT_BOOL *b)
1190 FolderItemImpl *This = impl_from_FolderItem(iface);
1192 TRACE("(%p,%p)\n", iface, b);
1194 *b = This->attributes & SFGAO_BROWSABLE ? VARIANT_TRUE : VARIANT_FALSE;
1196 return S_OK;
1199 static HRESULT WINAPI FolderItemImpl_get_ModifyDate(FolderItem2 *iface,
1200 DATE *pdt)
1202 FIXME("(%p,%p)\n", iface, pdt);
1204 return E_NOTIMPL;
1207 static HRESULT WINAPI FolderItemImpl_put_ModifyDate(FolderItem2 *iface, DATE dt)
1209 FIXME("(%p,%f)\n", iface, dt);
1211 return E_NOTIMPL;
1214 static HRESULT WINAPI FolderItemImpl_get_Size(FolderItem2 *iface, LONG *pul)
1216 FIXME("(%p,%p)\n", iface, pul);
1218 return E_NOTIMPL;
1221 static HRESULT WINAPI FolderItemImpl_get_Type(FolderItem2 *iface, BSTR *pbs)
1223 FIXME("(%p,%p)\n", iface, pbs);
1225 *pbs = NULL;
1226 return E_NOTIMPL;
1229 static HRESULT WINAPI FolderItemImpl_Verbs(FolderItem2 *iface, FolderItemVerbs **verbs)
1231 FolderItemImpl *This = impl_from_FolderItem(iface);
1233 TRACE("(%p, %p)\n", iface, verbs);
1235 if (!verbs)
1236 return E_INVALIDARG;
1238 return FolderItemVerbs_Constructor(This->path ? This->path : This->folder->path, verbs);
1241 static HRESULT WINAPI FolderItemImpl_InvokeVerb(FolderItem2 *iface,
1242 VARIANT vVerb)
1244 FIXME("(%p)\n", iface);
1246 return E_NOTIMPL;
1249 static HRESULT WINAPI FolderItemImpl_InvokeVerbEx(FolderItem2 *iface, VARIANT verb, VARIANT args)
1251 FIXME("(%p): stub\n", iface);
1253 return E_NOTIMPL;
1256 static HRESULT WINAPI FolderItemImpl_ExtendedProperty(FolderItem2 *iface, BSTR propname, VARIANT *ret)
1258 FIXME("(%p)->(%s %p): stub\n", iface, debugstr_w(propname), ret);
1260 return E_NOTIMPL;
1263 static const FolderItem2Vtbl FolderItemImpl_Vtbl = {
1264 FolderItemImpl_QueryInterface,
1265 FolderItemImpl_AddRef,
1266 FolderItemImpl_Release,
1267 FolderItemImpl_GetTypeInfoCount,
1268 FolderItemImpl_GetTypeInfo,
1269 FolderItemImpl_GetIDsOfNames,
1270 FolderItemImpl_Invoke,
1271 FolderItemImpl_get_Application,
1272 FolderItemImpl_get_Parent,
1273 FolderItemImpl_get_Name,
1274 FolderItemImpl_put_Name,
1275 FolderItemImpl_get_Path,
1276 FolderItemImpl_get_GetLink,
1277 FolderItemImpl_get_GetFolder,
1278 FolderItemImpl_get_IsLink,
1279 FolderItemImpl_get_IsFolder,
1280 FolderItemImpl_get_IsFileSystem,
1281 FolderItemImpl_get_IsBrowsable,
1282 FolderItemImpl_get_ModifyDate,
1283 FolderItemImpl_put_ModifyDate,
1284 FolderItemImpl_get_Size,
1285 FolderItemImpl_get_Type,
1286 FolderItemImpl_Verbs,
1287 FolderItemImpl_InvokeVerb,
1288 FolderItemImpl_InvokeVerbEx,
1289 FolderItemImpl_ExtendedProperty
1292 static HRESULT FolderItem_Constructor(FolderImpl *folder, const WCHAR *path, FolderItem **item)
1294 PIDLIST_ABSOLUTE pidl;
1295 FolderItemImpl *This;
1297 TRACE("%s\n", debugstr_w(path));
1299 *item = NULL;
1301 This = heap_alloc_zero(sizeof(*This));
1302 if (!This)
1303 return E_OUTOFMEMORY;
1305 This->FolderItem2_iface.lpVtbl = &FolderItemImpl_Vtbl;
1306 This->ref = 1;
1307 if (path)
1308 This->path = strdupW(path);
1310 This->folder = folder;
1311 Folder3_AddRef(&folder->Folder3_iface);
1313 if (SHParseDisplayName(This->path, NULL, &pidl, ~0u, &This->attributes) == S_OK)
1314 ILFree(pidl);
1316 *item = (FolderItem *)&This->FolderItem2_iface;
1317 return S_OK;
1320 static HRESULT WINAPI FolderItemsImpl_QueryInterface(FolderItems3 *iface,
1321 REFIID riid, LPVOID *ppv)
1323 FolderItemsImpl *This = impl_from_FolderItems(iface);
1325 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1327 if (!ppv) return E_INVALIDARG;
1329 if (IsEqualIID(&IID_IUnknown, riid) ||
1330 IsEqualIID(&IID_IDispatch, riid) ||
1331 IsEqualIID(&IID_FolderItems, riid) ||
1332 IsEqualIID(&IID_FolderItems2, riid) ||
1333 IsEqualIID(&IID_FolderItems3, riid))
1334 *ppv = &This->FolderItems3_iface;
1335 else
1337 WARN("not implemented for %s\n", debugstr_guid(riid));
1338 *ppv = NULL;
1339 return E_NOINTERFACE;
1341 IUnknown_AddRef((IUnknown*)*ppv);
1342 return S_OK;
1345 static ULONG WINAPI FolderItemsImpl_AddRef(FolderItems3 *iface)
1347 FolderItemsImpl *This = impl_from_FolderItems(iface);
1348 ULONG ref = InterlockedIncrement(&This->ref);
1350 TRACE("(%p), new refcount=%i\n", iface, ref);
1352 return ref;
1355 static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
1357 FolderItemsImpl *This = impl_from_FolderItems(iface);
1358 ULONG ref = InterlockedDecrement(&This->ref);
1359 LONG i;
1361 TRACE("(%p), new refcount=%i\n", iface, ref);
1363 if (!ref)
1365 Folder3_Release(&This->folder->Folder3_iface);
1366 for (i = 0; i < This->item_count; i++)
1367 SysFreeString(This->item_names[i]);
1368 heap_free(This->item_names);
1369 heap_free(This);
1371 return ref;
1374 static HRESULT WINAPI FolderItemsImpl_GetTypeInfoCount(FolderItems3 *iface,
1375 UINT *count)
1377 TRACE("(%p,%p)\n", iface, count);
1379 *count = 1;
1380 return S_OK;
1383 static HRESULT WINAPI FolderItemsImpl_GetTypeInfo(FolderItems3 *iface,
1384 UINT type, LCID lcid, ITypeInfo **ppti)
1386 HRESULT hr;
1388 TRACE("(%p,%u,%d,%p)\n", iface, type, lcid, ppti);
1390 hr = get_typeinfo(FolderItems3_tid, ppti);
1391 if (SUCCEEDED(hr))
1392 ITypeInfo_AddRef(*ppti);
1393 return hr;
1396 static HRESULT WINAPI FolderItemsImpl_GetIDsOfNames(FolderItems3 *iface,
1397 REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid)
1399 ITypeInfo *ti;
1400 HRESULT hr;
1402 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), names, count, lcid, dispid);
1404 hr = get_typeinfo(FolderItems3_tid, &ti);
1405 if (SUCCEEDED(hr))
1406 hr = ITypeInfo_GetIDsOfNames(ti, names, count, dispid);
1407 return hr;
1410 static HRESULT WINAPI FolderItemsImpl_Invoke(FolderItems3 *iface,
1411 DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params,
1412 VARIANT *result, EXCEPINFO *ei, UINT *err)
1414 FolderItemsImpl *This = impl_from_FolderItems(iface);
1415 ITypeInfo *ti;
1416 HRESULT hr;
1418 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispid, shdebugstr_guid(riid), lcid, flags, params, result, ei, err);
1420 hr = get_typeinfo(FolderItems3_tid, &ti);
1421 if (SUCCEEDED(hr))
1422 hr = ITypeInfo_Invoke(ti, This, dispid, flags, params, result, ei, err);
1423 return hr;
1426 static BOOL shellfolder_exists(const WCHAR *path)
1428 PIDLIST_ABSOLUTE pidl = NULL;
1429 HRESULT hr;
1431 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
1432 ILFree(pidl);
1434 return SUCCEEDED(hr);
1437 static HRESULT WINAPI FolderItemsImpl_get_Count(FolderItems3 *iface, LONG *count)
1439 FolderItemsImpl *This = impl_from_FolderItems(iface);
1441 TRACE("(%p,%p)\n", iface, count);
1443 *count = shellfolder_exists(This->folder->path) ? This->item_count : 0;
1444 return S_OK;
1447 static HRESULT WINAPI FolderItemsImpl_get_Application(FolderItems3 *iface, IDispatch **disp)
1449 FolderItemsImpl *This = impl_from_FolderItems(iface);
1451 TRACE("(%p,%p)\n", iface, disp);
1453 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
1456 static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch **ppid)
1458 TRACE("(%p,%p)\n", iface, ppid);
1460 if (ppid)
1461 *ppid = NULL;
1463 return E_NOTIMPL;
1466 static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT var, FolderItem **item)
1468 FolderItemsImpl *This = impl_from_FolderItems(iface);
1469 BSTR display_name = NULL;
1470 VARIANT index;
1471 HRESULT hr;
1473 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&var), item);
1475 *item = NULL;
1477 if (!shellfolder_exists(This->folder->path))
1478 return S_FALSE;
1480 VariantInit(&index);
1481 if (FAILED(hr = VariantCopyInd(&index, &var)))
1482 return hr;
1484 switch (V_VT(&index))
1486 case VT_I2:
1487 VariantChangeType(&index, &index, 0, VT_I4);
1488 /* fall through */
1490 case VT_I4:
1491 if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
1492 return S_FALSE;
1494 display_name = SysAllocString(This->item_names[V_I4(&index)]);
1495 break;
1497 case VT_BSTR:
1499 LPITEMIDLIST pidl;
1500 STRRET strret;
1502 if (!V_BSTR(&index))
1503 return S_FALSE;
1505 hr = IShellFolder2_ParseDisplayName(This->folder->folder, NULL, NULL, V_BSTR(&index), NULL, &pidl, NULL);
1506 VariantClear(&index);
1507 if (FAILED(hr))
1508 return S_FALSE;
1510 if (IShellFolder2_GetDisplayNameOf(This->folder->folder, pidl, SHGDN_FORPARSING, &strret) == S_OK)
1511 StrRetToBSTR(&strret, pidl, &display_name);
1512 ILFree(pidl);
1513 break;
1515 case VT_ERROR:
1516 break;
1518 default:
1519 FIXME("Index type %#x not handled.\n", V_VT(&index));
1520 VariantClear(&index);
1521 /* fall through */
1522 case VT_EMPTY:
1523 return E_NOTIMPL;
1526 hr = FolderItem_Constructor(This->folder, display_name, item);
1527 SysFreeString(display_name);
1528 return hr;
1531 static HRESULT WINAPI FolderItemsImpl__NewEnum(FolderItems3 *iface, IUnknown **ppunk)
1533 FIXME("(%p,%p)\n", iface, ppunk);
1535 if (!ppunk)
1536 return E_INVALIDARG;
1538 *ppunk = NULL;
1539 return E_NOTIMPL;
1542 static HRESULT WINAPI FolderItemsImpl_InvokeVerbEx(FolderItems3 *iface, VARIANT verb, VARIANT args)
1544 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&verb), debugstr_variant(&args));
1546 return E_NOTIMPL;
1549 static HRESULT WINAPI FolderItemsImpl_Filter(FolderItems3 *iface, LONG flags, BSTR spec)
1551 FIXME("(%p,%d,%s)\n", iface, flags, wine_dbgstr_w(spec));
1553 return E_NOTIMPL;
1556 static HRESULT WINAPI FolderItemsImpl_get_Verbs(FolderItems3 *iface, FolderItemVerbs **ppfic)
1558 FIXME("(%p,%p)\n", iface, ppfic);
1560 if (!ppfic)
1561 return E_INVALIDARG;
1563 *ppfic = NULL;
1564 return E_NOTIMPL;
1567 static const FolderItems3Vtbl FolderItemsImpl_Vtbl = {
1568 FolderItemsImpl_QueryInterface,
1569 FolderItemsImpl_AddRef,
1570 FolderItemsImpl_Release,
1571 FolderItemsImpl_GetTypeInfoCount,
1572 FolderItemsImpl_GetTypeInfo,
1573 FolderItemsImpl_GetIDsOfNames,
1574 FolderItemsImpl_Invoke,
1575 FolderItemsImpl_get_Count,
1576 FolderItemsImpl_get_Application,
1577 FolderItemsImpl_get_Parent,
1578 FolderItemsImpl_Item,
1579 FolderItemsImpl__NewEnum,
1580 FolderItemsImpl_InvokeVerbEx,
1581 FolderItemsImpl_Filter,
1582 FolderItemsImpl_get_Verbs
1585 static void idlist_sort(LPITEMIDLIST *idlist, unsigned int l, unsigned int r, IShellFolder2 *folder)
1587 unsigned int m;
1589 if (l == r)
1590 return;
1592 if (r < l)
1594 idlist_sort(idlist, r, l, folder);
1595 return;
1598 m = (l + r) / 2;
1599 idlist_sort(idlist, l, m, folder);
1600 idlist_sort(idlist, m + 1, r, folder);
1602 /* join the two sides */
1603 while (l <= m && m < r)
1605 if ((short)IShellFolder2_CompareIDs(folder, 0, idlist[l], idlist[m + 1]) > 0)
1607 LPITEMIDLIST t = idlist[m + 1];
1608 memmove(&idlist[l + 1], &idlist[l], (m - l + 1) * sizeof(idlist[l]));
1609 idlist[l] = t;
1611 m++;
1613 l++;
1617 static HRESULT FolderItems_Constructor(FolderImpl *folder, FolderItems **ret)
1619 IEnumIDList *enumidlist;
1620 FolderItemsImpl *This;
1621 LPITEMIDLIST pidl;
1622 unsigned int i;
1623 HRESULT hr;
1625 TRACE("(%s,%p)\n", debugstr_w(folder->path), ret);
1627 *ret = NULL;
1629 This = heap_alloc_zero(sizeof(*This));
1630 if (!This)
1631 return E_OUTOFMEMORY;
1633 This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
1634 This->ref = 1;
1635 This->folder = folder;
1636 Folder3_AddRef(&folder->Folder3_iface);
1638 enumidlist = NULL;
1639 if (FAILED(hr = IShellFolder2_EnumObjects(folder->folder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1640 &enumidlist)))
1642 goto failed;
1645 while (IEnumIDList_Next(enumidlist, 1, &pidl, NULL) == S_OK)
1647 This->item_count++;
1648 ILFree(pidl);
1651 if (This->item_count)
1653 LPITEMIDLIST *pidls;
1654 ULONG fetched;
1656 pidls = heap_alloc(This->item_count * sizeof(*pidls));
1657 This->item_names = heap_alloc_zero(This->item_count * sizeof(*This->item_names));
1659 if (!pidls || !This->item_names)
1661 heap_free(pidls);
1662 heap_free(This->item_names);
1663 hr = E_OUTOFMEMORY;
1664 goto failed;
1667 IEnumIDList_Reset(enumidlist);
1668 if (IEnumIDList_Next(enumidlist, This->item_count, pidls, &fetched) == S_OK)
1669 idlist_sort(pidls, 0, This->item_count - 1, folder->folder);
1671 for (i = 0; i < This->item_count; i++)
1673 STRRET strret;
1675 if (IShellFolder2_GetDisplayNameOf(folder->folder, pidls[i], SHGDN_FORPARSING, &strret) == S_OK)
1676 StrRetToBSTR(&strret, pidls[i], &This->item_names[i]);
1678 ILFree(pidls[i]);
1680 heap_free(pidls);
1682 IEnumIDList_Release(enumidlist);
1684 *ret = (FolderItems *)&This->FolderItems3_iface;
1685 return S_OK;
1687 failed:
1688 if (enumidlist)
1689 IEnumIDList_Release(enumidlist);
1690 return hr;
1693 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
1694 LPVOID *ppv)
1696 FolderImpl *This = impl_from_Folder(iface);
1698 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1700 if (!ppv) return E_INVALIDARG;
1702 if (IsEqualIID(&IID_IUnknown, riid) ||
1703 IsEqualIID(&IID_IDispatch, riid) ||
1704 IsEqualIID(&IID_Folder, riid) ||
1705 IsEqualIID(&IID_Folder2, riid) ||
1706 IsEqualIID(&IID_Folder3, riid))
1707 *ppv = &This->Folder3_iface;
1708 else
1710 WARN("not implemented for %s\n", debugstr_guid(riid));
1711 *ppv = NULL;
1712 return E_NOINTERFACE;
1714 IUnknown_AddRef((IUnknown*)*ppv);
1715 return S_OK;
1718 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
1720 FolderImpl *This = impl_from_Folder(iface);
1721 ULONG ref = InterlockedIncrement(&This->ref);
1723 TRACE("(%p), new refcount=%i\n", iface, ref);
1725 return ref;
1728 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
1730 FolderImpl *This = impl_from_Folder(iface);
1731 ULONG ref = InterlockedDecrement(&This->ref);
1733 TRACE("(%p), new refcount=%i\n", iface, ref);
1735 if (!ref)
1737 ILFree(This->pidl);
1738 SysFreeString(This->path);
1739 IShellFolder2_Release(This->folder);
1740 IDispatch_Release(This->application);
1741 heap_free(This);
1743 return ref;
1746 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
1748 TRACE("(%p,%p)\n", iface, pctinfo);
1750 *pctinfo = 1;
1751 return S_OK;
1754 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
1755 LCID lcid, ITypeInfo **ppTInfo)
1757 HRESULT hr;
1759 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
1761 hr = get_typeinfo(Folder3_tid, ppTInfo);
1762 if (SUCCEEDED(hr))
1763 ITypeInfo_AddRef(*ppTInfo);
1765 return hr;
1768 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
1769 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1771 ITypeInfo *ti;
1772 HRESULT hr;
1774 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1775 rgDispId);
1777 hr = get_typeinfo(Folder3_tid, &ti);
1778 if (SUCCEEDED(hr))
1779 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1780 return hr;
1783 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
1784 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1785 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1787 FolderImpl *This = impl_from_Folder(iface);
1788 ITypeInfo *ti;
1789 HRESULT hr;
1791 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1792 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1794 hr = get_typeinfo(Folder3_tid, &ti);
1795 if (SUCCEEDED(hr))
1796 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1797 return hr;
1800 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *title)
1802 FolderImpl *This = impl_from_Folder(iface);
1803 PCUITEMID_CHILD last_part;
1804 IShellFolder2 *parent;
1805 SHELLDETAILS sd;
1806 HRESULT hr;
1808 TRACE("(%p,%p)\n", iface, title);
1810 *title = NULL;
1812 if (FAILED(hr = SHBindToParent(This->pidl, &IID_IShellFolder2, (void **)&parent, &last_part)))
1813 return hr;
1815 hr = IShellFolder2_GetDetailsOf(parent, last_part, 0, &sd);
1816 IShellFolder2_Release(parent);
1817 if (FAILED(hr))
1818 return hr;
1820 return StrRetToBSTR(&sd.str, last_part, title);
1823 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
1825 FolderImpl *This = impl_from_Folder(iface);
1827 TRACE("(%p,%p)\n", iface, disp);
1829 if (!disp)
1830 return E_INVALIDARG;
1832 *disp = This->application;
1833 IDispatch_AddRef(*disp);
1835 return S_OK;
1838 static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **disp)
1840 TRACE("(%p,%p)\n", iface, disp);
1842 if (disp)
1843 *disp = NULL;
1844 return E_NOTIMPL;
1847 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
1849 FIXME("(%p,%p)\n", iface, ppsf);
1851 *ppsf = NULL;
1852 return E_NOTIMPL;
1855 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
1857 FolderImpl *This = impl_from_Folder(iface);
1859 TRACE("(%p,%p)\n", iface, ppid);
1861 return FolderItems_Constructor(This, ppid);
1864 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
1866 FolderImpl *This = impl_from_Folder(iface);
1867 LPITEMIDLIST pidl;
1868 STRRET strret;
1869 HRESULT hr;
1870 BSTR path;
1872 TRACE("(%p,%s,%p)\n", iface, debugstr_w(name), item);
1874 *item = NULL;
1876 if (FAILED(IShellFolder2_ParseDisplayName(This->folder, NULL, NULL, name, NULL, &pidl, NULL)))
1877 return S_FALSE;
1879 if ((hr = IShellFolder2_GetDisplayNameOf(This->folder, pidl, SHGDN_FORPARSING, &strret)) == S_OK)
1880 hr = StrRetToBSTR(&strret, pidl, &path);
1882 ILFree(pidl);
1883 if (hr != S_OK)
1884 return S_FALSE;
1886 hr = FolderItem_Constructor(This, path, item);
1887 SysFreeString(path);
1888 return hr;
1891 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR name, VARIANT options)
1893 FIXME("(%p,%s,%s)\n", iface, debugstr_w(name), debugstr_variant(&options));
1895 return E_NOTIMPL;
1898 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT item, VARIANT options)
1900 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1902 return E_NOTIMPL;
1905 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT item, VARIANT options)
1907 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1909 return E_NOTIMPL;
1912 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT item, int column, BSTR *str)
1914 FIXME("(%p,%s,%d,%p)\n", iface, debugstr_variant(&item), column, str);
1916 *str = NULL;
1917 return E_NOTIMPL;
1920 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **item)
1922 FolderImpl *This = impl_from_Folder(iface);
1924 TRACE("(%p,%p)\n", iface, item);
1926 return FolderItem_Constructor(This, NULL, item);
1929 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
1931 FIXME("(%p,%p)\n", iface, pul);
1933 return E_NOTIMPL;
1936 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
1938 FIXME("(%p)\n", iface);
1940 return E_NOTIMPL;
1943 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
1944 VARIANT_BOOL *pbHaveToShowWebViewBarricade)
1946 FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
1948 return E_NOTIMPL;
1951 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
1953 FIXME("(%p)\n", iface);
1955 return E_NOTIMPL;
1958 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
1959 VARIANT_BOOL *pbShowWebViewBarricade)
1961 FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
1963 return E_NOTIMPL;
1966 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
1967 VARIANT_BOOL bShowWebViewBarricade)
1969 FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
1971 return E_NOTIMPL;
1974 static const Folder3Vtbl FolderImpl_Vtbl = {
1975 FolderImpl_QueryInterface,
1976 FolderImpl_AddRef,
1977 FolderImpl_Release,
1978 FolderImpl_GetTypeInfoCount,
1979 FolderImpl_GetTypeInfo,
1980 FolderImpl_GetIDsOfNames,
1981 FolderImpl_Invoke,
1982 FolderImpl_get_Title,
1983 FolderImpl_get_Application,
1984 FolderImpl_get_Parent,
1985 FolderImpl_get_ParentFolder,
1986 FolderImpl_Items,
1987 FolderImpl_ParseName,
1988 FolderImpl_NewFolder,
1989 FolderImpl_MoveHere,
1990 FolderImpl_CopyHere,
1991 FolderImpl_GetDetailsOf,
1992 FolderImpl_get_Self,
1993 FolderImpl_get_OfflineStatus,
1994 FolderImpl_Synchronize,
1995 FolderImpl_get_HaveToShowWebViewBarricade,
1996 FolderImpl_DismissedWebViewBarricade,
1997 FolderImpl_get_ShowWebViewBarricade,
1998 FolderImpl_put_ShowWebViewBarricade
2001 static HRESULT Folder_Constructor(IShellFolder2 *folder, LPITEMIDLIST pidl, Folder **ret)
2003 PCUITEMID_CHILD last_part;
2004 IShellFolder2 *parent;
2005 FolderImpl *This;
2006 STRRET strret;
2007 HRESULT hr;
2009 *ret = NULL;
2011 This = heap_alloc(sizeof(*This));
2012 if (!This)
2013 return E_OUTOFMEMORY;
2015 This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
2016 This->ref = 1;
2017 This->folder = folder;
2018 This->pidl = ILClone(pidl);
2020 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
2021 IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_FORPARSING, &strret);
2022 StrRetToBSTR(&strret, last_part, &This->path);
2023 IShellFolder2_Release(parent);
2025 IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
2027 *ret = (Folder *)&This->Folder3_iface;
2028 return hr;
2031 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch6 *iface,
2032 REFIID riid, LPVOID *ppv)
2034 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2036 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
2038 if (!ppv) return E_INVALIDARG;
2040 if (IsEqualIID(&IID_IUnknown, riid) ||
2041 IsEqualIID(&IID_IDispatch, riid) ||
2042 IsEqualIID(&IID_IShellDispatch, riid) ||
2043 IsEqualIID(&IID_IShellDispatch2, riid) ||
2044 IsEqualIID(&IID_IShellDispatch3, riid) ||
2045 IsEqualIID(&IID_IShellDispatch4, riid) ||
2046 IsEqualIID(&IID_IShellDispatch5, riid) ||
2047 IsEqualIID(&IID_IShellDispatch6, riid))
2048 *ppv = &This->IShellDispatch6_iface;
2049 else
2051 WARN("not implemented for %s\n", debugstr_guid(riid));
2052 *ppv = NULL;
2053 return E_NOINTERFACE;
2056 IShellDispatch6_AddRef(iface);
2057 return S_OK;
2060 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch6 *iface)
2062 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2063 ULONG ref = InterlockedIncrement(&This->ref);
2065 TRACE("(%p), new refcount=%i\n", iface, ref);
2067 return ref;
2070 static ULONG WINAPI ShellDispatch_Release(IShellDispatch6 *iface)
2072 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2073 ULONG ref = InterlockedDecrement(&This->ref);
2075 TRACE("(%p), new refcount=%i\n", iface, ref);
2077 if (!ref)
2078 heap_free(This);
2080 return ref;
2083 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch6 *iface,
2084 UINT *pctinfo)
2086 TRACE("(%p,%p)\n", iface, pctinfo);
2088 *pctinfo = 1;
2089 return S_OK;
2092 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch6 *iface,
2093 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
2095 HRESULT hr;
2097 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
2099 hr = get_typeinfo(IShellDispatch6_tid, ppTInfo);
2100 if (SUCCEEDED(hr))
2101 ITypeInfo_AddRef(*ppTInfo);
2102 return hr;
2105 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch6 *iface,
2106 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2108 ITypeInfo *ti;
2109 HRESULT hr;
2111 TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
2112 rgDispId);
2114 hr = get_typeinfo(IShellDispatch6_tid, &ti);
2115 if (SUCCEEDED(hr))
2116 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
2117 return hr;
2120 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch6 *iface,
2121 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
2122 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
2123 UINT *puArgErr)
2125 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2126 ITypeInfo *ti;
2127 HRESULT hr;
2129 TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
2130 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2132 hr = get_typeinfo(IShellDispatch6_tid, &ti);
2133 if (SUCCEEDED(hr))
2134 hr = ITypeInfo_Invoke(ti, &This->IShellDispatch6_iface, dispIdMember, wFlags, pDispParams,
2135 pVarResult, pExcepInfo, puArgErr);
2136 return hr;
2139 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch6 *iface, IDispatch **disp)
2141 TRACE("(%p,%p)\n", iface, disp);
2143 if (!disp)
2144 return E_INVALIDARG;
2146 *disp = (IDispatch *)iface;
2147 IDispatch_AddRef(*disp);
2148 return S_OK;
2151 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch6 *iface, IDispatch **disp)
2153 TRACE("(%p,%p)\n", iface, disp);
2155 if (disp)
2157 *disp = (IDispatch *)iface;
2158 IDispatch_AddRef(*disp);
2161 return S_OK;
2164 static HRESULT create_folder_for_pidl(LPITEMIDLIST pidl, Folder **ret)
2166 IShellFolder2 *folder;
2167 IShellFolder *desktop;
2168 HRESULT hr;
2170 *ret = NULL;
2172 if (FAILED(hr = SHGetDesktopFolder(&desktop)))
2173 return hr;
2175 if (_ILIsDesktop(pidl))
2176 hr = IShellFolder_QueryInterface(desktop, &IID_IShellFolder2, (void **)&folder);
2177 else
2178 hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder2, (void **)&folder);
2180 IShellFolder_Release(desktop);
2182 if (FAILED(hr))
2183 return S_FALSE;
2185 return Folder_Constructor(folder, pidl, ret);
2188 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch6 *iface,
2189 VARIANT dir, Folder **ret)
2191 LPITEMIDLIST pidl;
2192 HRESULT hr;
2194 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&dir), ret);
2196 *ret = NULL;
2198 switch (V_VT(&dir))
2200 case VT_I2:
2201 if (FAILED(hr = VariantChangeType(&dir, &dir, 0, VT_I4)))
2202 return hr;
2204 /* fallthrough */
2205 case VT_I4:
2206 if (FAILED(hr = SHGetFolderLocation(NULL, V_I4(&dir), NULL, 0, &pidl)))
2207 return S_FALSE;
2209 break;
2210 case VT_BSTR:
2211 if (FAILED(hr = SHParseDisplayName(V_BSTR(&dir), NULL, &pidl, 0, NULL)))
2212 return S_FALSE;
2214 break;
2215 default:
2216 WARN("Ignoring directory value %s\n", debugstr_variant(&dir));
2217 return S_FALSE;
2220 hr = create_folder_for_pidl(pidl, ret);
2221 ILFree(pidl);
2223 return hr;
2226 static BOOL is_optional_argument(const VARIANT *arg)
2228 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
2231 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch6 *iface,
2232 LONG hwnd, BSTR title, LONG options, VARIANT rootfolder, Folder **folder)
2234 PIDLIST_ABSOLUTE selection;
2235 BROWSEINFOW bi = { 0 };
2236 HRESULT hr;
2238 TRACE("(%p,%x,%s,%x,%s,%p)\n", iface, hwnd, debugstr_w(title), options, debugstr_variant(&rootfolder), folder);
2240 *folder = NULL;
2242 if (!is_optional_argument(&rootfolder))
2243 FIXME("root folder is ignored\n");
2245 bi.hwndOwner = LongToHandle(hwnd);
2246 bi.lpszTitle = title;
2247 bi.ulFlags = options;
2249 selection = SHBrowseForFolderW(&bi);
2250 if (selection)
2252 hr = create_folder_for_pidl(selection, folder);
2253 ILFree(selection);
2255 else
2256 hr = S_FALSE;
2258 return hr;
2261 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch6 *iface,
2262 IDispatch **ppid)
2264 FIXME("(%p,%p)\n", iface, ppid);
2266 *ppid = NULL;
2267 return E_NOTIMPL;
2270 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch6 *iface, VARIANT dir)
2272 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
2274 return E_NOTIMPL;
2277 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch6 *iface, VARIANT dir)
2279 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
2281 return E_NOTIMPL;
2284 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch6 *iface)
2286 FIXME("(%p)\n", iface);
2288 return E_NOTIMPL;
2291 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch6 *iface)
2293 FIXME("(%p)\n", iface);
2295 return E_NOTIMPL;
2298 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch6 *iface)
2300 FIXME("(%p)\n", iface);
2302 return E_NOTIMPL;
2305 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch6 *iface)
2307 FIXME("(%p)\n", iface);
2309 return E_NOTIMPL;
2312 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch6 *iface)
2314 FIXME("(%p)\n", iface);
2316 return E_NOTIMPL;
2319 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch6 *iface)
2321 FIXME("(%p)\n", iface);
2323 return E_NOTIMPL;
2326 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch6 *iface)
2328 FIXME("(%p)\n", iface);
2330 return E_NOTIMPL;
2333 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch6 *iface)
2335 FIXME("(%p)\n", iface);
2337 return E_NOTIMPL;
2340 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch6 *iface)
2342 FIXME("(%p)\n", iface);
2344 return E_NOTIMPL;
2347 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch6 *iface)
2349 FIXME("(%p)\n", iface);
2351 return E_NOTIMPL;
2354 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch6 *iface)
2356 FIXME("(%p)\n", iface);
2358 return E_NOTIMPL;
2361 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch6 *iface)
2363 FIXME("(%p)\n", iface);
2365 return E_NOTIMPL;
2368 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch6 *iface)
2370 FIXME("(%p)\n", iface);
2372 return E_NOTIMPL;
2375 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch6 *iface)
2377 FIXME("(%p)\n", iface);
2379 return E_NOTIMPL;
2382 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch6 *iface)
2384 FIXME("(%p)\n", iface);
2386 return E_NOTIMPL;
2389 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch6 *iface,
2390 BSTR szDir)
2392 FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
2394 return E_NOTIMPL;
2397 static HRESULT WINAPI ShellDispatch_IsRestricted(IShellDispatch6 *iface, BSTR group, BSTR restriction, LONG *value)
2399 FIXME("(%s, %s, %p): stub\n", debugstr_w(group), debugstr_w(restriction), value);
2400 return E_NOTIMPL;
2403 static HRESULT WINAPI ShellDispatch_ShellExecute(IShellDispatch6 *iface,
2404 BSTR file, VARIANT v_args, VARIANT v_dir, VARIANT v_op, VARIANT v_show)
2406 VARIANT args_str, dir_str, op_str, show_int;
2407 WCHAR *args = NULL, *dir = NULL, *op = NULL;
2408 INT show = 0;
2409 HINSTANCE ret;
2411 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file), debugstr_variant(&v_args),
2412 debugstr_variant(&v_dir), debugstr_variant(&v_op), debugstr_variant(&v_show));
2414 VariantInit(&args_str);
2415 VariantChangeType(&args_str, &v_args, 0, VT_BSTR);
2416 if (V_VT(&args_str) == VT_BSTR)
2417 args = V_BSTR(&args_str);
2419 VariantInit(&dir_str);
2420 VariantChangeType(&dir_str, &v_dir, 0, VT_BSTR);
2421 if (V_VT(&dir_str) == VT_BSTR)
2422 dir = V_BSTR(&dir_str);
2424 VariantInit(&op_str);
2425 VariantChangeType(&op_str, &v_op, 0, VT_BSTR);
2426 if (V_VT(&op_str) == VT_BSTR)
2427 op = V_BSTR(&op_str);
2429 VariantInit(&show_int);
2430 VariantChangeType(&show_int, &v_show, 0, VT_I4);
2431 if (V_VT(&show_int) == VT_I4)
2432 show = V_I4(&show_int);
2434 ret = ShellExecuteW(NULL, op, file, args, dir, show);
2436 VariantClear(&args_str);
2437 VariantClear(&dir_str);
2438 VariantClear(&op_str);
2439 VariantClear(&show_int);
2441 return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE;
2444 static HRESULT WINAPI ShellDispatch_FindPrinter(IShellDispatch6 *iface, BSTR name, BSTR location, BSTR model)
2446 FIXME("(%s, %s, %s): stub\n", debugstr_w(name), debugstr_w(location), debugstr_w(model));
2447 return E_NOTIMPL;
2450 static HRESULT WINAPI ShellDispatch_GetSystemInformation(IShellDispatch6 *iface, BSTR name, VARIANT *ret)
2452 FIXME("(%s, %p): stub\n", debugstr_w(name), ret);
2453 return E_NOTIMPL;
2456 static HRESULT WINAPI ShellDispatch_ServiceStart(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2458 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2459 return E_NOTIMPL;
2462 static HRESULT WINAPI ShellDispatch_ServiceStop(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2464 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2465 return E_NOTIMPL;
2468 static HRESULT WINAPI ShellDispatch_IsServiceRunning(IShellDispatch6 *iface, BSTR name, VARIANT *running)
2470 SERVICE_STATUS_PROCESS status;
2471 SC_HANDLE scm, service;
2472 DWORD dummy;
2474 TRACE("(%s, %p)\n", debugstr_w(name), running);
2476 V_VT(running) = VT_BOOL;
2477 V_BOOL(running) = VARIANT_FALSE;
2479 scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
2480 if (!scm)
2482 ERR("failed to connect to service manager\n");
2483 return S_OK;
2486 service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS);
2487 if (!service)
2489 ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError());
2490 CloseServiceHandle(scm);
2491 return S_OK;
2494 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status,
2495 sizeof(SERVICE_STATUS_PROCESS), &dummy))
2497 TRACE("failed to query service status (%u)\n", GetLastError());
2498 CloseServiceHandle(service);
2499 CloseServiceHandle(scm);
2500 return S_OK;
2503 if (status.dwCurrentState == SERVICE_RUNNING)
2504 V_BOOL(running) = VARIANT_TRUE;
2506 CloseServiceHandle(service);
2507 CloseServiceHandle(scm);
2509 return S_OK;
2512 static HRESULT WINAPI ShellDispatch_CanStartStopService(IShellDispatch6 *iface, BSTR service, VARIANT *ret)
2514 FIXME("(%s, %p): stub\n", debugstr_w(service), ret);
2515 return E_NOTIMPL;
2518 static HRESULT WINAPI ShellDispatch_ShowBrowserBar(IShellDispatch6 *iface, BSTR clsid, VARIANT show, VARIANT *ret)
2520 FIXME("(%s, %s, %p): stub\n", debugstr_w(clsid), debugstr_variant(&show), ret);
2521 return E_NOTIMPL;
2524 static HRESULT WINAPI ShellDispatch_AddToRecent(IShellDispatch6 *iface, VARIANT file, BSTR category)
2526 FIXME("(%s, %s): stub\n", debugstr_variant(&file), debugstr_w(category));
2527 return E_NOTIMPL;
2530 static HRESULT WINAPI ShellDispatch_WindowsSecurity(IShellDispatch6 *iface)
2532 FIXME("stub\n");
2533 return E_NOTIMPL;
2536 static HRESULT WINAPI ShellDispatch_ToggleDesktop(IShellDispatch6 *iface)
2538 FIXME("stub\n");
2539 return E_NOTIMPL;
2542 static HRESULT WINAPI ShellDispatch_ExplorerPolicy(IShellDispatch6 *iface, BSTR policy, VARIANT *value)
2544 FIXME("(%s, %p): stub\n", debugstr_w(policy), value);
2545 return E_NOTIMPL;
2548 static HRESULT WINAPI ShellDispatch_GetSetting(IShellDispatch6 *iface, LONG setting, VARIANT_BOOL *result)
2550 FIXME("(%d %p): stub\n", setting, result);
2551 return E_NOTIMPL;
2554 static HRESULT WINAPI ShellDispatch_WindowSwitcher(IShellDispatch6 *iface)
2556 FIXME("stub\n");
2557 return E_NOTIMPL;
2560 static HRESULT WINAPI ShellDispatch_SearchCommand(IShellDispatch6 *iface)
2562 FIXME("stub\n");
2563 return E_NOTIMPL;
2566 static const IShellDispatch6Vtbl ShellDispatchVtbl = {
2567 ShellDispatch_QueryInterface,
2568 ShellDispatch_AddRef,
2569 ShellDispatch_Release,
2570 ShellDispatch_GetTypeInfoCount,
2571 ShellDispatch_GetTypeInfo,
2572 ShellDispatch_GetIDsOfNames,
2573 ShellDispatch_Invoke,
2574 ShellDispatch_get_Application,
2575 ShellDispatch_get_Parent,
2576 ShellDispatch_NameSpace,
2577 ShellDispatch_BrowseForFolder,
2578 ShellDispatch_Windows,
2579 ShellDispatch_Open,
2580 ShellDispatch_Explore,
2581 ShellDispatch_MinimizeAll,
2582 ShellDispatch_UndoMinimizeALL,
2583 ShellDispatch_FileRun,
2584 ShellDispatch_CascadeWindows,
2585 ShellDispatch_TileVertically,
2586 ShellDispatch_TileHorizontally,
2587 ShellDispatch_ShutdownWindows,
2588 ShellDispatch_Suspend,
2589 ShellDispatch_EjectPC,
2590 ShellDispatch_SetTime,
2591 ShellDispatch_TrayProperties,
2592 ShellDispatch_Help,
2593 ShellDispatch_FindFiles,
2594 ShellDispatch_FindComputer,
2595 ShellDispatch_RefreshMenu,
2596 ShellDispatch_ControlPanelItem,
2597 ShellDispatch_IsRestricted,
2598 ShellDispatch_ShellExecute,
2599 ShellDispatch_FindPrinter,
2600 ShellDispatch_GetSystemInformation,
2601 ShellDispatch_ServiceStart,
2602 ShellDispatch_ServiceStop,
2603 ShellDispatch_IsServiceRunning,
2604 ShellDispatch_CanStartStopService,
2605 ShellDispatch_ShowBrowserBar,
2606 ShellDispatch_AddToRecent,
2607 ShellDispatch_WindowsSecurity,
2608 ShellDispatch_ToggleDesktop,
2609 ShellDispatch_ExplorerPolicy,
2610 ShellDispatch_GetSetting,
2611 ShellDispatch_WindowSwitcher,
2612 ShellDispatch_SearchCommand
2615 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *outer, REFIID riid, void **ppv)
2617 ShellDispatch *This;
2618 HRESULT ret;
2620 TRACE("(%p, %s)\n", outer, debugstr_guid(riid));
2622 *ppv = NULL;
2624 if (outer) return CLASS_E_NOAGGREGATION;
2626 This = heap_alloc(sizeof(*This));
2627 if (!This) return E_OUTOFMEMORY;
2628 This->IShellDispatch6_iface.lpVtbl = &ShellDispatchVtbl;
2629 This->ref = 1;
2631 ret = IShellDispatch6_QueryInterface(&This->IShellDispatch6_iface, riid, ppv);
2632 IShellDispatch6_Release(&This->IShellDispatch6_iface);
2633 return ret;