| /* | 
 |  * IShellDispatch implementation | 
 |  * | 
 |  * Copyright 2010 Alexander Morozov for Etersoft | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
 |  */ | 
 |  | 
 | #include "config.h" | 
 | #include "wine/port.h" | 
 |  | 
 | #include <stdarg.h> | 
 |  | 
 | #define COBJMACROS | 
 | #define NONAMELESSUNION | 
 | #define NONAMELESSSTRUCT | 
 |  | 
 | #include "windef.h" | 
 | #include "winbase.h" | 
 | #include "winreg.h" | 
 | #include "winsvc.h" | 
 | #include "shlwapi.h" | 
 | #include "shlobj.h" | 
 | #include "shldisp.h" | 
 | #include "debughlp.h" | 
 |  | 
 | #include "wine/debug.h" | 
 |  | 
 | WINE_DEFAULT_DEBUG_CHANNEL(shell); | 
 |  | 
 | typedef struct { | 
 |     IShellDispatch2 IShellDispatch2_iface; | 
 |     LONG ref; | 
 |     ITypeInfo *typeinfo; | 
 | } ShellDispatch; | 
 |  | 
 | typedef struct { | 
 |     Folder3 Folder_iface; | 
 |     LONG ref; | 
 |     ITypeInfo *iTypeInfo; | 
 |     VARIANT dir; | 
 | } FolderImpl; | 
 |  | 
 | typedef struct { | 
 |     FolderItem FolderItem_iface; | 
 |     LONG ref; | 
 |     ITypeInfo *iTypeInfo; | 
 |     VARIANT dir; | 
 | } FolderItemImpl; | 
 |  | 
 | static inline ShellDispatch *impl_from_IShellDispatch2(IShellDispatch2 *iface) | 
 | { | 
 |     return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch2_iface); | 
 | } | 
 |  | 
 | static inline FolderImpl *impl_from_Folder(Folder3 *iface) | 
 | { | 
 |     return CONTAINING_RECORD(iface, FolderImpl, Folder_iface); | 
 | } | 
 |  | 
 | static inline FolderItemImpl *impl_from_FolderItem(FolderItem *iface) | 
 | { | 
 |     return CONTAINING_RECORD(iface, FolderItemImpl, FolderItem_iface); | 
 | } | 
 |  | 
 | static HRESULT load_type_info(REFGUID guid, ITypeInfo **pptinfo) | 
 | { | 
 |     ITypeLib *typelib; | 
 |     HRESULT ret; | 
 |  | 
 |     ret = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &typelib); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         ERR("LoadRegTypeLib failed: %08x\n", ret); | 
 |         return ret; | 
 |     } | 
 |  | 
 |     ret = ITypeLib_GetTypeInfoOfGuid(typelib, guid, pptinfo); | 
 |     ITypeLib_Release(typelib); | 
 |     if (FAILED(ret)) | 
 |         ERR("failed to load ITypeInfo\n"); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem *iface, | 
 |         REFIID riid, LPVOID *ppv) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p)\n", iface, riid, ppv); | 
 |  | 
 |     if (!ppv) return E_INVALIDARG; | 
 |  | 
 |     if (IsEqualIID(&IID_IUnknown, riid) || | 
 |         IsEqualIID(&IID_IDispatch, riid) || | 
 |         IsEqualIID(&IID_FolderItem, riid)) | 
 |         *ppv = This; | 
 |     else | 
 |     { | 
 |         FIXME("not implemented for %s\n", shdebugstr_guid(riid)); | 
 |         *ppv = NULL; | 
 |         return E_NOINTERFACE; | 
 |     } | 
 |     IUnknown_AddRef((IUnknown*)*ppv); | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static ULONG WINAPI FolderItemImpl_AddRef(FolderItem *iface) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |     ULONG ref = InterlockedIncrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     return ref; | 
 | } | 
 |  | 
 | static ULONG WINAPI FolderItemImpl_Release(FolderItem *iface) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |     ULONG ref = InterlockedDecrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     if (!ref) | 
 |     { | 
 |         VariantClear(&This->dir); | 
 |         ITypeInfo_Release(This->iTypeInfo); | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |     } | 
 |     return ref; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_GetTypeInfoCount(FolderItem *iface, | 
 |         UINT *pctinfo) | 
 | { | 
 |     TRACE("(%p,%p)\n", iface, pctinfo); | 
 |  | 
 |     *pctinfo = 1; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_GetTypeInfo(FolderItem *iface, UINT iTInfo, | 
 |         LCID lcid, ITypeInfo **ppTInfo) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |  | 
 |     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo); | 
 |  | 
 |     ITypeInfo_AddRef(This->iTypeInfo); | 
 |     *ppTInfo = This->iTypeInfo; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_GetIDsOfNames(FolderItem *iface, | 
 |         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, | 
 |         DISPID *rgDispId) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid, | 
 |             rgDispId); | 
 |  | 
 |     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId); | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_Invoke(FolderItem *iface, | 
 |         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, | 
 |         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, | 
 |         UINT *puArgErr) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |  | 
 |     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid, | 
 |             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 |  | 
 |     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags, | 
 |             pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Application(FolderItem *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Parent(FolderItem *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Name(FolderItem *iface, BSTR *pbs) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pbs); | 
 |  | 
 |     *pbs = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_put_Name(FolderItem *iface, BSTR bs) | 
 | { | 
 |     FIXME("(%p,%s)\n", iface, debugstr_w(bs)); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem *iface, BSTR *pbs) | 
 | { | 
 |     FolderItemImpl *This = impl_from_FolderItem(iface); | 
 |     HRESULT ret = S_OK; | 
 |     WCHAR *pathW; | 
 |     int len; | 
 |  | 
 |     TRACE("(%p,%p)\n", iface, pbs); | 
 |  | 
 |     *pbs = NULL; | 
 |     if (V_VT(&This->dir) == VT_I4) | 
 |     { | 
 |         pathW = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); | 
 |         if (!pathW) return E_OUTOFMEMORY; | 
 |         ret = SHGetFolderPathW(NULL, V_I4(&This->dir), NULL, SHGFP_TYPE_CURRENT, | 
 |                 pathW); | 
 |         if (ret == S_OK) | 
 |             *pbs = SysAllocString(pathW); | 
 |         else if (ret == E_INVALIDARG) | 
 |         { | 
 |             FIXME("not implemented for %#x\n", V_I4(&This->dir)); | 
 |             ret = E_NOTIMPL; | 
 |         } | 
 |         HeapFree(GetProcessHeap(), 0, pathW); | 
 |     } | 
 |     else /* VT_BSTR */ | 
 |     { | 
 |         pathW = V_BSTR(&This->dir); | 
 |         len = lstrlenW(pathW); | 
 |         *pbs = SysAllocStringLen(pathW, pathW[len - 1] == '\\' ? len - 1 : len); | 
 |     } | 
 |     if (ret == S_OK && !*pbs) | 
 |         ret = E_OUTOFMEMORY; | 
 |     return ret; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_IsLink(FolderItem *iface, | 
 |         VARIANT_BOOL *pb) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pb); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_IsFolder(FolderItem *iface, | 
 |         VARIANT_BOOL *pb) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pb); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_IsFileSystem(FolderItem *iface, | 
 |         VARIANT_BOOL *pb) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pb); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_IsBrowsable(FolderItem *iface, | 
 |         VARIANT_BOOL *pb) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pb); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_ModifyDate(FolderItem *iface, | 
 |         DATE *pdt) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pdt); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_put_ModifyDate(FolderItem *iface, DATE dt) | 
 | { | 
 |     FIXME("(%p,%f)\n", iface, dt); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Size(FolderItem *iface, LONG *pul) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pul); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_get_Type(FolderItem *iface, BSTR *pbs) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pbs); | 
 |  | 
 |     *pbs = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_Verbs(FolderItem *iface, | 
 |         FolderItemVerbs **ppfic) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppfic); | 
 |  | 
 |     *ppfic = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderItemImpl_InvokeVerb(FolderItem *iface, | 
 |         VARIANT vVerb) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static const FolderItemVtbl FolderItemImpl_Vtbl = { | 
 |     FolderItemImpl_QueryInterface, | 
 |     FolderItemImpl_AddRef, | 
 |     FolderItemImpl_Release, | 
 |     FolderItemImpl_GetTypeInfoCount, | 
 |     FolderItemImpl_GetTypeInfo, | 
 |     FolderItemImpl_GetIDsOfNames, | 
 |     FolderItemImpl_Invoke, | 
 |     FolderItemImpl_get_Application, | 
 |     FolderItemImpl_get_Parent, | 
 |     FolderItemImpl_get_Name, | 
 |     FolderItemImpl_put_Name, | 
 |     FolderItemImpl_get_Path, | 
 |     FolderItemImpl_get_GetLink, | 
 |     FolderItemImpl_get_GetFolder, | 
 |     FolderItemImpl_get_IsLink, | 
 |     FolderItemImpl_get_IsFolder, | 
 |     FolderItemImpl_get_IsFileSystem, | 
 |     FolderItemImpl_get_IsBrowsable, | 
 |     FolderItemImpl_get_ModifyDate, | 
 |     FolderItemImpl_put_ModifyDate, | 
 |     FolderItemImpl_get_Size, | 
 |     FolderItemImpl_get_Type, | 
 |     FolderItemImpl_Verbs, | 
 |     FolderItemImpl_InvokeVerb | 
 | }; | 
 |  | 
 | static HRESULT FolderItem_Constructor(VARIANT *dir, FolderItem **ppfi) | 
 | { | 
 |     FolderItemImpl *This; | 
 |     HRESULT ret; | 
 |  | 
 |     *ppfi = NULL; | 
 |  | 
 |     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderItemImpl)); | 
 |     if (!This) return E_OUTOFMEMORY; | 
 |     This->FolderItem_iface.lpVtbl = &FolderItemImpl_Vtbl; | 
 |     This->ref = 1; | 
 |  | 
 |     ret = load_type_info(&IID_FolderItem, &This->iTypeInfo); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |         return ret; | 
 |     } | 
 |  | 
 |     VariantInit(&This->dir); | 
 |     ret = VariantCopy(&This->dir, dir); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         ITypeInfo_Release(This->iTypeInfo); | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |         return E_OUTOFMEMORY; | 
 |     } | 
 |  | 
 |     *ppfi = (FolderItem*)This; | 
 |     return ret; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid, | 
 |         LPVOID *ppv) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p)\n", iface, riid, ppv); | 
 |  | 
 |     if (!ppv) return E_INVALIDARG; | 
 |  | 
 |     if (IsEqualIID(&IID_IUnknown, riid) || | 
 |         IsEqualIID(&IID_IDispatch, riid) || | 
 |         IsEqualIID(&IID_Folder, riid) || | 
 |         IsEqualIID(&IID_Folder2, riid) || | 
 |         IsEqualIID(&IID_Folder3, riid)) | 
 |         *ppv = This; | 
 |     else | 
 |     { | 
 |         FIXME("not implemented for %s\n", shdebugstr_guid(riid)); | 
 |         *ppv = NULL; | 
 |         return E_NOINTERFACE; | 
 |     } | 
 |     IUnknown_AddRef((IUnknown*)*ppv); | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |     ULONG ref = InterlockedIncrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     return ref; | 
 | } | 
 |  | 
 | static ULONG WINAPI FolderImpl_Release(Folder3 *iface) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |     ULONG ref = InterlockedDecrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     if (!ref) | 
 |     { | 
 |         VariantClear(&This->dir); | 
 |         ITypeInfo_Release(This->iTypeInfo); | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |     } | 
 |     return ref; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo) | 
 | { | 
 |     TRACE("(%p,%p)\n", iface, pctinfo); | 
 |  | 
 |     *pctinfo = 1; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo, | 
 |         LCID lcid, ITypeInfo **ppTInfo) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |  | 
 |     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo); | 
 |  | 
 |     ITypeInfo_AddRef(This->iTypeInfo); | 
 |     *ppTInfo = This->iTypeInfo; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid, | 
 |         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid, | 
 |             rgDispId); | 
 |  | 
 |     return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, | 
 |             rgDispId); | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember, | 
 |         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, | 
 |         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |  | 
 |     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid, | 
 |             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 |  | 
 |     return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags, | 
 |             pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |     WCHAR *p; | 
 |     int len; | 
 |  | 
 |     TRACE("(%p,%p)\n", iface, pbs); | 
 |  | 
 |     *pbs = NULL; | 
 |  | 
 |     if (V_VT(&This->dir) == VT_I4) | 
 |     { | 
 |         FIXME("special folder constants are not supported\n"); | 
 |         return E_NOTIMPL; | 
 |     } | 
 |     p = PathFindFileNameW(V_BSTR(&This->dir)); | 
 |     len = lstrlenW(p); | 
 |     *pbs = SysAllocStringLen(p, p[len - 1] == '\\' ? len - 1 : len); | 
 |     return *pbs ? S_OK : E_OUTOFMEMORY; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppsf); | 
 |  | 
 |     *ppsf = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR bName, | 
 |         FolderItem **ppid) | 
 | { | 
 |     FIXME("(%p,%s,%p)\n", iface, debugstr_w(bName), ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR bName, | 
 |         VARIANT vOptions) | 
 | { | 
 |     FIXME("(%p,%s)\n", iface, debugstr_w(bName)); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT vItem, | 
 |         VARIANT vOptions) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT vItem, | 
 |         VARIANT vOptions) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT vItem, | 
 |         int iColumn, BSTR *pbs) | 
 | { | 
 |     FIXME("(%p,%d,%p)\n", iface, iColumn, pbs); | 
 |  | 
 |     *pbs = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **ppfi) | 
 | { | 
 |     FolderImpl *This = impl_from_Folder(iface); | 
 |  | 
 |     TRACE("(%p,%p)\n", iface, ppfi); | 
 |  | 
 |     return FolderItem_Constructor(&This->dir, ppfi); | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pul); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface, | 
 |         VARIANT_BOOL *pbHaveToShowWebViewBarricade) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface, | 
 |         VARIANT_BOOL *pbShowWebViewBarricade) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface, | 
 |         VARIANT_BOOL bShowWebViewBarricade) | 
 | { | 
 |     FIXME("(%p,%d)\n", iface, bShowWebViewBarricade); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static const Folder3Vtbl FolderImpl_Vtbl = { | 
 |     FolderImpl_QueryInterface, | 
 |     FolderImpl_AddRef, | 
 |     FolderImpl_Release, | 
 |     FolderImpl_GetTypeInfoCount, | 
 |     FolderImpl_GetTypeInfo, | 
 |     FolderImpl_GetIDsOfNames, | 
 |     FolderImpl_Invoke, | 
 |     FolderImpl_get_Title, | 
 |     FolderImpl_get_Application, | 
 |     FolderImpl_get_Parent, | 
 |     FolderImpl_get_ParentFolder, | 
 |     FolderImpl_Items, | 
 |     FolderImpl_ParseName, | 
 |     FolderImpl_NewFolder, | 
 |     FolderImpl_MoveHere, | 
 |     FolderImpl_CopyHere, | 
 |     FolderImpl_GetDetailsOf, | 
 |     FolderImpl_get_Self, | 
 |     FolderImpl_get_OfflineStatus, | 
 |     FolderImpl_Synchronize, | 
 |     FolderImpl_get_HaveToShowWebViewBarricade, | 
 |     FolderImpl_DismissedWebViewBarricade, | 
 |     FolderImpl_get_ShowWebViewBarricade, | 
 |     FolderImpl_put_ShowWebViewBarricade | 
 | }; | 
 |  | 
 | static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf) | 
 | { | 
 |     FolderImpl *This; | 
 |     HRESULT ret; | 
 |  | 
 |     *ppsdf = NULL; | 
 |  | 
 |     switch (V_VT(dir)) | 
 |     { | 
 |         case VT_I4: | 
 |             /* FIXME: add some checks */ | 
 |             break; | 
 |         case VT_BSTR: | 
 |             if (PathIsDirectoryW(V_BSTR(dir)) && | 
 |                 !PathIsRelativeW(V_BSTR(dir)) && | 
 |                 PathFileExistsW(V_BSTR(dir))) | 
 |                 break; | 
 |         default: | 
 |             return S_FALSE; | 
 |     } | 
 |  | 
 |     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl)); | 
 |     if (!This) return E_OUTOFMEMORY; | 
 |     This->Folder_iface.lpVtbl = &FolderImpl_Vtbl; | 
 |     This->ref = 1; | 
 |  | 
 |     ret = load_type_info(&IID_Folder3, &This->iTypeInfo); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |         return ret; | 
 |     } | 
 |  | 
 |     VariantInit(&This->dir); | 
 |     ret = VariantCopy(&This->dir, dir); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         ITypeInfo_Release(This->iTypeInfo); | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |         return E_OUTOFMEMORY; | 
 |     } | 
 |  | 
 |     *ppsdf = (Folder*)This; | 
 |     return ret; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch2 *iface, | 
 |         REFIID riid, LPVOID *ppv) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p)\n", iface, riid, ppv); | 
 |  | 
 |     if (!ppv) return E_INVALIDARG; | 
 |  | 
 |     if (IsEqualIID(&IID_IUnknown, riid) || | 
 |         IsEqualIID(&IID_IDispatch, riid) || | 
 |         IsEqualIID(&IID_IShellDispatch, riid) || | 
 |         IsEqualIID(&IID_IShellDispatch2, riid)) | 
 |         *ppv = This; | 
 |     else | 
 |     { | 
 |         FIXME("not implemented for %s\n", shdebugstr_guid(riid)); | 
 |         *ppv = NULL; | 
 |         return E_NOINTERFACE; | 
 |     } | 
 |  | 
 |     IShellDispatch2_AddRef(iface); | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch2 *iface) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |     ULONG ref = InterlockedIncrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     return ref; | 
 | } | 
 |  | 
 | static ULONG WINAPI ShellDispatch_Release(IShellDispatch2 *iface) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |     ULONG ref = InterlockedDecrement(&This->ref); | 
 |  | 
 |     TRACE("(%p), new refcount=%i\n", iface, ref); | 
 |  | 
 |     if (!ref) | 
 |     { | 
 |         ITypeInfo_Release(This->typeinfo); | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |     } | 
 |     return ref; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch2 *iface, | 
 |         UINT *pctinfo) | 
 | { | 
 |     TRACE("(%p,%p)\n", iface, pctinfo); | 
 |  | 
 |     *pctinfo = 1; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch2 *iface, | 
 |         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |  | 
 |     TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo); | 
 |  | 
 |     ITypeInfo_AddRef(This->typeinfo); | 
 |     *ppTInfo = This->typeinfo; | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch2 *iface, | 
 |         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |  | 
 |     TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid, | 
 |             rgDispId); | 
 |  | 
 |     return ITypeInfo_GetIDsOfNames(This->typeinfo, rgszNames, cNames, rgDispId); | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch2 *iface, | 
 |         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, | 
 |         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, | 
 |         UINT *puArgErr) | 
 | { | 
 |     ShellDispatch *This = impl_from_IShellDispatch2(iface); | 
 |  | 
 |     TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid, | 
 |             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 |  | 
 |     return ITypeInfo_Invoke(This->typeinfo, This, dispIdMember, wFlags, | 
 |             pDispParams, pVarResult, pExcepInfo, puArgErr); | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch2 *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch2 *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch2 *iface, | 
 |         VARIANT vDir, Folder **ppsdf) | 
 | { | 
 |     TRACE("(%p,%p)\n", iface, ppsdf); | 
 |  | 
 |     return Folder_Constructor(&vDir, ppsdf); | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch2 *iface, | 
 |         LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf) | 
 | { | 
 |     FIXME("(%p,%x,%s,%x,%p)\n", iface, Hwnd, debugstr_w(Title), Options, ppsdf); | 
 |  | 
 |     *ppsdf = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch2 *iface, | 
 |         IDispatch **ppid) | 
 | { | 
 |     FIXME("(%p,%p)\n", iface, ppid); | 
 |  | 
 |     *ppid = NULL; | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Open(IShellDispatch2 *iface, VARIANT vDir) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch2 *iface, VARIANT vDir) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_Help(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch2 *iface) | 
 | { | 
 |     FIXME("(%p)\n", iface); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch2 *iface, | 
 |         BSTR szDir) | 
 | { | 
 |     FIXME("(%p,%s)\n", iface, debugstr_w(szDir)); | 
 |  | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_IsRestricted(IShellDispatch2 *iface, BSTR group, BSTR restriction, LONG *value) | 
 | { | 
 |     FIXME("(%s, %s, %p): stub\n", debugstr_w(group), debugstr_w(restriction), value); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ShellExecute(IShellDispatch2 *iface, BSTR file, VARIANT args, VARIANT dir, | 
 |         VARIANT op, VARIANT show) | 
 | { | 
 |     FIXME("(%s): stub\n", debugstr_w(file)); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_FindPrinter(IShellDispatch2 *iface, BSTR name, BSTR location, BSTR model) | 
 | { | 
 |     FIXME("(%s, %s, %s): stub\n", debugstr_w(name), debugstr_w(location), debugstr_w(model)); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_GetSystemInformation(IShellDispatch2 *iface, BSTR name, VARIANT *ret) | 
 | { | 
 |     FIXME("(%s, %p): stub\n", debugstr_w(name), ret); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ServiceStart(IShellDispatch2 *iface, BSTR service, VARIANT persistent, VARIANT *ret) | 
 | { | 
 |     FIXME("(%s, %p): stub\n", debugstr_w(service), ret); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ServiceStop(IShellDispatch2 *iface, BSTR service, VARIANT persistent, VARIANT *ret) | 
 | { | 
 |     FIXME("(%s, %p): stub\n", debugstr_w(service), ret); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_IsServiceRunning(IShellDispatch2 *iface, BSTR name, VARIANT *running) | 
 | { | 
 |     SERVICE_STATUS_PROCESS status; | 
 |     SC_HANDLE scm, service; | 
 |     DWORD dummy; | 
 |  | 
 |     TRACE("(%s, %p)\n", debugstr_w(name), running); | 
 |  | 
 |     V_VT(running) = VT_BOOL; | 
 |     V_BOOL(running) = VARIANT_FALSE; | 
 |  | 
 |     scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); | 
 |     if (!scm) | 
 |     { | 
 |         ERR("failed to connect to service manager\n"); | 
 |         return S_OK; | 
 |     } | 
 |  | 
 |     service = OpenServiceW(scm, name, SERVICE_QUERY_STATUS); | 
 |     if (!service) | 
 |     { | 
 |         ERR("Failed to open service %s (%u)\n", debugstr_w(name), GetLastError()); | 
 |         CloseServiceHandle(service); | 
 |         return S_OK; | 
 |     } | 
 |  | 
 |     if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, | 
 |              sizeof(SERVICE_STATUS_PROCESS), &dummy)) | 
 |     { | 
 |         TRACE("failed to query service status (%u)\n", GetLastError()); | 
 |         CloseServiceHandle(service); | 
 |         CloseServiceHandle(scm); | 
 |         return S_OK; | 
 |     } | 
 |  | 
 |     if (status.dwCurrentState == SERVICE_RUNNING) | 
 |        V_BOOL(running) = VARIANT_TRUE; | 
 |  | 
 |     CloseServiceHandle(service); | 
 |     CloseServiceHandle(scm); | 
 |  | 
 |     return S_OK; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_CanStartStopService(IShellDispatch2 *iface, BSTR service, VARIANT *ret) | 
 | { | 
 |     FIXME("(%s, %p): stub\n", debugstr_w(service), ret); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static HRESULT WINAPI ShellDispatch_ShowBrowserBar(IShellDispatch2 *iface, BSTR clsid, VARIANT show, VARIANT *ret) | 
 | { | 
 |     FIXME("(%s, %p): stub\n", debugstr_w(clsid), ret); | 
 |     return E_NOTIMPL; | 
 | } | 
 |  | 
 | static const IShellDispatch2Vtbl ShellDispatch2Vtbl = { | 
 |     ShellDispatch_QueryInterface, | 
 |     ShellDispatch_AddRef, | 
 |     ShellDispatch_Release, | 
 |     ShellDispatch_GetTypeInfoCount, | 
 |     ShellDispatch_GetTypeInfo, | 
 |     ShellDispatch_GetIDsOfNames, | 
 |     ShellDispatch_Invoke, | 
 |     ShellDispatch_get_Application, | 
 |     ShellDispatch_get_Parent, | 
 |     ShellDispatch_NameSpace, | 
 |     ShellDispatch_BrowseForFolder, | 
 |     ShellDispatch_Windows, | 
 |     ShellDispatch_Open, | 
 |     ShellDispatch_Explore, | 
 |     ShellDispatch_MinimizeAll, | 
 |     ShellDispatch_UndoMinimizeALL, | 
 |     ShellDispatch_FileRun, | 
 |     ShellDispatch_CascadeWindows, | 
 |     ShellDispatch_TileVertically, | 
 |     ShellDispatch_TileHorizontally, | 
 |     ShellDispatch_ShutdownWindows, | 
 |     ShellDispatch_Suspend, | 
 |     ShellDispatch_EjectPC, | 
 |     ShellDispatch_SetTime, | 
 |     ShellDispatch_TrayProperties, | 
 |     ShellDispatch_Help, | 
 |     ShellDispatch_FindFiles, | 
 |     ShellDispatch_FindComputer, | 
 |     ShellDispatch_RefreshMenu, | 
 |     ShellDispatch_ControlPanelItem, | 
 |     ShellDispatch_IsRestricted, | 
 |     ShellDispatch_ShellExecute, | 
 |     ShellDispatch_FindPrinter, | 
 |     ShellDispatch_GetSystemInformation, | 
 |     ShellDispatch_ServiceStart, | 
 |     ShellDispatch_ServiceStop, | 
 |     ShellDispatch_IsServiceRunning, | 
 |     ShellDispatch_CanStartStopService, | 
 |     ShellDispatch_ShowBrowserBar | 
 | }; | 
 |  | 
 | HRESULT WINAPI IShellDispatch_Constructor(IUnknown *outer, REFIID riid, void **ppv) | 
 | { | 
 |     ShellDispatch *This; | 
 |     HRESULT ret; | 
 |  | 
 |     TRACE("(%p, %s)\n", outer, debugstr_guid(riid)); | 
 |  | 
 |     *ppv = NULL; | 
 |  | 
 |     if (outer) return CLASS_E_NOAGGREGATION; | 
 |  | 
 |     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellDispatch)); | 
 |     if (!This) return E_OUTOFMEMORY; | 
 |     This->IShellDispatch2_iface.lpVtbl = &ShellDispatch2Vtbl; | 
 |     This->ref = 1; | 
 |  | 
 |     ret = load_type_info(&IID_IShellDispatch2, &This->typeinfo); | 
 |     if (FAILED(ret)) | 
 |     { | 
 |         HeapFree(GetProcessHeap(), 0, This); | 
 |         return ret; | 
 |     } | 
 |  | 
 |     ret = IShellDispatch2_QueryInterface(&This->IShellDispatch2_iface, riid, ppv); | 
 |     IShellDispatch2_Release(&This->IShellDispatch2_iface); | 
 |     return ret; | 
 | } |