cmd: DIR command outputs free space for the path.
[wine.git] / dlls / shell32 / shelldispatch.c
blobdd58c755c616a0bbbbc07221526ee6eac8937978
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 <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winsvc.h"
29 #include "shlwapi.h"
30 #include "shlobj.h"
31 #include "shldisp.h"
32 #include "debughlp.h"
34 #include "shell32_main.h"
35 #include "pidl.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 static ITypeLib *typelib;
42 static const IID * const tid_ids[] =
44 &IID_NULL,
45 &IID_IShellDispatch6,
46 &IID_IShellFolderViewDual3,
47 &IID_Folder3,
48 &IID_FolderItem2,
49 &IID_FolderItems3,
50 &IID_FolderItemVerb,
51 &IID_FolderItemVerbs,
52 &IID_IShellLinkDual2
54 static ITypeInfo *typeinfos[LAST_tid];
56 typedef struct {
57 IShellDispatch6 IShellDispatch6_iface;
58 LONG ref;
59 } ShellDispatch;
61 typedef struct {
62 Folder3 Folder3_iface;
63 LONG ref;
64 IDispatch *application;
65 IShellFolder2 *folder;
66 PIDLIST_ABSOLUTE pidl;
67 BSTR path;
68 } FolderImpl;
70 typedef struct {
71 FolderItems3 FolderItems3_iface;
72 LONG ref;
73 FolderImpl *folder;
74 BSTR *item_names;
75 LONG item_count;
76 } FolderItemsImpl;
78 typedef struct {
79 FolderItem2 FolderItem2_iface;
80 LONG ref;
81 FolderImpl *folder;
82 WCHAR *path; /* if NULL, folder path is used */
83 DWORD attributes;
84 } FolderItemImpl;
86 typedef struct {
87 FolderItemVerbs FolderItemVerbs_iface;
88 LONG ref;
90 IContextMenu *contextmenu;
91 HMENU hMenu;
92 LONG count;
93 } FolderItemVerbsImpl;
95 typedef struct {
96 FolderItemVerb FolderItemVerb_iface;
97 LONG ref;
99 IContextMenu *contextmenu;
100 BSTR name;
101 } FolderItemVerbImpl;
103 typedef struct {
104 IShellLinkDual2 IShellLinkDual2_iface;
105 LONG ref;
107 IShellLinkW *shell_link;
108 } ShellLinkObjectImpl;
110 static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface)
112 return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch6_iface);
115 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
117 return CONTAINING_RECORD(iface, FolderImpl, Folder3_iface);
120 static inline FolderItemsImpl *impl_from_FolderItems(FolderItems3 *iface)
122 return CONTAINING_RECORD(iface, FolderItemsImpl, FolderItems3_iface);
125 static inline FolderItemImpl *impl_from_FolderItem(FolderItem2 *iface)
127 return CONTAINING_RECORD(iface, FolderItemImpl, FolderItem2_iface);
130 static inline FolderItemVerbsImpl *impl_from_FolderItemVerbs(FolderItemVerbs *iface)
132 return CONTAINING_RECORD(iface, FolderItemVerbsImpl, FolderItemVerbs_iface);
135 static inline FolderItemVerbImpl *impl_from_FolderItemVerb(FolderItemVerb *iface)
137 return CONTAINING_RECORD(iface, FolderItemVerbImpl, FolderItemVerb_iface);
140 static inline ShellLinkObjectImpl *impl_from_IShellLinkDual(IShellLinkDual2 *iface)
142 return CONTAINING_RECORD(iface, ShellLinkObjectImpl, IShellLinkDual2_iface);
145 static HRESULT load_typelib(void)
147 ITypeLib *tl;
148 HRESULT hr;
150 hr = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
151 if (FAILED(hr)) {
152 ERR("LoadRegTypeLib failed: %08lx\n", hr);
153 return hr;
156 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
157 ITypeLib_Release(tl);
158 return hr;
161 void release_typelib(void)
163 unsigned i;
165 if (!typelib)
166 return;
168 for (i = 0; i < ARRAY_SIZE(typeinfos); i++)
169 if (typeinfos[i])
170 ITypeInfo_Release(typeinfos[i]);
172 ITypeLib_Release(typelib);
175 HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
177 HRESULT hr;
179 if (!typelib)
180 hr = load_typelib();
181 if (!typelib)
182 return hr;
184 if (!typeinfos[tid])
186 ITypeInfo *ti;
188 hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
189 if (FAILED(hr))
191 ERR("GetTypeInfoOfGuid(%s) failed: %08lx\n", debugstr_guid(tid_ids[tid]), hr);
192 return hr;
195 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
196 ITypeInfo_Release(ti);
199 *typeinfo = typeinfos[tid];
200 return S_OK;
203 /* FolderItemVerb */
204 static HRESULT WINAPI FolderItemVerbImpl_QueryInterface(FolderItemVerb *iface,
205 REFIID riid, void **ppv)
207 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
209 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
211 if (IsEqualIID(&IID_IUnknown, riid) ||
212 IsEqualIID(&IID_IDispatch, riid) ||
213 IsEqualIID(&IID_FolderItemVerb, riid))
214 *ppv = &This->FolderItemVerb_iface;
215 else
217 WARN("not implemented for %s\n", debugstr_guid(riid));
218 *ppv = NULL;
219 return E_NOINTERFACE;
222 IUnknown_AddRef((IUnknown*)*ppv);
223 return S_OK;
226 static ULONG WINAPI FolderItemVerbImpl_AddRef(FolderItemVerb *iface)
228 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
229 ULONG ref = InterlockedIncrement(&This->ref);
231 TRACE("(%p), new refcount=%li\n", iface, ref);
233 return ref;
236 static ULONG WINAPI FolderItemVerbImpl_Release(FolderItemVerb *iface)
238 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
239 ULONG ref = InterlockedDecrement(&This->ref);
241 TRACE("(%p), new refcount=%li\n", iface, ref);
243 if (!ref)
245 IContextMenu_Release(This->contextmenu);
246 SysFreeString(This->name);
247 free(This);
250 return ref;
253 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfoCount(FolderItemVerb *iface, UINT *pctinfo)
255 TRACE("(%p,%p)\n", iface, pctinfo);
256 *pctinfo = 1;
257 return S_OK;
260 static HRESULT WINAPI FolderItemVerbImpl_GetTypeInfo(FolderItemVerb *iface, UINT iTInfo,
261 LCID lcid, ITypeInfo **ppTInfo)
263 HRESULT hr;
265 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
267 hr = get_typeinfo(FolderItemVerb_tid, ppTInfo);
268 if (SUCCEEDED(hr))
269 ITypeInfo_AddRef(*ppTInfo);
270 return hr;
273 static HRESULT WINAPI FolderItemVerbImpl_GetIDsOfNames(FolderItemVerb *iface,
274 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
276 ITypeInfo *ti;
277 HRESULT hr;
279 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
280 rgDispId);
282 hr = get_typeinfo(FolderItemVerb_tid, &ti);
283 if (SUCCEEDED(hr))
284 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
285 return hr;
288 static HRESULT WINAPI FolderItemVerbImpl_Invoke(FolderItemVerb *iface,
289 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
290 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
291 UINT *puArgErr)
293 ITypeInfo *ti;
294 HRESULT hr;
296 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
297 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
299 hr = get_typeinfo(FolderItemVerb_tid, &ti);
300 if (SUCCEEDED(hr))
301 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
302 return hr;
305 static HRESULT WINAPI FolderItemVerbImpl_get_Application(FolderItemVerb *iface, IDispatch **disp)
307 TRACE("(%p, %p)\n", iface, disp);
309 if (disp)
310 *disp = NULL;
311 return E_NOTIMPL;
314 static HRESULT WINAPI FolderItemVerbImpl_get_Parent(FolderItemVerb *iface, IDispatch **disp)
316 TRACE("(%p, %p)\n", iface, disp);
318 if (disp)
319 *disp = NULL;
320 return E_NOTIMPL;
323 static HRESULT WINAPI FolderItemVerbImpl_get_Name(FolderItemVerb *iface, BSTR *name)
325 FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface);
327 TRACE("(%p, %p)\n", iface, name);
329 *name = SysAllocString(This->name);
330 return *name ? S_OK : E_OUTOFMEMORY;
333 static HRESULT WINAPI FolderItemVerbImpl_DoIt(FolderItemVerb *iface)
335 FIXME("(%p)\n", iface);
336 return E_NOTIMPL;
339 static FolderItemVerbVtbl folderitemverbvtbl = {
340 FolderItemVerbImpl_QueryInterface,
341 FolderItemVerbImpl_AddRef,
342 FolderItemVerbImpl_Release,
343 FolderItemVerbImpl_GetTypeInfoCount,
344 FolderItemVerbImpl_GetTypeInfo,
345 FolderItemVerbImpl_GetIDsOfNames,
346 FolderItemVerbImpl_Invoke,
347 FolderItemVerbImpl_get_Application,
348 FolderItemVerbImpl_get_Parent,
349 FolderItemVerbImpl_get_Name,
350 FolderItemVerbImpl_DoIt
353 static HRESULT FolderItemVerb_Constructor(IContextMenu *contextmenu, BSTR name, FolderItemVerb **verb)
355 FolderItemVerbImpl *This;
357 TRACE("%p, %s\n", contextmenu, debugstr_w(name));
359 This = malloc(sizeof(*This));
360 if (!This)
361 return E_OUTOFMEMORY;
363 This->FolderItemVerb_iface.lpVtbl = &folderitemverbvtbl;
364 This->ref = 1;
365 This->contextmenu = contextmenu;
366 IContextMenu_AddRef(contextmenu);
367 This->name = name;
369 *verb = &This->FolderItemVerb_iface;
370 return S_OK;
373 /* FolderItemVerbs */
374 static HRESULT WINAPI FolderItemVerbsImpl_QueryInterface(FolderItemVerbs *iface,
375 REFIID riid, void **ppv)
377 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
379 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
381 if (IsEqualIID(&IID_IUnknown, riid) ||
382 IsEqualIID(&IID_IDispatch, riid) ||
383 IsEqualIID(&IID_FolderItemVerbs, riid))
384 *ppv = &This->FolderItemVerbs_iface;
385 else
387 WARN("not implemented for %s\n", debugstr_guid(riid));
388 *ppv = NULL;
389 return E_NOINTERFACE;
392 IUnknown_AddRef((IUnknown*)*ppv);
393 return S_OK;
396 static ULONG WINAPI FolderItemVerbsImpl_AddRef(FolderItemVerbs *iface)
398 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
399 ULONG ref = InterlockedIncrement(&This->ref);
401 TRACE("(%p), new refcount=%li\n", iface, ref);
403 return ref;
406 static ULONG WINAPI FolderItemVerbsImpl_Release(FolderItemVerbs *iface)
408 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
409 ULONG ref = InterlockedDecrement(&This->ref);
411 TRACE("(%p), new refcount=%li\n", iface, ref);
413 if (!ref)
415 IContextMenu_Release(This->contextmenu);
416 DestroyMenu(This->hMenu);
417 free(This);
420 return ref;
423 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfoCount(FolderItemVerbs *iface, UINT *pctinfo)
425 TRACE("(%p,%p)\n", iface, pctinfo);
426 *pctinfo = 1;
427 return S_OK;
430 static HRESULT WINAPI FolderItemVerbsImpl_GetTypeInfo(FolderItemVerbs *iface, UINT iTInfo,
431 LCID lcid, ITypeInfo **ppTInfo)
433 HRESULT hr;
435 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
437 hr = get_typeinfo(FolderItemVerbs_tid, ppTInfo);
438 if (SUCCEEDED(hr))
439 ITypeInfo_AddRef(*ppTInfo);
440 return hr;
443 static HRESULT WINAPI FolderItemVerbsImpl_GetIDsOfNames(FolderItemVerbs *iface,
444 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
446 ITypeInfo *ti;
447 HRESULT hr;
449 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
450 rgDispId);
452 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
453 if (SUCCEEDED(hr))
454 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
455 return hr;
458 static HRESULT WINAPI FolderItemVerbsImpl_Invoke(FolderItemVerbs *iface,
459 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
460 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
461 UINT *puArgErr)
463 ITypeInfo *ti;
464 HRESULT hr;
466 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
467 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
469 hr = get_typeinfo(FolderItemVerbs_tid, &ti);
470 if (SUCCEEDED(hr))
471 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
472 return hr;
475 static HRESULT WINAPI FolderItemVerbsImpl_get_Count(FolderItemVerbs *iface, LONG *count)
477 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
479 TRACE("(%p, %p)\n", iface, count);
481 if (!count)
482 return E_INVALIDARG;
484 *count = This->count;
485 return S_OK;
488 static HRESULT WINAPI FolderItemVerbsImpl_get_Application(FolderItemVerbs *iface, IDispatch **disp)
490 TRACE("(%p, %p)\n", iface, disp);
492 if (disp)
493 *disp = NULL;
494 return E_NOTIMPL;
497 static HRESULT WINAPI FolderItemVerbsImpl_get_Parent(FolderItemVerbs *iface, IDispatch **disp)
499 TRACE("(%p, %p)\n", iface, disp);
501 if (disp)
502 *disp = NULL;
503 return E_NOTIMPL;
506 static HRESULT WINAPI FolderItemVerbsImpl_Item(FolderItemVerbs *iface, VARIANT index, FolderItemVerb **verb)
508 FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface);
509 MENUITEMINFOW info;
510 HRESULT hr;
511 VARIANT v;
512 BSTR name;
514 TRACE("(%p, %s, %p)\n", iface, debugstr_variant(&index), verb);
516 if (!verb)
517 return E_INVALIDARG;
519 *verb = NULL;
521 VariantInit(&v);
522 VariantCopyInd(&v, &index);
524 hr = VariantChangeType(&v, &v, 0, VT_I4);
525 if (FAILED(hr))
527 FIXME("failed to coerce to VT_I4, %s\n", debugstr_variant(&v));
528 return hr;
531 if (V_I4(&v) > This->count)
532 return S_OK;
534 if (V_I4(&v) == This->count)
535 name = SysAllocStringLen(NULL, 0);
536 else
538 /* get item name */
539 memset(&info, 0, sizeof(info));
540 info.cbSize = sizeof(info);
541 info.fMask = MIIM_STRING;
542 if (!GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info))
543 return E_FAIL;
545 name = SysAllocStringLen(NULL, info.cch);
546 if (name)
548 info.dwTypeData = name;
549 info.cch++;
550 GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info);
554 if (!name)
555 return E_OUTOFMEMORY;
557 return FolderItemVerb_Constructor(This->contextmenu, name, verb);
560 static HRESULT WINAPI FolderItemVerbsImpl__NewEnum(FolderItemVerbs *iface, IUnknown **ret)
562 FIXME("(%p, %p)\n", iface, ret);
563 return E_NOTIMPL;
566 static FolderItemVerbsVtbl folderitemverbsvtbl = {
567 FolderItemVerbsImpl_QueryInterface,
568 FolderItemVerbsImpl_AddRef,
569 FolderItemVerbsImpl_Release,
570 FolderItemVerbsImpl_GetTypeInfoCount,
571 FolderItemVerbsImpl_GetTypeInfo,
572 FolderItemVerbsImpl_GetIDsOfNames,
573 FolderItemVerbsImpl_Invoke,
574 FolderItemVerbsImpl_get_Count,
575 FolderItemVerbsImpl_get_Application,
576 FolderItemVerbsImpl_get_Parent,
577 FolderItemVerbsImpl_Item,
578 FolderItemVerbsImpl__NewEnum
581 static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs)
583 FolderItemVerbsImpl *This;
584 IShellFolder *folder;
585 LPCITEMIDLIST child;
586 LPITEMIDLIST pidl;
587 HRESULT hr;
589 *verbs = NULL;
591 This = malloc(sizeof(*This));
592 if (!This)
593 return E_OUTOFMEMORY;
595 This->FolderItemVerbs_iface.lpVtbl = &folderitemverbsvtbl;
596 This->ref = 1;
598 /* build context menu for this path */
599 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
600 if (FAILED(hr))
601 goto failed;
603 hr = SHBindToParent(pidl, &IID_IShellFolder, (void**)&folder, &child);
604 CoTaskMemFree(pidl);
605 if (FAILED(hr))
606 goto failed;
608 hr = IShellFolder_GetUIObjectOf(folder, NULL, 1, &child, &IID_IContextMenu, NULL, (void**)&This->contextmenu);
609 IShellFolder_Release(folder);
610 if (FAILED(hr))
611 goto failed;
613 This->hMenu = CreatePopupMenu();
614 hr = IContextMenu_QueryContextMenu(This->contextmenu, This->hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
615 if (FAILED(hr))
617 FolderItemVerbs_Release(&This->FolderItemVerbs_iface);
618 return hr;
621 This->count = GetMenuItemCount(This->hMenu);
622 *verbs = &This->FolderItemVerbs_iface;
623 return S_OK;
625 failed:
626 free(This);
627 return hr;
630 static HRESULT WINAPI ShellLinkObject_QueryInterface(IShellLinkDual2 *iface, REFIID riid,
631 LPVOID *ppv)
633 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
635 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
637 if (!ppv) return E_INVALIDARG;
639 if (IsEqualIID(&IID_IUnknown, riid) ||
640 IsEqualIID(&IID_IDispatch, riid) ||
641 IsEqualIID(&IID_IShellLinkDual, riid) ||
642 IsEqualIID(&IID_IShellLinkDual2, riid))
643 *ppv = &This->IShellLinkDual2_iface;
644 else
646 WARN("not implemented for %s\n", debugstr_guid(riid));
647 *ppv = NULL;
648 return E_NOINTERFACE;
650 IUnknown_AddRef((IUnknown*)*ppv);
651 return S_OK;
654 static ULONG WINAPI ShellLinkObject_AddRef(IShellLinkDual2 *iface)
656 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
657 ULONG ref = InterlockedIncrement(&This->ref);
659 TRACE("(%p), new refcount=%li\n", iface, ref);
661 return ref;
664 static ULONG WINAPI ShellLinkObject_Release(IShellLinkDual2 *iface)
666 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
667 ULONG ref = InterlockedDecrement(&This->ref);
669 TRACE("(%p), new refcount=%li\n", iface, ref);
671 if (!ref)
673 if (This->shell_link) IShellLinkW_Release(This->shell_link);
674 free(This);
676 return ref;
679 static HRESULT WINAPI ShellLinkObject_GetTypeInfoCount(IShellLinkDual2 *iface, UINT *pctinfo)
681 TRACE("(%p,%p)\n", iface, pctinfo);
683 *pctinfo = 1;
684 return S_OK;
687 static HRESULT WINAPI ShellLinkObject_GetTypeInfo(IShellLinkDual2 *iface, UINT iTInfo,
688 LCID lcid, ITypeInfo **ppTInfo)
690 HRESULT hr;
692 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
694 hr = get_typeinfo(IShellLinkDual2_tid, ppTInfo);
695 if (SUCCEEDED(hr))
696 ITypeInfo_AddRef(*ppTInfo);
698 return hr;
701 static HRESULT WINAPI ShellLinkObject_GetIDsOfNames(IShellLinkDual2 *iface, REFIID riid,
702 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
704 ITypeInfo *ti;
705 HRESULT hr;
707 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
708 rgDispId);
710 hr = get_typeinfo(IShellLinkDual2_tid, &ti);
711 if (SUCCEEDED(hr))
712 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
713 return hr;
716 static HRESULT WINAPI ShellLinkObject_Invoke(IShellLinkDual2 *iface, DISPID dispIdMember,
717 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
718 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
720 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
721 ITypeInfo *ti;
722 HRESULT hr;
724 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
725 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
727 hr = get_typeinfo(IShellLinkDual2_tid, &ti);
728 if (SUCCEEDED(hr))
729 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
730 return hr;
733 static HRESULT WINAPI ShellLinkObject_get_Path(IShellLinkDual2 *iface, BSTR *pbs)
735 ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
736 WCHAR path[MAX_PATH];
737 HRESULT hr;
739 TRACE("(%p, %p)\n", iface, pbs);
741 *pbs = NULL;
743 hr = IShellLinkW_GetPath(This->shell_link, path, MAX_PATH, NULL, 0);
744 if (hr != S_OK)
745 return hr;
747 *pbs = SysAllocString(path);
748 return hr;
751 static HRESULT WINAPI ShellLinkObject_put_Path(IShellLinkDual2 *iface, BSTR bs)
753 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
755 return E_NOTIMPL;
758 static HRESULT WINAPI ShellLinkObject_get_Description(IShellLinkDual2 *iface, BSTR *pbs)
760 FIXME("(%p, %p)\n", iface, pbs);
762 return E_NOTIMPL;
765 static HRESULT WINAPI ShellLinkObject_put_Description(IShellLinkDual2 *iface, BSTR bs)
767 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
769 return E_NOTIMPL;
772 static HRESULT WINAPI ShellLinkObject_get_WorkingDirectory(IShellLinkDual2 *iface, BSTR *pbs)
774 FIXME("(%p, %p)\n", iface, pbs);
776 return E_NOTIMPL;
779 static HRESULT WINAPI ShellLinkObject_put_WorkingDirectory(IShellLinkDual2 *iface, BSTR bs)
781 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
783 return E_NOTIMPL;
786 static HRESULT WINAPI ShellLinkObject_get_Arguments(IShellLinkDual2 *iface, BSTR *pbs)
788 FIXME("(%p, %p)\n", iface, pbs);
790 return E_NOTIMPL;
793 static HRESULT WINAPI ShellLinkObject_put_Arguments(IShellLinkDual2 *iface, BSTR bs)
795 FIXME("(%p, %s)\n", iface, debugstr_w(bs));
797 return E_NOTIMPL;
800 static HRESULT WINAPI ShellLinkObject_get_Hotkey(IShellLinkDual2 *iface, int *piHK)
802 FIXME("(%p, %p)\n", iface, piHK);
804 return E_NOTIMPL;
807 static HRESULT WINAPI ShellLinkObject_put_Hotkey(IShellLinkDual2 *iface, int iHK)
809 FIXME("(%p, %d)\n", iface, iHK);
811 return E_NOTIMPL;
814 static HRESULT WINAPI ShellLinkObject_get_ShowCommand(IShellLinkDual2 *iface, int *piShowCommand)
816 FIXME("(%p, %p)\n", iface, piShowCommand);
818 return E_NOTIMPL;
821 static HRESULT WINAPI ShellLinkObject_put_ShowCommand(IShellLinkDual2 *iface, int iShowCommand)
823 FIXME("(%p, %d)\n", iface, iShowCommand);
825 return E_NOTIMPL;
828 static HRESULT WINAPI ShellLinkObject_Resolve(IShellLinkDual2 *iface, int fFlags)
830 FIXME("(%p, %d)\n", iface, fFlags);
832 return E_NOTIMPL;
835 static HRESULT WINAPI ShellLinkObject_GetIconLocation(IShellLinkDual2 *iface, BSTR *pbs,
836 int *piIcon)
838 FIXME("(%p, %p, %p)\n", iface, pbs, piIcon);
840 return E_NOTIMPL;
843 static HRESULT WINAPI ShellLinkObject_SetIconLocation(IShellLinkDual2 *iface, BSTR bs,
844 int iIcon)
846 FIXME("(%p, %s, %d)\n", iface, debugstr_w(bs), iIcon);
848 return E_NOTIMPL;
851 static HRESULT WINAPI ShellLinkObject_Save(IShellLinkDual2 *iface, VARIANT vWhere)
853 FIXME("(%p, %s)\n", iface, debugstr_variant(&vWhere));
855 return E_NOTIMPL;
858 static HRESULT WINAPI ShellLinkObject_get_Target(IShellLinkDual2 *iface, FolderItem **ppfi)
860 FIXME("(%p, %p)\n", iface, ppfi);
862 return E_NOTIMPL;
865 static const IShellLinkDual2Vtbl ShellLinkObjectVtbl = {
866 ShellLinkObject_QueryInterface,
867 ShellLinkObject_AddRef,
868 ShellLinkObject_Release,
869 ShellLinkObject_GetTypeInfoCount,
870 ShellLinkObject_GetTypeInfo,
871 ShellLinkObject_GetIDsOfNames,
872 ShellLinkObject_Invoke,
873 ShellLinkObject_get_Path,
874 ShellLinkObject_put_Path,
875 ShellLinkObject_get_Description,
876 ShellLinkObject_put_Description,
877 ShellLinkObject_get_WorkingDirectory,
878 ShellLinkObject_put_WorkingDirectory,
879 ShellLinkObject_get_Arguments,
880 ShellLinkObject_put_Arguments,
881 ShellLinkObject_get_Hotkey,
882 ShellLinkObject_put_Hotkey,
883 ShellLinkObject_get_ShowCommand,
884 ShellLinkObject_put_ShowCommand,
885 ShellLinkObject_Resolve,
886 ShellLinkObject_GetIconLocation,
887 ShellLinkObject_SetIconLocation,
888 ShellLinkObject_Save,
889 ShellLinkObject_get_Target,
892 static HRESULT ShellLinkObject_Constructor(FolderItemImpl *item, IShellLinkDual2 **link)
894 HRESULT hr;
895 IPersistFile *persist_file = NULL;
896 ShellLinkObjectImpl *This;
898 TRACE("(%p, %p)\n", item, link);
900 *link = NULL;
902 This = malloc(sizeof(*This));
903 if (!This) return E_OUTOFMEMORY;
904 This->IShellLinkDual2_iface.lpVtbl = &ShellLinkObjectVtbl;
905 This->ref = 1;
907 This->shell_link = NULL;
908 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
909 &IID_IShellLinkW, (LPVOID*)&This->shell_link);
910 if (FAILED(hr))
912 free(This);
913 return hr;
916 hr = IShellLinkW_QueryInterface(This->shell_link, &IID_IPersistFile,
917 (LPVOID*)&persist_file);
918 if (FAILED(hr))
920 IShellLinkW_Release(This->shell_link);
921 free(This);
922 return hr;
925 hr = IPersistFile_Load(persist_file, item->path, STGM_READ);
926 IPersistFile_Release(persist_file);
927 if (FAILED(hr))
929 IShellLinkW_Release(This->shell_link);
930 free(This);
931 return hr;
934 *link = &This->IShellLinkDual2_iface;
935 return S_OK;
938 static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface,
939 REFIID riid, LPVOID *ppv)
941 FolderItemImpl *This = impl_from_FolderItem(iface);
943 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
945 if (!ppv) return E_INVALIDARG;
947 if (IsEqualIID(&IID_IUnknown, riid) ||
948 IsEqualIID(&IID_IDispatch, riid) ||
949 IsEqualIID(&IID_FolderItem, riid) ||
950 IsEqualIID(&IID_FolderItem2, riid))
951 *ppv = &This->FolderItem2_iface;
952 else
954 WARN("not implemented for %s\n", debugstr_guid(riid));
955 *ppv = NULL;
956 return E_NOINTERFACE;
958 IUnknown_AddRef((IUnknown*)*ppv);
959 return S_OK;
962 static ULONG WINAPI FolderItemImpl_AddRef(FolderItem2 *iface)
964 FolderItemImpl *This = impl_from_FolderItem(iface);
965 ULONG ref = InterlockedIncrement(&This->ref);
967 TRACE("(%p), new refcount=%li\n", iface, ref);
969 return ref;
972 static ULONG WINAPI FolderItemImpl_Release(FolderItem2 *iface)
974 FolderItemImpl *This = impl_from_FolderItem(iface);
975 ULONG ref = InterlockedDecrement(&This->ref);
977 TRACE("(%p), new refcount=%li\n", iface, ref);
979 if (!ref)
981 Folder3_Release(&This->folder->Folder3_iface);
982 free(This->path);
983 free(This);
985 return ref;
988 static HRESULT WINAPI FolderItemImpl_GetTypeInfoCount(FolderItem2 *iface,
989 UINT *pctinfo)
991 TRACE("(%p,%p)\n", iface, pctinfo);
993 *pctinfo = 1;
994 return S_OK;
997 static HRESULT WINAPI FolderItemImpl_GetTypeInfo(FolderItem2 *iface, UINT iTInfo,
998 LCID lcid, ITypeInfo **ppTInfo)
1000 HRESULT hr;
1002 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
1004 hr = get_typeinfo(FolderItem2_tid, ppTInfo);
1005 if (SUCCEEDED(hr))
1006 ITypeInfo_AddRef(*ppTInfo);
1007 return hr;
1010 static HRESULT WINAPI FolderItemImpl_GetIDsOfNames(FolderItem2 *iface,
1011 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid,
1012 DISPID *rgDispId)
1014 ITypeInfo *ti;
1015 HRESULT hr;
1017 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1018 rgDispId);
1020 hr = get_typeinfo(FolderItem2_tid, &ti);
1021 if (SUCCEEDED(hr))
1022 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1023 return hr;
1026 static HRESULT WINAPI FolderItemImpl_Invoke(FolderItem2 *iface,
1027 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
1028 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1029 UINT *puArgErr)
1031 FolderItemImpl *This = impl_from_FolderItem(iface);
1032 ITypeInfo *ti;
1033 HRESULT hr;
1035 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1036 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1038 hr = get_typeinfo(FolderItem2_tid, &ti);
1039 if (SUCCEEDED(hr))
1040 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1041 return hr;
1044 static HRESULT WINAPI FolderItemImpl_get_Application(FolderItem2 *iface, IDispatch **disp)
1046 FolderItemImpl *This = impl_from_FolderItem(iface);
1048 TRACE("(%p,%p)\n", iface, disp);
1050 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
1053 static HRESULT WINAPI FolderItemImpl_get_Parent(FolderItem2 *iface, IDispatch **disp)
1055 FolderItemImpl *This = impl_from_FolderItem(iface);
1057 TRACE("(%p,%p)\n", iface, disp);
1059 if (disp)
1061 *disp = (IDispatch *)&This->folder->Folder3_iface;
1062 IDispatch_AddRef(*disp);
1065 return S_OK;
1068 static HRESULT WINAPI FolderItemImpl_get_Name(FolderItem2 *iface, BSTR *name)
1070 FolderItemImpl *This = impl_from_FolderItem(iface);
1071 LPCITEMIDLIST last_part;
1072 IShellFolder2 *parent;
1073 HRESULT hr = S_OK;
1074 LPITEMIDLIST pidl;
1075 STRRET strret;
1077 TRACE("(%p,%p)\n", iface, name);
1079 *name = NULL;
1081 if (This->path)
1082 hr = SHParseDisplayName(This->path, NULL, &pidl, 0, NULL);
1083 else
1084 pidl = This->folder->pidl;
1086 if (FAILED(hr))
1087 return S_FALSE;
1089 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
1090 if (hr == S_OK)
1091 hr = IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_INFOLDER, &strret);
1093 IShellFolder2_Release(parent);
1095 if (hr == S_OK)
1096 hr = StrRetToBSTR(&strret, last_part, name);
1098 if (This->path)
1099 ILFree(pidl);
1101 return hr;
1104 static HRESULT WINAPI FolderItemImpl_put_Name(FolderItem2 *iface, BSTR bs)
1106 FIXME("(%p,%s)\n", iface, debugstr_w(bs));
1108 return E_NOTIMPL;
1111 static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path)
1113 FolderItemImpl *This = impl_from_FolderItem(iface);
1115 TRACE("(%p,%p)\n", iface, path);
1117 *path = SysAllocString(This->path ? This->path : This->folder->path);
1118 return *path ? S_OK : E_OUTOFMEMORY;
1121 static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface,
1122 IDispatch **ppid)
1124 IShellLinkDual2 *link;
1125 HRESULT hr;
1126 FolderItemImpl *This = impl_from_FolderItem(iface);
1128 TRACE("(%p,%p)\n", iface, ppid);
1130 *ppid = NULL;
1132 if (!(This->attributes & SFGAO_LINK))
1133 return E_NOTIMPL;
1135 hr = ShellLinkObject_Constructor(This, &link);
1136 if (hr != S_OK)
1137 return hr;
1139 *ppid = (IDispatch*)link;
1140 return S_OK;
1143 static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface,
1144 IDispatch **ppid)
1146 FIXME("(%p,%p)\n", iface, ppid);
1148 *ppid = NULL;
1149 return E_NOTIMPL;
1152 static HRESULT WINAPI FolderItemImpl_get_IsLink(FolderItem2 *iface, VARIANT_BOOL *b)
1154 FolderItemImpl *This = impl_from_FolderItem(iface);
1156 TRACE("(%p,%p)\n", iface, b);
1158 *b = This->attributes & SFGAO_LINK ? VARIANT_TRUE : VARIANT_FALSE;
1160 return S_OK;
1163 static HRESULT WINAPI FolderItemImpl_get_IsFolder(FolderItem2 *iface, VARIANT_BOOL *b)
1165 FolderItemImpl *This = impl_from_FolderItem(iface);
1167 TRACE("(%p,%p)\n", iface, b);
1169 *b = This->attributes & SFGAO_FOLDER ? VARIANT_TRUE : VARIANT_FALSE;
1171 return S_OK;
1174 static HRESULT WINAPI FolderItemImpl_get_IsFileSystem(FolderItem2 *iface, VARIANT_BOOL *b)
1176 FolderItemImpl *This = impl_from_FolderItem(iface);
1178 TRACE("(%p,%p)\n", iface, b);
1180 *b = This->attributes & SFGAO_FILESYSTEM ? VARIANT_TRUE : VARIANT_FALSE;
1182 return S_OK;
1185 static HRESULT WINAPI FolderItemImpl_get_IsBrowsable(FolderItem2 *iface, VARIANT_BOOL *b)
1187 FolderItemImpl *This = impl_from_FolderItem(iface);
1189 TRACE("(%p,%p)\n", iface, b);
1191 *b = This->attributes & SFGAO_BROWSABLE ? VARIANT_TRUE : VARIANT_FALSE;
1193 return S_OK;
1196 static HRESULT WINAPI FolderItemImpl_get_ModifyDate(FolderItem2 *iface,
1197 DATE *pdt)
1199 FIXME("(%p,%p)\n", iface, pdt);
1201 return E_NOTIMPL;
1204 static HRESULT WINAPI FolderItemImpl_put_ModifyDate(FolderItem2 *iface, DATE dt)
1206 FIXME("(%p,%f)\n", iface, dt);
1208 return E_NOTIMPL;
1211 static HRESULT WINAPI FolderItemImpl_get_Size(FolderItem2 *iface, LONG *pul)
1213 FIXME("(%p,%p)\n", iface, pul);
1215 return E_NOTIMPL;
1218 static HRESULT WINAPI FolderItemImpl_get_Type(FolderItem2 *iface, BSTR *pbs)
1220 FIXME("(%p,%p)\n", iface, pbs);
1222 *pbs = NULL;
1223 return E_NOTIMPL;
1226 static HRESULT WINAPI FolderItemImpl_Verbs(FolderItem2 *iface, FolderItemVerbs **verbs)
1228 FolderItemImpl *This = impl_from_FolderItem(iface);
1230 TRACE("(%p, %p)\n", iface, verbs);
1232 if (!verbs)
1233 return E_INVALIDARG;
1235 return FolderItemVerbs_Constructor(This->path ? This->path : This->folder->path, verbs);
1238 static HRESULT WINAPI FolderItemImpl_InvokeVerb(FolderItem2 *iface,
1239 VARIANT vVerb)
1241 FIXME("(%p)\n", iface);
1243 return E_NOTIMPL;
1246 static HRESULT WINAPI FolderItemImpl_InvokeVerbEx(FolderItem2 *iface, VARIANT verb, VARIANT args)
1248 FIXME("(%p): stub\n", iface);
1250 return E_NOTIMPL;
1253 static HRESULT WINAPI FolderItemImpl_ExtendedProperty(FolderItem2 *iface, BSTR propname, VARIANT *ret)
1255 FIXME("(%p)->(%s %p): stub\n", iface, debugstr_w(propname), ret);
1257 return E_NOTIMPL;
1260 static const FolderItem2Vtbl FolderItemImpl_Vtbl = {
1261 FolderItemImpl_QueryInterface,
1262 FolderItemImpl_AddRef,
1263 FolderItemImpl_Release,
1264 FolderItemImpl_GetTypeInfoCount,
1265 FolderItemImpl_GetTypeInfo,
1266 FolderItemImpl_GetIDsOfNames,
1267 FolderItemImpl_Invoke,
1268 FolderItemImpl_get_Application,
1269 FolderItemImpl_get_Parent,
1270 FolderItemImpl_get_Name,
1271 FolderItemImpl_put_Name,
1272 FolderItemImpl_get_Path,
1273 FolderItemImpl_get_GetLink,
1274 FolderItemImpl_get_GetFolder,
1275 FolderItemImpl_get_IsLink,
1276 FolderItemImpl_get_IsFolder,
1277 FolderItemImpl_get_IsFileSystem,
1278 FolderItemImpl_get_IsBrowsable,
1279 FolderItemImpl_get_ModifyDate,
1280 FolderItemImpl_put_ModifyDate,
1281 FolderItemImpl_get_Size,
1282 FolderItemImpl_get_Type,
1283 FolderItemImpl_Verbs,
1284 FolderItemImpl_InvokeVerb,
1285 FolderItemImpl_InvokeVerbEx,
1286 FolderItemImpl_ExtendedProperty
1289 static HRESULT FolderItem_Constructor(FolderImpl *folder, const WCHAR *path, FolderItem **item)
1291 PIDLIST_ABSOLUTE pidl;
1292 FolderItemImpl *This;
1294 TRACE("%s\n", debugstr_w(path));
1296 *item = NULL;
1298 This = calloc(1, sizeof(*This));
1299 if (!This)
1300 return E_OUTOFMEMORY;
1302 This->FolderItem2_iface.lpVtbl = &FolderItemImpl_Vtbl;
1303 This->ref = 1;
1304 if (path)
1305 This->path = wcsdup(path);
1307 This->folder = folder;
1308 Folder3_AddRef(&folder->Folder3_iface);
1310 if (SHParseDisplayName(This->path, NULL, &pidl, ~0u, &This->attributes) == S_OK)
1311 ILFree(pidl);
1313 *item = (FolderItem *)&This->FolderItem2_iface;
1314 return S_OK;
1317 static HRESULT WINAPI FolderItemsImpl_QueryInterface(FolderItems3 *iface,
1318 REFIID riid, LPVOID *ppv)
1320 FolderItemsImpl *This = impl_from_FolderItems(iface);
1322 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1324 if (!ppv) return E_INVALIDARG;
1326 if (IsEqualIID(&IID_IUnknown, riid) ||
1327 IsEqualIID(&IID_IDispatch, riid) ||
1328 IsEqualIID(&IID_FolderItems, riid) ||
1329 IsEqualIID(&IID_FolderItems2, riid) ||
1330 IsEqualIID(&IID_FolderItems3, riid))
1331 *ppv = &This->FolderItems3_iface;
1332 else
1334 WARN("not implemented for %s\n", debugstr_guid(riid));
1335 *ppv = NULL;
1336 return E_NOINTERFACE;
1338 IUnknown_AddRef((IUnknown*)*ppv);
1339 return S_OK;
1342 static ULONG WINAPI FolderItemsImpl_AddRef(FolderItems3 *iface)
1344 FolderItemsImpl *This = impl_from_FolderItems(iface);
1345 ULONG ref = InterlockedIncrement(&This->ref);
1347 TRACE("(%p), new refcount=%li\n", iface, ref);
1349 return ref;
1352 static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
1354 FolderItemsImpl *This = impl_from_FolderItems(iface);
1355 ULONG ref = InterlockedDecrement(&This->ref);
1356 LONG i;
1358 TRACE("(%p), new refcount=%li\n", iface, ref);
1360 if (!ref)
1362 Folder3_Release(&This->folder->Folder3_iface);
1363 for (i = 0; i < This->item_count; i++)
1364 SysFreeString(This->item_names[i]);
1365 free(This->item_names);
1366 free(This);
1368 return ref;
1371 static HRESULT WINAPI FolderItemsImpl_GetTypeInfoCount(FolderItems3 *iface,
1372 UINT *count)
1374 TRACE("(%p,%p)\n", iface, count);
1376 *count = 1;
1377 return S_OK;
1380 static HRESULT WINAPI FolderItemsImpl_GetTypeInfo(FolderItems3 *iface,
1381 UINT type, LCID lcid, ITypeInfo **ppti)
1383 HRESULT hr;
1385 TRACE("(%p,%u,%ld,%p)\n", iface, type, lcid, ppti);
1387 hr = get_typeinfo(FolderItems3_tid, ppti);
1388 if (SUCCEEDED(hr))
1389 ITypeInfo_AddRef(*ppti);
1390 return hr;
1393 static HRESULT WINAPI FolderItemsImpl_GetIDsOfNames(FolderItems3 *iface,
1394 REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid)
1396 ITypeInfo *ti;
1397 HRESULT hr;
1399 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), names, count, lcid, dispid);
1401 hr = get_typeinfo(FolderItems3_tid, &ti);
1402 if (SUCCEEDED(hr))
1403 hr = ITypeInfo_GetIDsOfNames(ti, names, count, dispid);
1404 return hr;
1407 static HRESULT WINAPI FolderItemsImpl_Invoke(FolderItems3 *iface,
1408 DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params,
1409 VARIANT *result, EXCEPINFO *ei, UINT *err)
1411 FolderItemsImpl *This = impl_from_FolderItems(iface);
1412 ITypeInfo *ti;
1413 HRESULT hr;
1415 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispid, shdebugstr_guid(riid), lcid, flags, params, result, ei, err);
1417 hr = get_typeinfo(FolderItems3_tid, &ti);
1418 if (SUCCEEDED(hr))
1419 hr = ITypeInfo_Invoke(ti, This, dispid, flags, params, result, ei, err);
1420 return hr;
1423 static BOOL shellfolder_exists(const WCHAR *path)
1425 PIDLIST_ABSOLUTE pidl = NULL;
1426 HRESULT hr;
1428 hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL);
1429 ILFree(pidl);
1431 return SUCCEEDED(hr);
1434 static HRESULT WINAPI FolderItemsImpl_get_Count(FolderItems3 *iface, LONG *count)
1436 FolderItemsImpl *This = impl_from_FolderItems(iface);
1438 TRACE("(%p,%p)\n", iface, count);
1440 *count = shellfolder_exists(This->folder->path) ? This->item_count : 0;
1441 return S_OK;
1444 static HRESULT WINAPI FolderItemsImpl_get_Application(FolderItems3 *iface, IDispatch **disp)
1446 FolderItemsImpl *This = impl_from_FolderItems(iface);
1448 TRACE("(%p,%p)\n", iface, disp);
1450 return Folder3_get_Application(&This->folder->Folder3_iface, disp);
1453 static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch **ppid)
1455 TRACE("(%p,%p)\n", iface, ppid);
1457 if (ppid)
1458 *ppid = NULL;
1460 return E_NOTIMPL;
1463 static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT var, FolderItem **item)
1465 FolderItemsImpl *This = impl_from_FolderItems(iface);
1466 BSTR display_name = NULL;
1467 VARIANT index;
1468 HRESULT hr;
1470 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&var), item);
1472 *item = NULL;
1474 if (!shellfolder_exists(This->folder->path))
1475 return S_FALSE;
1477 VariantInit(&index);
1478 if (FAILED(hr = VariantCopyInd(&index, &var)))
1479 return hr;
1481 switch (V_VT(&index))
1483 case VT_I2:
1484 VariantChangeType(&index, &index, 0, VT_I4);
1485 /* fall through */
1487 case VT_I4:
1488 if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
1489 return S_FALSE;
1491 display_name = SysAllocString(This->item_names[V_I4(&index)]);
1492 break;
1494 case VT_BSTR:
1496 LPITEMIDLIST pidl;
1497 STRRET strret;
1499 if (!V_BSTR(&index))
1500 return S_FALSE;
1502 hr = IShellFolder2_ParseDisplayName(This->folder->folder, NULL, NULL, V_BSTR(&index), NULL, &pidl, NULL);
1503 VariantClear(&index);
1504 if (FAILED(hr))
1505 return S_FALSE;
1507 if (IShellFolder2_GetDisplayNameOf(This->folder->folder, pidl, SHGDN_FORPARSING, &strret) == S_OK)
1508 StrRetToBSTR(&strret, pidl, &display_name);
1509 ILFree(pidl);
1510 break;
1512 case VT_ERROR:
1513 break;
1515 default:
1516 FIXME("Index type %#x not handled.\n", V_VT(&index));
1517 VariantClear(&index);
1518 /* fall through */
1519 case VT_EMPTY:
1520 return E_NOTIMPL;
1523 hr = FolderItem_Constructor(This->folder, display_name, item);
1524 SysFreeString(display_name);
1525 return hr;
1528 static HRESULT WINAPI FolderItemsImpl__NewEnum(FolderItems3 *iface, IUnknown **ppunk)
1530 FIXME("(%p,%p)\n", iface, ppunk);
1532 if (!ppunk)
1533 return E_INVALIDARG;
1535 *ppunk = NULL;
1536 return E_NOTIMPL;
1539 static HRESULT WINAPI FolderItemsImpl_InvokeVerbEx(FolderItems3 *iface, VARIANT verb, VARIANT args)
1541 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&verb), debugstr_variant(&args));
1543 return E_NOTIMPL;
1546 static HRESULT WINAPI FolderItemsImpl_Filter(FolderItems3 *iface, LONG flags, BSTR spec)
1548 FIXME("(%p,%ld,%s)\n", iface, flags, wine_dbgstr_w(spec));
1550 return E_NOTIMPL;
1553 static HRESULT WINAPI FolderItemsImpl_get_Verbs(FolderItems3 *iface, FolderItemVerbs **ppfic)
1555 FIXME("(%p,%p)\n", iface, ppfic);
1557 if (!ppfic)
1558 return E_INVALIDARG;
1560 *ppfic = NULL;
1561 return E_NOTIMPL;
1564 static const FolderItems3Vtbl FolderItemsImpl_Vtbl = {
1565 FolderItemsImpl_QueryInterface,
1566 FolderItemsImpl_AddRef,
1567 FolderItemsImpl_Release,
1568 FolderItemsImpl_GetTypeInfoCount,
1569 FolderItemsImpl_GetTypeInfo,
1570 FolderItemsImpl_GetIDsOfNames,
1571 FolderItemsImpl_Invoke,
1572 FolderItemsImpl_get_Count,
1573 FolderItemsImpl_get_Application,
1574 FolderItemsImpl_get_Parent,
1575 FolderItemsImpl_Item,
1576 FolderItemsImpl__NewEnum,
1577 FolderItemsImpl_InvokeVerbEx,
1578 FolderItemsImpl_Filter,
1579 FolderItemsImpl_get_Verbs
1582 static void idlist_sort(LPITEMIDLIST *idlist, unsigned int l, unsigned int r, IShellFolder2 *folder)
1584 unsigned int m;
1586 if (l == r)
1587 return;
1589 if (r < l)
1591 idlist_sort(idlist, r, l, folder);
1592 return;
1595 m = (l + r) / 2;
1596 idlist_sort(idlist, l, m, folder);
1597 idlist_sort(idlist, m + 1, r, folder);
1599 /* join the two sides */
1600 while (l <= m && m < r)
1602 if ((short)IShellFolder2_CompareIDs(folder, 0, idlist[l], idlist[m + 1]) > 0)
1604 LPITEMIDLIST t = idlist[m + 1];
1605 memmove(&idlist[l + 1], &idlist[l], (m - l + 1) * sizeof(idlist[l]));
1606 idlist[l] = t;
1608 m++;
1610 l++;
1614 static HRESULT FolderItems_Constructor(FolderImpl *folder, FolderItems **ret)
1616 IEnumIDList *enumidlist;
1617 FolderItemsImpl *This;
1618 LPITEMIDLIST pidl;
1619 unsigned int i;
1620 HRESULT hr;
1622 TRACE("(%s,%p)\n", debugstr_w(folder->path), ret);
1624 *ret = NULL;
1626 This = calloc(1, sizeof(*This));
1627 if (!This)
1628 return E_OUTOFMEMORY;
1630 This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
1631 This->ref = 1;
1632 This->folder = folder;
1633 Folder3_AddRef(&folder->Folder3_iface);
1635 enumidlist = NULL;
1636 if (FAILED(hr = IShellFolder2_EnumObjects(folder->folder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1637 &enumidlist)))
1639 goto failed;
1642 while (IEnumIDList_Next(enumidlist, 1, &pidl, NULL) == S_OK)
1644 This->item_count++;
1645 ILFree(pidl);
1648 if (This->item_count)
1650 LPITEMIDLIST *pidls;
1651 ULONG fetched;
1653 pidls = malloc(This->item_count * sizeof(*pidls));
1654 This->item_names = calloc(This->item_count, sizeof(*This->item_names));
1656 if (!pidls || !This->item_names)
1658 free(pidls);
1659 free(This->item_names);
1660 hr = E_OUTOFMEMORY;
1661 goto failed;
1664 IEnumIDList_Reset(enumidlist);
1665 if (IEnumIDList_Next(enumidlist, This->item_count, pidls, &fetched) == S_OK)
1666 idlist_sort(pidls, 0, This->item_count - 1, folder->folder);
1668 for (i = 0; i < This->item_count; i++)
1670 STRRET strret;
1672 if (IShellFolder2_GetDisplayNameOf(folder->folder, pidls[i], SHGDN_FORPARSING, &strret) == S_OK)
1673 StrRetToBSTR(&strret, pidls[i], &This->item_names[i]);
1675 ILFree(pidls[i]);
1677 free(pidls);
1679 IEnumIDList_Release(enumidlist);
1681 *ret = (FolderItems *)&This->FolderItems3_iface;
1682 return S_OK;
1684 failed:
1685 FolderItemsImpl_Release(&This->FolderItems3_iface);
1686 if (enumidlist)
1687 IEnumIDList_Release(enumidlist);
1688 return hr;
1691 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
1692 LPVOID *ppv)
1694 FolderImpl *This = impl_from_Folder(iface);
1696 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1698 if (!ppv) return E_INVALIDARG;
1700 if (IsEqualIID(&IID_IUnknown, riid) ||
1701 IsEqualIID(&IID_IDispatch, riid) ||
1702 IsEqualIID(&IID_Folder, riid) ||
1703 IsEqualIID(&IID_Folder2, riid) ||
1704 IsEqualIID(&IID_Folder3, riid))
1705 *ppv = &This->Folder3_iface;
1706 else
1708 WARN("not implemented for %s\n", debugstr_guid(riid));
1709 *ppv = NULL;
1710 return E_NOINTERFACE;
1712 IUnknown_AddRef((IUnknown*)*ppv);
1713 return S_OK;
1716 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
1718 FolderImpl *This = impl_from_Folder(iface);
1719 ULONG ref = InterlockedIncrement(&This->ref);
1721 TRACE("(%p), new refcount=%li\n", iface, ref);
1723 return ref;
1726 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
1728 FolderImpl *This = impl_from_Folder(iface);
1729 ULONG ref = InterlockedDecrement(&This->ref);
1731 TRACE("(%p), new refcount=%li\n", iface, ref);
1733 if (!ref)
1735 ILFree(This->pidl);
1736 SysFreeString(This->path);
1737 IShellFolder2_Release(This->folder);
1738 IDispatch_Release(This->application);
1739 free(This);
1741 return ref;
1744 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
1746 TRACE("(%p,%p)\n", iface, pctinfo);
1748 *pctinfo = 1;
1749 return S_OK;
1752 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
1753 LCID lcid, ITypeInfo **ppTInfo)
1755 HRESULT hr;
1757 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
1759 hr = get_typeinfo(Folder3_tid, ppTInfo);
1760 if (SUCCEEDED(hr))
1761 ITypeInfo_AddRef(*ppTInfo);
1763 return hr;
1766 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
1767 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1769 ITypeInfo *ti;
1770 HRESULT hr;
1772 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
1773 rgDispId);
1775 hr = get_typeinfo(Folder3_tid, &ti);
1776 if (SUCCEEDED(hr))
1777 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1778 return hr;
1781 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
1782 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1783 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1785 FolderImpl *This = impl_from_Folder(iface);
1786 ITypeInfo *ti;
1787 HRESULT hr;
1789 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
1790 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1792 hr = get_typeinfo(Folder3_tid, &ti);
1793 if (SUCCEEDED(hr))
1794 hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1795 return hr;
1798 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *title)
1800 FolderImpl *This = impl_from_Folder(iface);
1801 PCUITEMID_CHILD last_part;
1802 IShellFolder2 *parent;
1803 SHELLDETAILS sd;
1804 HRESULT hr;
1806 TRACE("(%p,%p)\n", iface, title);
1808 *title = NULL;
1810 if (FAILED(hr = SHBindToParent(This->pidl, &IID_IShellFolder2, (void **)&parent, &last_part)))
1811 return hr;
1813 hr = IShellFolder2_GetDetailsOf(parent, last_part, 0, &sd);
1814 IShellFolder2_Release(parent);
1815 if (FAILED(hr))
1816 return hr;
1818 return StrRetToBSTR(&sd.str, last_part, title);
1821 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, IDispatch **disp)
1823 FolderImpl *This = impl_from_Folder(iface);
1825 TRACE("(%p,%p)\n", iface, disp);
1827 if (!disp)
1828 return E_INVALIDARG;
1830 *disp = This->application;
1831 IDispatch_AddRef(*disp);
1833 return S_OK;
1836 static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **disp)
1838 TRACE("(%p,%p)\n", iface, disp);
1840 if (disp)
1841 *disp = NULL;
1842 return E_NOTIMPL;
1845 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
1847 FIXME("(%p,%p)\n", iface, ppsf);
1849 *ppsf = NULL;
1850 return E_NOTIMPL;
1853 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
1855 FolderImpl *This = impl_from_Folder(iface);
1857 TRACE("(%p,%p)\n", iface, ppid);
1859 return FolderItems_Constructor(This, ppid);
1862 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
1864 FolderImpl *This = impl_from_Folder(iface);
1865 LPITEMIDLIST pidl;
1866 STRRET strret;
1867 HRESULT hr;
1868 BSTR path;
1870 TRACE("(%p,%s,%p)\n", iface, debugstr_w(name), item);
1872 *item = NULL;
1874 if (FAILED(IShellFolder2_ParseDisplayName(This->folder, NULL, NULL, name, NULL, &pidl, NULL)))
1875 return S_FALSE;
1877 if ((hr = IShellFolder2_GetDisplayNameOf(This->folder, pidl, SHGDN_FORPARSING, &strret)) == S_OK)
1878 hr = StrRetToBSTR(&strret, pidl, &path);
1880 ILFree(pidl);
1881 if (hr != S_OK)
1882 return S_FALSE;
1884 hr = FolderItem_Constructor(This, path, item);
1885 SysFreeString(path);
1886 return hr;
1889 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR name, VARIANT options)
1891 FIXME("(%p,%s,%s)\n", iface, debugstr_w(name), debugstr_variant(&options));
1893 return E_NOTIMPL;
1896 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT item, VARIANT options)
1898 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1900 return E_NOTIMPL;
1903 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT item, VARIANT options)
1905 FIXME("(%p,%s,%s)\n", iface, debugstr_variant(&item), debugstr_variant(&options));
1907 return E_NOTIMPL;
1910 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT item, int column, BSTR *str)
1912 FIXME("(%p,%s,%d,%p)\n", iface, debugstr_variant(&item), column, str);
1914 *str = NULL;
1915 return E_NOTIMPL;
1918 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **item)
1920 FolderImpl *This = impl_from_Folder(iface);
1922 TRACE("(%p,%p)\n", iface, item);
1924 return FolderItem_Constructor(This, NULL, item);
1927 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
1929 FIXME("(%p,%p)\n", iface, pul);
1931 return E_NOTIMPL;
1934 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
1936 FIXME("(%p)\n", iface);
1938 return E_NOTIMPL;
1941 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
1942 VARIANT_BOOL *pbHaveToShowWebViewBarricade)
1944 FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
1946 return E_NOTIMPL;
1949 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
1951 FIXME("(%p)\n", iface);
1953 return E_NOTIMPL;
1956 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
1957 VARIANT_BOOL *pbShowWebViewBarricade)
1959 FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
1961 return E_NOTIMPL;
1964 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
1965 VARIANT_BOOL bShowWebViewBarricade)
1967 FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
1969 return E_NOTIMPL;
1972 static const Folder3Vtbl FolderImpl_Vtbl = {
1973 FolderImpl_QueryInterface,
1974 FolderImpl_AddRef,
1975 FolderImpl_Release,
1976 FolderImpl_GetTypeInfoCount,
1977 FolderImpl_GetTypeInfo,
1978 FolderImpl_GetIDsOfNames,
1979 FolderImpl_Invoke,
1980 FolderImpl_get_Title,
1981 FolderImpl_get_Application,
1982 FolderImpl_get_Parent,
1983 FolderImpl_get_ParentFolder,
1984 FolderImpl_Items,
1985 FolderImpl_ParseName,
1986 FolderImpl_NewFolder,
1987 FolderImpl_MoveHere,
1988 FolderImpl_CopyHere,
1989 FolderImpl_GetDetailsOf,
1990 FolderImpl_get_Self,
1991 FolderImpl_get_OfflineStatus,
1992 FolderImpl_Synchronize,
1993 FolderImpl_get_HaveToShowWebViewBarricade,
1994 FolderImpl_DismissedWebViewBarricade,
1995 FolderImpl_get_ShowWebViewBarricade,
1996 FolderImpl_put_ShowWebViewBarricade
1999 static HRESULT Folder_Constructor(IShellFolder2 *folder, LPITEMIDLIST pidl, Folder **ret)
2001 PCUITEMID_CHILD last_part;
2002 IShellFolder2 *parent;
2003 FolderImpl *This;
2004 STRRET strret;
2005 HRESULT hr;
2007 *ret = NULL;
2009 This = malloc(sizeof(*This));
2010 if (!This)
2011 return E_OUTOFMEMORY;
2013 This->Folder3_iface.lpVtbl = &FolderImpl_Vtbl;
2014 This->ref = 1;
2015 This->folder = folder;
2016 This->pidl = ILClone(pidl);
2018 hr = SHBindToParent(pidl, &IID_IShellFolder2, (void **)&parent, &last_part);
2019 IShellFolder2_GetDisplayNameOf(parent, last_part, SHGDN_FORPARSING, &strret);
2020 StrRetToBSTR(&strret, last_part, &This->path);
2021 IShellFolder2_Release(parent);
2023 IShellDispatch_Constructor(NULL, &IID_IDispatch, (void **)&This->application);
2025 *ret = (Folder *)&This->Folder3_iface;
2026 return hr;
2029 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch6 *iface,
2030 REFIID riid, LPVOID *ppv)
2032 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2034 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
2036 if (!ppv) return E_INVALIDARG;
2038 if (IsEqualIID(&IID_IUnknown, riid) ||
2039 IsEqualIID(&IID_IDispatch, riid) ||
2040 IsEqualIID(&IID_IShellDispatch, riid) ||
2041 IsEqualIID(&IID_IShellDispatch2, riid) ||
2042 IsEqualIID(&IID_IShellDispatch3, riid) ||
2043 IsEqualIID(&IID_IShellDispatch4, riid) ||
2044 IsEqualIID(&IID_IShellDispatch5, riid) ||
2045 IsEqualIID(&IID_IShellDispatch6, riid))
2046 *ppv = &This->IShellDispatch6_iface;
2047 else
2049 WARN("not implemented for %s\n", debugstr_guid(riid));
2050 *ppv = NULL;
2051 return E_NOINTERFACE;
2054 IShellDispatch6_AddRef(iface);
2055 return S_OK;
2058 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch6 *iface)
2060 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2061 ULONG ref = InterlockedIncrement(&This->ref);
2063 TRACE("(%p), new refcount=%li\n", iface, ref);
2065 return ref;
2068 static ULONG WINAPI ShellDispatch_Release(IShellDispatch6 *iface)
2070 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2071 ULONG ref = InterlockedDecrement(&This->ref);
2073 TRACE("(%p), new refcount=%li\n", iface, ref);
2075 if (!ref)
2076 free(This);
2078 return ref;
2081 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch6 *iface,
2082 UINT *pctinfo)
2084 TRACE("(%p,%p)\n", iface, pctinfo);
2086 *pctinfo = 1;
2087 return S_OK;
2090 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch6 *iface,
2091 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
2093 HRESULT hr;
2095 TRACE("(%p,%u,%ld,%p)\n", iface, iTInfo, lcid, ppTInfo);
2097 hr = get_typeinfo(IShellDispatch6_tid, ppTInfo);
2098 if (SUCCEEDED(hr))
2099 ITypeInfo_AddRef(*ppTInfo);
2100 return hr;
2103 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch6 *iface,
2104 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2106 ITypeInfo *ti;
2107 HRESULT hr;
2109 TRACE("(%p,%s,%p,%u,%ld,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
2110 rgDispId);
2112 hr = get_typeinfo(IShellDispatch6_tid, &ti);
2113 if (SUCCEEDED(hr))
2114 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
2115 return hr;
2118 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch6 *iface,
2119 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
2120 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
2121 UINT *puArgErr)
2123 ShellDispatch *This = impl_from_IShellDispatch6(iface);
2124 ITypeInfo *ti;
2125 HRESULT hr;
2127 TRACE("(%p,%ld,%s,%ld,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
2128 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2130 hr = get_typeinfo(IShellDispatch6_tid, &ti);
2131 if (SUCCEEDED(hr))
2132 hr = ITypeInfo_Invoke(ti, &This->IShellDispatch6_iface, dispIdMember, wFlags, pDispParams,
2133 pVarResult, pExcepInfo, puArgErr);
2134 return hr;
2137 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch6 *iface, IDispatch **disp)
2139 TRACE("(%p,%p)\n", iface, disp);
2141 if (!disp)
2142 return E_INVALIDARG;
2144 *disp = (IDispatch *)iface;
2145 IDispatch_AddRef(*disp);
2146 return S_OK;
2149 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch6 *iface, IDispatch **disp)
2151 TRACE("(%p,%p)\n", iface, disp);
2153 if (disp)
2155 *disp = (IDispatch *)iface;
2156 IDispatch_AddRef(*disp);
2159 return S_OK;
2162 static HRESULT create_folder_for_pidl(LPITEMIDLIST pidl, Folder **ret)
2164 IShellFolder2 *folder;
2165 IShellFolder *desktop;
2166 HRESULT hr;
2168 *ret = NULL;
2170 if (FAILED(hr = SHGetDesktopFolder(&desktop)))
2171 return hr;
2173 if (_ILIsDesktop(pidl))
2174 hr = IShellFolder_QueryInterface(desktop, &IID_IShellFolder2, (void **)&folder);
2175 else
2176 hr = IShellFolder_BindToObject(desktop, pidl, NULL, &IID_IShellFolder2, (void **)&folder);
2178 IShellFolder_Release(desktop);
2180 if (FAILED(hr))
2181 return S_FALSE;
2183 return Folder_Constructor(folder, pidl, ret);
2186 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch6 *iface,
2187 VARIANT dir, Folder **ret)
2189 LPITEMIDLIST pidl;
2190 HRESULT hr;
2192 TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&dir), ret);
2194 *ret = NULL;
2196 switch (V_VT(&dir))
2198 case VT_I2:
2199 if (FAILED(hr = VariantChangeType(&dir, &dir, 0, VT_I4)))
2200 return hr;
2202 /* fallthrough */
2203 case VT_I4:
2204 if (FAILED(hr = SHGetFolderLocation(NULL, V_I4(&dir), NULL, 0, &pidl)))
2205 return S_FALSE;
2207 break;
2208 case VT_BSTR:
2209 if (FAILED(hr = SHParseDisplayName(V_BSTR(&dir), NULL, &pidl, 0, NULL)))
2210 return S_FALSE;
2212 break;
2213 default:
2214 WARN("Ignoring directory value %s\n", debugstr_variant(&dir));
2215 return S_FALSE;
2218 hr = create_folder_for_pidl(pidl, ret);
2219 ILFree(pidl);
2221 return hr;
2224 static BOOL is_optional_argument(const VARIANT *arg)
2226 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
2229 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch6 *iface,
2230 LONG hwnd, BSTR title, LONG options, VARIANT rootfolder, Folder **folder)
2232 PIDLIST_ABSOLUTE selection;
2233 BROWSEINFOW bi = { 0 };
2234 HRESULT hr;
2236 TRACE("(%p,%lx,%s,%lx,%s,%p)\n", iface, hwnd, debugstr_w(title), options, debugstr_variant(&rootfolder), folder);
2238 *folder = NULL;
2240 if (!is_optional_argument(&rootfolder))
2241 FIXME("root folder is ignored\n");
2243 bi.hwndOwner = LongToHandle(hwnd);
2244 bi.lpszTitle = title;
2245 bi.ulFlags = options;
2247 selection = SHBrowseForFolderW(&bi);
2248 if (selection)
2250 hr = create_folder_for_pidl(selection, folder);
2251 ILFree(selection);
2253 else
2254 hr = S_FALSE;
2256 return hr;
2259 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch6 *iface,
2260 IDispatch **ppid)
2262 FIXME("(%p,%p)\n", iface, ppid);
2264 *ppid = NULL;
2265 return E_NOTIMPL;
2268 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch6 *iface, VARIANT dir)
2270 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
2272 return E_NOTIMPL;
2275 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch6 *iface, VARIANT dir)
2277 FIXME("(%p,%s)\n", iface, debugstr_variant(&dir));
2279 return E_NOTIMPL;
2282 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch6 *iface)
2284 FIXME("(%p)\n", iface);
2286 return E_NOTIMPL;
2289 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch6 *iface)
2291 FIXME("(%p)\n", iface);
2293 return E_NOTIMPL;
2296 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch6 *iface)
2298 FIXME("(%p)\n", iface);
2300 return E_NOTIMPL;
2303 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch6 *iface)
2305 FIXME("(%p)\n", iface);
2307 return E_NOTIMPL;
2310 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch6 *iface)
2312 FIXME("(%p)\n", iface);
2314 return E_NOTIMPL;
2317 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch6 *iface)
2319 FIXME("(%p)\n", iface);
2321 return E_NOTIMPL;
2324 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch6 *iface)
2326 FIXME("(%p)\n", iface);
2328 return E_NOTIMPL;
2331 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch6 *iface)
2333 FIXME("(%p)\n", iface);
2335 return E_NOTIMPL;
2338 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch6 *iface)
2340 FIXME("(%p)\n", iface);
2342 return E_NOTIMPL;
2345 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch6 *iface)
2347 FIXME("(%p)\n", iface);
2349 return E_NOTIMPL;
2352 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch6 *iface)
2354 FIXME("(%p)\n", iface);
2356 return E_NOTIMPL;
2359 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch6 *iface)
2361 FIXME("(%p)\n", iface);
2363 return E_NOTIMPL;
2366 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch6 *iface)
2368 FIXME("(%p)\n", iface);
2370 return E_NOTIMPL;
2373 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch6 *iface)
2375 FIXME("(%p)\n", iface);
2377 return E_NOTIMPL;
2380 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch6 *iface)
2382 FIXME("(%p)\n", iface);
2384 return E_NOTIMPL;
2387 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch6 *iface,
2388 BSTR szDir)
2390 FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
2392 return E_NOTIMPL;
2395 static HRESULT WINAPI ShellDispatch_IsRestricted(IShellDispatch6 *iface, BSTR group, BSTR restriction, LONG *value)
2397 FIXME("(%s, %s, %p): stub\n", debugstr_w(group), debugstr_w(restriction), value);
2398 return E_NOTIMPL;
2401 static HRESULT WINAPI ShellDispatch_ShellExecute(IShellDispatch6 *iface,
2402 BSTR file, VARIANT v_args, VARIANT v_dir, VARIANT v_op, VARIANT v_show)
2404 VARIANT args_str, dir_str, op_str, show_int;
2405 WCHAR *args = NULL, *dir = NULL, *op = NULL;
2406 INT show = 0;
2407 HINSTANCE ret;
2409 TRACE("(%s, %s, %s, %s, %s)\n", debugstr_w(file), debugstr_variant(&v_args),
2410 debugstr_variant(&v_dir), debugstr_variant(&v_op), debugstr_variant(&v_show));
2412 VariantInit(&args_str);
2413 VariantChangeType(&args_str, &v_args, 0, VT_BSTR);
2414 if (V_VT(&args_str) == VT_BSTR)
2415 args = V_BSTR(&args_str);
2417 VariantInit(&dir_str);
2418 VariantChangeType(&dir_str, &v_dir, 0, VT_BSTR);
2419 if (V_VT(&dir_str) == VT_BSTR)
2420 dir = V_BSTR(&dir_str);
2422 VariantInit(&op_str);
2423 VariantChangeType(&op_str, &v_op, 0, VT_BSTR);
2424 if (V_VT(&op_str) == VT_BSTR)
2425 op = V_BSTR(&op_str);
2427 VariantInit(&show_int);
2428 VariantChangeType(&show_int, &v_show, 0, VT_I4);
2429 if (V_VT(&show_int) == VT_I4)
2430 show = V_I4(&show_int);
2432 ret = ShellExecuteW(NULL, op, file, args, dir, show);
2434 VariantClear(&args_str);
2435 VariantClear(&dir_str);
2436 VariantClear(&op_str);
2437 VariantClear(&show_int);
2439 return (ULONG_PTR)ret > 32 ? S_OK : S_FALSE;
2442 static HRESULT WINAPI ShellDispatch_FindPrinter(IShellDispatch6 *iface, BSTR name, BSTR location, BSTR model)
2444 FIXME("(%s, %s, %s): stub\n", debugstr_w(name), debugstr_w(location), debugstr_w(model));
2445 return E_NOTIMPL;
2448 static HRESULT WINAPI ShellDispatch_GetSystemInformation(IShellDispatch6 *iface, BSTR name, VARIANT *ret)
2450 FIXME("(%s, %p): stub\n", debugstr_w(name), ret);
2451 return E_NOTIMPL;
2454 static HRESULT WINAPI ShellDispatch_ServiceStart(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2456 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2457 return E_NOTIMPL;
2460 static HRESULT WINAPI ShellDispatch_ServiceStop(IShellDispatch6 *iface, BSTR service, VARIANT persistent, VARIANT *ret)
2462 FIXME("(%s, %s, %p): stub\n", debugstr_w(service), debugstr_variant(&persistent), ret);
2463 return E_NOTIMPL;
2466 static HRESULT WINAPI ShellDispatch_IsServiceRunning(IShellDispatch6 *iface, BSTR name, VARIANT *running)
2468 SERVICE_STATUS_PROCESS status;
2469 SC_HANDLE scm, service;
2470 DWORD dummy;
2472 TRACE("(%s, %p)\n", debugstr_w(name), running);
2474 V_VT(running) = VT_BOOL;
2475 V_BOOL(running) = VARIANT_FALSE;
2477 scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
2478 if (!scm)
2480 ERR("failed to connect to service manager\n");
2481 return S_OK;
2484 service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS);
2485 if (!service)
2487 ERR("Failed to open service %s (%lu)\n", debugstr_w(name), GetLastError());
2488 CloseServiceHandle(scm);
2489 return S_OK;
2492 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status,
2493 sizeof(SERVICE_STATUS_PROCESS), &dummy))
2495 TRACE("failed to query service status (%lu)\n", GetLastError());
2496 CloseServiceHandle(service);
2497 CloseServiceHandle(scm);
2498 return S_OK;
2501 if (status.dwCurrentState == SERVICE_RUNNING)
2502 V_BOOL(running) = VARIANT_TRUE;
2504 CloseServiceHandle(service);
2505 CloseServiceHandle(scm);
2507 return S_OK;
2510 static HRESULT WINAPI ShellDispatch_CanStartStopService(IShellDispatch6 *iface, BSTR service, VARIANT *ret)
2512 FIXME("(%s, %p): stub\n", debugstr_w(service), ret);
2513 return E_NOTIMPL;
2516 static HRESULT WINAPI ShellDispatch_ShowBrowserBar(IShellDispatch6 *iface, BSTR clsid, VARIANT show, VARIANT *ret)
2518 FIXME("(%s, %s, %p): stub\n", debugstr_w(clsid), debugstr_variant(&show), ret);
2519 return E_NOTIMPL;
2522 static HRESULT WINAPI ShellDispatch_AddToRecent(IShellDispatch6 *iface, VARIANT file, BSTR category)
2524 FIXME("(%s, %s): stub\n", debugstr_variant(&file), debugstr_w(category));
2525 return E_NOTIMPL;
2528 static HRESULT WINAPI ShellDispatch_WindowsSecurity(IShellDispatch6 *iface)
2530 FIXME("stub\n");
2531 return E_NOTIMPL;
2534 static HRESULT WINAPI ShellDispatch_ToggleDesktop(IShellDispatch6 *iface)
2536 FIXME("stub\n");
2537 return E_NOTIMPL;
2540 static HRESULT WINAPI ShellDispatch_ExplorerPolicy(IShellDispatch6 *iface, BSTR policy, VARIANT *value)
2542 FIXME("(%s, %p): stub\n", debugstr_w(policy), value);
2543 return E_NOTIMPL;
2546 static HRESULT WINAPI ShellDispatch_GetSetting(IShellDispatch6 *iface, LONG setting, VARIANT_BOOL *result)
2548 FIXME("(%ld %p): stub\n", setting, result);
2549 return E_NOTIMPL;
2552 static HRESULT WINAPI ShellDispatch_WindowSwitcher(IShellDispatch6 *iface)
2554 FIXME("stub\n");
2555 return E_NOTIMPL;
2558 static HRESULT WINAPI ShellDispatch_SearchCommand(IShellDispatch6 *iface)
2560 FIXME("stub\n");
2561 return E_NOTIMPL;
2564 static const IShellDispatch6Vtbl ShellDispatchVtbl = {
2565 ShellDispatch_QueryInterface,
2566 ShellDispatch_AddRef,
2567 ShellDispatch_Release,
2568 ShellDispatch_GetTypeInfoCount,
2569 ShellDispatch_GetTypeInfo,
2570 ShellDispatch_GetIDsOfNames,
2571 ShellDispatch_Invoke,
2572 ShellDispatch_get_Application,
2573 ShellDispatch_get_Parent,
2574 ShellDispatch_NameSpace,
2575 ShellDispatch_BrowseForFolder,
2576 ShellDispatch_Windows,
2577 ShellDispatch_Open,
2578 ShellDispatch_Explore,
2579 ShellDispatch_MinimizeAll,
2580 ShellDispatch_UndoMinimizeALL,
2581 ShellDispatch_FileRun,
2582 ShellDispatch_CascadeWindows,
2583 ShellDispatch_TileVertically,
2584 ShellDispatch_TileHorizontally,
2585 ShellDispatch_ShutdownWindows,
2586 ShellDispatch_Suspend,
2587 ShellDispatch_EjectPC,
2588 ShellDispatch_SetTime,
2589 ShellDispatch_TrayProperties,
2590 ShellDispatch_Help,
2591 ShellDispatch_FindFiles,
2592 ShellDispatch_FindComputer,
2593 ShellDispatch_RefreshMenu,
2594 ShellDispatch_ControlPanelItem,
2595 ShellDispatch_IsRestricted,
2596 ShellDispatch_ShellExecute,
2597 ShellDispatch_FindPrinter,
2598 ShellDispatch_GetSystemInformation,
2599 ShellDispatch_ServiceStart,
2600 ShellDispatch_ServiceStop,
2601 ShellDispatch_IsServiceRunning,
2602 ShellDispatch_CanStartStopService,
2603 ShellDispatch_ShowBrowserBar,
2604 ShellDispatch_AddToRecent,
2605 ShellDispatch_WindowsSecurity,
2606 ShellDispatch_ToggleDesktop,
2607 ShellDispatch_ExplorerPolicy,
2608 ShellDispatch_GetSetting,
2609 ShellDispatch_WindowSwitcher,
2610 ShellDispatch_SearchCommand
2613 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *outer, REFIID riid, void **ppv)
2615 ShellDispatch *This;
2616 HRESULT ret;
2618 TRACE("(%p, %s)\n", outer, debugstr_guid(riid));
2620 *ppv = NULL;
2622 if (outer) return CLASS_E_NOAGGREGATION;
2624 This = malloc(sizeof(*This));
2625 if (!This) return E_OUTOFMEMORY;
2626 This->IShellDispatch6_iface.lpVtbl = &ShellDispatchVtbl;
2627 This->ref = 1;
2629 ret = IShellDispatch6_QueryInterface(&This->IShellDispatch6_iface, riid, ppv);
2630 IShellDispatch6_Release(&This->IShellDispatch6_iface);
2631 return ret;