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"
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wshom
);
31 static IWshShell3 WshShell3
;
35 IWshCollection IWshCollection_iface
;
41 IWshShortcut IWshShortcut_iface
;
50 IWshEnvironment IWshEnvironment_iface
;
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
))
81 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
86 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
105 HeapFree(GetProcessHeap(), 0, This
);
110 static HRESULT WINAPI
WshEnvironment_GetTypeInfoCount(IWshEnvironment
*iface
, UINT
*pctinfo
)
112 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
113 TRACE("(%p)->(%p)\n", This
, pctinfo
);
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
);
132 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
134 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
137 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
138 ITypeInfo_Release(typeinfo
);
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
);
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
);
157 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshEnvironment_iface
, dispIdMember
, wFlags
,
158 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
159 ITypeInfo_Release(typeinfo
);
165 static HRESULT WINAPI
WshEnvironment_get_Item(IWshEnvironment
*iface
, BSTR name
, BSTR
*value
)
167 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
170 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), value
);
175 len
= GetEnvironmentVariableW(name
, NULL
, 0);
176 *value
= SysAllocStringLen(NULL
, len
);
178 return E_OUTOFMEMORY
;
181 GetEnvironmentVariableW(name
, *value
, len
+1);
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
));
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
);
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
);
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
);
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
));
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
;
247 *env
= &This
->IWshEnvironment_iface
;
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
))
264 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
266 return E_NOINTERFACE
;
269 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
288 HeapFree(GetProcessHeap(), 0, This
);
293 static HRESULT WINAPI
WshCollection_GetTypeInfoCount(IWshCollection
*iface
, UINT
*pctinfo
)
295 WshCollection
*This
= impl_from_IWshCollection(iface
);
296 TRACE("(%p)->(%p)\n", This
, pctinfo
);
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
);
315 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
317 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
320 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
321 ITypeInfo_Release(typeinfo
);
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
);
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
);
340 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshCollection_iface
, dispIdMember
, wFlags
,
341 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
342 ITypeInfo_Release(typeinfo
);
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
];
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
));
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
;
377 FIXME("folder kind %s not supported\n", debugstr_w(folder
));
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
;
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
);
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
);
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
);
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
,
429 WshCollection_get_length
,
430 WshCollection__NewEnum
433 static HRESULT
WshCollection_Create(IWshCollection
**collection
)
437 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
438 if (!This
) return E_OUTOFMEMORY
;
440 This
->IWshCollection_iface
.lpVtbl
= &WshCollectionVtbl
;
443 *collection
= &This
->IWshCollection_iface
;
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
))
461 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
463 return E_NOINTERFACE
;
466 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
486 SysFreeString(This
->path_link
);
487 IShellLinkW_Release(This
->link
);
488 HeapFree(GetProcessHeap(), 0, This
);
494 static HRESULT WINAPI
WshShortcut_GetTypeInfoCount(IWshShortcut
*iface
, UINT
*pctinfo
)
496 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
497 TRACE("(%p)->(%p)\n", This
, pctinfo
);
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
);
516 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
518 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
521 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
522 ITypeInfo_Release(typeinfo
);
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
);
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
);
541 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshShortcut_iface
, dispIdMember
, wFlags
,
542 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
543 ITypeInfo_Release(typeinfo
);
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
);
556 static HRESULT WINAPI
WshShortcut_get_Arguments(IWshShortcut
*iface
, BSTR
*Arguments
)
558 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
559 WCHAR buffW
[INFOTIPSIZE
];
562 TRACE("(%p)->(%p)\n", This
, Arguments
);
569 hr
= IShellLinkW_GetArguments(This
->link
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
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
);
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
);
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
));
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
];
622 TRACE("(%p)->(%p)\n", This
, IconPath
);
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
;
637 static HRESULT WINAPI
WshShortcut_put_IconLocation(IWshShortcut
*iface
, BSTR IconPath
)
639 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
645 TRACE("(%p)->(%s)\n", This
, debugstr_w(IconPath
));
647 /* scan for icon id */
648 ptr
= strrchrW(IconPath
, ',');
651 WARN("icon index not found\n");
655 path
= SysAllocStringLen(IconPath
, ptr
-IconPath
);
657 /* skip spaces if any */
658 while (isspaceW(*++ptr
))
663 hr
= IShellLinkW_SetIconLocation(This
->link
, path
, icon
);
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
));
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
);
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
];
710 TRACE("(%p)->(%p)\n", This
, WorkingDirectory
);
712 if (!WorkingDirectory
)
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
));
737 static HRESULT WINAPI
WshShortcut_Save(IWshShortcut
*iface
)
739 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
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
);
752 static const IWshShortcutVtbl WshShortcutVtbl
= {
753 WshShortcut_QueryInterface
,
756 WshShortcut_GetTypeInfoCount
,
757 WshShortcut_GetTypeInfo
,
758 WshShortcut_GetIDsOfNames
,
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
,
780 static HRESULT
WshShortcut_Create(const WCHAR
*path
, IDispatch
**shortcut
)
787 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
788 if (!This
) return E_OUTOFMEMORY
;
790 This
->IWshShortcut_iface
.lpVtbl
= &WshShortcutVtbl
;
793 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
794 &IID_IShellLinkW
, (void**)&This
->link
);
797 HeapFree(GetProcessHeap(), 0, This
);
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
;
814 static HRESULT WINAPI
WshShell3_QueryInterface(IWshShell3
*iface
, REFIID riid
, void **ppv
)
816 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
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
))
828 else if (IsEqualGUID(riid
, &IID_IDispatchEx
))
830 return E_NOINTERFACE
;
834 WARN("unknown iface %s\n", debugstr_guid(riid
));
835 return E_NOINTERFACE
;
838 IWshShell3_AddRef(iface
);
842 static ULONG WINAPI
WshShell3_AddRef(IWshShell3
*iface
)
848 static ULONG WINAPI
WshShell3_Release(IWshShell3
*iface
)
854 static HRESULT WINAPI
WshShell3_GetTypeInfoCount(IWshShell3
*iface
, UINT
*pctinfo
)
856 TRACE("(%p)\n", pctinfo
);
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
)
873 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
875 hr
= get_typeinfo(IWshShell3_tid
, &typeinfo
);
878 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
879 ITypeInfo_Release(typeinfo
);
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
)
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
);
897 hr
= ITypeInfo_Invoke(typeinfo
, &WshShell3
, dispIdMember
, wFlags
,
898 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
899 ITypeInfo_Release(typeinfo
);
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
;
929 TRACE("(%s %s %s %p)\n", debugstr_w(cmd
), debugstr_variant(style
), debugstr_variant(wait
), exit_code
);
931 if (!style
|| !wait
|| !exit_code
)
935 hr
= VariantChangeType(&s
, style
, 0, VT_I4
);
938 ERR("failed to convert style argument, 0x%08x\n", hr
);
942 if (is_optional_argument(wait
))
948 hr
= VariantChangeType(&w
, wait
, 0, VT_I4
);
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
;
959 info
.nShow
= V_I4(&s
);
961 if (!ShellExecuteExW(&info
))
963 TRACE("ShellExecute failed, %d\n", GetLastError());
964 return HRESULT_FROM_WIN32(GetLastError());
970 GetExitCodeProcess(info
.hProcess
, exit_code
);
971 CloseHandle(info
.hProcess
);
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
);
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
)
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
))
1009 SysFreeString(*Dst
);
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];
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
}
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
;
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
)
1045 /* at least one separator should be present */
1046 *subkey
= strchrW(path
, '\\');
1048 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1050 /* default value or not */
1051 if ((*subkey
)[strlenW(*subkey
)-1] == '\\') {
1056 *value
= strrchrW(*subkey
, '\\');
1057 if (*value
- *subkey
> 1) {
1058 unsigned int len
= *value
- *subkey
- 1;
1061 ret
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
1063 return E_OUTOFMEMORY
;
1065 memcpy(ret
, *subkey
+ 1, len
*sizeof(WCHAR
));
1075 static HRESULT WINAPI
WshShell3_RegRead(IWshShell3
*iface
, BSTR name
, VARIANT
*value
)
1077 DWORD type
, datalen
, ret
;
1078 WCHAR
*subkey
, *val
;
1082 TRACE("(%s %p)\n", debugstr_w(name
), value
);
1084 if (!name
|| !value
)
1087 root
= get_root_key(name
);
1089 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1091 hr
= split_reg_path(name
, &subkey
, &val
);
1097 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, NULL
, &datalen
);
1098 if (ret
== ERROR_SUCCESS
) {
1101 data
= HeapAlloc(GetProcessHeap(), 0, datalen
);
1107 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, data
, &datalen
);
1109 HeapFree(GetProcessHeap(), 0, data
);
1110 hr
= HRESULT_FROM_WIN32(ret
);
1117 V_VT(value
) = VT_BSTR
;
1118 V_BSTR(value
) = SysAllocStringLen((WCHAR
*)data
, datalen
- sizeof(WCHAR
));
1123 V_VT(value
) = VT_I4
;
1124 V_I4(value
) = *(DWORD
*)data
;
1128 BYTE
*ptr
= (BYTE
*)data
;
1129 SAFEARRAYBOUND bound
;
1135 bound
.cElements
= datalen
;
1136 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1140 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1142 SafeArrayDestroy(sa
);
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
;
1158 WCHAR
*ptr
= (WCHAR
*)data
;
1159 SAFEARRAYBOUND bound
;
1163 /* get element count first */
1165 bound
.cElements
= 0;
1168 ptr
+= strlenW(ptr
)+1;
1171 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1175 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1177 SafeArrayDestroy(sa
);
1184 V_BSTR(v
) = SysAllocString(ptr
);
1185 ptr
+= strlenW(ptr
)+1;
1189 SafeArrayUnaccessData(sa
);
1190 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1191 V_ARRAY(value
) = sa
;
1195 FIXME("value type %d not supported\n", type
);
1199 HeapFree(GetProcessHeap(), 0, data
);
1204 hr
= HRESULT_FROM_WIN32(ret
);
1208 HeapFree(GetProcessHeap(), 0, subkey
);
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
;
1227 TRACE("(%s %s %s)\n", debugstr_w(name
), debugstr_variant(value
), debugstr_variant(type
));
1229 if (!name
|| !value
|| !type
)
1232 root
= get_root_key(name
);
1234 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1237 if (is_optional_argument(type
))
1240 if (V_VT(type
) != VT_BSTR
)
1241 return E_INVALIDARG
;
1243 if (!strcmpW(V_BSTR(type
), regszW
))
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
;
1252 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type
)));
1257 /* it's always a string or a DWORD */
1263 hr
= VariantChangeType(&v
, value
, 0, VT_BSTR
);
1265 data
= (BYTE
*)V_BSTR(&v
);
1266 data_len
= SysStringByteLen(V_BSTR(&v
)) + sizeof(WCHAR
);
1271 hr
= VariantChangeType(&v
, value
, 0, VT_I4
);
1272 data
= (BYTE
*)&V_I4(&v
);
1273 data_len
= sizeof(DWORD
);
1276 FIXME("unexpected regtype %d\n", regtype
);
1281 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype
, hr
);
1285 hr
= split_reg_path(name
, &subkey
, &val
);
1289 ret
= RegSetKeyValueW(root
, subkey
, val
, regtype
, data
, data_len
);
1291 hr
= HRESULT_FROM_WIN32(ret
);
1296 HeapFree(GetProcessHeap(), 0, subkey
);
1300 static HRESULT WINAPI
WshShell3_RegDelete(IWshShell3
*iface
, BSTR Name
)
1302 FIXME("(%s): stub\n", debugstr_w(Name
));
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
);
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
);
1318 static HRESULT WINAPI
WshShell3_SendKeys(IWshShell3
*iface
, BSTR Keys
, VARIANT
*Wait
)
1320 FIXME("(%s %p): stub\n", debugstr_w(Keys
), Wait
);
1324 static const IWshShell3Vtbl WshShell3Vtbl
= {
1325 WshShell3_QueryInterface
,
1328 WshShell3_GetTypeInfoCount
,
1329 WshShell3_GetTypeInfo
,
1330 WshShell3_GetIDsOfNames
,
1332 WshShell3_get_SpecialFolders
,
1333 WshShell3_get_Environment
,
1336 WshShell3_CreateShortcut
,
1337 WshShell3_ExpandEnvironmentStrings
,
1340 WshShell3_RegDelete
,
1342 WshShell3_AppActivate
,
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
);