dpnet/tests: Add a trailing '\n' to some ok() calls.
[wine.git] / dlls / wshom.ocx / shell.c
blob09c75041b9104510fec788b0d7e8586290de3af6
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 IWshShell3 WshShell3;
33 typedef struct
35 IWshCollection IWshCollection_iface;
36 LONG ref;
37 } WshCollection;
39 typedef struct
41 IWshShortcut IWshShortcut_iface;
42 LONG ref;
44 IShellLinkW *link;
45 BSTR path_link;
46 } WshShortcut;
48 typedef struct
50 IWshEnvironment IWshEnvironment_iface;
51 LONG ref;
52 } WshEnvironment;
54 static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
56 return CONTAINING_RECORD(iface, WshCollection, IWshCollection_iface);
59 static inline WshShortcut *impl_from_IWshShortcut( IWshShortcut *iface )
61 return CONTAINING_RECORD(iface, WshShortcut, IWshShortcut_iface);
64 static inline WshEnvironment *impl_from_IWshEnvironment( IWshEnvironment *iface )
66 return CONTAINING_RECORD(iface, WshEnvironment, IWshEnvironment_iface);
69 static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
71 WshEnvironment *This = impl_from_IWshEnvironment(iface);
73 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
75 if (IsEqualGUID(riid, &IID_IUnknown) ||
76 IsEqualGUID(riid, &IID_IDispatch) ||
77 IsEqualGUID(riid, &IID_IWshEnvironment))
79 *obj = iface;
80 }else {
81 FIXME("Unknown iface %s\n", debugstr_guid(riid));
82 *obj = NULL;
83 return E_NOINTERFACE;
86 IUnknown_AddRef((IUnknown*)*obj);
87 return S_OK;
90 static ULONG WINAPI WshEnvironment_AddRef(IWshEnvironment *iface)
92 WshEnvironment *This = impl_from_IWshEnvironment(iface);
93 LONG ref = InterlockedIncrement(&This->ref);
94 TRACE("(%p) ref = %d\n", This, ref);
95 return ref;
98 static ULONG WINAPI WshEnvironment_Release(IWshEnvironment *iface)
100 WshEnvironment *This = impl_from_IWshEnvironment(iface);
101 LONG ref = InterlockedDecrement(&This->ref);
102 TRACE("(%p) ref = %d\n", This, ref);
104 if (!ref)
105 HeapFree(GetProcessHeap(), 0, This);
107 return ref;
110 static HRESULT WINAPI WshEnvironment_GetTypeInfoCount(IWshEnvironment *iface, UINT *pctinfo)
112 WshEnvironment *This = impl_from_IWshEnvironment(iface);
113 TRACE("(%p)->(%p)\n", This, pctinfo);
114 *pctinfo = 1;
115 return S_OK;
118 static HRESULT WINAPI WshEnvironment_GetTypeInfo(IWshEnvironment *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
120 WshEnvironment *This = impl_from_IWshEnvironment(iface);
121 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
122 return get_typeinfo(IWshEnvironment_tid, ppTInfo);
125 static HRESULT WINAPI WshEnvironment_GetIDsOfNames(IWshEnvironment *iface, REFIID riid, LPOLESTR *rgszNames,
126 UINT cNames, LCID lcid, DISPID *rgDispId)
128 WshEnvironment *This = impl_from_IWshEnvironment(iface);
129 ITypeInfo *typeinfo;
130 HRESULT hr;
132 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
134 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
135 if(SUCCEEDED(hr))
137 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
138 ITypeInfo_Release(typeinfo);
141 return hr;
144 static HRESULT WINAPI WshEnvironment_Invoke(IWshEnvironment *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
145 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
147 WshEnvironment *This = impl_from_IWshEnvironment(iface);
148 ITypeInfo *typeinfo;
149 HRESULT hr;
151 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
152 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
154 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
155 if(SUCCEEDED(hr))
157 hr = ITypeInfo_Invoke(typeinfo, &This->IWshEnvironment_iface, dispIdMember, wFlags,
158 pDispParams, pVarResult, pExcepInfo, puArgErr);
159 ITypeInfo_Release(typeinfo);
162 return hr;
165 static HRESULT WINAPI WshEnvironment_get_Item(IWshEnvironment *iface, BSTR name, BSTR *value)
167 WshEnvironment *This = impl_from_IWshEnvironment(iface);
168 DWORD len;
170 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
172 if (!value)
173 return E_POINTER;
175 len = GetEnvironmentVariableW(name, NULL, 0);
176 *value = SysAllocStringLen(NULL, len);
177 if (!*value)
178 return E_OUTOFMEMORY;
180 if (len)
181 GetEnvironmentVariableW(name, *value, len+1);
183 return S_OK;
186 static HRESULT WINAPI WshEnvironment_put_Item(IWshEnvironment *iface, BSTR name, BSTR value)
188 WshEnvironment *This = impl_from_IWshEnvironment(iface);
189 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_w(value));
190 return E_NOTIMPL;
193 static HRESULT WINAPI WshEnvironment_Count(IWshEnvironment *iface, LONG *count)
195 WshEnvironment *This = impl_from_IWshEnvironment(iface);
196 FIXME("(%p)->(%p): stub\n", This, count);
197 return E_NOTIMPL;
200 static HRESULT WINAPI WshEnvironment_get_length(IWshEnvironment *iface, LONG *len)
202 WshEnvironment *This = impl_from_IWshEnvironment(iface);
203 FIXME("(%p)->(%p): stub\n", This, len);
204 return E_NOTIMPL;
207 static HRESULT WINAPI WshEnvironment__NewEnum(IWshEnvironment *iface, IUnknown **penum)
209 WshEnvironment *This = impl_from_IWshEnvironment(iface);
210 FIXME("(%p)->(%p): stub\n", This, penum);
211 return E_NOTIMPL;
214 static HRESULT WINAPI WshEnvironment_Remove(IWshEnvironment *iface, BSTR name)
216 WshEnvironment *This = impl_from_IWshEnvironment(iface);
217 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
218 return E_NOTIMPL;
221 static const IWshEnvironmentVtbl WshEnvironmentVtbl = {
222 WshEnvironment_QueryInterface,
223 WshEnvironment_AddRef,
224 WshEnvironment_Release,
225 WshEnvironment_GetTypeInfoCount,
226 WshEnvironment_GetTypeInfo,
227 WshEnvironment_GetIDsOfNames,
228 WshEnvironment_Invoke,
229 WshEnvironment_get_Item,
230 WshEnvironment_put_Item,
231 WshEnvironment_Count,
232 WshEnvironment_get_length,
233 WshEnvironment__NewEnum,
234 WshEnvironment_Remove
237 static HRESULT WshEnvironment_Create(IWshEnvironment **env)
239 WshEnvironment *This;
241 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
242 if (!This) return E_OUTOFMEMORY;
244 This->IWshEnvironment_iface.lpVtbl = &WshEnvironmentVtbl;
245 This->ref = 1;
247 *env = &This->IWshEnvironment_iface;
249 return S_OK;
252 static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID riid, void **ppv)
254 WshCollection *This = impl_from_IWshCollection(iface);
256 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
258 if (IsEqualGUID(riid, &IID_IUnknown) ||
259 IsEqualGUID(riid, &IID_IDispatch) ||
260 IsEqualGUID(riid, &IID_IWshCollection))
262 *ppv = iface;
263 }else {
264 FIXME("Unknown iface %s\n", debugstr_guid(riid));
265 *ppv = NULL;
266 return E_NOINTERFACE;
269 IUnknown_AddRef((IUnknown*)*ppv);
270 return S_OK;
273 static ULONG WINAPI WshCollection_AddRef(IWshCollection *iface)
275 WshCollection *This = impl_from_IWshCollection(iface);
276 LONG ref = InterlockedIncrement(&This->ref);
277 TRACE("(%p) ref = %d\n", This, ref);
278 return ref;
281 static ULONG WINAPI WshCollection_Release(IWshCollection *iface)
283 WshCollection *This = impl_from_IWshCollection(iface);
284 LONG ref = InterlockedDecrement(&This->ref);
285 TRACE("(%p) ref = %d\n", This, ref);
287 if (!ref)
288 HeapFree(GetProcessHeap(), 0, This);
290 return ref;
293 static HRESULT WINAPI WshCollection_GetTypeInfoCount(IWshCollection *iface, UINT *pctinfo)
295 WshCollection *This = impl_from_IWshCollection(iface);
296 TRACE("(%p)->(%p)\n", This, pctinfo);
297 *pctinfo = 1;
298 return S_OK;
301 static HRESULT WINAPI WshCollection_GetTypeInfo(IWshCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
303 WshCollection *This = impl_from_IWshCollection(iface);
304 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
305 return get_typeinfo(IWshCollection_tid, ppTInfo);
308 static HRESULT WINAPI WshCollection_GetIDsOfNames(IWshCollection *iface, REFIID riid, LPOLESTR *rgszNames,
309 UINT cNames, LCID lcid, DISPID *rgDispId)
311 WshCollection *This = impl_from_IWshCollection(iface);
312 ITypeInfo *typeinfo;
313 HRESULT hr;
315 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
317 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
318 if(SUCCEEDED(hr))
320 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
321 ITypeInfo_Release(typeinfo);
324 return hr;
327 static HRESULT WINAPI WshCollection_Invoke(IWshCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
328 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
330 WshCollection *This = impl_from_IWshCollection(iface);
331 ITypeInfo *typeinfo;
332 HRESULT hr;
334 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
335 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
337 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
338 if(SUCCEEDED(hr))
340 hr = ITypeInfo_Invoke(typeinfo, &This->IWshCollection_iface, dispIdMember, wFlags,
341 pDispParams, pVarResult, pExcepInfo, puArgErr);
342 ITypeInfo_Release(typeinfo);
345 return hr;
348 static HRESULT WINAPI WshCollection_Item(IWshCollection *iface, VARIANT *index, VARIANT *value)
350 WshCollection *This = impl_from_IWshCollection(iface);
351 static const WCHAR allusersdesktopW[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
352 static const WCHAR allusersprogramsW[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
353 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0};
354 PIDLIST_ABSOLUTE pidl;
355 WCHAR pathW[MAX_PATH];
356 int kind = 0;
357 BSTR folder;
358 HRESULT hr;
360 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(index), value);
362 if (V_VT(index) != VT_BSTR)
364 FIXME("only BSTR index supported, got %d\n", V_VT(index));
365 return E_NOTIMPL;
368 folder = V_BSTR(index);
369 if (!strcmpiW(folder, desktopW))
370 kind = CSIDL_DESKTOP;
371 else if (!strcmpiW(folder, allusersdesktopW))
372 kind = CSIDL_COMMON_DESKTOPDIRECTORY;
373 else if (!strcmpiW(folder, allusersprogramsW))
374 kind = CSIDL_COMMON_PROGRAMS;
375 else
377 FIXME("folder kind %s not supported\n", debugstr_w(folder));
378 return E_NOTIMPL;
381 hr = SHGetSpecialFolderLocation(NULL, kind, &pidl);
382 if (hr != S_OK) return hr;
384 if (SHGetPathFromIDListW(pidl, pathW))
386 V_VT(value) = VT_BSTR;
387 V_BSTR(value) = SysAllocString(pathW);
388 hr = V_BSTR(value) ? S_OK : E_OUTOFMEMORY;
390 else
391 hr = E_FAIL;
393 CoTaskMemFree(pidl);
395 return hr;
398 static HRESULT WINAPI WshCollection_Count(IWshCollection *iface, LONG *count)
400 WshCollection *This = impl_from_IWshCollection(iface);
401 FIXME("(%p)->(%p): stub\n", This, count);
402 return E_NOTIMPL;
405 static HRESULT WINAPI WshCollection_get_length(IWshCollection *iface, LONG *count)
407 WshCollection *This = impl_from_IWshCollection(iface);
408 FIXME("(%p)->(%p): stub\n", This, count);
409 return E_NOTIMPL;
412 static HRESULT WINAPI WshCollection__NewEnum(IWshCollection *iface, IUnknown *Enum)
414 WshCollection *This = impl_from_IWshCollection(iface);
415 FIXME("(%p)->(%p): stub\n", This, Enum);
416 return E_NOTIMPL;
419 static const IWshCollectionVtbl WshCollectionVtbl = {
420 WshCollection_QueryInterface,
421 WshCollection_AddRef,
422 WshCollection_Release,
423 WshCollection_GetTypeInfoCount,
424 WshCollection_GetTypeInfo,
425 WshCollection_GetIDsOfNames,
426 WshCollection_Invoke,
427 WshCollection_Item,
428 WshCollection_Count,
429 WshCollection_get_length,
430 WshCollection__NewEnum
433 static HRESULT WshCollection_Create(IWshCollection **collection)
435 WshCollection *This;
437 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
438 if (!This) return E_OUTOFMEMORY;
440 This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl;
441 This->ref = 1;
443 *collection = &This->IWshCollection_iface;
445 return S_OK;
448 /* IWshShortcut */
449 static HRESULT WINAPI WshShortcut_QueryInterface(IWshShortcut *iface, REFIID riid, void **ppv)
451 WshShortcut *This = impl_from_IWshShortcut(iface);
453 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
455 if (IsEqualGUID(riid, &IID_IUnknown) ||
456 IsEqualGUID(riid, &IID_IDispatch) ||
457 IsEqualGUID(riid, &IID_IWshShortcut))
459 *ppv = iface;
460 }else {
461 FIXME("Unknown iface %s\n", debugstr_guid(riid));
462 *ppv = NULL;
463 return E_NOINTERFACE;
466 IUnknown_AddRef((IUnknown*)*ppv);
467 return S_OK;
470 static ULONG WINAPI WshShortcut_AddRef(IWshShortcut *iface)
472 WshShortcut *This = impl_from_IWshShortcut(iface);
473 LONG ref = InterlockedIncrement(&This->ref);
474 TRACE("(%p) ref = %d\n", This, ref);
475 return ref;
478 static ULONG WINAPI WshShortcut_Release(IWshShortcut *iface)
480 WshShortcut *This = impl_from_IWshShortcut(iface);
481 LONG ref = InterlockedDecrement(&This->ref);
482 TRACE("(%p) ref = %d\n", This, ref);
484 if (!ref)
486 SysFreeString(This->path_link);
487 IShellLinkW_Release(This->link);
488 HeapFree(GetProcessHeap(), 0, This);
491 return ref;
494 static HRESULT WINAPI WshShortcut_GetTypeInfoCount(IWshShortcut *iface, UINT *pctinfo)
496 WshShortcut *This = impl_from_IWshShortcut(iface);
497 TRACE("(%p)->(%p)\n", This, pctinfo);
498 *pctinfo = 1;
499 return S_OK;
502 static HRESULT WINAPI WshShortcut_GetTypeInfo(IWshShortcut *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
504 WshShortcut *This = impl_from_IWshShortcut(iface);
505 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
506 return get_typeinfo(IWshShortcut_tid, ppTInfo);
509 static HRESULT WINAPI WshShortcut_GetIDsOfNames(IWshShortcut *iface, REFIID riid, LPOLESTR *rgszNames,
510 UINT cNames, LCID lcid, DISPID *rgDispId)
512 WshShortcut *This = impl_from_IWshShortcut(iface);
513 ITypeInfo *typeinfo;
514 HRESULT hr;
516 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
518 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
519 if(SUCCEEDED(hr))
521 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
522 ITypeInfo_Release(typeinfo);
525 return hr;
528 static HRESULT WINAPI WshShortcut_Invoke(IWshShortcut *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
529 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
531 WshShortcut *This = impl_from_IWshShortcut(iface);
532 ITypeInfo *typeinfo;
533 HRESULT hr;
535 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
536 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
538 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
539 if(SUCCEEDED(hr))
541 hr = ITypeInfo_Invoke(typeinfo, &This->IWshShortcut_iface, dispIdMember, wFlags,
542 pDispParams, pVarResult, pExcepInfo, puArgErr);
543 ITypeInfo_Release(typeinfo);
546 return hr;
549 static HRESULT WINAPI WshShortcut_get_FullName(IWshShortcut *iface, BSTR *name)
551 WshShortcut *This = impl_from_IWshShortcut(iface);
552 FIXME("(%p)->(%p): stub\n", This, name);
553 return E_NOTIMPL;
556 static HRESULT WINAPI WshShortcut_get_Arguments(IWshShortcut *iface, BSTR *Arguments)
558 WshShortcut *This = impl_from_IWshShortcut(iface);
559 WCHAR buffW[INFOTIPSIZE];
560 HRESULT hr;
562 TRACE("(%p)->(%p)\n", This, Arguments);
564 if (!Arguments)
565 return E_POINTER;
567 *Arguments = NULL;
569 hr = IShellLinkW_GetArguments(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
570 if (FAILED(hr))
571 return hr;
573 *Arguments = SysAllocString(buffW);
574 return *Arguments ? S_OK : E_OUTOFMEMORY;
577 static HRESULT WINAPI WshShortcut_put_Arguments(IWshShortcut *iface, BSTR Arguments)
579 WshShortcut *This = impl_from_IWshShortcut(iface);
581 TRACE("(%p)->(%s)\n", This, debugstr_w(Arguments));
583 return IShellLinkW_SetArguments(This->link, Arguments);
586 static HRESULT WINAPI WshShortcut_get_Description(IWshShortcut *iface, BSTR *Description)
588 WshShortcut *This = impl_from_IWshShortcut(iface);
589 FIXME("(%p)->(%p): stub\n", This, Description);
590 return E_NOTIMPL;
593 static HRESULT WINAPI WshShortcut_put_Description(IWshShortcut *iface, BSTR Description)
595 WshShortcut *This = impl_from_IWshShortcut(iface);
596 TRACE("(%p)->(%s)\n", This, debugstr_w(Description));
597 return IShellLinkW_SetDescription(This->link, Description);
600 static HRESULT WINAPI WshShortcut_get_Hotkey(IWshShortcut *iface, BSTR *Hotkey)
602 WshShortcut *This = impl_from_IWshShortcut(iface);
603 FIXME("(%p)->(%p): stub\n", This, Hotkey);
604 return E_NOTIMPL;
607 static HRESULT WINAPI WshShortcut_put_Hotkey(IWshShortcut *iface, BSTR Hotkey)
609 WshShortcut *This = impl_from_IWshShortcut(iface);
610 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Hotkey));
611 return E_NOTIMPL;
614 static HRESULT WINAPI WshShortcut_get_IconLocation(IWshShortcut *iface, BSTR *IconPath)
616 static const WCHAR fmtW[] = {'%','s',',',' ','%','d',0};
617 WshShortcut *This = impl_from_IWshShortcut(iface);
618 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
619 INT icon = 0;
620 HRESULT hr;
622 TRACE("(%p)->(%p)\n", This, IconPath);
624 if (!IconPath)
625 return E_POINTER;
627 hr = IShellLinkW_GetIconLocation(This->link, buffW, sizeof(buffW)/sizeof(WCHAR), &icon);
628 if (FAILED(hr)) return hr;
630 sprintfW(pathW, fmtW, buffW, icon);
631 *IconPath = SysAllocString(pathW);
632 if (!*IconPath) return E_OUTOFMEMORY;
634 return S_OK;
637 static HRESULT WINAPI WshShortcut_put_IconLocation(IWshShortcut *iface, BSTR IconPath)
639 WshShortcut *This = impl_from_IWshShortcut(iface);
640 HRESULT hr;
641 WCHAR *ptr;
642 BSTR path;
643 INT icon;
645 TRACE("(%p)->(%s)\n", This, debugstr_w(IconPath));
647 /* scan for icon id */
648 ptr = strrchrW(IconPath, ',');
649 if (!ptr)
651 WARN("icon index not found\n");
652 return E_FAIL;
655 path = SysAllocStringLen(IconPath, ptr-IconPath);
657 /* skip spaces if any */
658 while (isspaceW(*++ptr))
661 icon = atoiW(ptr);
663 hr = IShellLinkW_SetIconLocation(This->link, path, icon);
664 SysFreeString(path);
666 return hr;
669 static HRESULT WINAPI WshShortcut_put_RelativePath(IWshShortcut *iface, BSTR rhs)
671 WshShortcut *This = impl_from_IWshShortcut(iface);
672 FIXME("(%p)->(%s): stub\n", This, debugstr_w(rhs));
673 return E_NOTIMPL;
676 static HRESULT WINAPI WshShortcut_get_TargetPath(IWshShortcut *iface, BSTR *Path)
678 WshShortcut *This = impl_from_IWshShortcut(iface);
679 FIXME("(%p)->(%p): stub\n", This, Path);
680 return E_NOTIMPL;
683 static HRESULT WINAPI WshShortcut_put_TargetPath(IWshShortcut *iface, BSTR Path)
685 WshShortcut *This = impl_from_IWshShortcut(iface);
686 TRACE("(%p)->(%s)\n", This, debugstr_w(Path));
687 return IShellLinkW_SetPath(This->link, Path);
690 static HRESULT WINAPI WshShortcut_get_WindowStyle(IWshShortcut *iface, int *ShowCmd)
692 WshShortcut *This = impl_from_IWshShortcut(iface);
693 TRACE("(%p)->(%p)\n", This, ShowCmd);
694 return IShellLinkW_GetShowCmd(This->link, ShowCmd);
697 static HRESULT WINAPI WshShortcut_put_WindowStyle(IWshShortcut *iface, int ShowCmd)
699 WshShortcut *This = impl_from_IWshShortcut(iface);
700 TRACE("(%p)->(%d)\n", This, ShowCmd);
701 return IShellLinkW_SetShowCmd(This->link, ShowCmd);
704 static HRESULT WINAPI WshShortcut_get_WorkingDirectory(IWshShortcut *iface, BSTR *WorkingDirectory)
706 WshShortcut *This = impl_from_IWshShortcut(iface);
707 WCHAR buffW[MAX_PATH];
708 HRESULT hr;
710 TRACE("(%p)->(%p)\n", This, WorkingDirectory);
712 if (!WorkingDirectory)
713 return E_POINTER;
715 *WorkingDirectory = NULL;
716 hr = IShellLinkW_GetWorkingDirectory(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
717 if (FAILED(hr)) return hr;
719 *WorkingDirectory = SysAllocString(buffW);
720 return *WorkingDirectory ? S_OK : E_OUTOFMEMORY;
723 static HRESULT WINAPI WshShortcut_put_WorkingDirectory(IWshShortcut *iface, BSTR WorkingDirectory)
725 WshShortcut *This = impl_from_IWshShortcut(iface);
726 TRACE("(%p)->(%s)\n", This, debugstr_w(WorkingDirectory));
727 return IShellLinkW_SetWorkingDirectory(This->link, WorkingDirectory);
730 static HRESULT WINAPI WshShortcut_Load(IWshShortcut *iface, BSTR PathLink)
732 WshShortcut *This = impl_from_IWshShortcut(iface);
733 FIXME("(%p)->(%s): stub\n", This, debugstr_w(PathLink));
734 return E_NOTIMPL;
737 static HRESULT WINAPI WshShortcut_Save(IWshShortcut *iface)
739 WshShortcut *This = impl_from_IWshShortcut(iface);
740 IPersistFile *file;
741 HRESULT hr;
743 TRACE("(%p)\n", This);
745 IShellLinkW_QueryInterface(This->link, &IID_IPersistFile, (void**)&file);
746 hr = IPersistFile_Save(file, This->path_link, TRUE);
747 IPersistFile_Release(file);
749 return hr;
752 static const IWshShortcutVtbl WshShortcutVtbl = {
753 WshShortcut_QueryInterface,
754 WshShortcut_AddRef,
755 WshShortcut_Release,
756 WshShortcut_GetTypeInfoCount,
757 WshShortcut_GetTypeInfo,
758 WshShortcut_GetIDsOfNames,
759 WshShortcut_Invoke,
760 WshShortcut_get_FullName,
761 WshShortcut_get_Arguments,
762 WshShortcut_put_Arguments,
763 WshShortcut_get_Description,
764 WshShortcut_put_Description,
765 WshShortcut_get_Hotkey,
766 WshShortcut_put_Hotkey,
767 WshShortcut_get_IconLocation,
768 WshShortcut_put_IconLocation,
769 WshShortcut_put_RelativePath,
770 WshShortcut_get_TargetPath,
771 WshShortcut_put_TargetPath,
772 WshShortcut_get_WindowStyle,
773 WshShortcut_put_WindowStyle,
774 WshShortcut_get_WorkingDirectory,
775 WshShortcut_put_WorkingDirectory,
776 WshShortcut_Load,
777 WshShortcut_Save
780 static HRESULT WshShortcut_Create(const WCHAR *path, IDispatch **shortcut)
782 WshShortcut *This;
783 HRESULT hr;
785 *shortcut = NULL;
787 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
788 if (!This) return E_OUTOFMEMORY;
790 This->IWshShortcut_iface.lpVtbl = &WshShortcutVtbl;
791 This->ref = 1;
793 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
794 &IID_IShellLinkW, (void**)&This->link);
795 if (FAILED(hr))
797 HeapFree(GetProcessHeap(), 0, This);
798 return hr;
801 This->path_link = SysAllocString(path);
802 if (!This->path_link)
804 IShellLinkW_Release(This->link);
805 HeapFree(GetProcessHeap(), 0, This);
806 return E_OUTOFMEMORY;
809 *shortcut = (IDispatch*)&This->IWshShortcut_iface;
811 return S_OK;
814 static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
816 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
818 *ppv = NULL;
820 if(IsEqualGUID(riid, &IID_IUnknown) ||
821 IsEqualGUID(riid, &IID_IDispatch) ||
822 IsEqualGUID(riid, &IID_IWshShell3))
824 *ppv = iface;
826 else if (IsEqualGUID(riid, &IID_IDispatchEx))
828 return E_NOINTERFACE;
830 else
832 FIXME("Unknown iface %s\n", debugstr_guid(riid));
833 return E_NOINTERFACE;
836 IWshShell3_AddRef(iface);
837 return S_OK;
840 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
842 TRACE("()\n");
843 return 2;
846 static ULONG WINAPI WshShell3_Release(IWshShell3 *iface)
848 TRACE("()\n");
849 return 2;
852 static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinfo)
854 TRACE("(%p)\n", pctinfo);
855 *pctinfo = 1;
856 return S_OK;
859 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
861 TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
862 return get_typeinfo(IWshShell3_tid, ppTInfo);
865 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
866 UINT cNames, LCID lcid, DISPID *rgDispId)
868 ITypeInfo *typeinfo;
869 HRESULT hr;
871 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
873 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
874 if(SUCCEEDED(hr))
876 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
877 ITypeInfo_Release(typeinfo);
880 return hr;
883 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
884 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
886 ITypeInfo *typeinfo;
887 HRESULT hr;
889 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
890 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
892 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
893 if(SUCCEEDED(hr))
895 hr = ITypeInfo_Invoke(typeinfo, &WshShell3, dispIdMember, wFlags,
896 pDispParams, pVarResult, pExcepInfo, puArgErr);
897 ITypeInfo_Release(typeinfo);
900 return hr;
903 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
905 TRACE("(%p)\n", folders);
906 return WshCollection_Create(folders);
909 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *type, IWshEnvironment **env)
911 FIXME("(%s %p): semi-stub\n", debugstr_variant(type), env);
912 return WshEnvironment_Create(env);
915 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *WaitOnReturn, int *exit_code)
917 SHELLEXECUTEINFOW info;
918 int waitforprocess;
919 VARIANT s, w;
920 HRESULT hr;
922 TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(WaitOnReturn), exit_code);
924 VariantInit(&s);
925 hr = VariantChangeType(&s, style, 0, VT_I4);
926 if (FAILED(hr))
928 ERR("failed to convert style argument, 0x%08x\n", hr);
929 return hr;
932 VariantInit(&w);
933 hr = VariantChangeType(&w, WaitOnReturn, 0, VT_I4);
934 if (FAILED(hr))
936 ERR("failed to convert wait argument, 0x%08x\n", hr);
937 return hr;
940 memset(&info, 0, sizeof(info));
941 info.cbSize = sizeof(info);
943 waitforprocess = V_I4(&w);
945 info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
946 info.lpFile = cmd;
947 info.nShow = V_I4(&s);
949 if (!ShellExecuteExW(&info))
951 TRACE("ShellExecute failed, %d\n", GetLastError());
952 return HRESULT_FROM_WIN32(GetLastError());
954 else
956 if (waitforprocess)
958 if (exit_code)
960 DWORD code;
961 GetExitCodeProcess(info.hProcess, &code);
962 *exit_code = code;
964 CloseHandle(info.hProcess);
966 else
967 if (exit_code) *exit_code = 0;
969 return S_OK;
973 static HRESULT WINAPI WshShell3_Popup(IWshShell3 *iface, BSTR Text, VARIANT* SecondsToWait, VARIANT *Title, VARIANT *Type, int *button)
975 FIXME("(%s %s %s %s %p): stub\n", debugstr_w(Text), debugstr_variant(SecondsToWait),
976 debugstr_variant(Title), debugstr_variant(Type), button);
977 return E_NOTIMPL;
980 static HRESULT WINAPI WshShell3_CreateShortcut(IWshShell3 *iface, BSTR PathLink, IDispatch** Shortcut)
982 TRACE("(%s %p)\n", debugstr_w(PathLink), Shortcut);
983 return WshShortcut_Create(PathLink, Shortcut);
986 static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR Src, BSTR* Dst)
988 DWORD ret;
990 TRACE("(%s %p)\n", debugstr_w(Src), Dst);
992 if (!Src || !Dst) return E_POINTER;
994 ret = ExpandEnvironmentStringsW(Src, NULL, 0);
995 *Dst = SysAllocStringLen(NULL, ret);
996 if (!*Dst) return E_OUTOFMEMORY;
998 if (ExpandEnvironmentStringsW(Src, *Dst, ret))
999 return S_OK;
1000 else
1002 SysFreeString(*Dst);
1003 *Dst = NULL;
1004 return HRESULT_FROM_WIN32(GetLastError());
1008 static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR Name, VARIANT* out_Value)
1010 FIXME("(%s %p): stub\n", debugstr_w(Name), out_Value);
1011 return E_NOTIMPL;
1014 static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR Name, VARIANT *Value, VARIANT *Type)
1016 FIXME("(%s %s %s): stub\n", debugstr_w(Name), debugstr_variant(Value), debugstr_variant(Type));
1017 return E_NOTIMPL;
1020 static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name)
1022 FIXME("(%s): stub\n", debugstr_w(Name));
1023 return E_NOTIMPL;
1026 static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR Message, BSTR Target, VARIANT_BOOL *out_Success)
1028 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type), debugstr_w(Message), debugstr_w(Target), out_Success);
1029 return E_NOTIMPL;
1032 static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success)
1034 FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success);
1035 return E_NOTIMPL;
1038 static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait)
1040 FIXME("(%s %p): stub\n", debugstr_w(Keys), Wait);
1041 return E_NOTIMPL;
1044 static const IWshShell3Vtbl WshShell3Vtbl = {
1045 WshShell3_QueryInterface,
1046 WshShell3_AddRef,
1047 WshShell3_Release,
1048 WshShell3_GetTypeInfoCount,
1049 WshShell3_GetTypeInfo,
1050 WshShell3_GetIDsOfNames,
1051 WshShell3_Invoke,
1052 WshShell3_get_SpecialFolders,
1053 WshShell3_get_Environment,
1054 WshShell3_Run,
1055 WshShell3_Popup,
1056 WshShell3_CreateShortcut,
1057 WshShell3_ExpandEnvironmentStrings,
1058 WshShell3_RegRead,
1059 WshShell3_RegWrite,
1060 WshShell3_RegDelete,
1061 WshShell3_LogEvent,
1062 WshShell3_AppActivate,
1063 WshShell3_SendKeys
1066 static IWshShell3 WshShell3 = { &WshShell3Vtbl };
1068 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1070 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
1072 return IWshShell3_QueryInterface(&WshShell3, riid, ppv);