wined3d: Track synchronized buffer maps.
[wine.git] / dlls / wshom.ocx / shell.c
blob09b3fa0bd928ad8941dac6f054c4590d7dbb54fe
1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wshom_private.h"
20 #include "wshom.h"
22 #include "shellapi.h"
23 #include "shlobj.h"
24 #include "dispex.h"
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wshom);
31 static const char *debugstr_variant(const VARIANT *v)
33 if(!v)
34 return "(null)";
36 switch(V_VT(v)) {
37 case VT_EMPTY:
38 return "{VT_EMPTY}";
39 case VT_NULL:
40 return "{VT_NULL}";
41 case VT_I4:
42 return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
43 case VT_R8:
44 return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
45 case VT_BSTR:
46 return wine_dbg_sprintf("{VT_BSTR: %s}", debugstr_w(V_BSTR(v)));
47 case VT_DISPATCH:
48 return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
49 case VT_BOOL:
50 return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
51 case VT_UNKNOWN:
52 return wine_dbg_sprintf("{VT_UNKNOWN: %p}", V_UNKNOWN(v));
53 case VT_UINT:
54 return wine_dbg_sprintf("{VT_UINT: %u}", V_UINT(v));
55 case VT_BSTR|VT_BYREF:
56 return wine_dbg_sprintf("{VT_BSTR|VT_BYREF: ptr %p, data %s}",
57 V_BSTRREF(v), debugstr_w(V_BSTRREF(v) ? *V_BSTRREF(v) : NULL));
58 default:
59 return wine_dbg_sprintf("{vt %d}", V_VT(v));
63 static IWshShell3 WshShell3;
65 typedef struct
67 IWshCollection IWshCollection_iface;
68 LONG ref;
69 } WshCollection;
71 typedef struct
73 IWshShortcut IWshShortcut_iface;
74 LONG ref;
76 IShellLinkW *link;
77 BSTR path_link;
78 } WshShortcut;
80 typedef struct
82 IWshEnvironment IWshEnvironment_iface;
83 LONG ref;
84 } WshEnvironment;
86 static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
88 return CONTAINING_RECORD(iface, WshCollection, IWshCollection_iface);
91 static inline WshShortcut *impl_from_IWshShortcut( IWshShortcut *iface )
93 return CONTAINING_RECORD(iface, WshShortcut, IWshShortcut_iface);
96 static inline WshEnvironment *impl_from_IWshEnvironment( IWshEnvironment *iface )
98 return CONTAINING_RECORD(iface, WshEnvironment, IWshEnvironment_iface);
101 static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
103 WshEnvironment *This = impl_from_IWshEnvironment(iface);
105 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
107 if (IsEqualGUID(riid, &IID_IUnknown) ||
108 IsEqualGUID(riid, &IID_IDispatch) ||
109 IsEqualGUID(riid, &IID_IWshEnvironment))
111 *obj = iface;
112 }else {
113 FIXME("Unknown iface %s\n", debugstr_guid(riid));
114 *obj = NULL;
115 return E_NOINTERFACE;
118 IUnknown_AddRef((IUnknown*)*obj);
119 return S_OK;
122 static ULONG WINAPI WshEnvironment_AddRef(IWshEnvironment *iface)
124 WshEnvironment *This = impl_from_IWshEnvironment(iface);
125 LONG ref = InterlockedIncrement(&This->ref);
126 TRACE("(%p) ref = %d\n", This, ref);
127 return ref;
130 static ULONG WINAPI WshEnvironment_Release(IWshEnvironment *iface)
132 WshEnvironment *This = impl_from_IWshEnvironment(iface);
133 LONG ref = InterlockedDecrement(&This->ref);
134 TRACE("(%p) ref = %d\n", This, ref);
136 if (!ref)
137 HeapFree(GetProcessHeap(), 0, This);
139 return ref;
142 static HRESULT WINAPI WshEnvironment_GetTypeInfoCount(IWshEnvironment *iface, UINT *pctinfo)
144 WshEnvironment *This = impl_from_IWshEnvironment(iface);
145 TRACE("(%p)->(%p)\n", This, pctinfo);
146 *pctinfo = 1;
147 return S_OK;
150 static HRESULT WINAPI WshEnvironment_GetTypeInfo(IWshEnvironment *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
152 WshEnvironment *This = impl_from_IWshEnvironment(iface);
153 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
154 return get_typeinfo(IWshEnvironment_tid, ppTInfo);
157 static HRESULT WINAPI WshEnvironment_GetIDsOfNames(IWshEnvironment *iface, REFIID riid, LPOLESTR *rgszNames,
158 UINT cNames, LCID lcid, DISPID *rgDispId)
160 WshEnvironment *This = impl_from_IWshEnvironment(iface);
161 ITypeInfo *typeinfo;
162 HRESULT hr;
164 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
166 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
167 if(SUCCEEDED(hr))
169 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
170 ITypeInfo_Release(typeinfo);
173 return hr;
176 static HRESULT WINAPI WshEnvironment_Invoke(IWshEnvironment *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
177 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
179 WshEnvironment *This = impl_from_IWshEnvironment(iface);
180 ITypeInfo *typeinfo;
181 HRESULT hr;
183 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
184 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
186 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
187 if(SUCCEEDED(hr))
189 hr = ITypeInfo_Invoke(typeinfo, &This->IWshEnvironment_iface, dispIdMember, wFlags,
190 pDispParams, pVarResult, pExcepInfo, puArgErr);
191 ITypeInfo_Release(typeinfo);
194 return hr;
197 static HRESULT WINAPI WshEnvironment_get_Item(IWshEnvironment *iface, BSTR name, BSTR *value)
199 WshEnvironment *This = impl_from_IWshEnvironment(iface);
200 FIXME("(%p)->(%s %p): stub\n", This, debugstr_w(name), value);
201 return E_NOTIMPL;
204 static HRESULT WINAPI WshEnvironment_put_Item(IWshEnvironment *iface, BSTR name, BSTR value)
206 WshEnvironment *This = impl_from_IWshEnvironment(iface);
207 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_w(value));
208 return E_NOTIMPL;
211 static HRESULT WINAPI WshEnvironment_Count(IWshEnvironment *iface, LONG *count)
213 WshEnvironment *This = impl_from_IWshEnvironment(iface);
214 FIXME("(%p)->(%p): stub\n", This, count);
215 return E_NOTIMPL;
218 static HRESULT WINAPI WshEnvironment_get_length(IWshEnvironment *iface, LONG *len)
220 WshEnvironment *This = impl_from_IWshEnvironment(iface);
221 FIXME("(%p)->(%p): stub\n", This, len);
222 return E_NOTIMPL;
225 static HRESULT WINAPI WshEnvironment__NewEnum(IWshEnvironment *iface, IUnknown **penum)
227 WshEnvironment *This = impl_from_IWshEnvironment(iface);
228 FIXME("(%p)->(%p): stub\n", This, penum);
229 return E_NOTIMPL;
232 static HRESULT WINAPI WshEnvironment_Remove(IWshEnvironment *iface, BSTR name)
234 WshEnvironment *This = impl_from_IWshEnvironment(iface);
235 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
236 return E_NOTIMPL;
239 static const IWshEnvironmentVtbl WshEnvironmentVtbl = {
240 WshEnvironment_QueryInterface,
241 WshEnvironment_AddRef,
242 WshEnvironment_Release,
243 WshEnvironment_GetTypeInfoCount,
244 WshEnvironment_GetTypeInfo,
245 WshEnvironment_GetIDsOfNames,
246 WshEnvironment_Invoke,
247 WshEnvironment_get_Item,
248 WshEnvironment_put_Item,
249 WshEnvironment_Count,
250 WshEnvironment_get_length,
251 WshEnvironment__NewEnum,
252 WshEnvironment_Remove
255 static HRESULT WshEnvironment_Create(IWshEnvironment **env)
257 WshEnvironment *This;
259 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
260 if (!This) return E_OUTOFMEMORY;
262 This->IWshEnvironment_iface.lpVtbl = &WshEnvironmentVtbl;
263 This->ref = 1;
265 *env = &This->IWshEnvironment_iface;
267 return S_OK;
270 static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID riid, void **ppv)
272 WshCollection *This = impl_from_IWshCollection(iface);
274 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
276 if (IsEqualGUID(riid, &IID_IUnknown) ||
277 IsEqualGUID(riid, &IID_IDispatch) ||
278 IsEqualGUID(riid, &IID_IWshCollection))
280 *ppv = iface;
281 }else {
282 FIXME("Unknown iface %s\n", debugstr_guid(riid));
283 *ppv = NULL;
284 return E_NOINTERFACE;
287 IUnknown_AddRef((IUnknown*)*ppv);
288 return S_OK;
291 static ULONG WINAPI WshCollection_AddRef(IWshCollection *iface)
293 WshCollection *This = impl_from_IWshCollection(iface);
294 LONG ref = InterlockedIncrement(&This->ref);
295 TRACE("(%p) ref = %d\n", This, ref);
296 return ref;
299 static ULONG WINAPI WshCollection_Release(IWshCollection *iface)
301 WshCollection *This = impl_from_IWshCollection(iface);
302 LONG ref = InterlockedDecrement(&This->ref);
303 TRACE("(%p) ref = %d\n", This, ref);
305 if (!ref)
306 HeapFree(GetProcessHeap(), 0, This);
308 return ref;
311 static HRESULT WINAPI WshCollection_GetTypeInfoCount(IWshCollection *iface, UINT *pctinfo)
313 WshCollection *This = impl_from_IWshCollection(iface);
314 TRACE("(%p)->(%p)\n", This, pctinfo);
315 *pctinfo = 1;
316 return S_OK;
319 static HRESULT WINAPI WshCollection_GetTypeInfo(IWshCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
321 WshCollection *This = impl_from_IWshCollection(iface);
322 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
323 return get_typeinfo(IWshCollection_tid, ppTInfo);
326 static HRESULT WINAPI WshCollection_GetIDsOfNames(IWshCollection *iface, REFIID riid, LPOLESTR *rgszNames,
327 UINT cNames, LCID lcid, DISPID *rgDispId)
329 WshCollection *This = impl_from_IWshCollection(iface);
330 ITypeInfo *typeinfo;
331 HRESULT hr;
333 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
335 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
336 if(SUCCEEDED(hr))
338 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
339 ITypeInfo_Release(typeinfo);
342 return hr;
345 static HRESULT WINAPI WshCollection_Invoke(IWshCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
346 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
348 WshCollection *This = impl_from_IWshCollection(iface);
349 ITypeInfo *typeinfo;
350 HRESULT hr;
352 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
353 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
355 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
356 if(SUCCEEDED(hr))
358 hr = ITypeInfo_Invoke(typeinfo, &This->IWshCollection_iface, dispIdMember, wFlags,
359 pDispParams, pVarResult, pExcepInfo, puArgErr);
360 ITypeInfo_Release(typeinfo);
363 return hr;
366 static HRESULT WINAPI WshCollection_Item(IWshCollection *iface, VARIANT *index, VARIANT *value)
368 WshCollection *This = impl_from_IWshCollection(iface);
369 static const WCHAR allusersdesktopW[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
370 static const WCHAR allusersprogramsW[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
371 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0};
372 PIDLIST_ABSOLUTE pidl;
373 WCHAR pathW[MAX_PATH];
374 int kind = 0;
375 BSTR folder;
376 HRESULT hr;
378 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(index), value);
380 if (V_VT(index) != VT_BSTR)
382 FIXME("only BSTR index supported, got %d\n", V_VT(index));
383 return E_NOTIMPL;
386 folder = V_BSTR(index);
387 if (!strcmpiW(folder, desktopW))
388 kind = CSIDL_DESKTOP;
389 else if (!strcmpiW(folder, allusersdesktopW))
390 kind = CSIDL_COMMON_DESKTOPDIRECTORY;
391 else if (!strcmpiW(folder, allusersprogramsW))
392 kind = CSIDL_COMMON_PROGRAMS;
393 else
395 FIXME("folder kind %s not supported\n", debugstr_w(folder));
396 return E_NOTIMPL;
399 hr = SHGetSpecialFolderLocation(NULL, kind, &pidl);
400 if (hr != S_OK) return hr;
402 if (SHGetPathFromIDListW(pidl, pathW))
404 V_VT(value) = VT_BSTR;
405 V_BSTR(value) = SysAllocString(pathW);
406 hr = V_BSTR(value) ? S_OK : E_OUTOFMEMORY;
408 else
409 hr = E_FAIL;
411 CoTaskMemFree(pidl);
413 return hr;
416 static HRESULT WINAPI WshCollection_Count(IWshCollection *iface, LONG *count)
418 WshCollection *This = impl_from_IWshCollection(iface);
419 FIXME("(%p)->(%p): stub\n", This, count);
420 return E_NOTIMPL;
423 static HRESULT WINAPI WshCollection_get_length(IWshCollection *iface, LONG *count)
425 WshCollection *This = impl_from_IWshCollection(iface);
426 FIXME("(%p)->(%p): stub\n", This, count);
427 return E_NOTIMPL;
430 static HRESULT WINAPI WshCollection__NewEnum(IWshCollection *iface, IUnknown *Enum)
432 WshCollection *This = impl_from_IWshCollection(iface);
433 FIXME("(%p)->(%p): stub\n", This, Enum);
434 return E_NOTIMPL;
437 static const IWshCollectionVtbl WshCollectionVtbl = {
438 WshCollection_QueryInterface,
439 WshCollection_AddRef,
440 WshCollection_Release,
441 WshCollection_GetTypeInfoCount,
442 WshCollection_GetTypeInfo,
443 WshCollection_GetIDsOfNames,
444 WshCollection_Invoke,
445 WshCollection_Item,
446 WshCollection_Count,
447 WshCollection_get_length,
448 WshCollection__NewEnum
451 static HRESULT WshCollection_Create(IWshCollection **collection)
453 WshCollection *This;
455 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
456 if (!This) return E_OUTOFMEMORY;
458 This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl;
459 This->ref = 1;
461 *collection = &This->IWshCollection_iface;
463 return S_OK;
466 /* IWshShortcut */
467 static HRESULT WINAPI WshShortcut_QueryInterface(IWshShortcut *iface, REFIID riid, void **ppv)
469 WshShortcut *This = impl_from_IWshShortcut(iface);
471 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
473 if (IsEqualGUID(riid, &IID_IUnknown) ||
474 IsEqualGUID(riid, &IID_IDispatch) ||
475 IsEqualGUID(riid, &IID_IWshShortcut))
477 *ppv = iface;
478 }else {
479 FIXME("Unknown iface %s\n", debugstr_guid(riid));
480 *ppv = NULL;
481 return E_NOINTERFACE;
484 IUnknown_AddRef((IUnknown*)*ppv);
485 return S_OK;
488 static ULONG WINAPI WshShortcut_AddRef(IWshShortcut *iface)
490 WshShortcut *This = impl_from_IWshShortcut(iface);
491 LONG ref = InterlockedIncrement(&This->ref);
492 TRACE("(%p) ref = %d\n", This, ref);
493 return ref;
496 static ULONG WINAPI WshShortcut_Release(IWshShortcut *iface)
498 WshShortcut *This = impl_from_IWshShortcut(iface);
499 LONG ref = InterlockedDecrement(&This->ref);
500 TRACE("(%p) ref = %d\n", This, ref);
502 if (!ref)
504 SysFreeString(This->path_link);
505 IShellLinkW_Release(This->link);
506 HeapFree(GetProcessHeap(), 0, This);
509 return ref;
512 static HRESULT WINAPI WshShortcut_GetTypeInfoCount(IWshShortcut *iface, UINT *pctinfo)
514 WshShortcut *This = impl_from_IWshShortcut(iface);
515 TRACE("(%p)->(%p)\n", This, pctinfo);
516 *pctinfo = 1;
517 return S_OK;
520 static HRESULT WINAPI WshShortcut_GetTypeInfo(IWshShortcut *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
522 WshShortcut *This = impl_from_IWshShortcut(iface);
523 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
524 return get_typeinfo(IWshShortcut_tid, ppTInfo);
527 static HRESULT WINAPI WshShortcut_GetIDsOfNames(IWshShortcut *iface, REFIID riid, LPOLESTR *rgszNames,
528 UINT cNames, LCID lcid, DISPID *rgDispId)
530 WshShortcut *This = impl_from_IWshShortcut(iface);
531 ITypeInfo *typeinfo;
532 HRESULT hr;
534 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
536 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
537 if(SUCCEEDED(hr))
539 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
540 ITypeInfo_Release(typeinfo);
543 return hr;
546 static HRESULT WINAPI WshShortcut_Invoke(IWshShortcut *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
547 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
549 WshShortcut *This = impl_from_IWshShortcut(iface);
550 ITypeInfo *typeinfo;
551 HRESULT hr;
553 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
554 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
556 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
557 if(SUCCEEDED(hr))
559 hr = ITypeInfo_Invoke(typeinfo, &This->IWshShortcut_iface, dispIdMember, wFlags,
560 pDispParams, pVarResult, pExcepInfo, puArgErr);
561 ITypeInfo_Release(typeinfo);
564 return hr;
567 static HRESULT WINAPI WshShortcut_get_FullName(IWshShortcut *iface, BSTR *name)
569 WshShortcut *This = impl_from_IWshShortcut(iface);
570 FIXME("(%p)->(%p): stub\n", This, name);
571 return E_NOTIMPL;
574 static HRESULT WINAPI WshShortcut_get_Arguments(IWshShortcut *iface, BSTR *Arguments)
576 WshShortcut *This = impl_from_IWshShortcut(iface);
577 WCHAR buffW[INFOTIPSIZE];
578 HRESULT hr;
580 TRACE("(%p)->(%p)\n", This, Arguments);
582 if (!Arguments)
583 return E_POINTER;
585 *Arguments = NULL;
587 hr = IShellLinkW_GetArguments(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
588 if (FAILED(hr))
589 return hr;
591 *Arguments = SysAllocString(buffW);
592 return *Arguments ? S_OK : E_OUTOFMEMORY;
595 static HRESULT WINAPI WshShortcut_put_Arguments(IWshShortcut *iface, BSTR Arguments)
597 WshShortcut *This = impl_from_IWshShortcut(iface);
599 TRACE("(%p)->(%s)\n", This, debugstr_w(Arguments));
601 return IShellLinkW_SetArguments(This->link, Arguments);
604 static HRESULT WINAPI WshShortcut_get_Description(IWshShortcut *iface, BSTR *Description)
606 WshShortcut *This = impl_from_IWshShortcut(iface);
607 FIXME("(%p)->(%p): stub\n", This, Description);
608 return E_NOTIMPL;
611 static HRESULT WINAPI WshShortcut_put_Description(IWshShortcut *iface, BSTR Description)
613 WshShortcut *This = impl_from_IWshShortcut(iface);
614 TRACE("(%p)->(%s)\n", This, debugstr_w(Description));
615 return IShellLinkW_SetDescription(This->link, Description);
618 static HRESULT WINAPI WshShortcut_get_Hotkey(IWshShortcut *iface, BSTR *Hotkey)
620 WshShortcut *This = impl_from_IWshShortcut(iface);
621 FIXME("(%p)->(%p): stub\n", This, Hotkey);
622 return E_NOTIMPL;
625 static HRESULT WINAPI WshShortcut_put_Hotkey(IWshShortcut *iface, BSTR Hotkey)
627 WshShortcut *This = impl_from_IWshShortcut(iface);
628 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Hotkey));
629 return E_NOTIMPL;
632 static HRESULT WINAPI WshShortcut_get_IconLocation(IWshShortcut *iface, BSTR *IconPath)
634 static const WCHAR fmtW[] = {'%','s',',',' ','%','d',0};
635 WshShortcut *This = impl_from_IWshShortcut(iface);
636 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
637 INT icon = 0;
638 HRESULT hr;
640 TRACE("(%p)->(%p)\n", This, IconPath);
642 if (!IconPath)
643 return E_POINTER;
645 hr = IShellLinkW_GetIconLocation(This->link, buffW, sizeof(buffW)/sizeof(WCHAR), &icon);
646 if (FAILED(hr)) return hr;
648 sprintfW(pathW, fmtW, buffW, icon);
649 *IconPath = SysAllocString(pathW);
650 if (!*IconPath) return E_OUTOFMEMORY;
652 return S_OK;
655 static HRESULT WINAPI WshShortcut_put_IconLocation(IWshShortcut *iface, BSTR IconPath)
657 WshShortcut *This = impl_from_IWshShortcut(iface);
658 HRESULT hr;
659 WCHAR *ptr;
660 BSTR path;
661 INT icon;
663 TRACE("(%p)->(%s)\n", This, debugstr_w(IconPath));
665 /* scan for icon id */
666 ptr = strrchrW(IconPath, ',');
667 if (!ptr)
669 WARN("icon index not found\n");
670 return E_FAIL;
673 path = SysAllocStringLen(IconPath, ptr-IconPath);
675 /* skip spaces if any */
676 while (isspaceW(*++ptr))
679 icon = atoiW(ptr);
681 hr = IShellLinkW_SetIconLocation(This->link, path, icon);
682 SysFreeString(path);
684 return hr;
687 static HRESULT WINAPI WshShortcut_put_RelativePath(IWshShortcut *iface, BSTR rhs)
689 WshShortcut *This = impl_from_IWshShortcut(iface);
690 FIXME("(%p)->(%s): stub\n", This, debugstr_w(rhs));
691 return E_NOTIMPL;
694 static HRESULT WINAPI WshShortcut_get_TargetPath(IWshShortcut *iface, BSTR *Path)
696 WshShortcut *This = impl_from_IWshShortcut(iface);
697 FIXME("(%p)->(%p): stub\n", This, Path);
698 return E_NOTIMPL;
701 static HRESULT WINAPI WshShortcut_put_TargetPath(IWshShortcut *iface, BSTR Path)
703 WshShortcut *This = impl_from_IWshShortcut(iface);
704 TRACE("(%p)->(%s)\n", This, debugstr_w(Path));
705 return IShellLinkW_SetPath(This->link, Path);
708 static HRESULT WINAPI WshShortcut_get_WindowStyle(IWshShortcut *iface, int *ShowCmd)
710 WshShortcut *This = impl_from_IWshShortcut(iface);
711 TRACE("(%p)->(%p)\n", This, ShowCmd);
712 return IShellLinkW_GetShowCmd(This->link, ShowCmd);
715 static HRESULT WINAPI WshShortcut_put_WindowStyle(IWshShortcut *iface, int ShowCmd)
717 WshShortcut *This = impl_from_IWshShortcut(iface);
718 TRACE("(%p)->(%d)\n", This, ShowCmd);
719 return IShellLinkW_SetShowCmd(This->link, ShowCmd);
722 static HRESULT WINAPI WshShortcut_get_WorkingDirectory(IWshShortcut *iface, BSTR *WorkingDirectory)
724 WshShortcut *This = impl_from_IWshShortcut(iface);
725 WCHAR buffW[MAX_PATH];
726 HRESULT hr;
728 TRACE("(%p)->(%p)\n", This, WorkingDirectory);
730 if (!WorkingDirectory)
731 return E_POINTER;
733 *WorkingDirectory = NULL;
734 hr = IShellLinkW_GetWorkingDirectory(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
735 if (FAILED(hr)) return hr;
737 *WorkingDirectory = SysAllocString(buffW);
738 return *WorkingDirectory ? S_OK : E_OUTOFMEMORY;
741 static HRESULT WINAPI WshShortcut_put_WorkingDirectory(IWshShortcut *iface, BSTR WorkingDirectory)
743 WshShortcut *This = impl_from_IWshShortcut(iface);
744 TRACE("(%p)->(%s)\n", This, debugstr_w(WorkingDirectory));
745 return IShellLinkW_SetWorkingDirectory(This->link, WorkingDirectory);
748 static HRESULT WINAPI WshShortcut_Load(IWshShortcut *iface, BSTR PathLink)
750 WshShortcut *This = impl_from_IWshShortcut(iface);
751 FIXME("(%p)->(%s): stub\n", This, debugstr_w(PathLink));
752 return E_NOTIMPL;
755 static HRESULT WINAPI WshShortcut_Save(IWshShortcut *iface)
757 WshShortcut *This = impl_from_IWshShortcut(iface);
758 IPersistFile *file;
759 HRESULT hr;
761 TRACE("(%p)\n", This);
763 IShellLinkW_QueryInterface(This->link, &IID_IPersistFile, (void**)&file);
764 hr = IPersistFile_Save(file, This->path_link, TRUE);
765 IPersistFile_Release(file);
767 return hr;
770 static const IWshShortcutVtbl WshShortcutVtbl = {
771 WshShortcut_QueryInterface,
772 WshShortcut_AddRef,
773 WshShortcut_Release,
774 WshShortcut_GetTypeInfoCount,
775 WshShortcut_GetTypeInfo,
776 WshShortcut_GetIDsOfNames,
777 WshShortcut_Invoke,
778 WshShortcut_get_FullName,
779 WshShortcut_get_Arguments,
780 WshShortcut_put_Arguments,
781 WshShortcut_get_Description,
782 WshShortcut_put_Description,
783 WshShortcut_get_Hotkey,
784 WshShortcut_put_Hotkey,
785 WshShortcut_get_IconLocation,
786 WshShortcut_put_IconLocation,
787 WshShortcut_put_RelativePath,
788 WshShortcut_get_TargetPath,
789 WshShortcut_put_TargetPath,
790 WshShortcut_get_WindowStyle,
791 WshShortcut_put_WindowStyle,
792 WshShortcut_get_WorkingDirectory,
793 WshShortcut_put_WorkingDirectory,
794 WshShortcut_Load,
795 WshShortcut_Save
798 static HRESULT WshShortcut_Create(const WCHAR *path, IDispatch **shortcut)
800 WshShortcut *This;
801 HRESULT hr;
803 *shortcut = NULL;
805 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
806 if (!This) return E_OUTOFMEMORY;
808 This->IWshShortcut_iface.lpVtbl = &WshShortcutVtbl;
809 This->ref = 1;
811 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
812 &IID_IShellLinkW, (void**)&This->link);
813 if (FAILED(hr))
815 HeapFree(GetProcessHeap(), 0, This);
816 return hr;
819 This->path_link = SysAllocString(path);
820 if (!This->path_link)
822 IShellLinkW_Release(This->link);
823 HeapFree(GetProcessHeap(), 0, This);
824 return E_OUTOFMEMORY;
827 *shortcut = (IDispatch*)&This->IWshShortcut_iface;
829 return S_OK;
832 static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
834 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
836 *ppv = NULL;
838 if(IsEqualGUID(riid, &IID_IUnknown) ||
839 IsEqualGUID(riid, &IID_IDispatch) ||
840 IsEqualGUID(riid, &IID_IWshShell3))
842 *ppv = iface;
844 else if (IsEqualGUID(riid, &IID_IDispatchEx))
846 return E_NOINTERFACE;
848 else
850 FIXME("Unknown iface %s\n", debugstr_guid(riid));
851 return E_NOINTERFACE;
854 IWshShell3_AddRef(iface);
855 return S_OK;
858 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
860 TRACE("()\n");
861 return 2;
864 static ULONG WINAPI WshShell3_Release(IWshShell3 *iface)
866 TRACE("()\n");
867 return 2;
870 static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinfo)
872 TRACE("(%p)\n", pctinfo);
873 *pctinfo = 1;
874 return S_OK;
877 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
879 TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
880 return get_typeinfo(IWshShell3_tid, ppTInfo);
883 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
884 UINT cNames, LCID lcid, DISPID *rgDispId)
886 ITypeInfo *typeinfo;
887 HRESULT hr;
889 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
891 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
892 if(SUCCEEDED(hr))
894 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
895 ITypeInfo_Release(typeinfo);
898 return hr;
901 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
902 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
904 ITypeInfo *typeinfo;
905 HRESULT hr;
907 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
908 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
910 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
911 if(SUCCEEDED(hr))
913 hr = ITypeInfo_Invoke(typeinfo, &WshShell3, dispIdMember, wFlags,
914 pDispParams, pVarResult, pExcepInfo, puArgErr);
915 ITypeInfo_Release(typeinfo);
918 return hr;
921 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
923 TRACE("(%p)\n", folders);
924 return WshCollection_Create(folders);
927 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *type, IWshEnvironment **env)
929 FIXME("(%s %p): semi-stub\n", debugstr_variant(type), env);
930 return WshEnvironment_Create(env);
933 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *WaitOnReturn, int *exit_code)
935 SHELLEXECUTEINFOW info;
936 int waitforprocess;
937 VARIANT s, w;
938 HRESULT hr;
940 TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(WaitOnReturn), exit_code);
942 VariantInit(&s);
943 hr = VariantChangeType(&s, style, 0, VT_I4);
944 if (FAILED(hr))
946 ERR("failed to convert style argument, 0x%08x\n", hr);
947 return hr;
950 VariantInit(&w);
951 hr = VariantChangeType(&w, WaitOnReturn, 0, VT_I4);
952 if (FAILED(hr))
954 ERR("failed to convert wait argument, 0x%08x\n", hr);
955 return hr;
958 memset(&info, 0, sizeof(info));
959 info.cbSize = sizeof(info);
961 waitforprocess = V_I4(&w);
963 info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
964 info.lpFile = cmd;
965 info.nShow = V_I4(&s);
967 if (!ShellExecuteExW(&info))
969 TRACE("ShellExecute failed, %d\n", GetLastError());
970 return HRESULT_FROM_WIN32(GetLastError());
972 else
974 if (waitforprocess)
976 if (exit_code)
978 DWORD code;
979 GetExitCodeProcess(info.hProcess, &code);
980 *exit_code = code;
982 CloseHandle(info.hProcess);
984 else
985 if (exit_code) *exit_code = 0;
987 return S_OK;
991 static HRESULT WINAPI WshShell3_Popup(IWshShell3 *iface, BSTR Text, VARIANT* SecondsToWait, VARIANT *Title, VARIANT *Type, int *button)
993 FIXME("(%s %s %s %s %p): stub\n", debugstr_w(Text), debugstr_variant(SecondsToWait),
994 debugstr_variant(Title), debugstr_variant(Type), button);
995 return E_NOTIMPL;
998 static HRESULT WINAPI WshShell3_CreateShortcut(IWshShell3 *iface, BSTR PathLink, IDispatch** Shortcut)
1000 TRACE("(%s %p)\n", debugstr_w(PathLink), Shortcut);
1001 return WshShortcut_Create(PathLink, Shortcut);
1004 static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR Src, BSTR* Dst)
1006 DWORD ret;
1008 TRACE("(%s %p)\n", debugstr_w(Src), Dst);
1010 if (!Src || !Dst) return E_POINTER;
1012 ret = ExpandEnvironmentStringsW(Src, NULL, 0);
1013 *Dst = SysAllocStringLen(NULL, ret);
1014 if (!*Dst) return E_OUTOFMEMORY;
1016 if (ExpandEnvironmentStringsW(Src, *Dst, ret))
1017 return S_OK;
1018 else
1020 SysFreeString(*Dst);
1021 *Dst = NULL;
1022 return HRESULT_FROM_WIN32(GetLastError());
1026 static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR Name, VARIANT* out_Value)
1028 FIXME("(%s %p): stub\n", debugstr_w(Name), out_Value);
1029 return E_NOTIMPL;
1032 static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR Name, VARIANT *Value, VARIANT *Type)
1034 FIXME("(%s %s %s): stub\n", debugstr_w(Name), debugstr_variant(Value), debugstr_variant(Type));
1035 return E_NOTIMPL;
1038 static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name)
1040 FIXME("(%s): stub\n", debugstr_w(Name));
1041 return E_NOTIMPL;
1044 static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR Message, BSTR Target, VARIANT_BOOL *out_Success)
1046 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type), debugstr_w(Message), debugstr_w(Target), out_Success);
1047 return E_NOTIMPL;
1050 static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success)
1052 FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success);
1053 return E_NOTIMPL;
1056 static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait)
1058 FIXME("(%s %p): stub\n", debugstr_w(Keys), Wait);
1059 return E_NOTIMPL;
1062 static const IWshShell3Vtbl WshShell3Vtbl = {
1063 WshShell3_QueryInterface,
1064 WshShell3_AddRef,
1065 WshShell3_Release,
1066 WshShell3_GetTypeInfoCount,
1067 WshShell3_GetTypeInfo,
1068 WshShell3_GetIDsOfNames,
1069 WshShell3_Invoke,
1070 WshShell3_get_SpecialFolders,
1071 WshShell3_get_Environment,
1072 WshShell3_Run,
1073 WshShell3_Popup,
1074 WshShell3_CreateShortcut,
1075 WshShell3_ExpandEnvironmentStrings,
1076 WshShell3_RegRead,
1077 WshShell3_RegWrite,
1078 WshShell3_RegDelete,
1079 WshShell3_LogEvent,
1080 WshShell3_AppActivate,
1081 WshShell3_SendKeys
1084 static IWshShell3 WshShell3 = { &WshShell3Vtbl };
1086 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1088 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
1090 return IWshShell3_QueryInterface(&WshShell3, riid, ppv);