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/heap.h"
28 #include "wine/unicode.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wshom
);
34 struct provideclassinfo classinfo
;
35 IWshShell3 IWshShell3_iface
;
37 static WshShellImpl WshShell3
;
41 struct provideclassinfo classinfo
;
42 IWshCollection IWshCollection_iface
;
48 struct provideclassinfo classinfo
;
49 IWshShortcut IWshShortcut_iface
;
58 struct provideclassinfo classinfo
;
59 IWshEnvironment IWshEnvironment_iface
;
65 struct provideclassinfo classinfo
;
66 IWshExec IWshExec_iface
;
68 PROCESS_INFORMATION info
;
71 static inline WshCollection
*impl_from_IWshCollection( IWshCollection
*iface
)
73 return CONTAINING_RECORD(iface
, WshCollection
, IWshCollection_iface
);
76 static inline WshShortcut
*impl_from_IWshShortcut( IWshShortcut
*iface
)
78 return CONTAINING_RECORD(iface
, WshShortcut
, IWshShortcut_iface
);
81 static inline WshEnvironment
*impl_from_IWshEnvironment( IWshEnvironment
*iface
)
83 return CONTAINING_RECORD(iface
, WshEnvironment
, IWshEnvironment_iface
);
86 static inline WshExecImpl
*impl_from_IWshExec( IWshExec
*iface
)
88 return CONTAINING_RECORD(iface
, WshExecImpl
, IWshExec_iface
);
91 static HRESULT WINAPI
WshExec_QueryInterface(IWshExec
*iface
, REFIID riid
, void **obj
)
93 WshExecImpl
*This
= impl_from_IWshExec(iface
);
95 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
97 if (IsEqualGUID(riid
, &IID_IDispatch
) ||
98 IsEqualGUID(riid
, &IID_IWshExec
) ||
99 IsEqualGUID(riid
, &IID_IUnknown
))
103 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
105 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
108 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
110 return E_NOINTERFACE
;
113 IUnknown_AddRef((IUnknown
*)*obj
);
117 static ULONG WINAPI
WshExec_AddRef(IWshExec
*iface
)
119 WshExecImpl
*This
= impl_from_IWshExec(iface
);
120 LONG ref
= InterlockedIncrement(&This
->ref
);
121 TRACE("(%p) ref = %d\n", This
, ref
);
125 static ULONG WINAPI
WshExec_Release(IWshExec
*iface
)
127 WshExecImpl
*This
= impl_from_IWshExec(iface
);
128 LONG ref
= InterlockedDecrement(&This
->ref
);
129 TRACE("(%p) ref = %d\n", This
, ref
);
132 CloseHandle(This
->info
.hThread
);
133 CloseHandle(This
->info
.hProcess
);
140 static HRESULT WINAPI
WshExec_GetTypeInfoCount(IWshExec
*iface
, UINT
*pctinfo
)
142 WshExecImpl
*This
= impl_from_IWshExec(iface
);
143 TRACE("(%p)->(%p)\n", This
, pctinfo
);
148 static HRESULT WINAPI
WshExec_GetTypeInfo(IWshExec
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
150 WshExecImpl
*This
= impl_from_IWshExec(iface
);
151 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
152 return get_typeinfo(IWshExec_tid
, ppTInfo
);
155 static HRESULT WINAPI
WshExec_GetIDsOfNames(IWshExec
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
156 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
158 WshExecImpl
*This
= impl_from_IWshExec(iface
);
162 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
164 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
167 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
168 ITypeInfo_Release(typeinfo
);
174 static HRESULT WINAPI
WshExec_Invoke(IWshExec
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
175 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
177 WshExecImpl
*This
= impl_from_IWshExec(iface
);
181 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
182 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
184 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
187 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshExec_iface
, dispIdMember
, wFlags
,
188 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
189 ITypeInfo_Release(typeinfo
);
195 static HRESULT WINAPI
WshExec_get_Status(IWshExec
*iface
, WshExecStatus
*status
)
197 WshExecImpl
*This
= impl_from_IWshExec(iface
);
200 TRACE("(%p)->(%p)\n", This
, status
);
205 if (!GetExitCodeProcess(This
->info
.hProcess
, &code
))
206 return HRESULT_FROM_WIN32(GetLastError());
211 *status
= WshFinished
;
214 *status
= WshRunning
;
223 static HRESULT WINAPI
WshExec_get_StdIn(IWshExec
*iface
, ITextStream
**stream
)
225 WshExecImpl
*This
= impl_from_IWshExec(iface
);
227 FIXME("(%p)->(%p): stub\n", This
, stream
);
232 static HRESULT WINAPI
WshExec_get_StdOut(IWshExec
*iface
, ITextStream
**stream
)
234 WshExecImpl
*This
= impl_from_IWshExec(iface
);
236 FIXME("(%p)->(%p): stub\n", This
, stream
);
241 static HRESULT WINAPI
WshExec_get_StdErr(IWshExec
*iface
, ITextStream
**stream
)
243 WshExecImpl
*This
= impl_from_IWshExec(iface
);
245 FIXME("(%p)->(%p): stub\n", This
, stream
);
250 static HRESULT WINAPI
WshExec_get_ProcessID(IWshExec
*iface
, DWORD
*pid
)
252 WshExecImpl
*This
= impl_from_IWshExec(iface
);
254 TRACE("(%p)->(%p)\n", This
, pid
);
259 *pid
= This
->info
.dwProcessId
;
263 static HRESULT WINAPI
WshExec_get_ExitCode(IWshExec
*iface
, DWORD
*code
)
265 WshExecImpl
*This
= impl_from_IWshExec(iface
);
267 FIXME("(%p)->(%p): stub\n", This
, code
);
272 static BOOL CALLBACK
enum_thread_wnd_proc(HWND hwnd
, LPARAM lParam
)
274 INT
*count
= (INT
*)lParam
;
277 PostMessageW(hwnd
, WM_CLOSE
, 0, 0);
278 /* try to send it to all windows, even if failed for some */
282 static HRESULT WINAPI
WshExec_Terminate(IWshExec
*iface
)
284 WshExecImpl
*This
= impl_from_IWshExec(iface
);
285 BOOL ret
, kill
= FALSE
;
288 TRACE("(%p)\n", This
);
290 ret
= EnumThreadWindows(This
->info
.dwThreadId
, enum_thread_wnd_proc
, (LPARAM
)&count
);
292 /* manual testing shows that it waits 2 seconds before forcing termination */
293 if (WaitForSingleObject(This
->info
.hProcess
, 2000) != WAIT_OBJECT_0
)
300 TerminateProcess(This
->info
.hProcess
, 0);
305 static const IWshExecVtbl WshExecVtbl
= {
306 WshExec_QueryInterface
,
309 WshExec_GetTypeInfoCount
,
311 WshExec_GetIDsOfNames
,
317 WshExec_get_ProcessID
,
318 WshExec_get_ExitCode
,
322 static HRESULT
WshExec_create(BSTR command
, IWshExec
**ret
)
324 STARTUPINFOW si
= {0};
329 This
= heap_alloc(sizeof(*This
));
331 return E_OUTOFMEMORY
;
333 This
->IWshExec_iface
.lpVtbl
= &WshExecVtbl
;
336 if (!CreateProcessW(NULL
, command
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &This
->info
)) {
338 return HRESULT_FROM_WIN32(GetLastError());
341 init_classinfo(&CLSID_WshExec
, (IUnknown
*)&This
->IWshExec_iface
, &This
->classinfo
);
342 *ret
= &This
->IWshExec_iface
;
346 static HRESULT WINAPI
WshEnvironment_QueryInterface(IWshEnvironment
*iface
, REFIID riid
, void **obj
)
348 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
350 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
352 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
353 IsEqualGUID(riid
, &IID_IDispatch
) ||
354 IsEqualGUID(riid
, &IID_IWshEnvironment
))
358 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
360 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
363 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
365 return E_NOINTERFACE
;
368 IUnknown_AddRef((IUnknown
*)*obj
);
372 static ULONG WINAPI
WshEnvironment_AddRef(IWshEnvironment
*iface
)
374 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
375 LONG ref
= InterlockedIncrement(&This
->ref
);
376 TRACE("(%p) ref = %d\n", This
, ref
);
380 static ULONG WINAPI
WshEnvironment_Release(IWshEnvironment
*iface
)
382 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
383 LONG ref
= InterlockedDecrement(&This
->ref
);
384 TRACE("(%p) ref = %d\n", This
, ref
);
392 static HRESULT WINAPI
WshEnvironment_GetTypeInfoCount(IWshEnvironment
*iface
, UINT
*pctinfo
)
394 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
395 TRACE("(%p)->(%p)\n", This
, pctinfo
);
400 static HRESULT WINAPI
WshEnvironment_GetTypeInfo(IWshEnvironment
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
402 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
403 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
404 return get_typeinfo(IWshEnvironment_tid
, ppTInfo
);
407 static HRESULT WINAPI
WshEnvironment_GetIDsOfNames(IWshEnvironment
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
408 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
410 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
414 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
416 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
419 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
420 ITypeInfo_Release(typeinfo
);
426 static HRESULT WINAPI
WshEnvironment_Invoke(IWshEnvironment
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
427 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
429 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
433 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
434 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
436 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
439 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshEnvironment_iface
, dispIdMember
, wFlags
,
440 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
441 ITypeInfo_Release(typeinfo
);
447 static HRESULT WINAPI
WshEnvironment_get_Item(IWshEnvironment
*iface
, BSTR name
, BSTR
*value
)
449 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
452 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), value
);
457 len
= GetEnvironmentVariableW(name
, NULL
, 0);
458 *value
= SysAllocStringLen(NULL
, len
);
460 return E_OUTOFMEMORY
;
463 GetEnvironmentVariableW(name
, *value
, len
+1);
468 static HRESULT WINAPI
WshEnvironment_put_Item(IWshEnvironment
*iface
, BSTR name
, BSTR value
)
470 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
471 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(name
), debugstr_w(value
));
475 static HRESULT WINAPI
WshEnvironment_Count(IWshEnvironment
*iface
, LONG
*count
)
477 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
478 FIXME("(%p)->(%p): stub\n", This
, count
);
482 static HRESULT WINAPI
WshEnvironment_get_length(IWshEnvironment
*iface
, LONG
*len
)
484 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
485 FIXME("(%p)->(%p): stub\n", This
, len
);
489 static HRESULT WINAPI
WshEnvironment__NewEnum(IWshEnvironment
*iface
, IUnknown
**penum
)
491 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
492 FIXME("(%p)->(%p): stub\n", This
, penum
);
496 static HRESULT WINAPI
WshEnvironment_Remove(IWshEnvironment
*iface
, BSTR name
)
498 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
499 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
503 static const IWshEnvironmentVtbl WshEnvironmentVtbl
= {
504 WshEnvironment_QueryInterface
,
505 WshEnvironment_AddRef
,
506 WshEnvironment_Release
,
507 WshEnvironment_GetTypeInfoCount
,
508 WshEnvironment_GetTypeInfo
,
509 WshEnvironment_GetIDsOfNames
,
510 WshEnvironment_Invoke
,
511 WshEnvironment_get_Item
,
512 WshEnvironment_put_Item
,
513 WshEnvironment_Count
,
514 WshEnvironment_get_length
,
515 WshEnvironment__NewEnum
,
516 WshEnvironment_Remove
519 static HRESULT
WshEnvironment_Create(IWshEnvironment
**env
)
521 WshEnvironment
*This
;
523 This
= heap_alloc(sizeof(*This
));
524 if (!This
) return E_OUTOFMEMORY
;
526 This
->IWshEnvironment_iface
.lpVtbl
= &WshEnvironmentVtbl
;
529 init_classinfo(&IID_IWshEnvironment
, (IUnknown
*)&This
->IWshEnvironment_iface
, &This
->classinfo
);
530 *env
= &This
->IWshEnvironment_iface
;
535 static HRESULT WINAPI
WshCollection_QueryInterface(IWshCollection
*iface
, REFIID riid
, void **ppv
)
537 WshCollection
*This
= impl_from_IWshCollection(iface
);
539 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
541 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
542 IsEqualGUID(riid
, &IID_IDispatch
) ||
543 IsEqualGUID(riid
, &IID_IWshCollection
))
547 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
549 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
552 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
554 return E_NOINTERFACE
;
557 IUnknown_AddRef((IUnknown
*)*ppv
);
561 static ULONG WINAPI
WshCollection_AddRef(IWshCollection
*iface
)
563 WshCollection
*This
= impl_from_IWshCollection(iface
);
564 LONG ref
= InterlockedIncrement(&This
->ref
);
565 TRACE("(%p) ref = %d\n", This
, ref
);
569 static ULONG WINAPI
WshCollection_Release(IWshCollection
*iface
)
571 WshCollection
*This
= impl_from_IWshCollection(iface
);
572 LONG ref
= InterlockedDecrement(&This
->ref
);
573 TRACE("(%p) ref = %d\n", This
, ref
);
581 static HRESULT WINAPI
WshCollection_GetTypeInfoCount(IWshCollection
*iface
, UINT
*pctinfo
)
583 WshCollection
*This
= impl_from_IWshCollection(iface
);
584 TRACE("(%p)->(%p)\n", This
, pctinfo
);
589 static HRESULT WINAPI
WshCollection_GetTypeInfo(IWshCollection
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
591 WshCollection
*This
= impl_from_IWshCollection(iface
);
592 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
593 return get_typeinfo(IWshCollection_tid
, ppTInfo
);
596 static HRESULT WINAPI
WshCollection_GetIDsOfNames(IWshCollection
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
597 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
599 WshCollection
*This
= impl_from_IWshCollection(iface
);
603 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
605 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
608 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
609 ITypeInfo_Release(typeinfo
);
615 static HRESULT WINAPI
WshCollection_Invoke(IWshCollection
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
616 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
618 WshCollection
*This
= impl_from_IWshCollection(iface
);
622 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
623 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
625 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
628 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshCollection_iface
, dispIdMember
, wFlags
,
629 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
630 ITypeInfo_Release(typeinfo
);
636 static HRESULT WINAPI
WshCollection_Item(IWshCollection
*iface
, VARIANT
*index
, VARIANT
*value
)
638 WshCollection
*This
= impl_from_IWshCollection(iface
);
639 static const WCHAR allusersdesktopW
[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
640 static const WCHAR allusersprogramsW
[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
641 static const WCHAR desktopW
[] = {'D','e','s','k','t','o','p',0};
642 PIDLIST_ABSOLUTE pidl
;
643 WCHAR pathW
[MAX_PATH
];
648 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(index
), value
);
650 if (V_VT(index
) != VT_BSTR
)
652 FIXME("only BSTR index supported, got %d\n", V_VT(index
));
656 folder
= V_BSTR(index
);
657 if (!strcmpiW(folder
, desktopW
))
658 kind
= CSIDL_DESKTOP
;
659 else if (!strcmpiW(folder
, allusersdesktopW
))
660 kind
= CSIDL_COMMON_DESKTOPDIRECTORY
;
661 else if (!strcmpiW(folder
, allusersprogramsW
))
662 kind
= CSIDL_COMMON_PROGRAMS
;
665 FIXME("folder kind %s not supported\n", debugstr_w(folder
));
669 hr
= SHGetSpecialFolderLocation(NULL
, kind
, &pidl
);
670 if (hr
!= S_OK
) return hr
;
672 if (SHGetPathFromIDListW(pidl
, pathW
))
674 V_VT(value
) = VT_BSTR
;
675 V_BSTR(value
) = SysAllocString(pathW
);
676 hr
= V_BSTR(value
) ? S_OK
: E_OUTOFMEMORY
;
686 static HRESULT WINAPI
WshCollection_Count(IWshCollection
*iface
, LONG
*count
)
688 WshCollection
*This
= impl_from_IWshCollection(iface
);
689 FIXME("(%p)->(%p): stub\n", This
, count
);
693 static HRESULT WINAPI
WshCollection_get_length(IWshCollection
*iface
, LONG
*count
)
695 WshCollection
*This
= impl_from_IWshCollection(iface
);
696 FIXME("(%p)->(%p): stub\n", This
, count
);
700 static HRESULT WINAPI
WshCollection__NewEnum(IWshCollection
*iface
, IUnknown
*Enum
)
702 WshCollection
*This
= impl_from_IWshCollection(iface
);
703 FIXME("(%p)->(%p): stub\n", This
, Enum
);
707 static const IWshCollectionVtbl WshCollectionVtbl
= {
708 WshCollection_QueryInterface
,
709 WshCollection_AddRef
,
710 WshCollection_Release
,
711 WshCollection_GetTypeInfoCount
,
712 WshCollection_GetTypeInfo
,
713 WshCollection_GetIDsOfNames
,
714 WshCollection_Invoke
,
717 WshCollection_get_length
,
718 WshCollection__NewEnum
721 static HRESULT
WshCollection_Create(IWshCollection
**collection
)
725 This
= heap_alloc(sizeof(*This
));
726 if (!This
) return E_OUTOFMEMORY
;
728 This
->IWshCollection_iface
.lpVtbl
= &WshCollectionVtbl
;
731 init_classinfo(&IID_IWshCollection
, (IUnknown
*)&This
->IWshCollection_iface
, &This
->classinfo
);
732 *collection
= &This
->IWshCollection_iface
;
738 static HRESULT WINAPI
WshShortcut_QueryInterface(IWshShortcut
*iface
, REFIID riid
, void **ppv
)
740 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
742 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
744 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
745 IsEqualGUID(riid
, &IID_IDispatch
) ||
746 IsEqualGUID(riid
, &IID_IWshShortcut
))
750 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
752 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
755 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
757 return E_NOINTERFACE
;
760 IUnknown_AddRef((IUnknown
*)*ppv
);
764 static ULONG WINAPI
WshShortcut_AddRef(IWshShortcut
*iface
)
766 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
767 LONG ref
= InterlockedIncrement(&This
->ref
);
768 TRACE("(%p) ref = %d\n", This
, ref
);
772 static ULONG WINAPI
WshShortcut_Release(IWshShortcut
*iface
)
774 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
775 LONG ref
= InterlockedDecrement(&This
->ref
);
776 TRACE("(%p) ref = %d\n", This
, ref
);
780 SysFreeString(This
->path_link
);
781 IShellLinkW_Release(This
->link
);
788 static HRESULT WINAPI
WshShortcut_GetTypeInfoCount(IWshShortcut
*iface
, UINT
*pctinfo
)
790 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
791 TRACE("(%p)->(%p)\n", This
, pctinfo
);
796 static HRESULT WINAPI
WshShortcut_GetTypeInfo(IWshShortcut
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
798 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
799 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
800 return get_typeinfo(IWshShortcut_tid
, ppTInfo
);
803 static HRESULT WINAPI
WshShortcut_GetIDsOfNames(IWshShortcut
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
804 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
806 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
810 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
812 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
815 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
816 ITypeInfo_Release(typeinfo
);
822 static HRESULT WINAPI
WshShortcut_Invoke(IWshShortcut
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
823 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
825 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
829 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
830 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
832 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
835 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshShortcut_iface
, dispIdMember
, wFlags
,
836 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
837 ITypeInfo_Release(typeinfo
);
843 static HRESULT WINAPI
WshShortcut_get_FullName(IWshShortcut
*iface
, BSTR
*name
)
845 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
846 FIXME("(%p)->(%p): stub\n", This
, name
);
850 static HRESULT WINAPI
WshShortcut_get_Arguments(IWshShortcut
*iface
, BSTR
*Arguments
)
852 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
853 WCHAR buffW
[INFOTIPSIZE
];
856 TRACE("(%p)->(%p)\n", This
, Arguments
);
863 hr
= IShellLinkW_GetArguments(This
->link
, buffW
, ARRAY_SIZE(buffW
));
867 *Arguments
= SysAllocString(buffW
);
868 return *Arguments
? S_OK
: E_OUTOFMEMORY
;
871 static HRESULT WINAPI
WshShortcut_put_Arguments(IWshShortcut
*iface
, BSTR Arguments
)
873 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
875 TRACE("(%p)->(%s)\n", This
, debugstr_w(Arguments
));
877 return IShellLinkW_SetArguments(This
->link
, Arguments
);
880 static HRESULT WINAPI
WshShortcut_get_Description(IWshShortcut
*iface
, BSTR
*Description
)
882 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
883 FIXME("(%p)->(%p): stub\n", This
, Description
);
887 static HRESULT WINAPI
WshShortcut_put_Description(IWshShortcut
*iface
, BSTR Description
)
889 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
890 TRACE("(%p)->(%s)\n", This
, debugstr_w(Description
));
891 return IShellLinkW_SetDescription(This
->link
, Description
);
894 static HRESULT WINAPI
WshShortcut_get_Hotkey(IWshShortcut
*iface
, BSTR
*Hotkey
)
896 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
897 FIXME("(%p)->(%p): stub\n", This
, Hotkey
);
901 static HRESULT WINAPI
WshShortcut_put_Hotkey(IWshShortcut
*iface
, BSTR Hotkey
)
903 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
904 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(Hotkey
));
908 static HRESULT WINAPI
WshShortcut_get_IconLocation(IWshShortcut
*iface
, BSTR
*IconPath
)
910 static const WCHAR fmtW
[] = {'%','s',',',' ','%','d',0};
911 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
912 WCHAR buffW
[MAX_PATH
], pathW
[MAX_PATH
];
916 TRACE("(%p)->(%p)\n", This
, IconPath
);
921 hr
= IShellLinkW_GetIconLocation(This
->link
, buffW
, ARRAY_SIZE(buffW
), &icon
);
922 if (FAILED(hr
)) return hr
;
924 sprintfW(pathW
, fmtW
, buffW
, icon
);
925 *IconPath
= SysAllocString(pathW
);
926 if (!*IconPath
) return E_OUTOFMEMORY
;
931 static HRESULT WINAPI
WshShortcut_put_IconLocation(IWshShortcut
*iface
, BSTR IconPath
)
933 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
939 TRACE("(%p)->(%s)\n", This
, debugstr_w(IconPath
));
941 /* scan for icon id */
942 ptr
= strrchrW(IconPath
, ',');
945 WARN("icon index not found\n");
949 path
= SysAllocStringLen(IconPath
, ptr
-IconPath
);
951 /* skip spaces if any */
952 while (isspaceW(*++ptr
))
957 hr
= IShellLinkW_SetIconLocation(This
->link
, path
, icon
);
963 static HRESULT WINAPI
WshShortcut_put_RelativePath(IWshShortcut
*iface
, BSTR rhs
)
965 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
966 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(rhs
));
970 static HRESULT WINAPI
WshShortcut_get_TargetPath(IWshShortcut
*iface
, BSTR
*Path
)
972 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
973 FIXME("(%p)->(%p): stub\n", This
, Path
);
977 static HRESULT WINAPI
WshShortcut_put_TargetPath(IWshShortcut
*iface
, BSTR Path
)
979 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
980 TRACE("(%p)->(%s)\n", This
, debugstr_w(Path
));
981 return IShellLinkW_SetPath(This
->link
, Path
);
984 static HRESULT WINAPI
WshShortcut_get_WindowStyle(IWshShortcut
*iface
, int *ShowCmd
)
986 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
987 TRACE("(%p)->(%p)\n", This
, ShowCmd
);
988 return IShellLinkW_GetShowCmd(This
->link
, ShowCmd
);
991 static HRESULT WINAPI
WshShortcut_put_WindowStyle(IWshShortcut
*iface
, int ShowCmd
)
993 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
994 TRACE("(%p)->(%d)\n", This
, ShowCmd
);
995 return IShellLinkW_SetShowCmd(This
->link
, ShowCmd
);
998 static HRESULT WINAPI
WshShortcut_get_WorkingDirectory(IWshShortcut
*iface
, BSTR
*WorkingDirectory
)
1000 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1001 WCHAR buffW
[MAX_PATH
];
1004 TRACE("(%p)->(%p)\n", This
, WorkingDirectory
);
1006 if (!WorkingDirectory
)
1009 *WorkingDirectory
= NULL
;
1010 hr
= IShellLinkW_GetWorkingDirectory(This
->link
, buffW
, ARRAY_SIZE(buffW
));
1011 if (FAILED(hr
)) return hr
;
1013 *WorkingDirectory
= SysAllocString(buffW
);
1014 return *WorkingDirectory
? S_OK
: E_OUTOFMEMORY
;
1017 static HRESULT WINAPI
WshShortcut_put_WorkingDirectory(IWshShortcut
*iface
, BSTR WorkingDirectory
)
1019 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1020 TRACE("(%p)->(%s)\n", This
, debugstr_w(WorkingDirectory
));
1021 return IShellLinkW_SetWorkingDirectory(This
->link
, WorkingDirectory
);
1024 static HRESULT WINAPI
WshShortcut_Load(IWshShortcut
*iface
, BSTR PathLink
)
1026 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1027 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(PathLink
));
1031 static HRESULT WINAPI
WshShortcut_Save(IWshShortcut
*iface
)
1033 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1037 TRACE("(%p)\n", This
);
1039 IShellLinkW_QueryInterface(This
->link
, &IID_IPersistFile
, (void**)&file
);
1040 hr
= IPersistFile_Save(file
, This
->path_link
, TRUE
);
1041 IPersistFile_Release(file
);
1046 static const IWshShortcutVtbl WshShortcutVtbl
= {
1047 WshShortcut_QueryInterface
,
1049 WshShortcut_Release
,
1050 WshShortcut_GetTypeInfoCount
,
1051 WshShortcut_GetTypeInfo
,
1052 WshShortcut_GetIDsOfNames
,
1054 WshShortcut_get_FullName
,
1055 WshShortcut_get_Arguments
,
1056 WshShortcut_put_Arguments
,
1057 WshShortcut_get_Description
,
1058 WshShortcut_put_Description
,
1059 WshShortcut_get_Hotkey
,
1060 WshShortcut_put_Hotkey
,
1061 WshShortcut_get_IconLocation
,
1062 WshShortcut_put_IconLocation
,
1063 WshShortcut_put_RelativePath
,
1064 WshShortcut_get_TargetPath
,
1065 WshShortcut_put_TargetPath
,
1066 WshShortcut_get_WindowStyle
,
1067 WshShortcut_put_WindowStyle
,
1068 WshShortcut_get_WorkingDirectory
,
1069 WshShortcut_put_WorkingDirectory
,
1074 static HRESULT
WshShortcut_Create(const WCHAR
*path
, IDispatch
**shortcut
)
1081 This
= heap_alloc(sizeof(*This
));
1082 if (!This
) return E_OUTOFMEMORY
;
1084 This
->IWshShortcut_iface
.lpVtbl
= &WshShortcutVtbl
;
1087 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
1088 &IID_IShellLinkW
, (void**)&This
->link
);
1095 This
->path_link
= SysAllocString(path
);
1096 if (!This
->path_link
)
1098 IShellLinkW_Release(This
->link
);
1100 return E_OUTOFMEMORY
;
1103 init_classinfo(&IID_IWshShortcut
, (IUnknown
*)&This
->IWshShortcut_iface
, &This
->classinfo
);
1104 *shortcut
= (IDispatch
*)&This
->IWshShortcut_iface
;
1109 static HRESULT WINAPI
WshShell3_QueryInterface(IWshShell3
*iface
, REFIID riid
, void **ppv
)
1111 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
1115 if (IsEqualGUID(riid
, &IID_IDispatch
) ||
1116 IsEqualGUID(riid
, &IID_IWshShell3
) ||
1117 IsEqualGUID(riid
, &IID_IWshShell2
) ||
1118 IsEqualGUID(riid
, &IID_IWshShell
) ||
1119 IsEqualGUID(riid
, &IID_IUnknown
))
1123 else if (IsEqualGUID(riid
, &IID_IDispatchEx
))
1125 return E_NOINTERFACE
;
1127 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
1129 *ppv
= &WshShell3
.classinfo
.IProvideClassInfo_iface
;
1133 WARN("unknown iface %s\n", debugstr_guid(riid
));
1134 return E_NOINTERFACE
;
1137 IUnknown_AddRef((IUnknown
*)*ppv
);
1141 static ULONG WINAPI
WshShell3_AddRef(IWshShell3
*iface
)
1147 static ULONG WINAPI
WshShell3_Release(IWshShell3
*iface
)
1153 static HRESULT WINAPI
WshShell3_GetTypeInfoCount(IWshShell3
*iface
, UINT
*pctinfo
)
1155 TRACE("(%p)\n", pctinfo
);
1160 static HRESULT WINAPI
WshShell3_GetTypeInfo(IWshShell3
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
1162 TRACE("(%u %u %p)\n", iTInfo
, lcid
, ppTInfo
);
1163 return get_typeinfo(IWshShell3_tid
, ppTInfo
);
1166 static HRESULT WINAPI
WshShell3_GetIDsOfNames(IWshShell3
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
1167 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1169 ITypeInfo
*typeinfo
;
1172 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
1174 hr
= get_typeinfo(IWshShell3_tid
, &typeinfo
);
1177 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1178 ITypeInfo_Release(typeinfo
);
1184 static HRESULT WINAPI
WshShell3_Invoke(IWshShell3
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
1185 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1187 ITypeInfo
*typeinfo
;
1190 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember
, debugstr_guid(riid
),
1191 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1193 hr
= get_typeinfo(IWshShell3_tid
, &typeinfo
);
1196 hr
= ITypeInfo_Invoke(typeinfo
, &WshShell3
.IWshShell3_iface
, dispIdMember
, wFlags
,
1197 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1198 ITypeInfo_Release(typeinfo
);
1204 static HRESULT WINAPI
WshShell3_get_SpecialFolders(IWshShell3
*iface
, IWshCollection
**folders
)
1206 TRACE("(%p)\n", folders
);
1207 return WshCollection_Create(folders
);
1210 static HRESULT WINAPI
WshShell3_get_Environment(IWshShell3
*iface
, VARIANT
*type
, IWshEnvironment
**env
)
1212 FIXME("(%s %p): semi-stub\n", debugstr_variant(type
), env
);
1213 return WshEnvironment_Create(env
);
1216 static inline BOOL
is_optional_argument(const VARIANT
*arg
)
1218 return V_VT(arg
) == VT_ERROR
&& V_ERROR(arg
) == DISP_E_PARAMNOTFOUND
;
1221 static HRESULT WINAPI
WshShell3_Run(IWshShell3
*iface
, BSTR cmd
, VARIANT
*style
, VARIANT
*wait
, DWORD
*exit_code
)
1223 SHELLEXECUTEINFOW info
;
1228 TRACE("(%s %s %s %p)\n", debugstr_w(cmd
), debugstr_variant(style
), debugstr_variant(wait
), exit_code
);
1230 if (!style
|| !wait
|| !exit_code
)
1234 hr
= VariantChangeType(&s
, style
, 0, VT_I4
);
1237 ERR("failed to convert style argument, 0x%08x\n", hr
);
1241 if (is_optional_argument(wait
))
1247 hr
= VariantChangeType(&w
, wait
, 0, VT_I4
);
1251 waitforprocess
= V_I4(&w
);
1254 memset(&info
, 0, sizeof(info
));
1255 info
.cbSize
= sizeof(info
);
1256 info
.fMask
= waitforprocess
? SEE_MASK_NOASYNC
| SEE_MASK_NOCLOSEPROCESS
: SEE_MASK_DEFAULT
;
1258 info
.nShow
= V_I4(&s
);
1260 if (!ShellExecuteExW(&info
))
1262 TRACE("ShellExecute failed, %d\n", GetLastError());
1263 return HRESULT_FROM_WIN32(GetLastError());
1269 GetExitCodeProcess(info
.hProcess
, exit_code
);
1270 CloseHandle(info
.hProcess
);
1279 struct popup_thread_param
1287 static DWORD WINAPI
popup_thread_proc(void *arg
)
1289 static const WCHAR defaulttitleW
[] = {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0};
1290 struct popup_thread_param
*param
= (struct popup_thread_param
*)arg
;
1292 param
->button
= MessageBoxW(NULL
, param
->text
, is_optional_argument(¶m
->title
) ?
1293 defaulttitleW
: V_BSTR(¶m
->title
), V_I4(¶m
->type
));
1297 static HRESULT WINAPI
WshShell3_Popup(IWshShell3
*iface
, BSTR text
, VARIANT
*seconds_to_wait
, VARIANT
*title
,
1298 VARIANT
*type
, int *button
)
1300 struct popup_thread_param param
;
1306 TRACE("(%s %s %s %s %p)\n", debugstr_w(text
), debugstr_variant(seconds_to_wait
), debugstr_variant(title
),
1307 debugstr_variant(type
), button
);
1309 if (!seconds_to_wait
|| !title
|| !type
|| !button
)
1312 VariantInit(&timeout
);
1313 if (!is_optional_argument(seconds_to_wait
))
1315 hr
= VariantChangeType(&timeout
, seconds_to_wait
, 0, VT_I4
);
1320 VariantInit(¶m
.type
);
1321 if (!is_optional_argument(type
))
1323 hr
= VariantChangeType(¶m
.type
, type
, 0, VT_I4
);
1328 if (is_optional_argument(title
))
1329 param
.title
= *title
;
1332 VariantInit(¶m
.title
);
1333 hr
= VariantChangeType(¶m
.title
, title
, 0, VT_BSTR
);
1340 hthread
= CreateThread(NULL
, 0, popup_thread_proc
, ¶m
, 0, &tid
);
1341 status
= MsgWaitForMultipleObjects(1, &hthread
, FALSE
, V_I4(&timeout
) ? V_I4(&timeout
) * 1000: INFINITE
, 0);
1342 if (status
== WAIT_TIMEOUT
)
1344 PostThreadMessageW(tid
, WM_QUIT
, 0, 0);
1345 MsgWaitForMultipleObjects(1, &hthread
, FALSE
, INFINITE
, 0);
1348 *button
= param
.button
;
1350 VariantClear(¶m
.title
);
1351 CloseHandle(hthread
);
1356 static HRESULT WINAPI
WshShell3_CreateShortcut(IWshShell3
*iface
, BSTR PathLink
, IDispatch
** Shortcut
)
1358 TRACE("(%s %p)\n", debugstr_w(PathLink
), Shortcut
);
1359 return WshShortcut_Create(PathLink
, Shortcut
);
1362 static HRESULT WINAPI
WshShell3_ExpandEnvironmentStrings(IWshShell3
*iface
, BSTR Src
, BSTR
* Dst
)
1366 TRACE("(%s %p)\n", debugstr_w(Src
), Dst
);
1368 if (!Src
|| !Dst
) return E_POINTER
;
1370 ret
= ExpandEnvironmentStringsW(Src
, NULL
, 0);
1371 *Dst
= SysAllocStringLen(NULL
, ret
);
1372 if (!*Dst
) return E_OUTOFMEMORY
;
1374 if (ExpandEnvironmentStringsW(Src
, *Dst
, ret
))
1378 SysFreeString(*Dst
);
1380 return HRESULT_FROM_WIN32(GetLastError());
1384 static HKEY
get_root_key(const WCHAR
*path
)
1386 static const struct {
1387 const WCHAR full
[20];
1388 const WCHAR abbrev
[5];
1391 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER
},
1392 { {'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
},
1393 { {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT
},
1394 { {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS
},
1395 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG
}
1399 for (i
= 0; i
< ARRAY_SIZE(rootkeys
); i
++) {
1400 if (!strncmpW(path
, rootkeys
[i
].full
, strlenW(rootkeys
[i
].full
)))
1401 return rootkeys
[i
].hkey
;
1402 if (rootkeys
[i
].abbrev
[0] && !strncmpW(path
, rootkeys
[i
].abbrev
, strlenW(rootkeys
[i
].abbrev
)))
1403 return rootkeys
[i
].hkey
;
1409 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
1410 static HRESULT
split_reg_path(const WCHAR
*path
, WCHAR
**subkey
, WCHAR
**value
)
1414 /* at least one separator should be present */
1415 *subkey
= strchrW(path
, '\\');
1417 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1419 /* default value or not */
1420 if ((*subkey
)[strlenW(*subkey
)-1] == '\\') {
1425 *value
= strrchrW(*subkey
, '\\');
1426 if (*value
- *subkey
> 1) {
1427 unsigned int len
= *value
- *subkey
- 1;
1430 ret
= heap_alloc((len
+ 1)*sizeof(WCHAR
));
1432 return E_OUTOFMEMORY
;
1434 memcpy(ret
, *subkey
+ 1, len
*sizeof(WCHAR
));
1444 static HRESULT WINAPI
WshShell3_RegRead(IWshShell3
*iface
, BSTR name
, VARIANT
*value
)
1446 DWORD type
, datalen
, ret
;
1447 WCHAR
*subkey
, *val
;
1451 TRACE("(%s %p)\n", debugstr_w(name
), value
);
1453 if (!name
|| !value
)
1456 root
= get_root_key(name
);
1458 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1460 hr
= split_reg_path(name
, &subkey
, &val
);
1466 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, NULL
, &datalen
);
1467 if (ret
== ERROR_SUCCESS
) {
1470 data
= heap_alloc(datalen
);
1476 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, data
, &datalen
);
1479 hr
= HRESULT_FROM_WIN32(ret
);
1486 V_VT(value
) = VT_BSTR
;
1487 V_BSTR(value
) = SysAllocString((WCHAR
*)data
);
1492 V_VT(value
) = VT_I4
;
1493 V_I4(value
) = *(DWORD
*)data
;
1497 BYTE
*ptr
= (BYTE
*)data
;
1498 SAFEARRAYBOUND bound
;
1504 bound
.cElements
= datalen
;
1505 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1509 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1511 SafeArrayDestroy(sa
);
1515 for (i
= 0; i
< datalen
; i
++) {
1516 V_VT(&v
[i
]) = VT_UI1
;
1517 V_UI1(&v
[i
]) = ptr
[i
];
1519 SafeArrayUnaccessData(sa
);
1521 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1522 V_ARRAY(value
) = sa
;
1527 WCHAR
*ptr
= (WCHAR
*)data
;
1528 SAFEARRAYBOUND bound
;
1532 /* get element count first */
1534 bound
.cElements
= 0;
1537 ptr
+= strlenW(ptr
)+1;
1540 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1544 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1546 SafeArrayDestroy(sa
);
1553 V_BSTR(v
) = SysAllocString(ptr
);
1554 ptr
+= strlenW(ptr
)+1;
1558 SafeArrayUnaccessData(sa
);
1559 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1560 V_ARRAY(value
) = sa
;
1564 FIXME("value type %d not supported\n", type
);
1573 hr
= HRESULT_FROM_WIN32(ret
);
1581 static HRESULT WINAPI
WshShell3_RegWrite(IWshShell3
*iface
, BSTR name
, VARIANT
*value
, VARIANT
*type
)
1583 static const WCHAR regexpandszW
[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
1584 static const WCHAR regszW
[] = {'R','E','G','_','S','Z',0};
1585 static const WCHAR regdwordW
[] = {'R','E','G','_','D','W','O','R','D',0};
1586 static const WCHAR regbinaryW
[] = {'R','E','G','_','B','I','N','A','R','Y',0};
1588 DWORD regtype
, data_len
;
1589 WCHAR
*subkey
, *val
;
1596 TRACE("(%s %s %s)\n", debugstr_w(name
), debugstr_variant(value
), debugstr_variant(type
));
1598 if (!name
|| !value
|| !type
)
1601 root
= get_root_key(name
);
1603 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1606 if (is_optional_argument(type
))
1609 if (V_VT(type
) != VT_BSTR
)
1610 return E_INVALIDARG
;
1612 if (!strcmpW(V_BSTR(type
), regszW
))
1614 else if (!strcmpW(V_BSTR(type
), regdwordW
))
1615 regtype
= REG_DWORD
;
1616 else if (!strcmpW(V_BSTR(type
), regexpandszW
))
1617 regtype
= REG_EXPAND_SZ
;
1618 else if (!strcmpW(V_BSTR(type
), regbinaryW
))
1619 regtype
= REG_BINARY
;
1621 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type
)));
1626 /* it's always a string or a DWORD */
1632 hr
= VariantChangeType(&v
, value
, 0, VT_BSTR
);
1634 data
= (BYTE
*)V_BSTR(&v
);
1635 data_len
= SysStringByteLen(V_BSTR(&v
)) + sizeof(WCHAR
);
1640 hr
= VariantChangeType(&v
, value
, 0, VT_I4
);
1641 data
= (BYTE
*)&V_I4(&v
);
1642 data_len
= sizeof(DWORD
);
1645 FIXME("unexpected regtype %d\n", regtype
);
1650 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype
, hr
);
1654 hr
= split_reg_path(name
, &subkey
, &val
);
1658 ret
= RegSetKeyValueW(root
, subkey
, val
, regtype
, data
, data_len
);
1660 hr
= HRESULT_FROM_WIN32(ret
);
1669 static HRESULT WINAPI
WshShell3_RegDelete(IWshShell3
*iface
, BSTR Name
)
1671 FIXME("(%s): stub\n", debugstr_w(Name
));
1675 static HRESULT WINAPI
WshShell3_LogEvent(IWshShell3
*iface
, VARIANT
*Type
, BSTR Message
, BSTR Target
, VARIANT_BOOL
*out_Success
)
1677 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type
), debugstr_w(Message
), debugstr_w(Target
), out_Success
);
1681 static HRESULT WINAPI
WshShell3_AppActivate(IWshShell3
*iface
, VARIANT
*App
, VARIANT
*Wait
, VARIANT_BOOL
*out_Success
)
1683 FIXME("(%s %s %p): stub\n", debugstr_variant(App
), debugstr_variant(Wait
), out_Success
);
1687 static HRESULT WINAPI
WshShell3_SendKeys(IWshShell3
*iface
, BSTR Keys
, VARIANT
*Wait
)
1689 FIXME("(%s %p): stub\n", debugstr_w(Keys
), Wait
);
1693 static HRESULT WINAPI
WshShell3_Exec(IWshShell3
*iface
, BSTR command
, IWshExec
**ret
)
1695 TRACE("(%s %p)\n", debugstr_w(command
), ret
);
1701 return DISP_E_EXCEPTION
;
1703 return WshExec_create(command
, ret
);
1706 static HRESULT WINAPI
WshShell3_get_CurrentDirectory(IWshShell3
*iface
, BSTR
*dir
)
1710 TRACE("(%p)\n", dir
);
1712 ret
= GetCurrentDirectoryW(0, NULL
);
1714 return HRESULT_FROM_WIN32(GetLastError());
1716 *dir
= SysAllocStringLen(NULL
, ret
-1);
1718 return E_OUTOFMEMORY
;
1720 ret
= GetCurrentDirectoryW(ret
, *dir
);
1722 SysFreeString(*dir
);
1724 return HRESULT_FROM_WIN32(GetLastError());
1730 static HRESULT WINAPI
WshShell3_put_CurrentDirectory(IWshShell3
*iface
, BSTR dir
)
1732 TRACE("(%s)\n", debugstr_w(dir
));
1735 return E_INVALIDARG
;
1737 if (!SetCurrentDirectoryW(dir
))
1738 return HRESULT_FROM_WIN32(GetLastError());
1743 static const IWshShell3Vtbl WshShell3Vtbl
= {
1744 WshShell3_QueryInterface
,
1747 WshShell3_GetTypeInfoCount
,
1748 WshShell3_GetTypeInfo
,
1749 WshShell3_GetIDsOfNames
,
1751 WshShell3_get_SpecialFolders
,
1752 WshShell3_get_Environment
,
1755 WshShell3_CreateShortcut
,
1756 WshShell3_ExpandEnvironmentStrings
,
1759 WshShell3_RegDelete
,
1761 WshShell3_AppActivate
,
1764 WshShell3_get_CurrentDirectory
,
1765 WshShell3_put_CurrentDirectory
1768 HRESULT WINAPI
WshShellFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
1770 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
1772 WshShell3
.IWshShell3_iface
.lpVtbl
= &WshShell3Vtbl
;
1773 init_classinfo(&IID_IWshShell3
, (IUnknown
*)&WshShell3
.IWshShell3_iface
, &WshShell3
.classinfo
);
1774 return IWshShell3_QueryInterface(&WshShell3
.IWshShell3_iface
, riid
, ppv
);