shell32: Release iTypeInfo on error.
[wine/multimedia.git] / dlls / shell32 / shelldispatch.c
blob4458252a5a633ddb38be456aaefd8c25490d294b
1 /*
2 * IShellDispatch implementation
4 * Copyright 2010 Alexander Morozov for Etersoft
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
26 #define COBJMACROS
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "shlwapi.h"
34 #include "shlobj.h"
35 #include "shldisp.h"
36 #include "debughlp.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(shell);
42 typedef struct {
43 IShellDispatch IShellDispatch_iface;
44 LONG ref;
45 ITypeInfo *iTypeInfo;
46 } ShellDispatch;
48 typedef struct {
49 Folder3 Folder_iface;
50 LONG ref;
51 ITypeInfo *iTypeInfo;
52 VARIANT dir;
53 } FolderImpl;
55 static inline ShellDispatch *impl_from_IShellDispatch(IShellDispatch *iface)
57 return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch_iface);
60 static inline FolderImpl *impl_from_Folder(Folder3 *iface)
62 return CONTAINING_RECORD(iface, FolderImpl, Folder_iface);
65 static HRESULT load_type_info(REFGUID guid, ITypeInfo **pptinfo)
67 ITypeLib *typelib;
68 HRESULT ret;
70 ret = LoadRegTypeLib(&LIBID_Shell32, 1, 0, LOCALE_SYSTEM_DEFAULT, &typelib);
71 if (FAILED(ret))
73 ERR("LoadRegTypeLib failed: %08x\n", ret);
74 return ret;
77 ret = ITypeLib_GetTypeInfoOfGuid(typelib, guid, pptinfo);
78 ITypeLib_Release(typelib);
79 if (FAILED(ret))
80 ERR("failed to load ITypeInfo\n");
82 return ret;
85 static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
86 LPVOID *ppv)
88 FolderImpl *This = impl_from_Folder(iface);
90 TRACE("(%p,%p,%p)\n", iface, riid, ppv);
92 if (!ppv) return E_INVALIDARG;
94 if (IsEqualIID(&IID_IUnknown, riid) ||
95 IsEqualIID(&IID_IDispatch, riid) ||
96 IsEqualIID(&IID_Folder, riid) ||
97 IsEqualIID(&IID_Folder2, riid) ||
98 IsEqualIID(&IID_Folder3, riid))
99 *ppv = This;
100 else
102 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
103 *ppv = NULL;
104 return E_NOINTERFACE;
106 IUnknown_AddRef((IUnknown*)*ppv);
107 return S_OK;
110 static ULONG WINAPI FolderImpl_AddRef(Folder3 *iface)
112 FolderImpl *This = impl_from_Folder(iface);
113 ULONG ref = InterlockedIncrement(&This->ref);
115 TRACE("(%p), new refcount=%i\n", iface, ref);
117 return ref;
120 static ULONG WINAPI FolderImpl_Release(Folder3 *iface)
122 FolderImpl *This = impl_from_Folder(iface);
123 ULONG ref = InterlockedDecrement(&This->ref);
125 TRACE("(%p), new refcount=%i\n", iface, ref);
127 if (!ref)
129 VariantClear(&This->dir);
130 ITypeInfo_Release(This->iTypeInfo);
131 HeapFree(GetProcessHeap(), 0, This);
133 return ref;
136 static HRESULT WINAPI FolderImpl_GetTypeInfoCount(Folder3 *iface, UINT *pctinfo)
138 TRACE("(%p,%p)\n", iface, pctinfo);
140 *pctinfo = 1;
141 return S_OK;
144 static HRESULT WINAPI FolderImpl_GetTypeInfo(Folder3 *iface, UINT iTInfo,
145 LCID lcid, ITypeInfo **ppTInfo)
147 FolderImpl *This = impl_from_Folder(iface);
149 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
151 ITypeInfo_AddRef(This->iTypeInfo);
152 *ppTInfo = This->iTypeInfo;
153 return S_OK;
156 static HRESULT WINAPI FolderImpl_GetIDsOfNames(Folder3 *iface, REFIID riid,
157 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
159 FolderImpl *This = impl_from_Folder(iface);
161 TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
162 rgDispId);
164 return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames,
165 rgDispId);
168 static HRESULT WINAPI FolderImpl_Invoke(Folder3 *iface, DISPID dispIdMember,
169 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
170 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
172 FolderImpl *This = impl_from_Folder(iface);
174 TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
175 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
177 return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
178 pDispParams, pVarResult, pExcepInfo, puArgErr);
181 static HRESULT WINAPI FolderImpl_get_Title(Folder3 *iface, BSTR *pbs)
183 FolderImpl *This = impl_from_Folder(iface);
184 WCHAR *p;
185 int len;
187 TRACE("(%p,%p)\n", iface, pbs);
189 *pbs = NULL;
191 if (V_VT(&This->dir) == VT_I4)
193 FIXME("special folder constants are not supported\n");
194 return E_NOTIMPL;
196 p = PathFindFileNameW(V_BSTR(&This->dir));
197 len = lstrlenW(p);
198 *pbs = SysAllocStringLen(p, p[len - 1] == '\\' ? len - 1 : len);
199 return *pbs ? S_OK : E_OUTOFMEMORY;
202 static HRESULT WINAPI FolderImpl_get_Application(Folder3 *iface,
203 IDispatch **ppid)
205 FIXME("(%p,%p)\n", iface, ppid);
207 *ppid = NULL;
208 return E_NOTIMPL;
211 static HRESULT WINAPI FolderImpl_get_Parent(Folder3 *iface, IDispatch **ppid)
213 FIXME("(%p,%p)\n", iface, ppid);
215 *ppid = NULL;
216 return E_NOTIMPL;
219 static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
221 FIXME("(%p,%p)\n", iface, ppsf);
223 *ppsf = NULL;
224 return E_NOTIMPL;
227 static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
229 FIXME("(%p,%p)\n", iface, ppid);
231 *ppid = NULL;
232 return E_NOTIMPL;
235 static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR bName,
236 FolderItem **ppid)
238 FIXME("(%p,%s,%p)\n", iface, debugstr_w(bName), ppid);
240 *ppid = NULL;
241 return E_NOTIMPL;
244 static HRESULT WINAPI FolderImpl_NewFolder(Folder3 *iface, BSTR bName,
245 VARIANT vOptions)
247 FIXME("(%p,%s)\n", iface, debugstr_w(bName));
249 return E_NOTIMPL;
252 static HRESULT WINAPI FolderImpl_MoveHere(Folder3 *iface, VARIANT vItem,
253 VARIANT vOptions)
255 FIXME("(%p)\n", iface);
257 return E_NOTIMPL;
260 static HRESULT WINAPI FolderImpl_CopyHere(Folder3 *iface, VARIANT vItem,
261 VARIANT vOptions)
263 FIXME("(%p)\n", iface);
265 return E_NOTIMPL;
268 static HRESULT WINAPI FolderImpl_GetDetailsOf(Folder3 *iface, VARIANT vItem,
269 int iColumn, BSTR *pbs)
271 FIXME("(%p,%d,%p)\n", iface, iColumn, pbs);
273 *pbs = NULL;
274 return E_NOTIMPL;
277 static HRESULT WINAPI FolderImpl_get_Self(Folder3 *iface, FolderItem **ppfi)
279 FIXME("(%p,%p)\n", iface, ppfi);
281 *ppfi = NULL;
282 return E_NOTIMPL;
285 static HRESULT WINAPI FolderImpl_get_OfflineStatus(Folder3 *iface, LONG *pul)
287 FIXME("(%p,%p)\n", iface, pul);
289 return E_NOTIMPL;
292 static HRESULT WINAPI FolderImpl_Synchronize(Folder3 *iface)
294 FIXME("(%p)\n", iface);
296 return E_NOTIMPL;
299 static HRESULT WINAPI FolderImpl_get_HaveToShowWebViewBarricade(Folder3 *iface,
300 VARIANT_BOOL *pbHaveToShowWebViewBarricade)
302 FIXME("(%p,%p)\n", iface, pbHaveToShowWebViewBarricade);
304 return E_NOTIMPL;
307 static HRESULT WINAPI FolderImpl_DismissedWebViewBarricade(Folder3 *iface)
309 FIXME("(%p)\n", iface);
311 return E_NOTIMPL;
314 static HRESULT WINAPI FolderImpl_get_ShowWebViewBarricade(Folder3 *iface,
315 VARIANT_BOOL *pbShowWebViewBarricade)
317 FIXME("(%p,%p)\n", iface, pbShowWebViewBarricade);
319 return E_NOTIMPL;
322 static HRESULT WINAPI FolderImpl_put_ShowWebViewBarricade(Folder3 *iface,
323 VARIANT_BOOL bShowWebViewBarricade)
325 FIXME("(%p,%d)\n", iface, bShowWebViewBarricade);
327 return E_NOTIMPL;
330 static const Folder3Vtbl FolderImpl_Vtbl = {
331 FolderImpl_QueryInterface,
332 FolderImpl_AddRef,
333 FolderImpl_Release,
334 FolderImpl_GetTypeInfoCount,
335 FolderImpl_GetTypeInfo,
336 FolderImpl_GetIDsOfNames,
337 FolderImpl_Invoke,
338 FolderImpl_get_Title,
339 FolderImpl_get_Application,
340 FolderImpl_get_Parent,
341 FolderImpl_get_ParentFolder,
342 FolderImpl_Items,
343 FolderImpl_ParseName,
344 FolderImpl_NewFolder,
345 FolderImpl_MoveHere,
346 FolderImpl_CopyHere,
347 FolderImpl_GetDetailsOf,
348 FolderImpl_get_Self,
349 FolderImpl_get_OfflineStatus,
350 FolderImpl_Synchronize,
351 FolderImpl_get_HaveToShowWebViewBarricade,
352 FolderImpl_DismissedWebViewBarricade,
353 FolderImpl_get_ShowWebViewBarricade,
354 FolderImpl_put_ShowWebViewBarricade
357 static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf)
359 FolderImpl *This;
360 HRESULT ret;
362 *ppsdf = NULL;
364 switch (V_VT(dir))
366 case VT_I4:
367 /* FIXME: add some checks */
368 break;
369 case VT_BSTR:
370 if (PathIsDirectoryW(V_BSTR(dir)) &&
371 !PathIsRelativeW(V_BSTR(dir)) &&
372 PathFileExistsW(V_BSTR(dir)))
373 break;
374 default:
375 return S_FALSE;
378 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl));
379 if (!This) return E_OUTOFMEMORY;
380 This->Folder_iface.lpVtbl = &FolderImpl_Vtbl;
381 This->ref = 1;
383 ret = load_type_info(&IID_Folder3, &This->iTypeInfo);
384 if (FAILED(ret))
386 HeapFree(GetProcessHeap(), 0, This);
387 return ret;
390 VariantInit(&This->dir);
391 ret = VariantCopy(&This->dir, dir);
392 if (FAILED(ret))
394 ITypeInfo_Release(This->iTypeInfo);
395 HeapFree(GetProcessHeap(), 0, This);
396 return E_OUTOFMEMORY;
399 *ppsdf = (Folder*)This;
400 return ret;
403 static HRESULT WINAPI ShellDispatch_QueryInterface(IShellDispatch *iface,
404 REFIID riid, LPVOID *ppv)
406 ShellDispatch *This = impl_from_IShellDispatch(iface);
408 TRACE("(%p,%p,%p)\n", iface, riid, ppv);
410 if (!ppv) return E_INVALIDARG;
412 if (IsEqualIID(&IID_IUnknown, riid) ||
413 IsEqualIID(&IID_IDispatch, riid) ||
414 IsEqualIID(&IID_IShellDispatch, riid))
415 *ppv = This;
416 else
418 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
419 *ppv = NULL;
420 return E_NOINTERFACE;
422 IUnknown_AddRef((IUnknown*)*ppv);
423 return S_OK;
426 static ULONG WINAPI ShellDispatch_AddRef(IShellDispatch *iface)
428 ShellDispatch *This = impl_from_IShellDispatch(iface);
429 ULONG ref = InterlockedIncrement(&This->ref);
431 TRACE("(%p), new refcount=%i\n", iface, ref);
433 return ref;
436 static ULONG WINAPI ShellDispatch_Release(IShellDispatch *iface)
438 ShellDispatch *This = impl_from_IShellDispatch(iface);
439 ULONG ref = InterlockedDecrement(&This->ref);
441 TRACE("(%p), new refcount=%i\n", iface, ref);
443 if (!ref)
445 ITypeInfo_Release(This->iTypeInfo);
446 HeapFree(GetProcessHeap(), 0, This);
448 return ref;
451 static HRESULT WINAPI ShellDispatch_GetTypeInfoCount(IShellDispatch *iface,
452 UINT *pctinfo)
454 TRACE("(%p,%p)\n", iface, pctinfo);
456 *pctinfo = 1;
457 return S_OK;
460 static HRESULT WINAPI ShellDispatch_GetTypeInfo(IShellDispatch *iface,
461 UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
463 ShellDispatch *This = impl_from_IShellDispatch(iface);
465 TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
467 ITypeInfo_AddRef(This->iTypeInfo);
468 *ppTInfo = This->iTypeInfo;
469 return S_OK;
472 static HRESULT WINAPI ShellDispatch_GetIDsOfNames(IShellDispatch *iface,
473 REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
475 ShellDispatch *This = impl_from_IShellDispatch(iface);
477 TRACE("(%p,%p,%p,%u,%d,%p)\n", iface, riid, rgszNames, cNames, lcid,
478 rgDispId);
480 return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId);
483 static HRESULT WINAPI ShellDispatch_Invoke(IShellDispatch *iface,
484 DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
485 DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
486 UINT *puArgErr)
488 ShellDispatch *This = impl_from_IShellDispatch(iface);
490 TRACE("(%p,%d,%p,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, riid, lcid,
491 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
493 return ITypeInfo_Invoke(This->iTypeInfo, This, dispIdMember, wFlags,
494 pDispParams, pVarResult, pExcepInfo, puArgErr);
497 static HRESULT WINAPI ShellDispatch_get_Application(IShellDispatch *iface,
498 IDispatch **ppid)
500 FIXME("(%p,%p)\n", iface, ppid);
502 *ppid = NULL;
503 return E_NOTIMPL;
506 static HRESULT WINAPI ShellDispatch_get_Parent(IShellDispatch *iface,
507 IDispatch **ppid)
509 FIXME("(%p,%p)\n", iface, ppid);
511 *ppid = NULL;
512 return E_NOTIMPL;
515 static HRESULT WINAPI ShellDispatch_NameSpace(IShellDispatch *iface,
516 VARIANT vDir, Folder **ppsdf)
518 TRACE("(%p,%p)\n", iface, ppsdf);
520 return Folder_Constructor(&vDir, ppsdf);
523 static HRESULT WINAPI ShellDispatch_BrowseForFolder(IShellDispatch *iface,
524 LONG Hwnd, BSTR Title, LONG Options, VARIANT RootFolder, Folder **ppsdf)
526 FIXME("(%p,%x,%s,%x,%p)\n", iface, Hwnd, debugstr_w(Title), Options, ppsdf);
528 *ppsdf = NULL;
529 return E_NOTIMPL;
532 static HRESULT WINAPI ShellDispatch_Windows(IShellDispatch *iface,
533 IDispatch **ppid)
535 FIXME("(%p,%p)\n", iface, ppid);
537 *ppid = NULL;
538 return E_NOTIMPL;
541 static HRESULT WINAPI ShellDispatch_Open(IShellDispatch *iface, VARIANT vDir)
543 FIXME("(%p)\n", iface);
545 return E_NOTIMPL;
548 static HRESULT WINAPI ShellDispatch_Explore(IShellDispatch *iface, VARIANT vDir)
550 FIXME("(%p)\n", iface);
552 return E_NOTIMPL;
555 static HRESULT WINAPI ShellDispatch_MinimizeAll(IShellDispatch *iface)
557 FIXME("(%p)\n", iface);
559 return E_NOTIMPL;
562 static HRESULT WINAPI ShellDispatch_UndoMinimizeALL(IShellDispatch *iface)
564 FIXME("(%p)\n", iface);
566 return E_NOTIMPL;
569 static HRESULT WINAPI ShellDispatch_FileRun(IShellDispatch *iface)
571 FIXME("(%p)\n", iface);
573 return E_NOTIMPL;
576 static HRESULT WINAPI ShellDispatch_CascadeWindows(IShellDispatch *iface)
578 FIXME("(%p)\n", iface);
580 return E_NOTIMPL;
583 static HRESULT WINAPI ShellDispatch_TileVertically(IShellDispatch *iface)
585 FIXME("(%p)\n", iface);
587 return E_NOTIMPL;
590 static HRESULT WINAPI ShellDispatch_TileHorizontally(IShellDispatch *iface)
592 FIXME("(%p)\n", iface);
594 return E_NOTIMPL;
597 static HRESULT WINAPI ShellDispatch_ShutdownWindows(IShellDispatch *iface)
599 FIXME("(%p)\n", iface);
601 return E_NOTIMPL;
604 static HRESULT WINAPI ShellDispatch_Suspend(IShellDispatch *iface)
606 FIXME("(%p)\n", iface);
608 return E_NOTIMPL;
611 static HRESULT WINAPI ShellDispatch_EjectPC(IShellDispatch *iface)
613 FIXME("(%p)\n", iface);
615 return E_NOTIMPL;
618 static HRESULT WINAPI ShellDispatch_SetTime(IShellDispatch *iface)
620 FIXME("(%p)\n", iface);
622 return E_NOTIMPL;
625 static HRESULT WINAPI ShellDispatch_TrayProperties(IShellDispatch *iface)
627 FIXME("(%p)\n", iface);
629 return E_NOTIMPL;
632 static HRESULT WINAPI ShellDispatch_Help(IShellDispatch *iface)
634 FIXME("(%p)\n", iface);
636 return E_NOTIMPL;
639 static HRESULT WINAPI ShellDispatch_FindFiles(IShellDispatch *iface)
641 FIXME("(%p)\n", iface);
643 return E_NOTIMPL;
646 static HRESULT WINAPI ShellDispatch_FindComputer(IShellDispatch *iface)
648 FIXME("(%p)\n", iface);
650 return E_NOTIMPL;
653 static HRESULT WINAPI ShellDispatch_RefreshMenu(IShellDispatch *iface)
655 FIXME("(%p)\n", iface);
657 return E_NOTIMPL;
660 static HRESULT WINAPI ShellDispatch_ControlPanelItem(IShellDispatch *iface,
661 BSTR szDir)
663 FIXME("(%p,%s)\n", iface, debugstr_w(szDir));
665 return E_NOTIMPL;
668 static const IShellDispatchVtbl ShellDispatch_Vtbl = {
669 ShellDispatch_QueryInterface,
670 ShellDispatch_AddRef,
671 ShellDispatch_Release,
672 ShellDispatch_GetTypeInfoCount,
673 ShellDispatch_GetTypeInfo,
674 ShellDispatch_GetIDsOfNames,
675 ShellDispatch_Invoke,
676 ShellDispatch_get_Application,
677 ShellDispatch_get_Parent,
678 ShellDispatch_NameSpace,
679 ShellDispatch_BrowseForFolder,
680 ShellDispatch_Windows,
681 ShellDispatch_Open,
682 ShellDispatch_Explore,
683 ShellDispatch_MinimizeAll,
684 ShellDispatch_UndoMinimizeALL,
685 ShellDispatch_FileRun,
686 ShellDispatch_CascadeWindows,
687 ShellDispatch_TileVertically,
688 ShellDispatch_TileHorizontally,
689 ShellDispatch_ShutdownWindows,
690 ShellDispatch_Suspend,
691 ShellDispatch_EjectPC,
692 ShellDispatch_SetTime,
693 ShellDispatch_TrayProperties,
694 ShellDispatch_Help,
695 ShellDispatch_FindFiles,
696 ShellDispatch_FindComputer,
697 ShellDispatch_RefreshMenu,
698 ShellDispatch_ControlPanelItem
701 HRESULT WINAPI IShellDispatch_Constructor(IUnknown *pUnkOuter, REFIID riid,
702 LPVOID *ppv)
704 ShellDispatch *This;
705 HRESULT ret;
707 TRACE("(%p,%s)\n", pUnkOuter, debugstr_guid(riid));
709 *ppv = NULL;
711 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
713 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellDispatch));
714 if (!This) return E_OUTOFMEMORY;
715 This->IShellDispatch_iface.lpVtbl = &ShellDispatch_Vtbl;
716 This->ref = 1;
718 ret = load_type_info(&IID_IShellDispatch, &This->iTypeInfo);
719 if (FAILED(ret))
721 HeapFree(GetProcessHeap(), 0, This);
722 return ret;
725 ret = ShellDispatch_QueryInterface(&This->IShellDispatch_iface, riid, ppv);
726 ShellDispatch_Release(&This->IShellDispatch_iface);
727 return ret;