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/unicode.h>
30 struct provideclassinfo classinfo
;
31 IWshShell3 IWshShell3_iface
;
33 static WshShellImpl WshShell3
;
37 struct provideclassinfo classinfo
;
38 IWshCollection IWshCollection_iface
;
44 struct provideclassinfo classinfo
;
45 IWshShortcut IWshShortcut_iface
;
54 struct provideclassinfo classinfo
;
55 IWshEnvironment IWshEnvironment_iface
;
61 struct provideclassinfo classinfo
;
62 IWshExec IWshExec_iface
;
64 PROCESS_INFORMATION info
;
67 static inline WshCollection
*impl_from_IWshCollection( IWshCollection
*iface
)
69 return CONTAINING_RECORD(iface
, WshCollection
, IWshCollection_iface
);
72 static inline WshShortcut
*impl_from_IWshShortcut( IWshShortcut
*iface
)
74 return CONTAINING_RECORD(iface
, WshShortcut
, IWshShortcut_iface
);
77 static inline WshEnvironment
*impl_from_IWshEnvironment( IWshEnvironment
*iface
)
79 return CONTAINING_RECORD(iface
, WshEnvironment
, IWshEnvironment_iface
);
82 static inline WshExecImpl
*impl_from_IWshExec( IWshExec
*iface
)
84 return CONTAINING_RECORD(iface
, WshExecImpl
, IWshExec_iface
);
87 static HRESULT WINAPI
WshExec_QueryInterface(IWshExec
*iface
, REFIID riid
, void **obj
)
89 WshExecImpl
*This
= impl_from_IWshExec(iface
);
91 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
93 if (IsEqualGUID(riid
, &IID_IDispatch
) ||
94 IsEqualGUID(riid
, &IID_IWshExec
) ||
95 IsEqualGUID(riid
, &IID_IUnknown
))
99 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
101 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
104 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
106 return E_NOINTERFACE
;
109 IUnknown_AddRef((IUnknown
*)*obj
);
113 static ULONG WINAPI
WshExec_AddRef(IWshExec
*iface
)
115 WshExecImpl
*This
= impl_from_IWshExec(iface
);
116 LONG ref
= InterlockedIncrement(&This
->ref
);
117 TRACE("(%p) ref = %d\n", This
, ref
);
121 static ULONG WINAPI
WshExec_Release(IWshExec
*iface
)
123 WshExecImpl
*This
= impl_from_IWshExec(iface
);
124 LONG ref
= InterlockedDecrement(&This
->ref
);
125 TRACE("(%p) ref = %d\n", This
, ref
);
128 CloseHandle(This
->info
.hThread
);
129 CloseHandle(This
->info
.hProcess
);
130 HeapFree(GetProcessHeap(), 0, This
);
136 static HRESULT WINAPI
WshExec_GetTypeInfoCount(IWshExec
*iface
, UINT
*pctinfo
)
138 WshExecImpl
*This
= impl_from_IWshExec(iface
);
139 TRACE("(%p)->(%p)\n", This
, pctinfo
);
144 static HRESULT WINAPI
WshExec_GetTypeInfo(IWshExec
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
146 WshExecImpl
*This
= impl_from_IWshExec(iface
);
147 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
148 return get_typeinfo(IWshExec_tid
, ppTInfo
);
151 static HRESULT WINAPI
WshExec_GetIDsOfNames(IWshExec
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
152 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
154 WshExecImpl
*This
= impl_from_IWshExec(iface
);
158 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
160 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
163 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
164 ITypeInfo_Release(typeinfo
);
170 static HRESULT WINAPI
WshExec_Invoke(IWshExec
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
171 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
173 WshExecImpl
*This
= impl_from_IWshExec(iface
);
177 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
178 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
180 hr
= get_typeinfo(IWshExec_tid
, &typeinfo
);
183 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshExec_iface
, dispIdMember
, wFlags
,
184 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
185 ITypeInfo_Release(typeinfo
);
191 static HRESULT WINAPI
WshExec_get_Status(IWshExec
*iface
, WshExecStatus
*status
)
193 WshExecImpl
*This
= impl_from_IWshExec(iface
);
196 TRACE("(%p)->(%p)\n", This
, status
);
201 if (!GetExitCodeProcess(This
->info
.hProcess
, &code
))
202 return HRESULT_FROM_WIN32(GetLastError());
207 *status
= WshFinished
;
210 *status
= WshRunning
;
219 static HRESULT WINAPI
WshExec_get_StdIn(IWshExec
*iface
, ITextStream
**stream
)
221 WshExecImpl
*This
= impl_from_IWshExec(iface
);
223 FIXME("(%p)->(%p): stub\n", This
, stream
);
228 static HRESULT WINAPI
WshExec_get_StdOut(IWshExec
*iface
, ITextStream
**stream
)
230 WshExecImpl
*This
= impl_from_IWshExec(iface
);
232 FIXME("(%p)->(%p): stub\n", This
, stream
);
237 static HRESULT WINAPI
WshExec_get_StdErr(IWshExec
*iface
, ITextStream
**stream
)
239 WshExecImpl
*This
= impl_from_IWshExec(iface
);
241 FIXME("(%p)->(%p): stub\n", This
, stream
);
246 static HRESULT WINAPI
WshExec_get_ProcessID(IWshExec
*iface
, DWORD
*pid
)
248 WshExecImpl
*This
= impl_from_IWshExec(iface
);
250 TRACE("(%p)->(%p)\n", This
, pid
);
255 *pid
= This
->info
.dwProcessId
;
259 static HRESULT WINAPI
WshExec_get_ExitCode(IWshExec
*iface
, DWORD
*code
)
261 WshExecImpl
*This
= impl_from_IWshExec(iface
);
263 FIXME("(%p)->(%p): stub\n", This
, code
);
268 static BOOL CALLBACK
enum_thread_wnd_proc(HWND hwnd
, LPARAM lParam
)
270 INT
*count
= (INT
*)lParam
;
273 PostMessageW(hwnd
, WM_CLOSE
, 0, 0);
274 /* try to send it to all windows, even if failed for some */
278 static HRESULT WINAPI
WshExec_Terminate(IWshExec
*iface
)
280 WshExecImpl
*This
= impl_from_IWshExec(iface
);
281 BOOL ret
, kill
= FALSE
;
284 TRACE("(%p)\n", This
);
286 ret
= EnumThreadWindows(This
->info
.dwThreadId
, enum_thread_wnd_proc
, (LPARAM
)&count
);
288 /* manual testing shows that it waits 2 seconds before forcing termination */
289 if (WaitForSingleObject(This
->info
.hProcess
, 2000) != WAIT_OBJECT_0
)
296 TerminateProcess(This
->info
.hProcess
, 0);
301 static const IWshExecVtbl WshExecVtbl
= {
302 WshExec_QueryInterface
,
305 WshExec_GetTypeInfoCount
,
307 WshExec_GetIDsOfNames
,
313 WshExec_get_ProcessID
,
314 WshExec_get_ExitCode
,
318 static HRESULT
WshExec_create(BSTR command
, IWshExec
**ret
)
320 STARTUPINFOW si
= {0};
325 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
327 return E_OUTOFMEMORY
;
329 This
->IWshExec_iface
.lpVtbl
= &WshExecVtbl
;
332 if (!CreateProcessW(NULL
, command
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &This
->info
)) {
333 HeapFree(GetProcessHeap(), 0, This
);
334 return HRESULT_FROM_WIN32(GetLastError());
337 init_classinfo(&CLSID_WshExec
, (IUnknown
*)&This
->IWshExec_iface
, &This
->classinfo
);
338 *ret
= &This
->IWshExec_iface
;
342 static HRESULT WINAPI
WshEnvironment_QueryInterface(IWshEnvironment
*iface
, REFIID riid
, void **obj
)
344 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
346 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), obj
);
348 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
349 IsEqualGUID(riid
, &IID_IDispatch
) ||
350 IsEqualGUID(riid
, &IID_IWshEnvironment
))
354 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
356 *obj
= &This
->classinfo
.IProvideClassInfo_iface
;
359 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
361 return E_NOINTERFACE
;
364 IUnknown_AddRef((IUnknown
*)*obj
);
368 static ULONG WINAPI
WshEnvironment_AddRef(IWshEnvironment
*iface
)
370 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
371 LONG ref
= InterlockedIncrement(&This
->ref
);
372 TRACE("(%p) ref = %d\n", This
, ref
);
376 static ULONG WINAPI
WshEnvironment_Release(IWshEnvironment
*iface
)
378 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
379 LONG ref
= InterlockedDecrement(&This
->ref
);
380 TRACE("(%p) ref = %d\n", This
, ref
);
383 HeapFree(GetProcessHeap(), 0, This
);
388 static HRESULT WINAPI
WshEnvironment_GetTypeInfoCount(IWshEnvironment
*iface
, UINT
*pctinfo
)
390 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
391 TRACE("(%p)->(%p)\n", This
, pctinfo
);
396 static HRESULT WINAPI
WshEnvironment_GetTypeInfo(IWshEnvironment
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
398 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
399 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
400 return get_typeinfo(IWshEnvironment_tid
, ppTInfo
);
403 static HRESULT WINAPI
WshEnvironment_GetIDsOfNames(IWshEnvironment
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
404 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
406 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
410 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
412 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
415 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
416 ITypeInfo_Release(typeinfo
);
422 static HRESULT WINAPI
WshEnvironment_Invoke(IWshEnvironment
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
423 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
425 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
429 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
430 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
432 hr
= get_typeinfo(IWshEnvironment_tid
, &typeinfo
);
435 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshEnvironment_iface
, dispIdMember
, wFlags
,
436 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
437 ITypeInfo_Release(typeinfo
);
443 static HRESULT WINAPI
WshEnvironment_get_Item(IWshEnvironment
*iface
, BSTR name
, BSTR
*value
)
445 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
448 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(name
), value
);
453 len
= GetEnvironmentVariableW(name
, NULL
, 0);
454 *value
= SysAllocStringLen(NULL
, len
);
456 return E_OUTOFMEMORY
;
459 GetEnvironmentVariableW(name
, *value
, len
+1);
464 static HRESULT WINAPI
WshEnvironment_put_Item(IWshEnvironment
*iface
, BSTR name
, BSTR value
)
466 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
467 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(name
), debugstr_w(value
));
471 static HRESULT WINAPI
WshEnvironment_Count(IWshEnvironment
*iface
, LONG
*count
)
473 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
474 FIXME("(%p)->(%p): stub\n", This
, count
);
478 static HRESULT WINAPI
WshEnvironment_get_length(IWshEnvironment
*iface
, LONG
*len
)
480 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
481 FIXME("(%p)->(%p): stub\n", This
, len
);
485 static HRESULT WINAPI
WshEnvironment__NewEnum(IWshEnvironment
*iface
, IUnknown
**penum
)
487 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
488 FIXME("(%p)->(%p): stub\n", This
, penum
);
492 static HRESULT WINAPI
WshEnvironment_Remove(IWshEnvironment
*iface
, BSTR name
)
494 WshEnvironment
*This
= impl_from_IWshEnvironment(iface
);
495 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(name
));
499 static const IWshEnvironmentVtbl WshEnvironmentVtbl
= {
500 WshEnvironment_QueryInterface
,
501 WshEnvironment_AddRef
,
502 WshEnvironment_Release
,
503 WshEnvironment_GetTypeInfoCount
,
504 WshEnvironment_GetTypeInfo
,
505 WshEnvironment_GetIDsOfNames
,
506 WshEnvironment_Invoke
,
507 WshEnvironment_get_Item
,
508 WshEnvironment_put_Item
,
509 WshEnvironment_Count
,
510 WshEnvironment_get_length
,
511 WshEnvironment__NewEnum
,
512 WshEnvironment_Remove
515 static HRESULT
WshEnvironment_Create(IWshEnvironment
**env
)
517 WshEnvironment
*This
;
519 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
520 if (!This
) return E_OUTOFMEMORY
;
522 This
->IWshEnvironment_iface
.lpVtbl
= &WshEnvironmentVtbl
;
525 init_classinfo(&IID_IWshEnvironment
, (IUnknown
*)&This
->IWshEnvironment_iface
, &This
->classinfo
);
526 *env
= &This
->IWshEnvironment_iface
;
531 static HRESULT WINAPI
WshCollection_QueryInterface(IWshCollection
*iface
, REFIID riid
, void **ppv
)
533 WshCollection
*This
= impl_from_IWshCollection(iface
);
535 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
537 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
538 IsEqualGUID(riid
, &IID_IDispatch
) ||
539 IsEqualGUID(riid
, &IID_IWshCollection
))
543 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
545 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
548 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
550 return E_NOINTERFACE
;
553 IUnknown_AddRef((IUnknown
*)*ppv
);
557 static ULONG WINAPI
WshCollection_AddRef(IWshCollection
*iface
)
559 WshCollection
*This
= impl_from_IWshCollection(iface
);
560 LONG ref
= InterlockedIncrement(&This
->ref
);
561 TRACE("(%p) ref = %d\n", This
, ref
);
565 static ULONG WINAPI
WshCollection_Release(IWshCollection
*iface
)
567 WshCollection
*This
= impl_from_IWshCollection(iface
);
568 LONG ref
= InterlockedDecrement(&This
->ref
);
569 TRACE("(%p) ref = %d\n", This
, ref
);
572 HeapFree(GetProcessHeap(), 0, This
);
577 static HRESULT WINAPI
WshCollection_GetTypeInfoCount(IWshCollection
*iface
, UINT
*pctinfo
)
579 WshCollection
*This
= impl_from_IWshCollection(iface
);
580 TRACE("(%p)->(%p)\n", This
, pctinfo
);
585 static HRESULT WINAPI
WshCollection_GetTypeInfo(IWshCollection
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
587 WshCollection
*This
= impl_from_IWshCollection(iface
);
588 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
589 return get_typeinfo(IWshCollection_tid
, ppTInfo
);
592 static HRESULT WINAPI
WshCollection_GetIDsOfNames(IWshCollection
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
593 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
595 WshCollection
*This
= impl_from_IWshCollection(iface
);
599 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
601 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
604 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
605 ITypeInfo_Release(typeinfo
);
611 static HRESULT WINAPI
WshCollection_Invoke(IWshCollection
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
612 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
614 WshCollection
*This
= impl_from_IWshCollection(iface
);
618 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
619 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
621 hr
= get_typeinfo(IWshCollection_tid
, &typeinfo
);
624 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshCollection_iface
, dispIdMember
, wFlags
,
625 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
626 ITypeInfo_Release(typeinfo
);
632 static HRESULT WINAPI
WshCollection_Item(IWshCollection
*iface
, VARIANT
*index
, VARIANT
*value
)
634 WshCollection
*This
= impl_from_IWshCollection(iface
);
635 static const WCHAR allusersdesktopW
[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
636 static const WCHAR allusersprogramsW
[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
637 static const WCHAR desktopW
[] = {'D','e','s','k','t','o','p',0};
638 PIDLIST_ABSOLUTE pidl
;
639 WCHAR pathW
[MAX_PATH
];
644 TRACE("(%p)->(%s %p)\n", This
, debugstr_variant(index
), value
);
646 if (V_VT(index
) != VT_BSTR
)
648 FIXME("only BSTR index supported, got %d\n", V_VT(index
));
652 folder
= V_BSTR(index
);
653 if (!strcmpiW(folder
, desktopW
))
654 kind
= CSIDL_DESKTOP
;
655 else if (!strcmpiW(folder
, allusersdesktopW
))
656 kind
= CSIDL_COMMON_DESKTOPDIRECTORY
;
657 else if (!strcmpiW(folder
, allusersprogramsW
))
658 kind
= CSIDL_COMMON_PROGRAMS
;
661 FIXME("folder kind %s not supported\n", debugstr_w(folder
));
665 hr
= SHGetSpecialFolderLocation(NULL
, kind
, &pidl
);
666 if (hr
!= S_OK
) return hr
;
668 if (SHGetPathFromIDListW(pidl
, pathW
))
670 V_VT(value
) = VT_BSTR
;
671 V_BSTR(value
) = SysAllocString(pathW
);
672 hr
= V_BSTR(value
) ? S_OK
: E_OUTOFMEMORY
;
682 static HRESULT WINAPI
WshCollection_Count(IWshCollection
*iface
, LONG
*count
)
684 WshCollection
*This
= impl_from_IWshCollection(iface
);
685 FIXME("(%p)->(%p): stub\n", This
, count
);
689 static HRESULT WINAPI
WshCollection_get_length(IWshCollection
*iface
, LONG
*count
)
691 WshCollection
*This
= impl_from_IWshCollection(iface
);
692 FIXME("(%p)->(%p): stub\n", This
, count
);
696 static HRESULT WINAPI
WshCollection__NewEnum(IWshCollection
*iface
, IUnknown
*Enum
)
698 WshCollection
*This
= impl_from_IWshCollection(iface
);
699 FIXME("(%p)->(%p): stub\n", This
, Enum
);
703 static const IWshCollectionVtbl WshCollectionVtbl
= {
704 WshCollection_QueryInterface
,
705 WshCollection_AddRef
,
706 WshCollection_Release
,
707 WshCollection_GetTypeInfoCount
,
708 WshCollection_GetTypeInfo
,
709 WshCollection_GetIDsOfNames
,
710 WshCollection_Invoke
,
713 WshCollection_get_length
,
714 WshCollection__NewEnum
717 static HRESULT
WshCollection_Create(IWshCollection
**collection
)
721 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
722 if (!This
) return E_OUTOFMEMORY
;
724 This
->IWshCollection_iface
.lpVtbl
= &WshCollectionVtbl
;
727 init_classinfo(&IID_IWshCollection
, (IUnknown
*)&This
->IWshCollection_iface
, &This
->classinfo
);
728 *collection
= &This
->IWshCollection_iface
;
734 static HRESULT WINAPI
WshShortcut_QueryInterface(IWshShortcut
*iface
, REFIID riid
, void **ppv
)
736 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
738 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
740 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
741 IsEqualGUID(riid
, &IID_IDispatch
) ||
742 IsEqualGUID(riid
, &IID_IWshShortcut
))
746 else if (IsEqualIID(riid
, &IID_IProvideClassInfo
))
748 *ppv
= &This
->classinfo
.IProvideClassInfo_iface
;
751 FIXME("Unknown iface %s\n", debugstr_guid(riid
));
753 return E_NOINTERFACE
;
756 IUnknown_AddRef((IUnknown
*)*ppv
);
760 static ULONG WINAPI
WshShortcut_AddRef(IWshShortcut
*iface
)
762 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
763 LONG ref
= InterlockedIncrement(&This
->ref
);
764 TRACE("(%p) ref = %d\n", This
, ref
);
768 static ULONG WINAPI
WshShortcut_Release(IWshShortcut
*iface
)
770 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
771 LONG ref
= InterlockedDecrement(&This
->ref
);
772 TRACE("(%p) ref = %d\n", This
, ref
);
776 SysFreeString(This
->path_link
);
777 IShellLinkW_Release(This
->link
);
778 HeapFree(GetProcessHeap(), 0, This
);
784 static HRESULT WINAPI
WshShortcut_GetTypeInfoCount(IWshShortcut
*iface
, UINT
*pctinfo
)
786 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
787 TRACE("(%p)->(%p)\n", This
, pctinfo
);
792 static HRESULT WINAPI
WshShortcut_GetTypeInfo(IWshShortcut
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
794 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
795 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
796 return get_typeinfo(IWshShortcut_tid
, ppTInfo
);
799 static HRESULT WINAPI
WshShortcut_GetIDsOfNames(IWshShortcut
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
800 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
802 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
806 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
, lcid
, rgDispId
);
808 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
811 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
812 ITypeInfo_Release(typeinfo
);
818 static HRESULT WINAPI
WshShortcut_Invoke(IWshShortcut
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
819 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
821 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
825 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
826 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
828 hr
= get_typeinfo(IWshShortcut_tid
, &typeinfo
);
831 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IWshShortcut_iface
, dispIdMember
, wFlags
,
832 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
833 ITypeInfo_Release(typeinfo
);
839 static HRESULT WINAPI
WshShortcut_get_FullName(IWshShortcut
*iface
, BSTR
*name
)
841 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
842 FIXME("(%p)->(%p): stub\n", This
, name
);
846 static HRESULT WINAPI
WshShortcut_get_Arguments(IWshShortcut
*iface
, BSTR
*Arguments
)
848 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
849 WCHAR buffW
[INFOTIPSIZE
];
852 TRACE("(%p)->(%p)\n", This
, Arguments
);
859 hr
= IShellLinkW_GetArguments(This
->link
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
863 *Arguments
= SysAllocString(buffW
);
864 return *Arguments
? S_OK
: E_OUTOFMEMORY
;
867 static HRESULT WINAPI
WshShortcut_put_Arguments(IWshShortcut
*iface
, BSTR Arguments
)
869 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
871 TRACE("(%p)->(%s)\n", This
, debugstr_w(Arguments
));
873 return IShellLinkW_SetArguments(This
->link
, Arguments
);
876 static HRESULT WINAPI
WshShortcut_get_Description(IWshShortcut
*iface
, BSTR
*Description
)
878 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
879 FIXME("(%p)->(%p): stub\n", This
, Description
);
883 static HRESULT WINAPI
WshShortcut_put_Description(IWshShortcut
*iface
, BSTR Description
)
885 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
886 TRACE("(%p)->(%s)\n", This
, debugstr_w(Description
));
887 return IShellLinkW_SetDescription(This
->link
, Description
);
890 static HRESULT WINAPI
WshShortcut_get_Hotkey(IWshShortcut
*iface
, BSTR
*Hotkey
)
892 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
893 FIXME("(%p)->(%p): stub\n", This
, Hotkey
);
897 static HRESULT WINAPI
WshShortcut_put_Hotkey(IWshShortcut
*iface
, BSTR Hotkey
)
899 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
900 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(Hotkey
));
904 static HRESULT WINAPI
WshShortcut_get_IconLocation(IWshShortcut
*iface
, BSTR
*IconPath
)
906 static const WCHAR fmtW
[] = {'%','s',',',' ','%','d',0};
907 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
908 WCHAR buffW
[MAX_PATH
], pathW
[MAX_PATH
];
912 TRACE("(%p)->(%p)\n", This
, IconPath
);
917 hr
= IShellLinkW_GetIconLocation(This
->link
, buffW
, sizeof(buffW
)/sizeof(WCHAR
), &icon
);
918 if (FAILED(hr
)) return hr
;
920 sprintfW(pathW
, fmtW
, buffW
, icon
);
921 *IconPath
= SysAllocString(pathW
);
922 if (!*IconPath
) return E_OUTOFMEMORY
;
927 static HRESULT WINAPI
WshShortcut_put_IconLocation(IWshShortcut
*iface
, BSTR IconPath
)
929 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
935 TRACE("(%p)->(%s)\n", This
, debugstr_w(IconPath
));
937 /* scan for icon id */
938 ptr
= strrchrW(IconPath
, ',');
941 WARN("icon index not found\n");
945 path
= SysAllocStringLen(IconPath
, ptr
-IconPath
);
947 /* skip spaces if any */
948 while (isspaceW(*++ptr
))
953 hr
= IShellLinkW_SetIconLocation(This
->link
, path
, icon
);
959 static HRESULT WINAPI
WshShortcut_put_RelativePath(IWshShortcut
*iface
, BSTR rhs
)
961 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
962 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(rhs
));
966 static HRESULT WINAPI
WshShortcut_get_TargetPath(IWshShortcut
*iface
, BSTR
*Path
)
968 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
969 FIXME("(%p)->(%p): stub\n", This
, Path
);
973 static HRESULT WINAPI
WshShortcut_put_TargetPath(IWshShortcut
*iface
, BSTR Path
)
975 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
976 TRACE("(%p)->(%s)\n", This
, debugstr_w(Path
));
977 return IShellLinkW_SetPath(This
->link
, Path
);
980 static HRESULT WINAPI
WshShortcut_get_WindowStyle(IWshShortcut
*iface
, int *ShowCmd
)
982 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
983 TRACE("(%p)->(%p)\n", This
, ShowCmd
);
984 return IShellLinkW_GetShowCmd(This
->link
, ShowCmd
);
987 static HRESULT WINAPI
WshShortcut_put_WindowStyle(IWshShortcut
*iface
, int ShowCmd
)
989 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
990 TRACE("(%p)->(%d)\n", This
, ShowCmd
);
991 return IShellLinkW_SetShowCmd(This
->link
, ShowCmd
);
994 static HRESULT WINAPI
WshShortcut_get_WorkingDirectory(IWshShortcut
*iface
, BSTR
*WorkingDirectory
)
996 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
997 WCHAR buffW
[MAX_PATH
];
1000 TRACE("(%p)->(%p)\n", This
, WorkingDirectory
);
1002 if (!WorkingDirectory
)
1005 *WorkingDirectory
= NULL
;
1006 hr
= IShellLinkW_GetWorkingDirectory(This
->link
, buffW
, sizeof(buffW
)/sizeof(WCHAR
));
1007 if (FAILED(hr
)) return hr
;
1009 *WorkingDirectory
= SysAllocString(buffW
);
1010 return *WorkingDirectory
? S_OK
: E_OUTOFMEMORY
;
1013 static HRESULT WINAPI
WshShortcut_put_WorkingDirectory(IWshShortcut
*iface
, BSTR WorkingDirectory
)
1015 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1016 TRACE("(%p)->(%s)\n", This
, debugstr_w(WorkingDirectory
));
1017 return IShellLinkW_SetWorkingDirectory(This
->link
, WorkingDirectory
);
1020 static HRESULT WINAPI
WshShortcut_Load(IWshShortcut
*iface
, BSTR PathLink
)
1022 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1023 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(PathLink
));
1027 static HRESULT WINAPI
WshShortcut_Save(IWshShortcut
*iface
)
1029 WshShortcut
*This
= impl_from_IWshShortcut(iface
);
1033 TRACE("(%p)\n", This
);
1035 IShellLinkW_QueryInterface(This
->link
, &IID_IPersistFile
, (void**)&file
);
1036 hr
= IPersistFile_Save(file
, This
->path_link
, TRUE
);
1037 IPersistFile_Release(file
);
1042 static const IWshShortcutVtbl WshShortcutVtbl
= {
1043 WshShortcut_QueryInterface
,
1045 WshShortcut_Release
,
1046 WshShortcut_GetTypeInfoCount
,
1047 WshShortcut_GetTypeInfo
,
1048 WshShortcut_GetIDsOfNames
,
1050 WshShortcut_get_FullName
,
1051 WshShortcut_get_Arguments
,
1052 WshShortcut_put_Arguments
,
1053 WshShortcut_get_Description
,
1054 WshShortcut_put_Description
,
1055 WshShortcut_get_Hotkey
,
1056 WshShortcut_put_Hotkey
,
1057 WshShortcut_get_IconLocation
,
1058 WshShortcut_put_IconLocation
,
1059 WshShortcut_put_RelativePath
,
1060 WshShortcut_get_TargetPath
,
1061 WshShortcut_put_TargetPath
,
1062 WshShortcut_get_WindowStyle
,
1063 WshShortcut_put_WindowStyle
,
1064 WshShortcut_get_WorkingDirectory
,
1065 WshShortcut_put_WorkingDirectory
,
1070 static HRESULT
WshShortcut_Create(const WCHAR
*path
, IDispatch
**shortcut
)
1077 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1078 if (!This
) return E_OUTOFMEMORY
;
1080 This
->IWshShortcut_iface
.lpVtbl
= &WshShortcutVtbl
;
1083 hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
,
1084 &IID_IShellLinkW
, (void**)&This
->link
);
1087 HeapFree(GetProcessHeap(), 0, This
);
1091 This
->path_link
= SysAllocString(path
);
1092 if (!This
->path_link
)
1094 IShellLinkW_Release(This
->link
);
1095 HeapFree(GetProcessHeap(), 0, This
);
1096 return E_OUTOFMEMORY
;
1099 init_classinfo(&IID_IWshShortcut
, (IUnknown
*)&This
->IWshShortcut_iface
, &This
->classinfo
);
1100 *shortcut
= (IDispatch
*)&This
->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
, 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 HRESULT WINAPI
WshShell3_Run(IWshShell3
*iface
, BSTR cmd
, VARIANT
*style
, VARIANT
*wait
, DWORD
*exit_code
)
1219 SHELLEXECUTEINFOW info
;
1224 TRACE("(%s %s %s %p)\n", debugstr_w(cmd
), debugstr_variant(style
), debugstr_variant(wait
), exit_code
);
1226 if (!style
|| !wait
|| !exit_code
)
1230 hr
= VariantChangeType(&s
, style
, 0, VT_I4
);
1233 ERR("failed to convert style argument, 0x%08x\n", hr
);
1237 if (is_optional_argument(wait
))
1243 hr
= VariantChangeType(&w
, wait
, 0, VT_I4
);
1247 waitforprocess
= V_I4(&w
);
1250 memset(&info
, 0, sizeof(info
));
1251 info
.cbSize
= sizeof(info
);
1252 info
.fMask
= waitforprocess
? SEE_MASK_NOASYNC
| SEE_MASK_NOCLOSEPROCESS
: SEE_MASK_DEFAULT
;
1254 info
.nShow
= V_I4(&s
);
1256 if (!ShellExecuteExW(&info
))
1258 TRACE("ShellExecute failed, %d\n", GetLastError());
1259 return HRESULT_FROM_WIN32(GetLastError());
1265 GetExitCodeProcess(info
.hProcess
, exit_code
);
1266 CloseHandle(info
.hProcess
);
1275 static HRESULT WINAPI
WshShell3_Popup(IWshShell3
*iface
, BSTR Text
, VARIANT
* SecondsToWait
, VARIANT
*Title
, VARIANT
*Type
, int *button
)
1277 FIXME("(%s %s %s %s %p): stub\n", debugstr_w(Text
), debugstr_variant(SecondsToWait
),
1278 debugstr_variant(Title
), debugstr_variant(Type
), button
);
1282 static HRESULT WINAPI
WshShell3_CreateShortcut(IWshShell3
*iface
, BSTR PathLink
, IDispatch
** Shortcut
)
1284 TRACE("(%s %p)\n", debugstr_w(PathLink
), Shortcut
);
1285 return WshShortcut_Create(PathLink
, Shortcut
);
1288 static HRESULT WINAPI
WshShell3_ExpandEnvironmentStrings(IWshShell3
*iface
, BSTR Src
, BSTR
* Dst
)
1292 TRACE("(%s %p)\n", debugstr_w(Src
), Dst
);
1294 if (!Src
|| !Dst
) return E_POINTER
;
1296 ret
= ExpandEnvironmentStringsW(Src
, NULL
, 0);
1297 *Dst
= SysAllocStringLen(NULL
, ret
);
1298 if (!*Dst
) return E_OUTOFMEMORY
;
1300 if (ExpandEnvironmentStringsW(Src
, *Dst
, ret
))
1304 SysFreeString(*Dst
);
1306 return HRESULT_FROM_WIN32(GetLastError());
1310 static HKEY
get_root_key(const WCHAR
*path
)
1312 static const struct {
1313 const WCHAR full
[20];
1314 const WCHAR abbrev
[5];
1317 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER
},
1318 { {'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
},
1319 { {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT
},
1320 { {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS
},
1321 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG
}
1325 for (i
= 0; i
< sizeof(rootkeys
)/sizeof(rootkeys
[0]); i
++) {
1326 if (!strncmpW(path
, rootkeys
[i
].full
, strlenW(rootkeys
[i
].full
)))
1327 return rootkeys
[i
].hkey
;
1328 if (rootkeys
[i
].abbrev
[0] && !strncmpW(path
, rootkeys
[i
].abbrev
, strlenW(rootkeys
[i
].abbrev
)))
1329 return rootkeys
[i
].hkey
;
1335 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
1336 static HRESULT
split_reg_path(const WCHAR
*path
, WCHAR
**subkey
, WCHAR
**value
)
1340 /* at least one separator should be present */
1341 *subkey
= strchrW(path
, '\\');
1343 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1345 /* default value or not */
1346 if ((*subkey
)[strlenW(*subkey
)-1] == '\\') {
1351 *value
= strrchrW(*subkey
, '\\');
1352 if (*value
- *subkey
> 1) {
1353 unsigned int len
= *value
- *subkey
- 1;
1356 ret
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
1358 return E_OUTOFMEMORY
;
1360 memcpy(ret
, *subkey
+ 1, len
*sizeof(WCHAR
));
1370 static HRESULT WINAPI
WshShell3_RegRead(IWshShell3
*iface
, BSTR name
, VARIANT
*value
)
1372 DWORD type
, datalen
, ret
;
1373 WCHAR
*subkey
, *val
;
1377 TRACE("(%s %p)\n", debugstr_w(name
), value
);
1379 if (!name
|| !value
)
1382 root
= get_root_key(name
);
1384 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1386 hr
= split_reg_path(name
, &subkey
, &val
);
1392 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, NULL
, &datalen
);
1393 if (ret
== ERROR_SUCCESS
) {
1396 data
= HeapAlloc(GetProcessHeap(), 0, datalen
);
1402 ret
= RegGetValueW(root
, subkey
, val
, RRF_RT_ANY
, &type
, data
, &datalen
);
1404 HeapFree(GetProcessHeap(), 0, data
);
1405 hr
= HRESULT_FROM_WIN32(ret
);
1412 V_VT(value
) = VT_BSTR
;
1413 V_BSTR(value
) = SysAllocString((WCHAR
*)data
);
1418 V_VT(value
) = VT_I4
;
1419 V_I4(value
) = *(DWORD
*)data
;
1423 BYTE
*ptr
= (BYTE
*)data
;
1424 SAFEARRAYBOUND bound
;
1430 bound
.cElements
= datalen
;
1431 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1435 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1437 SafeArrayDestroy(sa
);
1441 for (i
= 0; i
< datalen
; i
++) {
1442 V_VT(&v
[i
]) = VT_UI1
;
1443 V_UI1(&v
[i
]) = ptr
[i
];
1445 SafeArrayUnaccessData(sa
);
1447 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1448 V_ARRAY(value
) = sa
;
1453 WCHAR
*ptr
= (WCHAR
*)data
;
1454 SAFEARRAYBOUND bound
;
1458 /* get element count first */
1460 bound
.cElements
= 0;
1463 ptr
+= strlenW(ptr
)+1;
1466 sa
= SafeArrayCreate(VT_VARIANT
, 1, &bound
);
1470 hr
= SafeArrayAccessData(sa
, (void**)&v
);
1472 SafeArrayDestroy(sa
);
1479 V_BSTR(v
) = SysAllocString(ptr
);
1480 ptr
+= strlenW(ptr
)+1;
1484 SafeArrayUnaccessData(sa
);
1485 V_VT(value
) = VT_ARRAY
|VT_VARIANT
;
1486 V_ARRAY(value
) = sa
;
1490 FIXME("value type %d not supported\n", type
);
1494 HeapFree(GetProcessHeap(), 0, data
);
1499 hr
= HRESULT_FROM_WIN32(ret
);
1503 HeapFree(GetProcessHeap(), 0, subkey
);
1507 static HRESULT WINAPI
WshShell3_RegWrite(IWshShell3
*iface
, BSTR name
, VARIANT
*value
, VARIANT
*type
)
1509 static const WCHAR regexpandszW
[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
1510 static const WCHAR regszW
[] = {'R','E','G','_','S','Z',0};
1511 static const WCHAR regdwordW
[] = {'R','E','G','_','D','W','O','R','D',0};
1512 static const WCHAR regbinaryW
[] = {'R','E','G','_','B','I','N','A','R','Y',0};
1514 DWORD regtype
, data_len
;
1515 WCHAR
*subkey
, *val
;
1522 TRACE("(%s %s %s)\n", debugstr_w(name
), debugstr_variant(value
), debugstr_variant(type
));
1524 if (!name
|| !value
|| !type
)
1527 root
= get_root_key(name
);
1529 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND
);
1532 if (is_optional_argument(type
))
1535 if (V_VT(type
) != VT_BSTR
)
1536 return E_INVALIDARG
;
1538 if (!strcmpW(V_BSTR(type
), regszW
))
1540 else if (!strcmpW(V_BSTR(type
), regdwordW
))
1541 regtype
= REG_DWORD
;
1542 else if (!strcmpW(V_BSTR(type
), regexpandszW
))
1543 regtype
= REG_EXPAND_SZ
;
1544 else if (!strcmpW(V_BSTR(type
), regbinaryW
))
1545 regtype
= REG_BINARY
;
1547 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type
)));
1552 /* it's always a string or a DWORD */
1558 hr
= VariantChangeType(&v
, value
, 0, VT_BSTR
);
1560 data
= (BYTE
*)V_BSTR(&v
);
1561 data_len
= SysStringByteLen(V_BSTR(&v
)) + sizeof(WCHAR
);
1566 hr
= VariantChangeType(&v
, value
, 0, VT_I4
);
1567 data
= (BYTE
*)&V_I4(&v
);
1568 data_len
= sizeof(DWORD
);
1571 FIXME("unexpected regtype %d\n", regtype
);
1576 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype
, hr
);
1580 hr
= split_reg_path(name
, &subkey
, &val
);
1584 ret
= RegSetKeyValueW(root
, subkey
, val
, regtype
, data
, data_len
);
1586 hr
= HRESULT_FROM_WIN32(ret
);
1591 HeapFree(GetProcessHeap(), 0, subkey
);
1595 static HRESULT WINAPI
WshShell3_RegDelete(IWshShell3
*iface
, BSTR Name
)
1597 FIXME("(%s): stub\n", debugstr_w(Name
));
1601 static HRESULT WINAPI
WshShell3_LogEvent(IWshShell3
*iface
, VARIANT
*Type
, BSTR Message
, BSTR Target
, VARIANT_BOOL
*out_Success
)
1603 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type
), debugstr_w(Message
), debugstr_w(Target
), out_Success
);
1607 static HRESULT WINAPI
WshShell3_AppActivate(IWshShell3
*iface
, VARIANT
*App
, VARIANT
*Wait
, VARIANT_BOOL
*out_Success
)
1609 FIXME("(%s %s %p): stub\n", debugstr_variant(App
), debugstr_variant(Wait
), out_Success
);
1613 static HRESULT WINAPI
WshShell3_SendKeys(IWshShell3
*iface
, BSTR Keys
, VARIANT
*Wait
)
1615 FIXME("(%s %p): stub\n", debugstr_w(Keys
), Wait
);
1619 static HRESULT WINAPI
WshShell3_Exec(IWshShell3
*iface
, BSTR command
, IWshExec
**ret
)
1621 TRACE("(%s %p)\n", debugstr_w(command
), ret
);
1627 return DISP_E_EXCEPTION
;
1629 return WshExec_create(command
, ret
);
1632 static HRESULT WINAPI
WshShell3_get_CurrentDirectory(IWshShell3
*iface
, BSTR
*dir
)
1636 TRACE("(%p)\n", dir
);
1638 ret
= GetCurrentDirectoryW(0, NULL
);
1640 return HRESULT_FROM_WIN32(GetLastError());
1642 *dir
= SysAllocStringLen(NULL
, ret
-1);
1644 return E_OUTOFMEMORY
;
1646 ret
= GetCurrentDirectoryW(ret
, *dir
);
1648 SysFreeString(*dir
);
1650 return HRESULT_FROM_WIN32(GetLastError());
1656 static HRESULT WINAPI
WshShell3_put_CurrentDirectory(IWshShell3
*iface
, BSTR dir
)
1658 TRACE("(%s)\n", debugstr_w(dir
));
1661 return E_INVALIDARG
;
1663 if (!SetCurrentDirectoryW(dir
))
1664 return HRESULT_FROM_WIN32(GetLastError());
1669 static const IWshShell3Vtbl WshShell3Vtbl
= {
1670 WshShell3_QueryInterface
,
1673 WshShell3_GetTypeInfoCount
,
1674 WshShell3_GetTypeInfo
,
1675 WshShell3_GetIDsOfNames
,
1677 WshShell3_get_SpecialFolders
,
1678 WshShell3_get_Environment
,
1681 WshShell3_CreateShortcut
,
1682 WshShell3_ExpandEnvironmentStrings
,
1685 WshShell3_RegDelete
,
1687 WshShell3_AppActivate
,
1690 WshShell3_get_CurrentDirectory
,
1691 WshShell3_put_CurrentDirectory
1694 HRESULT WINAPI
WshShellFactory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
1696 TRACE("(%p %s %p)\n", outer
, debugstr_guid(riid
), ppv
);
1698 WshShell3
.IWshShell3_iface
.lpVtbl
= &WshShell3Vtbl
;
1699 init_classinfo(&IID_IWshShell3
, (IUnknown
*)&WshShell3
.IWshShell3_iface
, &WshShell3
.classinfo
);
1700 return IWshShell3_QueryInterface(&WshShell3
.IWshShell3_iface
, riid
, ppv
);