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"
28 WINE_DEFAULT_DEBUG_CHANNEL(wshom
);
32 struct provideclassinfo classinfo
;
33 IWshShell3 IWshShell3_iface
;
35 static WshShellImpl WshShell3
;
39 struct provideclassinfo classinfo
;
40 IWshCollection IWshCollection_iface
;
46 struct provideclassinfo classinfo
;
47 IWshShortcut IWshShortcut_iface
;
56 struct provideclassinfo classinfo
;
57 IWshEnvironment IWshEnvironment_iface
;
63 struct provideclassinfo classinfo
;
64 IWshExec IWshExec_iface
;
66 PROCESS_INFORMATION info
;
69 static inline WshCollection
*impl_from_IWshCollection( IWshCollection
*iface
)
71 return CONTAINING_RECORD(iface
, WshCollection
, IWshCollection_iface
);
74 static inline WshShortcut
*impl_from_IWshShortcut( IWshShortcut
*iface
)
76 return CONTAINING_RECORD(iface
, WshShortcut
, IWshShortcut_iface
);
79 static inline WshEnvironment
*impl_from_IWshEnvironment( IWshEnvironment
*iface
)
81 return CONTAINING_RECORD(iface
, WshEnvironment
, IWshEnvironment_iface
);
84 static inline WshExecImpl
*impl_from_IWshExec( IWshExec
*iface
)
86 return CONTAINING_RECORD(iface
, WshExecImpl
, IWshExec_iface
);
89 static HRESULT WINAPI
WshExec_QueryInterface(IWshExec
*iface
, REFIID riid
, void **obj
)
91 WshExecImpl
*This
= impl_from_IWshExec(iface
);
93 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
95 if (IsEqualGUID(riid
, &IID_IDispatch
) ||
96 IsEqualGUID(riid
, &IID_IWshExec
) ||
97 IsEqualGUID(riid
, &IID_IUnknown
))
101 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
103 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
106 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
108 return E_NOINTERFACE
;
111 IUnknown_AddRef((IUnknown
*)*obj
);
115 static ULONG WINAPI
WshExec_AddRef(IWshExec
*iface
)
117 WshExecImpl
*This
= impl_from_IWshExec(iface
);
118 LONG ref
= InterlockedIncrement(&This
->ref
);
119 TRACE("(%p) ref = %d\n", This
, ref
);
123 static ULONG WINAPI
WshExec_Release(IWshExec
*iface
)
125 WshExecImpl
*This
= impl_from_IWshExec(iface
);
126 LONG ref
= InterlockedDecrement(&This
->ref
);
127 TRACE("(%p) ref = %d\n", This
, ref
);
130 CloseHandle(This
->info
.hThread
);
131 CloseHandle(This
->info
.hProcess
);
138 static HRESULT WINAPI
WshExec_GetTypeInfoCount(IWshExec
*iface
, UINT
*pctinfo
)
140 WshExecImpl
*This
= impl_from_IWshExec(iface
);
141 TRACE("(%p)->(%p)\n", This
, pctinfo
);
146 static HRESULT WINAPI
WshExec_GetTypeInfo(IWshExec
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
148 WshExecImpl
*This
= impl_from_IWshExec(iface
);
149 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
150 return get_typeinfo(IWshExec_tid
, ppTInfo
);
153 static HRESULT WINAPI
WshExec_GetIDsOfNames(IWshExec
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
154 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
156 WshExecImpl
*This
= impl_from_IWshExec(iface
);
160 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
162 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
165 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
166 ITypeInfo_Release(typeinfo
);
172 static HRESULT WINAPI
WshExec_Invoke(IWshExec
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
173 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
175 WshExecImpl
*This
= impl_from_IWshExec(iface
);
179 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
180 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
182 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
185 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshExec_iface
, dispIdMember
, wFlags
,
186 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
187 ITypeInfo_Release(typeinfo
);
193 static HRESULT WINAPI
WshExec_get_Status(IWshExec
*iface
, WshExecStatus
*status
)
195 WshExecImpl
*This
= impl_from_IWshExec(iface
);
198 TRACE("(%p)->(%p)\n", This
, status
);
203 if (!GetExitCodeProcess(This
->info
.hProcess
, &code
))
204 return HRESULT_FROM_WIN32(GetLastError());
209 *status
= WshFinished
;
212 *status
= WshRunning
;
221 static HRESULT WINAPI
WshExec_get_StdIn(IWshExec
*iface
, ITextStream
**stream
)
223 WshExecImpl
*This
= impl_from_IWshExec(iface
);
225 FIXME("(%p)->(%p): stub\n", This
, stream
);
230 static HRESULT WINAPI
WshExec_get_StdOut(IWshExec
*iface
, ITextStream
**stream
)
232 WshExecImpl
*This
= impl_from_IWshExec(iface
);
234 FIXME("(%p)->(%p): stub\n", This
, stream
);
239 static HRESULT WINAPI
WshExec_get_StdErr(IWshExec
*iface
, ITextStream
**stream
)
241 WshExecImpl
*This
= impl_from_IWshExec(iface
);
243 FIXME("(%p)->(%p): stub\n", This
, stream
);
248 static HRESULT WINAPI
WshExec_get_ProcessID(IWshExec
*iface
, DWORD
*pid
)
250 WshExecImpl
*This
= impl_from_IWshExec(iface
);
252 TRACE("(%p)->(%p)\n", This
, pid
);
257 *pid
= This
->info
.dwProcessId
;
261 static HRESULT WINAPI
WshExec_get_ExitCode(IWshExec
*iface
, DWORD
*code
)
263 WshExecImpl
*This
= impl_from_IWshExec(iface
);
265 FIXME("(%p)->(%p): stub\n", This
, code
);
270 static BOOL CALLBACK
enum_thread_wnd_proc(HWND hwnd
, LPARAM lParam
)
272 INT
*count
= (INT
*)lParam
;
275 PostMessageW(hwnd
, WM_CLOSE
, 0, 0);
276 /* try to send it to all windows, even if failed for some */
280 static HRESULT WINAPI
WshExec_Terminate(IWshExec
*iface
)
282 WshExecImpl
*This
= impl_from_IWshExec(iface
);
283 BOOL ret
, kill
= FALSE
;
286 TRACE("(%p)\n", This
);
288 ret
= EnumThreadWindows(This
->info
.dwThreadId
, enum_thread_wnd_proc
, (LPARAM
)&count
);
290 /* manual testing shows that it waits 2 seconds before forcing termination */
291 if (WaitForSingleObject(This
->info
.hProcess
, 2000) != WAIT_OBJECT_0
)
298 TerminateProcess(This
->info
.hProcess
, 0);
303 static const IWshExecVtbl WshExecVtbl
= {
304 WshExec_QueryInterface
,
307 WshExec_GetTypeInfoCount
,
309 WshExec_GetIDsOfNames
,
315 WshExec_get_ProcessID
,
316 WshExec_get_ExitCode
,
320 static HRESULT
WshExec_create(BSTR command
, IWshExec
**ret
)
322 STARTUPINFOW si
= {0};
327 if (!(object
= calloc(1, sizeof(*object
))))
328 return E_OUTOFMEMORY
;
330 object
->IWshExec_iface
.lpVtbl
= &WshExecVtbl
;
333 if (!CreateProcessW(NULL
, command
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &object
->info
))
336 return HRESULT_FROM_WIN32(GetLastError());
339 init_classinfo(&CLSID_WshExec
, (IUnknown
*)&object
->IWshExec_iface
, &object
->classinfo
);
340 *ret
= &object
->IWshExec_iface
;
345 static HRESULT WINAPI
WshEnvironment_QueryInterface(IWshEnvironment
*iface
, REFIID riid
, void **obj
)
347 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
349 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
351 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
352 IsEqualGUID(riid
, &IID_IDispatch
) ||
353 IsEqualGUID(riid
, &IID_IWshEnvironment
))
357 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
359 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
362 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
364 return E_NOINTERFACE
;
367 IUnknown_AddRef((IUnknown
*)*obj
);
371 static ULONG WINAPI
WshEnvironment_AddRef(IWshEnvironment
*iface
)
373 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
374 LONG ref
= InterlockedIncrement(&This
->ref
);
375 TRACE("(%p) ref = %d\n", This
, ref
);
379 static ULONG WINAPI
WshEnvironment_Release(IWshEnvironment
*iface
)
381 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
382 LONG ref
= InterlockedDecrement(&This
->ref
);
383 TRACE("(%p) ref = %d\n", This
, ref
);
391 static HRESULT WINAPI
WshEnvironment_GetTypeInfoCount(IWshEnvironment
*iface
, UINT
*pctinfo
)
393 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
394 TRACE("(%p)->(%p)\n", This
, pctinfo
);
399 static HRESULT WINAPI
WshEnvironment_GetTypeInfo(IWshEnvironment
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
401 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
402 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
403 return get_typeinfo(IWshEnvironment_tid
, ppTInfo
);
406 static HRESULT WINAPI
WshEnvironment_GetIDsOfNames(IWshEnvironment
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
407 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
409 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
413 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
415 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
418 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
419 ITypeInfo_Release(typeinfo
);
425 static HRESULT WINAPI
WshEnvironment_Invoke(IWshEnvironment
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
426 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
428 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
432 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
433 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
435 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
438 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshEnvironment_iface
, dispIdMember
, wFlags
,
439 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
440 ITypeInfo_Release(typeinfo
);
446 static HRESULT WINAPI
WshEnvironment_get_Item(IWshEnvironment
*iface
, BSTR name
, BSTR
*value
)
448 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
451 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), value
);
456 len
= GetEnvironmentVariableW(name
, NULL
, 0);
459 *value
= SysAllocStringLen(NULL
, len
- 1);
461 GetEnvironmentVariableW(name
, *value
, len
);
464 *value
= SysAllocStringLen(NULL
, 0);
466 return *value
? S_OK
: E_OUTOFMEMORY
;
469 static HRESULT WINAPI
WshEnvironment_put_Item(IWshEnvironment
*iface
, BSTR name
, BSTR value
)
471 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
472 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(name
), debugstr_w(value
));
476 static HRESULT WINAPI
WshEnvironment_Count(IWshEnvironment
*iface
, LONG
*count
)
478 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
479 FIXME("(%p)->(%p): stub\n", This
, count
);
483 static HRESULT WINAPI
WshEnvironment_get_length(IWshEnvironment
*iface
, LONG
*len
)
485 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
486 FIXME("(%p)->(%p): stub\n", This
, len
);
490 static HRESULT WINAPI
WshEnvironment__NewEnum(IWshEnvironment
*iface
, IUnknown
**penum
)
492 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
493 FIXME("(%p)->(%p): stub\n", This
, penum
);
497 static HRESULT WINAPI
WshEnvironment_Remove(IWshEnvironment
*iface
, BSTR name
)
499 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
500 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
504 static const IWshEnvironmentVtbl WshEnvironmentVtbl
= {
505 WshEnvironment_QueryInterface
,
506 WshEnvironment_AddRef
,
507 WshEnvironment_Release
,
508 WshEnvironment_GetTypeInfoCount
,
509 WshEnvironment_GetTypeInfo
,
510 WshEnvironment_GetIDsOfNames
,
511 WshEnvironment_Invoke
,
512 WshEnvironment_get_Item
,
513 WshEnvironment_put_Item
,
514 WshEnvironment_Count
,
515 WshEnvironment_get_length
,
516 WshEnvironment__NewEnum
,
517 WshEnvironment_Remove
520 static HRESULT
WshEnvironment_Create(IWshEnvironment
**env
)
522 WshEnvironment
*object
;
524 if (!(object
= calloc(1, sizeof(*object
))))
525 return E_OUTOFMEMORY
;
527 object
->IWshEnvironment_iface
.lpVtbl
= &WshEnvironmentVtbl
;
530 init_classinfo(&IID_IWshEnvironment
, (IUnknown
*)&object
->IWshEnvironment_iface
, &object
->classinfo
);
531 *env
= &object
->IWshEnvironment_iface
;
536 static HRESULT WINAPI
WshCollection_QueryInterface(IWshCollection
*iface
, REFIID riid
, void **ppv
)
538 WshCollection
*This
= impl_from_IWshCollection(iface
);
540 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
542 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
543 IsEqualGUID(riid
, &IID_IDispatch
) ||
544 IsEqualGUID(riid
, &IID_IWshCollection
))
548 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
550 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
553 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
555 return E_NOINTERFACE
;
558 IUnknown_AddRef((IUnknown
*)*ppv
);
562 static ULONG WINAPI
WshCollection_AddRef(IWshCollection
*iface
)
564 WshCollection
*This
= impl_from_IWshCollection(iface
);
565 LONG ref
= InterlockedIncrement(&This
->ref
);
566 TRACE("(%p) ref = %d\n", This
, ref
);
570 static ULONG WINAPI
WshCollection_Release(IWshCollection
*iface
)
572 WshCollection
*This
= impl_from_IWshCollection(iface
);
573 LONG ref
= InterlockedDecrement(&This
->ref
);
574 TRACE("(%p) ref = %d\n", This
, ref
);
582 static HRESULT WINAPI
WshCollection_GetTypeInfoCount(IWshCollection
*iface
, UINT
*pctinfo
)
584 WshCollection
*This
= impl_from_IWshCollection(iface
);
585 TRACE("(%p)->(%p)\n", This
, pctinfo
);
590 static HRESULT WINAPI
WshCollection_GetTypeInfo(IWshCollection
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
592 WshCollection
*This
= impl_from_IWshCollection(iface
);
593 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
594 return get_typeinfo(IWshCollection_tid
, ppTInfo
);
597 static HRESULT WINAPI
WshCollection_GetIDsOfNames(IWshCollection
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
598 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
600 WshCollection
*This
= impl_from_IWshCollection(iface
);
604 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
606 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
609 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
610 ITypeInfo_Release(typeinfo
);
616 static HRESULT WINAPI
WshCollection_Invoke(IWshCollection
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
617 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
619 WshCollection
*This
= impl_from_IWshCollection(iface
);
623 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
624 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
626 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
629 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshCollection_iface
, dispIdMember
, wFlags
,
630 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
631 ITypeInfo_Release(typeinfo
);
637 static HRESULT WINAPI
WshCollection_Item(IWshCollection
*iface
, VARIANT
*index
, VARIANT
*value
)
639 WshCollection
*This
= impl_from_IWshCollection(iface
);
640 PIDLIST_ABSOLUTE pidl
;
641 WCHAR pathW
[MAX_PATH
];
646 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(index
), value
);
648 if (V_VT(index
) != VT_BSTR
)
650 FIXME("only BSTR index supported, got %d\n", V_VT(index
));
654 folder
= V_BSTR(index
);
655 if (!wcsicmp(folder
, L
"Desktop"))
656 kind
= CSIDL_DESKTOP
;
657 else if (!wcsicmp(folder
, L
"AllUsersDesktop"))
658 kind
= CSIDL_COMMON_DESKTOPDIRECTORY
;
659 else if (!wcsicmp(folder
, L
"AllUsersPrograms"))
660 kind
= CSIDL_COMMON_PROGRAMS
;
663 FIXME("folder kind %s not supported\n", debugstr_w(folder
));
667 hr
= SHGetSpecialFolderLocation(NULL
, kind
, &pidl
);
668 if (hr
!= S_OK
) return hr
;
670 if (SHGetPathFromIDListW(pidl
, pathW
))
672 V_VT(value
) = VT_BSTR
;
673 V_BSTR(value
) = SysAllocString(pathW
);
674 hr
= V_BSTR(value
) ? S_OK
: E_OUTOFMEMORY
;
684 static HRESULT WINAPI
WshCollection_Count(IWshCollection
*iface
, LONG
*count
)
686 WshCollection
*This
= impl_from_IWshCollection(iface
);
687 FIXME("(%p)->(%p): stub\n", This
, count
);
691 static HRESULT WINAPI
WshCollection_get_length(IWshCollection
*iface
, LONG
*count
)
693 WshCollection
*This
= impl_from_IWshCollection(iface
);
694 FIXME("(%p)->(%p): stub\n", This
, count
);
698 static HRESULT WINAPI
WshCollection__NewEnum(IWshCollection
*iface
, IUnknown
**Enum
)
700 WshCollection
*This
= impl_from_IWshCollection(iface
);
701 FIXME("(%p)->(%p): stub\n", This
, Enum
);
705 static const IWshCollectionVtbl WshCollectionVtbl
= {
706 WshCollection_QueryInterface
,
707 WshCollection_AddRef
,
708 WshCollection_Release
,
709 WshCollection_GetTypeInfoCount
,
710 WshCollection_GetTypeInfo
,
711 WshCollection_GetIDsOfNames
,
712 WshCollection_Invoke
,
715 WshCollection_get_length
,
716 WshCollection__NewEnum
719 static HRESULT
WshCollection_Create(IWshCollection
**collection
)
721 WshCollection
*object
;
723 if (!(object
= calloc(1, sizeof(*object
))))
724 return E_OUTOFMEMORY
;
726 object
->IWshCollection_iface
.lpVtbl
= &WshCollectionVtbl
;
729 init_classinfo(&IID_IWshCollection
, (IUnknown
*)&object
->IWshCollection_iface
, &object
->classinfo
);
730 *collection
= &object
->IWshCollection_iface
;
736 static HRESULT WINAPI
WshShortcut_QueryInterface(IWshShortcut
*iface
, REFIID riid
, void **ppv
)
738 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
740 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
742 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
743 IsEqualGUID(riid
, &IID_IDispatch
) ||
744 IsEqualGUID(riid
, &IID_IWshShortcut
))
748 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
750 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
753 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
755 return E_NOINTERFACE
;
758 IUnknown_AddRef((IUnknown
*)*ppv
);
762 static ULONG WINAPI
WshShortcut_AddRef(IWshShortcut
*iface
)
764 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
765 LONG ref
= InterlockedIncrement(&This
->ref
);
766 TRACE("(%p) ref = %d\n", This
, ref
);
770 static ULONG WINAPI
WshShortcut_Release(IWshShortcut
*iface
)
772 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
773 LONG ref
= InterlockedDecrement(&This
->ref
);
774 TRACE("(%p) ref = %d\n", This
, ref
);
778 IShellLinkW_Release(This
->link
);
779 free(This
->path_link
);
786 static HRESULT WINAPI
WshShortcut_GetTypeInfoCount(IWshShortcut
*iface
, UINT
*pctinfo
)
788 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
789 TRACE("(%p)->(%p)\n", This
, pctinfo
);
794 static HRESULT WINAPI
WshShortcut_GetTypeInfo(IWshShortcut
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
796 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
797 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
798 return get_typeinfo(IWshShortcut_tid
, ppTInfo
);
801 static HRESULT WINAPI
WshShortcut_GetIDsOfNames(IWshShortcut
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
802 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
804 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
808 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
810 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
813 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
814 ITypeInfo_Release(typeinfo
);
820 static HRESULT WINAPI
WshShortcut_Invoke(IWshShortcut
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
821 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
823 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
827 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
828 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
830 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
833 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshShortcut_iface
, dispIdMember
, wFlags
,
834 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
835 ITypeInfo_Release(typeinfo
);
841 static HRESULT WINAPI
WshShortcut_get_FullName(IWshShortcut
*iface
, BSTR
*name
)
843 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
844 FIXME("(%p)->(%p): stub\n", This
, name
);
848 static HRESULT WINAPI
WshShortcut_get_Arguments(IWshShortcut
*iface
, BSTR
*Arguments
)
850 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
851 WCHAR buffW
[INFOTIPSIZE
];
854 TRACE("(%p)->(%p)\n", This
, Arguments
);
861 hr
= IShellLinkW_GetArguments(This
->link
, buffW
, ARRAY_SIZE(buffW
));
865 *Arguments
= SysAllocString(buffW
);
866 return *Arguments
? S_OK
: E_OUTOFMEMORY
;
869 static HRESULT WINAPI
WshShortcut_put_Arguments(IWshShortcut
*iface
, BSTR Arguments
)
871 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
873 TRACE("(%p)->(%s)\n", This
, debugstr_w(Arguments
));
875 return IShellLinkW_SetArguments(This
->link
, Arguments
);
878 static HRESULT WINAPI
WshShortcut_get_Description(IWshShortcut
*iface
, BSTR
*Description
)
880 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
881 FIXME("(%p)->(%p): stub\n", This
, Description
);
885 static HRESULT WINAPI
WshShortcut_put_Description(IWshShortcut
*iface
, BSTR Description
)
887 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
888 TRACE("(%p)->(%s)\n", This
, debugstr_w(Description
));
889 return IShellLinkW_SetDescription(This
->link
, Description
);
892 static HRESULT WINAPI
WshShortcut_get_Hotkey(IWshShortcut
*iface
, BSTR
*Hotkey
)
894 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
895 FIXME("(%p)->(%p): stub\n", This
, Hotkey
);
899 static HRESULT WINAPI
WshShortcut_put_Hotkey(IWshShortcut
*iface
, BSTR Hotkey
)
901 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
902 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(Hotkey
));
906 static HRESULT WINAPI
WshShortcut_get_IconLocation(IWshShortcut
*iface
, BSTR
*IconPath
)
908 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
909 WCHAR buffW
[MAX_PATH
], pathW
[MAX_PATH
];
913 TRACE("(%p)->(%p)\n", This
, IconPath
);
918 hr
= IShellLinkW_GetIconLocation(This
->link
, buffW
, ARRAY_SIZE(buffW
), &icon
);
919 if (FAILED(hr
)) return hr
;
921 swprintf(pathW
, ARRAY_SIZE(pathW
), L
"%s, %d", buffW
, icon
);
922 *IconPath
= SysAllocString(pathW
);
923 if (!*IconPath
) return E_OUTOFMEMORY
;
928 static HRESULT WINAPI
WshShortcut_put_IconLocation(IWshShortcut
*iface
, BSTR IconPath
)
930 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
936 TRACE("(%p)->(%s)\n", This
, debugstr_w(IconPath
));
938 /* scan for icon id */
939 ptr
= wcsrchr(IconPath
, ',');
942 WARN("icon index not found\n");
946 path
= SysAllocStringLen(IconPath
, ptr
-IconPath
);
948 /* skip spaces if any */
949 while (iswspace(*++ptr
))
952 icon
= wcstol(ptr
, NULL
, 10);
954 hr
= IShellLinkW_SetIconLocation(This
->link
, path
, icon
);
960 static HRESULT WINAPI
WshShortcut_put_RelativePath(IWshShortcut
*iface
, BSTR rhs
)
962 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
963 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(rhs
));
967 static HRESULT WINAPI
WshShortcut_get_TargetPath(IWshShortcut
*iface
, BSTR
*Path
)
969 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
970 FIXME("(%p)->(%p): stub\n", This
, Path
);
974 static HRESULT WINAPI
WshShortcut_put_TargetPath(IWshShortcut
*iface
, BSTR Path
)
976 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
977 TRACE("(%p)->(%s)\n", This
, debugstr_w(Path
));
978 return IShellLinkW_SetPath(This
->link
, Path
);
981 static HRESULT WINAPI
WshShortcut_get_WindowStyle(IWshShortcut
*iface
, int *ShowCmd
)
983 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
984 TRACE("(%p)->(%p)\n", This
, ShowCmd
);
985 return IShellLinkW_GetShowCmd(This
->link
, ShowCmd
);
988 static HRESULT WINAPI
WshShortcut_put_WindowStyle(IWshShortcut
*iface
, int ShowCmd
)
990 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
991 TRACE("(%p)->(%d)\n", This
, ShowCmd
);
992 return IShellLinkW_SetShowCmd(This
->link
, ShowCmd
);
995 static HRESULT WINAPI
WshShortcut_get_WorkingDirectory(IWshShortcut
*iface
, BSTR
*WorkingDirectory
)
997 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
998 WCHAR buffW
[MAX_PATH
];
1001 TRACE("(%p)->(%p)\n", This
, WorkingDirectory
);
1003 if (!WorkingDirectory
)
1006 *WorkingDirectory
= NULL
;
1007 hr
= IShellLinkW_GetWorkingDirectory(This
->link
, buffW
, ARRAY_SIZE(buffW
));
1008 if (FAILED(hr
)) return hr
;
1010 *WorkingDirectory
= SysAllocString(buffW
);
1011 return *WorkingDirectory
? S_OK
: E_OUTOFMEMORY
;
1014 static HRESULT WINAPI
WshShortcut_put_WorkingDirectory(IWshShortcut
*iface
, BSTR WorkingDirectory
)
1016 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1017 TRACE("(%p)->(%s)\n", This
, debugstr_w(WorkingDirectory
));
1018 return IShellLinkW_SetWorkingDirectory(This
->link
, WorkingDirectory
);
1021 static HRESULT WINAPI
WshShortcut_Load(IWshShortcut
*iface
, BSTR PathLink
)
1023 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1024 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(PathLink
));
1028 static HRESULT WINAPI
WshShortcut_Save(IWshShortcut
*iface
)
1030 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1034 TRACE("(%p)\n", This
);
1036 IShellLinkW_QueryInterface(This
->link
, &IID_IPersistFile
, (void**)&file
);
1037 hr
= IPersistFile_Save(file
, This
->path_link
, TRUE
);
1038 IPersistFile_Release(file
);
1043 static const IWshShortcutVtbl WshShortcutVtbl
= {
1044 WshShortcut_QueryInterface
,
1046 WshShortcut_Release
,
1047 WshShortcut_GetTypeInfoCount
,
1048 WshShortcut_GetTypeInfo
,
1049 WshShortcut_GetIDsOfNames
,
1051 WshShortcut_get_FullName
,
1052 WshShortcut_get_Arguments
,
1053 WshShortcut_put_Arguments
,
1054 WshShortcut_get_Description
,
1055 WshShortcut_put_Description
,
1056 WshShortcut_get_Hotkey
,
1057 WshShortcut_put_Hotkey
,
1058 WshShortcut_get_IconLocation
,
1059 WshShortcut_put_IconLocation
,
1060 WshShortcut_put_RelativePath
,
1061 WshShortcut_get_TargetPath
,
1062 WshShortcut_put_TargetPath
,
1063 WshShortcut_get_WindowStyle
,
1064 WshShortcut_put_WindowStyle
,
1065 WshShortcut_get_WorkingDirectory
,
1066 WshShortcut_put_WorkingDirectory
,
1071 static HRESULT
WshShortcut_Create(const WCHAR
*path
, IDispatch
**shortcut
)
1073 WshShortcut
*object
;
1078 if (!(object
= calloc(1, sizeof(*object
))))
1079 return E_OUTOFMEMORY
;
1081 object
->IWshShortcut_iface
.lpVtbl
= &WshShortcutVtbl
;
1084 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLinkW
, (void **)&object
->link
);
1091 object
->path_link
= wcsdup(path
);
1092 if (!object
->path_link
)
1094 IShellLinkW_Release(object
->link
);
1096 return E_OUTOFMEMORY
;
1099 init_classinfo(&IID_IWshShortcut
, (IUnknown
*)&object
->IWshShortcut_iface
, &object
->classinfo
);
1100 *shortcut
= (IDispatch
*)&object
->IWshShortcut_iface
;
1105 static HRESULT WINAPI
WshShell3_QueryInterface(IWshShell3
*iface
, REFIID riid
, void **ppv
)
1107 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
1111 if (IsEqualGUID(riid
, &IID_IDispatch
) ||
1112 IsEqualGUID(riid
, &IID_IWshShell3
) ||
1113 IsEqualGUID(riid
, &IID_IWshShell2
) ||
1114 IsEqualGUID(riid
, &IID_IWshShell
) ||
1115 IsEqualGUID(riid
, &IID_IUnknown
))
1119 else if (IsEqualGUID(riid
, &IID_IDispatchEx
))
1121 return E_NOINTERFACE
;
1123 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
1125 *ppv
= &WshShell3
.classinfo
.IProvideClassInfo_iface
;
1129 WARN("unknown iface %s\n", debugstr_guid(riid
));
1130 return E_NOINTERFACE
;
1133 IUnknown_AddRef((IUnknown
*)*ppv
);
1137 static ULONG WINAPI
WshShell3_AddRef(IWshShell3
*iface
)
1143 static ULONG WINAPI
WshShell3_Release(IWshShell3
*iface
)
1149 static HRESULT WINAPI
WshShell3_GetTypeInfoCount(IWshShell3
*iface
, UINT
*pctinfo
)
1151 TRACE("(%p)\n", pctinfo
);
1156 static HRESULT WINAPI
WshShell3_GetTypeInfo(IWshShell3
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1158 TRACE("(%u %u %p)\n", iTInfo
, lcid
, ppTInfo
);
1159 return get_typeinfo(IWshShell3_tid
, ppTInfo
);
1162 static HRESULT WINAPI
WshShell3_GetIDsOfNames(IWshShell3
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
1163 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1165 ITypeInfo
*typeinfo
;
1168 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1170 hr
= get_typeinfo(IWshShell3_tid
, &typeinfo
);
1173 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1174 ITypeInfo_Release(typeinfo
);
1180 static HRESULT WINAPI
WshShell3_Invoke(IWshShell3
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1181 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1183 ITypeInfo
*typeinfo
;
1186 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember
, debugstr_guid(riid
),
1187 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1189 hr
= get_typeinfo(IWshShell3_tid
, &typeinfo
);
1192 hr
= ITypeInfo_Invoke(typeinfo
, &WshShell3
.IWshShell3_iface
, dispIdMember
, wFlags
,
1193 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1194 ITypeInfo_Release(typeinfo
);
1200 static HRESULT WINAPI
WshShell3_get_SpecialFolders(IWshShell3
*iface
, IWshCollection
**folders
)
1202 TRACE("(%p)\n", folders
);
1203 return WshCollection_Create(folders
);
1206 static HRESULT WINAPI
WshShell3_get_Environment(IWshShell3
*iface
, VARIANT
*type
, IWshEnvironment
**env
)
1208 FIXME("(%s %p): semi-stub\n", debugstr_variant(type
), env
);
1209 return WshEnvironment_Create(env
);
1212 static inline BOOL
is_optional_argument(const VARIANT
*arg
)
1214 return V_VT(arg
) == VT_ERROR
&& V_ERROR(arg
) == DISP_E_PARAMNOTFOUND
;
1217 static WCHAR
*split_command( BSTR cmd
, WCHAR
**params
)
1220 BOOL in_quotes
= FALSE
;
1222 if (!(ret
= malloc((lstrlenW(cmd
) + 1) * sizeof(WCHAR
)))) return NULL
;
1223 lstrcpyW( ret
, cmd
);
1226 for (ptr
= ret
; *ptr
; ptr
++)
1228 if (*ptr
== '"') in_quotes
= !in_quotes
;
1229 else if (*ptr
== ' ' && !in_quotes
)
1240 static HRESULT WINAPI
WshShell3_Run(IWshShell3
*iface
, BSTR cmd
, VARIANT
*style
, VARIANT
*wait
, DWORD
*exit_code
)
1242 SHELLEXECUTEINFOW info
;
1244 WCHAR
*file
, *params
;
1249 TRACE("(%s %s %s %p)\n", debugstr_w(cmd
), debugstr_variant(style
), debugstr_variant(wait
), exit_code
);
1251 if (!style
|| !wait
|| !exit_code
)
1255 hr
= VariantChangeType(&s
, style
, 0, VT_I4
);
1258 ERR("failed to convert style argument, 0x%08x\n", hr
);
1262 if (is_optional_argument(wait
))
1268 hr
= VariantChangeType(&w
, wait
, 0, VT_I4
);
1272 waitforprocess
= V_I4(&w
);
1275 if (!(file
= split_command(cmd
, ¶ms
))) return E_OUTOFMEMORY
;
1277 memset(&info
, 0, sizeof(info
));
1278 info
.cbSize
= sizeof(info
);
1279 info
.fMask
= waitforprocess
? SEE_MASK_NOASYNC
| SEE_MASK_NOCLOSEPROCESS
: SEE_MASK_DEFAULT
;
1281 info
.lpParameters
= params
;
1282 info
.nShow
= V_I4(&s
);
1284 ret
= ShellExecuteExW(&info
);
1288 TRACE("ShellExecute failed, %d\n", GetLastError());
1289 return HRESULT_FROM_WIN32(GetLastError());
1295 WaitForSingleObject(info
.hProcess
, INFINITE
);
1296 GetExitCodeProcess(info
.hProcess
, exit_code
);
1297 CloseHandle(info
.hProcess
);
1306 struct popup_thread_param
1314 static DWORD WINAPI
popup_thread_proc(void *arg
)
1316 struct popup_thread_param
*param
= (struct popup_thread_param
*)arg
;
1318 param
->button
= MessageBoxW(NULL
, param
->text
, is_optional_argument(¶m
->title
) ?
1319 L
"Windows Script Host" : V_BSTR(¶m
->title
), V_I4(¶m
->type
));
1323 static HRESULT WINAPI
WshShell3_Popup(IWshShell3
*iface
, BSTR text
, VARIANT
*seconds_to_wait
, VARIANT
*title
,
1324 VARIANT
*type
, int *button
)
1326 struct popup_thread_param param
;
1332 TRACE("(%s %s %s %s %p)\n", debugstr_w(text
), debugstr_variant(seconds_to_wait
), debugstr_variant(title
),
1333 debugstr_variant(type
), button
);
1335 if (!seconds_to_wait
|| !title
|| !type
|| !button
)
1338 VariantInit(&timeout
);
1339 if (!is_optional_argument(seconds_to_wait
))
1341 hr
= VariantChangeType(&timeout
, seconds_to_wait
, 0, VT_I4
);
1346 VariantInit(¶m
.type
);
1347 if (!is_optional_argument(type
))
1349 hr
= VariantChangeType(¶m
.type
, type
, 0, VT_I4
);
1354 if (is_optional_argument(title
))
1355 param
.title
= *title
;
1358 VariantInit(¶m
.title
);
1359 hr
= VariantChangeType(¶m
.title
, title
, 0, VT_BSTR
);
1366 hthread
= CreateThread(NULL
, 0, popup_thread_proc
, ¶m
, 0, &tid
);
1367 status
= MsgWaitForMultipleObjects(1, &hthread
, FALSE
, V_I4(&timeout
) ? V_I4(&timeout
) * 1000: INFINITE
, 0);
1368 if (status
== WAIT_TIMEOUT
)
1370 PostThreadMessageW(tid
, WM_QUIT
, 0, 0);
1371 MsgWaitForMultipleObjects(1, &hthread
, FALSE
, INFINITE
, 0);
1374 *button
= param
.button
;
1376 VariantClear(¶m
.title
);
1377 CloseHandle(hthread
);
1382 static HRESULT WINAPI
WshShell3_CreateShortcut(IWshShell3
*iface
, BSTR PathLink
, IDispatch
** Shortcut
)
1384 TRACE("(%s %p)\n", debugstr_w(PathLink
), Shortcut
);
1385 return WshShortcut_Create(PathLink
, Shortcut
);
1388 static HRESULT WINAPI
WshShell3_ExpandEnvironmentStrings(IWshShell3
*iface
, BSTR Src
, BSTR
* Dst
)
1392 TRACE("(%s %p)\n", debugstr_w(Src
), Dst
);
1394 if (!Src
|| !Dst
) return E_POINTER
;
1396 ret
= ExpandEnvironmentStringsW(Src
, NULL
, 0);
1397 *Dst
= SysAllocStringLen(NULL
, ret
);
1398 if (!*Dst
) return E_OUTOFMEMORY
;
1400 if (ExpandEnvironmentStringsW(Src
, *Dst
, ret
))
1404 SysFreeString(*Dst
);
1406 return HRESULT_FROM_WIN32(GetLastError());
1410 static HKEY
get_root_key(const WCHAR
*path
)
1412 static const struct {
1413 const WCHAR full
[20];
1414 const WCHAR abbrev
[5];
1417 { L
"HKEY_CURRENT_USER", L
"HKCU", HKEY_CURRENT_USER
},
1418 { L
"HKEY_LOCAL_MACHINE", L
"HKLM", HKEY_LOCAL_MACHINE
},
1419 { L
"HKEY_CLASSES_ROOT", L
"HKCR", HKEY_CLASSES_ROOT
},
1420 { L
"HKEY_USERS", {0}, HKEY_USERS
},
1421 { L
"HKEY_CURRENT_CONFIG", {0}, HKEY_CURRENT_CONFIG
}
1425 for (i
= 0; i
< ARRAY_SIZE(rootkeys
); i
++) {
1426 if (!wcsncmp(path
, rootkeys
[i
].full
, lstrlenW(rootkeys
[i
].full
)))
1427 return rootkeys
[i
].hkey
;
1428 if (rootkeys
[i
].abbrev
[0] && !wcsncmp(path
, rootkeys
[i
].abbrev
, lstrlenW(rootkeys
[i
].abbrev
)))
1429 return rootkeys
[i
].hkey
;
1435 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
1436 static HRESULT
split_reg_path(const WCHAR
*path
, WCHAR
**subkey
, WCHAR
**value
)
1440 /* at least one separator should be present */
1441 *subkey
= wcschr(path
, '\\');
1443 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1445 /* default value or not */
1446 if ((*subkey
)[lstrlenW(*subkey
)-1] == '\\') {
1451 *value
= wcsrchr(*subkey
, '\\');
1452 if (*value
- *subkey
> 1) {
1453 unsigned int len
= *value
- *subkey
- 1;
1456 ret
= malloc((len
+ 1)*sizeof(WCHAR
));
1458 return E_OUTOFMEMORY
;
1460 memcpy(ret
, *subkey
+ 1, len
*sizeof(WCHAR
));
1470 static HRESULT WINAPI
WshShell3_RegRead(IWshShell3
*iface
, BSTR name
, VARIANT
*value
)
1472 DWORD type
, datalen
, ret
;
1473 WCHAR
*subkey
, *val
;
1477 TRACE("(%s %p)\n", debugstr_w(name
), value
);
1479 if (!name
|| !value
)
1482 root
= get_root_key(name
);
1484 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1486 hr
= split_reg_path(name
, &subkey
, &val
);
1492 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, NULL
, &datalen
);
1493 if (ret
== ERROR_SUCCESS
) {
1496 data
= malloc(datalen
);
1502 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, data
, &datalen
);
1505 hr
= HRESULT_FROM_WIN32(ret
);
1512 V_VT(value
) = VT_BSTR
;
1513 V_BSTR(value
) = SysAllocString((WCHAR
*)data
);
1518 V_VT(value
) = VT_I4
;
1519 V_I4(value
) = *(DWORD
*)data
;
1523 BYTE
*ptr
= (BYTE
*)data
;
1524 SAFEARRAYBOUND bound
;
1530 bound
.cElements
= datalen
;
1531 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1535 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1537 SafeArrayDestroy(sa
);
1541 for (i
= 0; i
< datalen
; i
++) {
1542 V_VT(&v
[i
]) = VT_UI1
;
1543 V_UI1(&v
[i
]) = ptr
[i
];
1545 SafeArrayUnaccessData(sa
);
1547 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1548 V_ARRAY(value
) = sa
;
1553 WCHAR
*ptr
= (WCHAR
*)data
;
1554 SAFEARRAYBOUND bound
;
1558 /* get element count first */
1560 bound
.cElements
= 0;
1563 ptr
+= lstrlenW(ptr
)+1;
1566 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1570 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1572 SafeArrayDestroy(sa
);
1579 V_BSTR(v
) = SysAllocString(ptr
);
1580 ptr
+= lstrlenW(ptr
)+1;
1584 SafeArrayUnaccessData(sa
);
1585 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1586 V_ARRAY(value
) = sa
;
1590 FIXME("value type %d not supported\n", type
);
1599 hr
= HRESULT_FROM_WIN32(ret
);
1607 static HRESULT WINAPI
WshShell3_RegWrite(IWshShell3
*iface
, BSTR name
, VARIANT
*value
, VARIANT
*type
)
1609 DWORD regtype
, data_len
;
1610 WCHAR
*subkey
, *val
;
1617 TRACE("(%s %s %s)\n", debugstr_w(name
), debugstr_variant(value
), debugstr_variant(type
));
1619 if (!name
|| !value
|| !type
)
1622 root
= get_root_key(name
);
1624 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1627 if (is_optional_argument(type
))
1630 if (V_VT(type
) != VT_BSTR
)
1631 return E_INVALIDARG
;
1633 if (!wcscmp(V_BSTR(type
), L
"REG_SZ"))
1635 else if (!wcscmp(V_BSTR(type
), L
"REG_DWORD"))
1636 regtype
= REG_DWORD
;
1637 else if (!wcscmp(V_BSTR(type
), L
"REG_EXPAND_SZ"))
1638 regtype
= REG_EXPAND_SZ
;
1639 else if (!wcscmp(V_BSTR(type
), L
"REG_BINARY"))
1640 regtype
= REG_BINARY
;
1642 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type
)));
1647 /* it's always a string or a DWORD */
1653 hr
= VariantChangeType(&v
, value
, 0, VT_BSTR
);
1655 data
= (BYTE
*)V_BSTR(&v
);
1656 data_len
= SysStringByteLen(V_BSTR(&v
)) + sizeof(WCHAR
);
1661 hr
= VariantChangeType(&v
, value
, 0, VT_I4
);
1662 data
= (BYTE
*)&V_I4(&v
);
1663 data_len
= sizeof(DWORD
);
1666 FIXME("unexpected regtype %d\n", regtype
);
1671 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype
, hr
);
1675 hr
= split_reg_path(name
, &subkey
, &val
);
1679 ret
= RegSetKeyValueW(root
, subkey
, val
, regtype
, data
, data_len
);
1681 hr
= HRESULT_FROM_WIN32(ret
);
1690 static HRESULT WINAPI
WshShell3_RegDelete(IWshShell3
*iface
, BSTR Name
)
1692 FIXME("(%s): stub\n", debugstr_w(Name
));
1696 static HRESULT WINAPI
WshShell3_LogEvent(IWshShell3
*iface
, VARIANT
*Type
, BSTR Message
, BSTR Target
, VARIANT_BOOL
*out_Success
)
1698 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type
), debugstr_w(Message
), debugstr_w(Target
), out_Success
);
1702 static HRESULT WINAPI
WshShell3_AppActivate(IWshShell3
*iface
, VARIANT
*App
, VARIANT
*Wait
, VARIANT_BOOL
*out_Success
)
1704 FIXME("(%s %s %p): stub\n", debugstr_variant(App
), debugstr_variant(Wait
), out_Success
);
1708 static HRESULT WINAPI
WshShell3_SendKeys(IWshShell3
*iface
, BSTR Keys
, VARIANT
*Wait
)
1710 FIXME("(%s %p): stub\n", debugstr_w(Keys
), Wait
);
1714 static HRESULT WINAPI
WshShell3_Exec(IWshShell3
*iface
, BSTR command
, IWshExec
**ret
)
1719 TRACE("(%s %p)\n", debugstr_w(command
), ret
);
1725 return DISP_E_EXCEPTION
;
1727 hr
= WshShell3_ExpandEnvironmentStrings(iface
, command
, &expandedcmd
);
1731 hr
= WshExec_create(expandedcmd
, ret
);
1732 SysFreeString(expandedcmd
);
1736 static HRESULT WINAPI
WshShell3_get_CurrentDirectory(IWshShell3
*iface
, BSTR
*dir
)
1740 TRACE("(%p)\n", dir
);
1742 ret
= GetCurrentDirectoryW(0, NULL
);
1744 return HRESULT_FROM_WIN32(GetLastError());
1746 *dir
= SysAllocStringLen(NULL
, ret
-1);
1748 return E_OUTOFMEMORY
;
1750 ret
= GetCurrentDirectoryW(ret
, *dir
);
1752 SysFreeString(*dir
);
1754 return HRESULT_FROM_WIN32(GetLastError());
1760 static HRESULT WINAPI
WshShell3_put_CurrentDirectory(IWshShell3
*iface
, BSTR dir
)
1762 TRACE("(%s)\n", debugstr_w(dir
));
1765 return E_INVALIDARG
;
1767 if (!SetCurrentDirectoryW(dir
))
1768 return HRESULT_FROM_WIN32(GetLastError());
1773 static const IWshShell3Vtbl WshShell3Vtbl
= {
1774 WshShell3_QueryInterface
,
1777 WshShell3_GetTypeInfoCount
,
1778 WshShell3_GetTypeInfo
,
1779 WshShell3_GetIDsOfNames
,
1781 WshShell3_get_SpecialFolders
,
1782 WshShell3_get_Environment
,
1785 WshShell3_CreateShortcut
,
1786 WshShell3_ExpandEnvironmentStrings
,
1789 WshShell3_RegDelete
,
1791 WshShell3_AppActivate
,
1794 WshShell3_get_CurrentDirectory
,
1795 WshShell3_put_CurrentDirectory
1798 HRESULT WINAPI
WshShellFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
1800 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
1802 WshShell3
.IWshShell3_iface
.lpVtbl
= &WshShell3Vtbl
;
1803 init_classinfo(&IID_IWshShell3
, (IUnknown
*)&WshShell3
.IWshShell3_iface
, &WshShell3
.classinfo
);
1804 return IWshShell3_QueryInterface(&WshShell3
.IWshShell3_iface
, riid
, ppv
);