po: Fix a mistake in Dutch translation.
[wine.git] / dlls / wshom.ocx / shell.c
blob198531ea82e19faab520ff396ce45bc6753c2d0a
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_IDispatch) ||
821 IsEqualGUID(riid, &IID_IWshShell3) ||
822 IsEqualGUID(riid, &IID_IWshShell2) ||
823 IsEqualGUID(riid, &IID_IWshShell) ||
824 IsEqualGUID(riid, &IID_IUnknown))
826 *ppv = iface;
828 else if (IsEqualGUID(riid, &IID_IDispatchEx))
830 return E_NOINTERFACE;
832 else
834 WARN("unknown iface %s\n", debugstr_guid(riid));
835 return E_NOINTERFACE;
838 IWshShell3_AddRef(iface);
839 return S_OK;
842 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
844 TRACE("()\n");
845 return 2;
848 static ULONG WINAPI WshShell3_Release(IWshShell3 *iface)
850 TRACE("()\n");
851 return 2;
854 static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinfo)
856 TRACE("(%p)\n", pctinfo);
857 *pctinfo = 1;
858 return S_OK;
861 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
863 TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
864 return get_typeinfo(IWshShell3_tid, ppTInfo);
867 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
868 UINT cNames, LCID lcid, DISPID *rgDispId)
870 ITypeInfo *typeinfo;
871 HRESULT hr;
873 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
875 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
876 if(SUCCEEDED(hr))
878 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
879 ITypeInfo_Release(typeinfo);
882 return hr;
885 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
886 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
888 ITypeInfo *typeinfo;
889 HRESULT hr;
891 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
892 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
894 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
895 if(SUCCEEDED(hr))
897 hr = ITypeInfo_Invoke(typeinfo, &WshShell3, dispIdMember, wFlags,
898 pDispParams, pVarResult, pExcepInfo, puArgErr);
899 ITypeInfo_Release(typeinfo);
902 return hr;
905 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
907 TRACE("(%p)\n", folders);
908 return WshCollection_Create(folders);
911 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *type, IWshEnvironment **env)
913 FIXME("(%s %p): semi-stub\n", debugstr_variant(type), env);
914 return WshEnvironment_Create(env);
917 static inline BOOL is_optional_argument(const VARIANT *arg)
919 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
922 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *wait, DWORD *exit_code)
924 SHELLEXECUTEINFOW info;
925 int waitforprocess;
926 VARIANT s;
927 HRESULT hr;
929 TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(wait), exit_code);
931 if (!style || !wait || !exit_code)
932 return E_POINTER;
934 VariantInit(&s);
935 hr = VariantChangeType(&s, style, 0, VT_I4);
936 if (FAILED(hr))
938 ERR("failed to convert style argument, 0x%08x\n", hr);
939 return hr;
942 if (is_optional_argument(wait))
943 waitforprocess = 0;
944 else {
945 VARIANT w;
947 VariantInit(&w);
948 hr = VariantChangeType(&w, wait, 0, VT_I4);
949 if (FAILED(hr))
950 return hr;
952 waitforprocess = V_I4(&w);
955 memset(&info, 0, sizeof(info));
956 info.cbSize = sizeof(info);
957 info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
958 info.lpFile = cmd;
959 info.nShow = V_I4(&s);
961 if (!ShellExecuteExW(&info))
963 TRACE("ShellExecute failed, %d\n", GetLastError());
964 return HRESULT_FROM_WIN32(GetLastError());
966 else
968 if (waitforprocess)
970 GetExitCodeProcess(info.hProcess, exit_code);
971 CloseHandle(info.hProcess);
973 else
974 *exit_code = 0;
976 return S_OK;
980 static HRESULT WINAPI WshShell3_Popup(IWshShell3 *iface, BSTR Text, VARIANT* SecondsToWait, VARIANT *Title, VARIANT *Type, int *button)
982 FIXME("(%s %s %s %s %p): stub\n", debugstr_w(Text), debugstr_variant(SecondsToWait),
983 debugstr_variant(Title), debugstr_variant(Type), button);
984 return E_NOTIMPL;
987 static HRESULT WINAPI WshShell3_CreateShortcut(IWshShell3 *iface, BSTR PathLink, IDispatch** Shortcut)
989 TRACE("(%s %p)\n", debugstr_w(PathLink), Shortcut);
990 return WshShortcut_Create(PathLink, Shortcut);
993 static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR Src, BSTR* Dst)
995 DWORD ret;
997 TRACE("(%s %p)\n", debugstr_w(Src), Dst);
999 if (!Src || !Dst) return E_POINTER;
1001 ret = ExpandEnvironmentStringsW(Src, NULL, 0);
1002 *Dst = SysAllocStringLen(NULL, ret);
1003 if (!*Dst) return E_OUTOFMEMORY;
1005 if (ExpandEnvironmentStringsW(Src, *Dst, ret))
1006 return S_OK;
1007 else
1009 SysFreeString(*Dst);
1010 *Dst = NULL;
1011 return HRESULT_FROM_WIN32(GetLastError());
1015 static HKEY get_root_key(const WCHAR *path)
1017 static const struct {
1018 const WCHAR full[20];
1019 const WCHAR abbrev[5];
1020 HKEY hkey;
1021 } rootkeys[] = {
1022 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER },
1023 { {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}, {'H','K','L','M',0}, HKEY_LOCAL_MACHINE },
1024 { {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT },
1025 { {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS },
1026 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG }
1028 int i;
1030 for (i = 0; i < sizeof(rootkeys)/sizeof(rootkeys[0]); i++) {
1031 if (!strncmpW(path, rootkeys[i].full, strlenW(rootkeys[i].full)))
1032 return rootkeys[i].hkey;
1033 if (rootkeys[i].abbrev[0] && !strncmpW(path, rootkeys[i].abbrev, strlenW(rootkeys[i].abbrev)))
1034 return rootkeys[i].hkey;
1037 return NULL;
1040 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
1041 static HRESULT split_reg_path(const WCHAR *path, WCHAR **subkey, WCHAR **value)
1043 *value = NULL;
1045 /* at least one separator should be present */
1046 *subkey = strchrW(path, '\\');
1047 if (!*subkey)
1048 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1050 /* default value or not */
1051 if ((*subkey)[strlenW(*subkey)-1] == '\\') {
1052 (*subkey)++;
1053 *value = NULL;
1055 else {
1056 *value = strrchrW(*subkey, '\\');
1057 if (*value - *subkey > 1) {
1058 unsigned int len = *value - *subkey - 1;
1059 WCHAR *ret;
1061 ret = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
1062 if (!ret)
1063 return E_OUTOFMEMORY;
1065 memcpy(ret, *subkey + 1, len*sizeof(WCHAR));
1066 ret[len] = 0;
1067 *subkey = ret;
1069 (*value)++;
1072 return S_OK;
1075 static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *value)
1077 DWORD type, datalen, ret;
1078 WCHAR *subkey, *val;
1079 HRESULT hr;
1080 HKEY root;
1082 TRACE("(%s %p)\n", debugstr_w(name), value);
1084 if (!name || !value)
1085 return E_POINTER;
1087 root = get_root_key(name);
1088 if (!root)
1089 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1091 hr = split_reg_path(name, &subkey, &val);
1092 if (FAILED(hr))
1093 return hr;
1095 type = REG_NONE;
1096 datalen = 0;
1097 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, NULL, &datalen);
1098 if (ret == ERROR_SUCCESS) {
1099 void *data;
1101 data = HeapAlloc(GetProcessHeap(), 0, datalen);
1102 if (!data) {
1103 hr = E_OUTOFMEMORY;
1104 goto fail;
1107 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, data, &datalen);
1108 if (ret) {
1109 HeapFree(GetProcessHeap(), 0, data);
1110 hr = HRESULT_FROM_WIN32(ret);
1111 goto fail;
1114 switch (type) {
1115 case REG_SZ:
1116 case REG_EXPAND_SZ:
1117 V_VT(value) = VT_BSTR;
1118 V_BSTR(value) = SysAllocStringLen((WCHAR*)data, datalen - sizeof(WCHAR));
1119 if (!V_BSTR(value))
1120 hr = E_OUTOFMEMORY;
1121 break;
1122 case REG_DWORD:
1123 V_VT(value) = VT_I4;
1124 V_I4(value) = *(DWORD*)data;
1125 break;
1126 case REG_BINARY:
1128 BYTE *ptr = (BYTE*)data;
1129 SAFEARRAYBOUND bound;
1130 unsigned int i;
1131 SAFEARRAY *sa;
1132 VARIANT *v;
1134 bound.lLbound = 0;
1135 bound.cElements = datalen;
1136 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1137 if (!sa)
1138 break;
1140 hr = SafeArrayAccessData(sa, (void**)&v);
1141 if (FAILED(hr)) {
1142 SafeArrayDestroy(sa);
1143 break;
1146 for (i = 0; i < datalen; i++) {
1147 V_VT(&v[i]) = VT_UI1;
1148 V_UI1(&v[i]) = ptr[i];
1150 SafeArrayUnaccessData(sa);
1152 V_VT(value) = VT_ARRAY|VT_VARIANT;
1153 V_ARRAY(value) = sa;
1154 break;
1156 case REG_MULTI_SZ:
1158 WCHAR *ptr = (WCHAR*)data;
1159 SAFEARRAYBOUND bound;
1160 SAFEARRAY *sa;
1161 VARIANT *v;
1163 /* get element count first */
1164 bound.lLbound = 0;
1165 bound.cElements = 0;
1166 while (*ptr) {
1167 bound.cElements++;
1168 ptr += strlenW(ptr)+1;
1171 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1172 if (!sa)
1173 break;
1175 hr = SafeArrayAccessData(sa, (void**)&v);
1176 if (FAILED(hr)) {
1177 SafeArrayDestroy(sa);
1178 break;
1181 ptr = (WCHAR*)data;
1182 while (*ptr) {
1183 V_VT(v) = VT_BSTR;
1184 V_BSTR(v) = SysAllocString(ptr);
1185 ptr += strlenW(ptr)+1;
1186 v++;
1189 SafeArrayUnaccessData(sa);
1190 V_VT(value) = VT_ARRAY|VT_VARIANT;
1191 V_ARRAY(value) = sa;
1192 break;
1194 default:
1195 FIXME("value type %d not supported\n", type);
1196 hr = E_FAIL;
1199 HeapFree(GetProcessHeap(), 0, data);
1200 if (FAILED(hr))
1201 VariantInit(value);
1203 else
1204 hr = HRESULT_FROM_WIN32(ret);
1206 fail:
1207 if (val)
1208 HeapFree(GetProcessHeap(), 0, subkey);
1209 return hr;
1212 static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR name, VARIANT *value, VARIANT *type)
1214 static const WCHAR regexpandszW[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
1215 static const WCHAR regszW[] = {'R','E','G','_','S','Z',0};
1216 static const WCHAR regdwordW[] = {'R','E','G','_','D','W','O','R','D',0};
1217 static const WCHAR regbinaryW[] = {'R','E','G','_','B','I','N','A','R','Y',0};
1219 DWORD regtype, data_len;
1220 WCHAR *subkey, *val;
1221 const BYTE *data;
1222 HRESULT hr;
1223 HKEY root;
1224 VARIANT v;
1225 LONG ret;
1227 TRACE("(%s %s %s)\n", debugstr_w(name), debugstr_variant(value), debugstr_variant(type));
1229 if (!name || !value || !type)
1230 return E_POINTER;
1232 root = get_root_key(name);
1233 if (!root)
1234 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1236 /* value type */
1237 if (is_optional_argument(type))
1238 regtype = REG_SZ;
1239 else {
1240 if (V_VT(type) != VT_BSTR)
1241 return E_INVALIDARG;
1243 if (!strcmpW(V_BSTR(type), regszW))
1244 regtype = REG_SZ;
1245 else if (!strcmpW(V_BSTR(type), regdwordW))
1246 regtype = REG_DWORD;
1247 else if (!strcmpW(V_BSTR(type), regexpandszW))
1248 regtype = REG_EXPAND_SZ;
1249 else if (!strcmpW(V_BSTR(type), regbinaryW))
1250 regtype = REG_BINARY;
1251 else {
1252 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type)));
1253 return E_FAIL;
1257 /* it's always a string or a DWORD */
1258 VariantInit(&v);
1259 switch (regtype)
1261 case REG_SZ:
1262 case REG_EXPAND_SZ:
1263 hr = VariantChangeType(&v, value, 0, VT_BSTR);
1264 if (hr == S_OK) {
1265 data = (BYTE*)V_BSTR(&v);
1266 data_len = SysStringByteLen(V_BSTR(&v)) + sizeof(WCHAR);
1268 break;
1269 case REG_DWORD:
1270 case REG_BINARY:
1271 hr = VariantChangeType(&v, value, 0, VT_I4);
1272 data = (BYTE*)&V_I4(&v);
1273 data_len = sizeof(DWORD);
1274 break;
1275 default:
1276 FIXME("unexpected regtype %d\n", regtype);
1277 return E_FAIL;
1280 if (FAILED(hr)) {
1281 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype, hr);
1282 return hr;
1285 hr = split_reg_path(name, &subkey, &val);
1286 if (FAILED(hr))
1287 goto fail;
1289 ret = RegSetKeyValueW(root, subkey, val, regtype, data, data_len);
1290 if (ret)
1291 hr = HRESULT_FROM_WIN32(ret);
1293 fail:
1294 VariantClear(&v);
1295 if (val)
1296 HeapFree(GetProcessHeap(), 0, subkey);
1297 return hr;
1300 static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name)
1302 FIXME("(%s): stub\n", debugstr_w(Name));
1303 return E_NOTIMPL;
1306 static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR Message, BSTR Target, VARIANT_BOOL *out_Success)
1308 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type), debugstr_w(Message), debugstr_w(Target), out_Success);
1309 return E_NOTIMPL;
1312 static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success)
1314 FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success);
1315 return E_NOTIMPL;
1318 static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait)
1320 FIXME("(%s %p): stub\n", debugstr_w(Keys), Wait);
1321 return E_NOTIMPL;
1324 static const IWshShell3Vtbl WshShell3Vtbl = {
1325 WshShell3_QueryInterface,
1326 WshShell3_AddRef,
1327 WshShell3_Release,
1328 WshShell3_GetTypeInfoCount,
1329 WshShell3_GetTypeInfo,
1330 WshShell3_GetIDsOfNames,
1331 WshShell3_Invoke,
1332 WshShell3_get_SpecialFolders,
1333 WshShell3_get_Environment,
1334 WshShell3_Run,
1335 WshShell3_Popup,
1336 WshShell3_CreateShortcut,
1337 WshShell3_ExpandEnvironmentStrings,
1338 WshShell3_RegRead,
1339 WshShell3_RegWrite,
1340 WshShell3_RegDelete,
1341 WshShell3_LogEvent,
1342 WshShell3_AppActivate,
1343 WshShell3_SendKeys
1346 static IWshShell3 WshShell3 = { &WshShell3Vtbl };
1348 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1350 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
1352 return IWshShell3_QueryInterface(&WshShell3, riid, ppv);