wshom.ocx: Implement ProcessID() property.
[wine.git] / dlls / wshom.ocx / shell.c
blobdcf14623e06ca4bc586c0ae11c40d1173baf8fa6
1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wshom_private.h"
20 #include "wshom.h"
22 #include "shellapi.h"
23 #include "shlobj.h"
24 #include "dispex.h"
26 #include "wine/debug.h"
27 #include "wine/unicode.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(wshom);
31 static IWshShell3 WshShell3;
33 typedef struct
35 IWshCollection IWshCollection_iface;
36 LONG ref;
37 } WshCollection;
39 typedef struct
41 IWshShortcut IWshShortcut_iface;
42 LONG ref;
44 IShellLinkW *link;
45 BSTR path_link;
46 } WshShortcut;
48 typedef struct
50 IWshEnvironment IWshEnvironment_iface;
51 LONG ref;
52 } WshEnvironment;
54 typedef struct
56 IWshExec IWshExec_iface;
57 LONG ref;
58 PROCESS_INFORMATION info;
59 } WshExec;
61 static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
63 return CONTAINING_RECORD(iface, WshCollection, IWshCollection_iface);
66 static inline WshShortcut *impl_from_IWshShortcut( IWshShortcut *iface )
68 return CONTAINING_RECORD(iface, WshShortcut, IWshShortcut_iface);
71 static inline WshEnvironment *impl_from_IWshEnvironment( IWshEnvironment *iface )
73 return CONTAINING_RECORD(iface, WshEnvironment, IWshEnvironment_iface);
76 static inline WshExec *impl_from_IWshExec( IWshExec *iface )
78 return CONTAINING_RECORD(iface, WshExec, IWshExec_iface);
81 static HRESULT WINAPI WshExec_QueryInterface(IWshExec *iface, REFIID riid, void **obj)
83 WshExec *This = impl_from_IWshExec(iface);
85 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
87 if (IsEqualGUID(riid, &IID_IDispatch) ||
88 IsEqualGUID(riid, &IID_IWshExec) ||
89 IsEqualGUID(riid, &IID_IUnknown))
91 *obj = iface;
92 }else {
93 FIXME("Unknown iface %s\n", debugstr_guid(riid));
94 *obj = NULL;
95 return E_NOINTERFACE;
98 IWshExec_AddRef(iface);
99 return S_OK;
102 static ULONG WINAPI WshExec_AddRef(IWshExec *iface)
104 WshExec *This = impl_from_IWshExec(iface);
105 LONG ref = InterlockedIncrement(&This->ref);
106 TRACE("(%p) ref = %d\n", This, ref);
107 return ref;
110 static ULONG WINAPI WshExec_Release(IWshExec *iface)
112 WshExec *This = impl_from_IWshExec(iface);
113 LONG ref = InterlockedDecrement(&This->ref);
114 TRACE("(%p) ref = %d\n", This, ref);
116 if (!ref) {
117 CloseHandle(This->info.hThread);
118 CloseHandle(This->info.hProcess);
119 HeapFree(GetProcessHeap(), 0, This);
122 return ref;
125 static HRESULT WINAPI WshExec_GetTypeInfoCount(IWshExec *iface, UINT *pctinfo)
127 WshExec *This = impl_from_IWshExec(iface);
128 TRACE("(%p)->(%p)\n", This, pctinfo);
129 *pctinfo = 1;
130 return S_OK;
133 static HRESULT WINAPI WshExec_GetTypeInfo(IWshExec *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
135 WshExec *This = impl_from_IWshExec(iface);
136 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
137 return get_typeinfo(IWshExec_tid, ppTInfo);
140 static HRESULT WINAPI WshExec_GetIDsOfNames(IWshExec *iface, REFIID riid, LPOLESTR *rgszNames,
141 UINT cNames, LCID lcid, DISPID *rgDispId)
143 WshExec *This = impl_from_IWshExec(iface);
144 ITypeInfo *typeinfo;
145 HRESULT hr;
147 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
149 hr = get_typeinfo(IWshExec_tid, &typeinfo);
150 if(SUCCEEDED(hr))
152 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
153 ITypeInfo_Release(typeinfo);
156 return hr;
159 static HRESULT WINAPI WshExec_Invoke(IWshExec *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
160 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
162 WshExec *This = impl_from_IWshExec(iface);
163 ITypeInfo *typeinfo;
164 HRESULT hr;
166 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
167 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
169 hr = get_typeinfo(IWshExec_tid, &typeinfo);
170 if(SUCCEEDED(hr))
172 hr = ITypeInfo_Invoke(typeinfo, &This->IWshExec_iface, dispIdMember, wFlags,
173 pDispParams, pVarResult, pExcepInfo, puArgErr);
174 ITypeInfo_Release(typeinfo);
177 return hr;
180 static HRESULT WINAPI WshExec_get_Status(IWshExec *iface, WshExecStatus *status)
182 WshExec *This = impl_from_IWshExec(iface);
183 DWORD code;
185 TRACE("(%p)->(%p)\n", This, status);
187 if (!status)
188 return E_INVALIDARG;
190 if (!GetExitCodeProcess(This->info.hProcess, &code))
191 return HRESULT_FROM_WIN32(GetLastError());
193 switch (code)
195 case 0:
196 *status = WshFinished;
197 break;
198 case STILL_ACTIVE:
199 *status = WshRunning;
200 break;
201 default:
202 *status = WshFailed;
205 return S_OK;
208 static HRESULT WINAPI WshExec_get_StdIn(IWshExec *iface, ITextStream **stream)
210 WshExec *This = impl_from_IWshExec(iface);
212 FIXME("(%p)->(%p): stub\n", This, stream);
214 return E_NOTIMPL;
217 static HRESULT WINAPI WshExec_get_StdOut(IWshExec *iface, ITextStream **stream)
219 WshExec *This = impl_from_IWshExec(iface);
221 FIXME("(%p)->(%p): stub\n", This, stream);
223 return E_NOTIMPL;
226 static HRESULT WINAPI WshExec_get_StdErr(IWshExec *iface, ITextStream **stream)
228 WshExec *This = impl_from_IWshExec(iface);
230 FIXME("(%p)->(%p): stub\n", This, stream);
232 return E_NOTIMPL;
235 static HRESULT WINAPI WshExec_get_ProcessID(IWshExec *iface, DWORD *pid)
237 WshExec *This = impl_from_IWshExec(iface);
239 TRACE("(%p)->(%p)\n", This, pid);
241 if (!pid)
242 return E_INVALIDARG;
244 *pid = This->info.dwProcessId;
245 return S_OK;
248 static HRESULT WINAPI WshExec_get_ExitCode(IWshExec *iface, DWORD *code)
250 WshExec *This = impl_from_IWshExec(iface);
252 FIXME("(%p)->(%p): stub\n", This, code);
254 return E_NOTIMPL;
257 static HRESULT WINAPI WshExec_Terminate(IWshExec *iface)
259 WshExec *This = impl_from_IWshExec(iface);
261 FIXME("(%p): stub\n", This);
263 return E_NOTIMPL;
266 static const IWshExecVtbl WshExecVtbl = {
267 WshExec_QueryInterface,
268 WshExec_AddRef,
269 WshExec_Release,
270 WshExec_GetTypeInfoCount,
271 WshExec_GetTypeInfo,
272 WshExec_GetIDsOfNames,
273 WshExec_Invoke,
274 WshExec_get_Status,
275 WshExec_get_StdIn,
276 WshExec_get_StdOut,
277 WshExec_get_StdErr,
278 WshExec_get_ProcessID,
279 WshExec_get_ExitCode,
280 WshExec_Terminate
283 static HRESULT WshExec_create(BSTR command, IWshExec **ret)
285 STARTUPINFOW si = {0};
286 WshExec *This;
288 *ret = NULL;
290 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
291 if (!This)
292 return E_OUTOFMEMORY;
294 This->IWshExec_iface.lpVtbl = &WshExecVtbl;
295 This->ref = 1;
297 if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &This->info)) {
298 HeapFree(GetProcessHeap(), 0, This);
299 return HRESULT_FROM_WIN32(GetLastError());
302 *ret = &This->IWshExec_iface;
303 return S_OK;
306 static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
308 WshEnvironment *This = impl_from_IWshEnvironment(iface);
310 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
312 if (IsEqualGUID(riid, &IID_IUnknown) ||
313 IsEqualGUID(riid, &IID_IDispatch) ||
314 IsEqualGUID(riid, &IID_IWshEnvironment))
316 *obj = iface;
317 }else {
318 FIXME("Unknown iface %s\n", debugstr_guid(riid));
319 *obj = NULL;
320 return E_NOINTERFACE;
323 IUnknown_AddRef((IUnknown*)*obj);
324 return S_OK;
327 static ULONG WINAPI WshEnvironment_AddRef(IWshEnvironment *iface)
329 WshEnvironment *This = impl_from_IWshEnvironment(iface);
330 LONG ref = InterlockedIncrement(&This->ref);
331 TRACE("(%p) ref = %d\n", This, ref);
332 return ref;
335 static ULONG WINAPI WshEnvironment_Release(IWshEnvironment *iface)
337 WshEnvironment *This = impl_from_IWshEnvironment(iface);
338 LONG ref = InterlockedDecrement(&This->ref);
339 TRACE("(%p) ref = %d\n", This, ref);
341 if (!ref)
342 HeapFree(GetProcessHeap(), 0, This);
344 return ref;
347 static HRESULT WINAPI WshEnvironment_GetTypeInfoCount(IWshEnvironment *iface, UINT *pctinfo)
349 WshEnvironment *This = impl_from_IWshEnvironment(iface);
350 TRACE("(%p)->(%p)\n", This, pctinfo);
351 *pctinfo = 1;
352 return S_OK;
355 static HRESULT WINAPI WshEnvironment_GetTypeInfo(IWshEnvironment *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
357 WshEnvironment *This = impl_from_IWshEnvironment(iface);
358 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
359 return get_typeinfo(IWshEnvironment_tid, ppTInfo);
362 static HRESULT WINAPI WshEnvironment_GetIDsOfNames(IWshEnvironment *iface, REFIID riid, LPOLESTR *rgszNames,
363 UINT cNames, LCID lcid, DISPID *rgDispId)
365 WshEnvironment *This = impl_from_IWshEnvironment(iface);
366 ITypeInfo *typeinfo;
367 HRESULT hr;
369 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
371 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
372 if(SUCCEEDED(hr))
374 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
375 ITypeInfo_Release(typeinfo);
378 return hr;
381 static HRESULT WINAPI WshEnvironment_Invoke(IWshEnvironment *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
382 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
384 WshEnvironment *This = impl_from_IWshEnvironment(iface);
385 ITypeInfo *typeinfo;
386 HRESULT hr;
388 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
389 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
391 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
392 if(SUCCEEDED(hr))
394 hr = ITypeInfo_Invoke(typeinfo, &This->IWshEnvironment_iface, dispIdMember, wFlags,
395 pDispParams, pVarResult, pExcepInfo, puArgErr);
396 ITypeInfo_Release(typeinfo);
399 return hr;
402 static HRESULT WINAPI WshEnvironment_get_Item(IWshEnvironment *iface, BSTR name, BSTR *value)
404 WshEnvironment *This = impl_from_IWshEnvironment(iface);
405 DWORD len;
407 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
409 if (!value)
410 return E_POINTER;
412 len = GetEnvironmentVariableW(name, NULL, 0);
413 *value = SysAllocStringLen(NULL, len);
414 if (!*value)
415 return E_OUTOFMEMORY;
417 if (len)
418 GetEnvironmentVariableW(name, *value, len+1);
420 return S_OK;
423 static HRESULT WINAPI WshEnvironment_put_Item(IWshEnvironment *iface, BSTR name, BSTR value)
425 WshEnvironment *This = impl_from_IWshEnvironment(iface);
426 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_w(value));
427 return E_NOTIMPL;
430 static HRESULT WINAPI WshEnvironment_Count(IWshEnvironment *iface, LONG *count)
432 WshEnvironment *This = impl_from_IWshEnvironment(iface);
433 FIXME("(%p)->(%p): stub\n", This, count);
434 return E_NOTIMPL;
437 static HRESULT WINAPI WshEnvironment_get_length(IWshEnvironment *iface, LONG *len)
439 WshEnvironment *This = impl_from_IWshEnvironment(iface);
440 FIXME("(%p)->(%p): stub\n", This, len);
441 return E_NOTIMPL;
444 static HRESULT WINAPI WshEnvironment__NewEnum(IWshEnvironment *iface, IUnknown **penum)
446 WshEnvironment *This = impl_from_IWshEnvironment(iface);
447 FIXME("(%p)->(%p): stub\n", This, penum);
448 return E_NOTIMPL;
451 static HRESULT WINAPI WshEnvironment_Remove(IWshEnvironment *iface, BSTR name)
453 WshEnvironment *This = impl_from_IWshEnvironment(iface);
454 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
455 return E_NOTIMPL;
458 static const IWshEnvironmentVtbl WshEnvironmentVtbl = {
459 WshEnvironment_QueryInterface,
460 WshEnvironment_AddRef,
461 WshEnvironment_Release,
462 WshEnvironment_GetTypeInfoCount,
463 WshEnvironment_GetTypeInfo,
464 WshEnvironment_GetIDsOfNames,
465 WshEnvironment_Invoke,
466 WshEnvironment_get_Item,
467 WshEnvironment_put_Item,
468 WshEnvironment_Count,
469 WshEnvironment_get_length,
470 WshEnvironment__NewEnum,
471 WshEnvironment_Remove
474 static HRESULT WshEnvironment_Create(IWshEnvironment **env)
476 WshEnvironment *This;
478 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
479 if (!This) return E_OUTOFMEMORY;
481 This->IWshEnvironment_iface.lpVtbl = &WshEnvironmentVtbl;
482 This->ref = 1;
484 *env = &This->IWshEnvironment_iface;
486 return S_OK;
489 static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID riid, void **ppv)
491 WshCollection *This = impl_from_IWshCollection(iface);
493 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
495 if (IsEqualGUID(riid, &IID_IUnknown) ||
496 IsEqualGUID(riid, &IID_IDispatch) ||
497 IsEqualGUID(riid, &IID_IWshCollection))
499 *ppv = iface;
500 }else {
501 FIXME("Unknown iface %s\n", debugstr_guid(riid));
502 *ppv = NULL;
503 return E_NOINTERFACE;
506 IUnknown_AddRef((IUnknown*)*ppv);
507 return S_OK;
510 static ULONG WINAPI WshCollection_AddRef(IWshCollection *iface)
512 WshCollection *This = impl_from_IWshCollection(iface);
513 LONG ref = InterlockedIncrement(&This->ref);
514 TRACE("(%p) ref = %d\n", This, ref);
515 return ref;
518 static ULONG WINAPI WshCollection_Release(IWshCollection *iface)
520 WshCollection *This = impl_from_IWshCollection(iface);
521 LONG ref = InterlockedDecrement(&This->ref);
522 TRACE("(%p) ref = %d\n", This, ref);
524 if (!ref)
525 HeapFree(GetProcessHeap(), 0, This);
527 return ref;
530 static HRESULT WINAPI WshCollection_GetTypeInfoCount(IWshCollection *iface, UINT *pctinfo)
532 WshCollection *This = impl_from_IWshCollection(iface);
533 TRACE("(%p)->(%p)\n", This, pctinfo);
534 *pctinfo = 1;
535 return S_OK;
538 static HRESULT WINAPI WshCollection_GetTypeInfo(IWshCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
540 WshCollection *This = impl_from_IWshCollection(iface);
541 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
542 return get_typeinfo(IWshCollection_tid, ppTInfo);
545 static HRESULT WINAPI WshCollection_GetIDsOfNames(IWshCollection *iface, REFIID riid, LPOLESTR *rgszNames,
546 UINT cNames, LCID lcid, DISPID *rgDispId)
548 WshCollection *This = impl_from_IWshCollection(iface);
549 ITypeInfo *typeinfo;
550 HRESULT hr;
552 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
554 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
555 if(SUCCEEDED(hr))
557 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
558 ITypeInfo_Release(typeinfo);
561 return hr;
564 static HRESULT WINAPI WshCollection_Invoke(IWshCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
565 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
567 WshCollection *This = impl_from_IWshCollection(iface);
568 ITypeInfo *typeinfo;
569 HRESULT hr;
571 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
572 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
574 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
575 if(SUCCEEDED(hr))
577 hr = ITypeInfo_Invoke(typeinfo, &This->IWshCollection_iface, dispIdMember, wFlags,
578 pDispParams, pVarResult, pExcepInfo, puArgErr);
579 ITypeInfo_Release(typeinfo);
582 return hr;
585 static HRESULT WINAPI WshCollection_Item(IWshCollection *iface, VARIANT *index, VARIANT *value)
587 WshCollection *This = impl_from_IWshCollection(iface);
588 static const WCHAR allusersdesktopW[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
589 static const WCHAR allusersprogramsW[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
590 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0};
591 PIDLIST_ABSOLUTE pidl;
592 WCHAR pathW[MAX_PATH];
593 int kind = 0;
594 BSTR folder;
595 HRESULT hr;
597 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(index), value);
599 if (V_VT(index) != VT_BSTR)
601 FIXME("only BSTR index supported, got %d\n", V_VT(index));
602 return E_NOTIMPL;
605 folder = V_BSTR(index);
606 if (!strcmpiW(folder, desktopW))
607 kind = CSIDL_DESKTOP;
608 else if (!strcmpiW(folder, allusersdesktopW))
609 kind = CSIDL_COMMON_DESKTOPDIRECTORY;
610 else if (!strcmpiW(folder, allusersprogramsW))
611 kind = CSIDL_COMMON_PROGRAMS;
612 else
614 FIXME("folder kind %s not supported\n", debugstr_w(folder));
615 return E_NOTIMPL;
618 hr = SHGetSpecialFolderLocation(NULL, kind, &pidl);
619 if (hr != S_OK) return hr;
621 if (SHGetPathFromIDListW(pidl, pathW))
623 V_VT(value) = VT_BSTR;
624 V_BSTR(value) = SysAllocString(pathW);
625 hr = V_BSTR(value) ? S_OK : E_OUTOFMEMORY;
627 else
628 hr = E_FAIL;
630 CoTaskMemFree(pidl);
632 return hr;
635 static HRESULT WINAPI WshCollection_Count(IWshCollection *iface, LONG *count)
637 WshCollection *This = impl_from_IWshCollection(iface);
638 FIXME("(%p)->(%p): stub\n", This, count);
639 return E_NOTIMPL;
642 static HRESULT WINAPI WshCollection_get_length(IWshCollection *iface, LONG *count)
644 WshCollection *This = impl_from_IWshCollection(iface);
645 FIXME("(%p)->(%p): stub\n", This, count);
646 return E_NOTIMPL;
649 static HRESULT WINAPI WshCollection__NewEnum(IWshCollection *iface, IUnknown *Enum)
651 WshCollection *This = impl_from_IWshCollection(iface);
652 FIXME("(%p)->(%p): stub\n", This, Enum);
653 return E_NOTIMPL;
656 static const IWshCollectionVtbl WshCollectionVtbl = {
657 WshCollection_QueryInterface,
658 WshCollection_AddRef,
659 WshCollection_Release,
660 WshCollection_GetTypeInfoCount,
661 WshCollection_GetTypeInfo,
662 WshCollection_GetIDsOfNames,
663 WshCollection_Invoke,
664 WshCollection_Item,
665 WshCollection_Count,
666 WshCollection_get_length,
667 WshCollection__NewEnum
670 static HRESULT WshCollection_Create(IWshCollection **collection)
672 WshCollection *This;
674 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
675 if (!This) return E_OUTOFMEMORY;
677 This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl;
678 This->ref = 1;
680 *collection = &This->IWshCollection_iface;
682 return S_OK;
685 /* IWshShortcut */
686 static HRESULT WINAPI WshShortcut_QueryInterface(IWshShortcut *iface, REFIID riid, void **ppv)
688 WshShortcut *This = impl_from_IWshShortcut(iface);
690 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
692 if (IsEqualGUID(riid, &IID_IUnknown) ||
693 IsEqualGUID(riid, &IID_IDispatch) ||
694 IsEqualGUID(riid, &IID_IWshShortcut))
696 *ppv = iface;
697 }else {
698 FIXME("Unknown iface %s\n", debugstr_guid(riid));
699 *ppv = NULL;
700 return E_NOINTERFACE;
703 IUnknown_AddRef((IUnknown*)*ppv);
704 return S_OK;
707 static ULONG WINAPI WshShortcut_AddRef(IWshShortcut *iface)
709 WshShortcut *This = impl_from_IWshShortcut(iface);
710 LONG ref = InterlockedIncrement(&This->ref);
711 TRACE("(%p) ref = %d\n", This, ref);
712 return ref;
715 static ULONG WINAPI WshShortcut_Release(IWshShortcut *iface)
717 WshShortcut *This = impl_from_IWshShortcut(iface);
718 LONG ref = InterlockedDecrement(&This->ref);
719 TRACE("(%p) ref = %d\n", This, ref);
721 if (!ref)
723 SysFreeString(This->path_link);
724 IShellLinkW_Release(This->link);
725 HeapFree(GetProcessHeap(), 0, This);
728 return ref;
731 static HRESULT WINAPI WshShortcut_GetTypeInfoCount(IWshShortcut *iface, UINT *pctinfo)
733 WshShortcut *This = impl_from_IWshShortcut(iface);
734 TRACE("(%p)->(%p)\n", This, pctinfo);
735 *pctinfo = 1;
736 return S_OK;
739 static HRESULT WINAPI WshShortcut_GetTypeInfo(IWshShortcut *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
741 WshShortcut *This = impl_from_IWshShortcut(iface);
742 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
743 return get_typeinfo(IWshShortcut_tid, ppTInfo);
746 static HRESULT WINAPI WshShortcut_GetIDsOfNames(IWshShortcut *iface, REFIID riid, LPOLESTR *rgszNames,
747 UINT cNames, LCID lcid, DISPID *rgDispId)
749 WshShortcut *This = impl_from_IWshShortcut(iface);
750 ITypeInfo *typeinfo;
751 HRESULT hr;
753 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
755 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
756 if(SUCCEEDED(hr))
758 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
759 ITypeInfo_Release(typeinfo);
762 return hr;
765 static HRESULT WINAPI WshShortcut_Invoke(IWshShortcut *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
766 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
768 WshShortcut *This = impl_from_IWshShortcut(iface);
769 ITypeInfo *typeinfo;
770 HRESULT hr;
772 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
773 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
775 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
776 if(SUCCEEDED(hr))
778 hr = ITypeInfo_Invoke(typeinfo, &This->IWshShortcut_iface, dispIdMember, wFlags,
779 pDispParams, pVarResult, pExcepInfo, puArgErr);
780 ITypeInfo_Release(typeinfo);
783 return hr;
786 static HRESULT WINAPI WshShortcut_get_FullName(IWshShortcut *iface, BSTR *name)
788 WshShortcut *This = impl_from_IWshShortcut(iface);
789 FIXME("(%p)->(%p): stub\n", This, name);
790 return E_NOTIMPL;
793 static HRESULT WINAPI WshShortcut_get_Arguments(IWshShortcut *iface, BSTR *Arguments)
795 WshShortcut *This = impl_from_IWshShortcut(iface);
796 WCHAR buffW[INFOTIPSIZE];
797 HRESULT hr;
799 TRACE("(%p)->(%p)\n", This, Arguments);
801 if (!Arguments)
802 return E_POINTER;
804 *Arguments = NULL;
806 hr = IShellLinkW_GetArguments(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
807 if (FAILED(hr))
808 return hr;
810 *Arguments = SysAllocString(buffW);
811 return *Arguments ? S_OK : E_OUTOFMEMORY;
814 static HRESULT WINAPI WshShortcut_put_Arguments(IWshShortcut *iface, BSTR Arguments)
816 WshShortcut *This = impl_from_IWshShortcut(iface);
818 TRACE("(%p)->(%s)\n", This, debugstr_w(Arguments));
820 return IShellLinkW_SetArguments(This->link, Arguments);
823 static HRESULT WINAPI WshShortcut_get_Description(IWshShortcut *iface, BSTR *Description)
825 WshShortcut *This = impl_from_IWshShortcut(iface);
826 FIXME("(%p)->(%p): stub\n", This, Description);
827 return E_NOTIMPL;
830 static HRESULT WINAPI WshShortcut_put_Description(IWshShortcut *iface, BSTR Description)
832 WshShortcut *This = impl_from_IWshShortcut(iface);
833 TRACE("(%p)->(%s)\n", This, debugstr_w(Description));
834 return IShellLinkW_SetDescription(This->link, Description);
837 static HRESULT WINAPI WshShortcut_get_Hotkey(IWshShortcut *iface, BSTR *Hotkey)
839 WshShortcut *This = impl_from_IWshShortcut(iface);
840 FIXME("(%p)->(%p): stub\n", This, Hotkey);
841 return E_NOTIMPL;
844 static HRESULT WINAPI WshShortcut_put_Hotkey(IWshShortcut *iface, BSTR Hotkey)
846 WshShortcut *This = impl_from_IWshShortcut(iface);
847 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Hotkey));
848 return E_NOTIMPL;
851 static HRESULT WINAPI WshShortcut_get_IconLocation(IWshShortcut *iface, BSTR *IconPath)
853 static const WCHAR fmtW[] = {'%','s',',',' ','%','d',0};
854 WshShortcut *This = impl_from_IWshShortcut(iface);
855 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
856 INT icon = 0;
857 HRESULT hr;
859 TRACE("(%p)->(%p)\n", This, IconPath);
861 if (!IconPath)
862 return E_POINTER;
864 hr = IShellLinkW_GetIconLocation(This->link, buffW, sizeof(buffW)/sizeof(WCHAR), &icon);
865 if (FAILED(hr)) return hr;
867 sprintfW(pathW, fmtW, buffW, icon);
868 *IconPath = SysAllocString(pathW);
869 if (!*IconPath) return E_OUTOFMEMORY;
871 return S_OK;
874 static HRESULT WINAPI WshShortcut_put_IconLocation(IWshShortcut *iface, BSTR IconPath)
876 WshShortcut *This = impl_from_IWshShortcut(iface);
877 HRESULT hr;
878 WCHAR *ptr;
879 BSTR path;
880 INT icon;
882 TRACE("(%p)->(%s)\n", This, debugstr_w(IconPath));
884 /* scan for icon id */
885 ptr = strrchrW(IconPath, ',');
886 if (!ptr)
888 WARN("icon index not found\n");
889 return E_FAIL;
892 path = SysAllocStringLen(IconPath, ptr-IconPath);
894 /* skip spaces if any */
895 while (isspaceW(*++ptr))
898 icon = atoiW(ptr);
900 hr = IShellLinkW_SetIconLocation(This->link, path, icon);
901 SysFreeString(path);
903 return hr;
906 static HRESULT WINAPI WshShortcut_put_RelativePath(IWshShortcut *iface, BSTR rhs)
908 WshShortcut *This = impl_from_IWshShortcut(iface);
909 FIXME("(%p)->(%s): stub\n", This, debugstr_w(rhs));
910 return E_NOTIMPL;
913 static HRESULT WINAPI WshShortcut_get_TargetPath(IWshShortcut *iface, BSTR *Path)
915 WshShortcut *This = impl_from_IWshShortcut(iface);
916 FIXME("(%p)->(%p): stub\n", This, Path);
917 return E_NOTIMPL;
920 static HRESULT WINAPI WshShortcut_put_TargetPath(IWshShortcut *iface, BSTR Path)
922 WshShortcut *This = impl_from_IWshShortcut(iface);
923 TRACE("(%p)->(%s)\n", This, debugstr_w(Path));
924 return IShellLinkW_SetPath(This->link, Path);
927 static HRESULT WINAPI WshShortcut_get_WindowStyle(IWshShortcut *iface, int *ShowCmd)
929 WshShortcut *This = impl_from_IWshShortcut(iface);
930 TRACE("(%p)->(%p)\n", This, ShowCmd);
931 return IShellLinkW_GetShowCmd(This->link, ShowCmd);
934 static HRESULT WINAPI WshShortcut_put_WindowStyle(IWshShortcut *iface, int ShowCmd)
936 WshShortcut *This = impl_from_IWshShortcut(iface);
937 TRACE("(%p)->(%d)\n", This, ShowCmd);
938 return IShellLinkW_SetShowCmd(This->link, ShowCmd);
941 static HRESULT WINAPI WshShortcut_get_WorkingDirectory(IWshShortcut *iface, BSTR *WorkingDirectory)
943 WshShortcut *This = impl_from_IWshShortcut(iface);
944 WCHAR buffW[MAX_PATH];
945 HRESULT hr;
947 TRACE("(%p)->(%p)\n", This, WorkingDirectory);
949 if (!WorkingDirectory)
950 return E_POINTER;
952 *WorkingDirectory = NULL;
953 hr = IShellLinkW_GetWorkingDirectory(This->link, buffW, sizeof(buffW)/sizeof(WCHAR));
954 if (FAILED(hr)) return hr;
956 *WorkingDirectory = SysAllocString(buffW);
957 return *WorkingDirectory ? S_OK : E_OUTOFMEMORY;
960 static HRESULT WINAPI WshShortcut_put_WorkingDirectory(IWshShortcut *iface, BSTR WorkingDirectory)
962 WshShortcut *This = impl_from_IWshShortcut(iface);
963 TRACE("(%p)->(%s)\n", This, debugstr_w(WorkingDirectory));
964 return IShellLinkW_SetWorkingDirectory(This->link, WorkingDirectory);
967 static HRESULT WINAPI WshShortcut_Load(IWshShortcut *iface, BSTR PathLink)
969 WshShortcut *This = impl_from_IWshShortcut(iface);
970 FIXME("(%p)->(%s): stub\n", This, debugstr_w(PathLink));
971 return E_NOTIMPL;
974 static HRESULT WINAPI WshShortcut_Save(IWshShortcut *iface)
976 WshShortcut *This = impl_from_IWshShortcut(iface);
977 IPersistFile *file;
978 HRESULT hr;
980 TRACE("(%p)\n", This);
982 IShellLinkW_QueryInterface(This->link, &IID_IPersistFile, (void**)&file);
983 hr = IPersistFile_Save(file, This->path_link, TRUE);
984 IPersistFile_Release(file);
986 return hr;
989 static const IWshShortcutVtbl WshShortcutVtbl = {
990 WshShortcut_QueryInterface,
991 WshShortcut_AddRef,
992 WshShortcut_Release,
993 WshShortcut_GetTypeInfoCount,
994 WshShortcut_GetTypeInfo,
995 WshShortcut_GetIDsOfNames,
996 WshShortcut_Invoke,
997 WshShortcut_get_FullName,
998 WshShortcut_get_Arguments,
999 WshShortcut_put_Arguments,
1000 WshShortcut_get_Description,
1001 WshShortcut_put_Description,
1002 WshShortcut_get_Hotkey,
1003 WshShortcut_put_Hotkey,
1004 WshShortcut_get_IconLocation,
1005 WshShortcut_put_IconLocation,
1006 WshShortcut_put_RelativePath,
1007 WshShortcut_get_TargetPath,
1008 WshShortcut_put_TargetPath,
1009 WshShortcut_get_WindowStyle,
1010 WshShortcut_put_WindowStyle,
1011 WshShortcut_get_WorkingDirectory,
1012 WshShortcut_put_WorkingDirectory,
1013 WshShortcut_Load,
1014 WshShortcut_Save
1017 static HRESULT WshShortcut_Create(const WCHAR *path, IDispatch **shortcut)
1019 WshShortcut *This;
1020 HRESULT hr;
1022 *shortcut = NULL;
1024 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1025 if (!This) return E_OUTOFMEMORY;
1027 This->IWshShortcut_iface.lpVtbl = &WshShortcutVtbl;
1028 This->ref = 1;
1030 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1031 &IID_IShellLinkW, (void**)&This->link);
1032 if (FAILED(hr))
1034 HeapFree(GetProcessHeap(), 0, This);
1035 return hr;
1038 This->path_link = SysAllocString(path);
1039 if (!This->path_link)
1041 IShellLinkW_Release(This->link);
1042 HeapFree(GetProcessHeap(), 0, This);
1043 return E_OUTOFMEMORY;
1046 *shortcut = (IDispatch*)&This->IWshShortcut_iface;
1048 return S_OK;
1051 static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
1053 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1055 *ppv = NULL;
1057 if (IsEqualGUID(riid, &IID_IDispatch) ||
1058 IsEqualGUID(riid, &IID_IWshShell3) ||
1059 IsEqualGUID(riid, &IID_IWshShell2) ||
1060 IsEqualGUID(riid, &IID_IWshShell) ||
1061 IsEqualGUID(riid, &IID_IUnknown))
1063 *ppv = iface;
1065 else if (IsEqualGUID(riid, &IID_IDispatchEx))
1067 return E_NOINTERFACE;
1069 else
1071 WARN("unknown iface %s\n", debugstr_guid(riid));
1072 return E_NOINTERFACE;
1075 IWshShell3_AddRef(iface);
1076 return S_OK;
1079 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
1081 TRACE("()\n");
1082 return 2;
1085 static ULONG WINAPI WshShell3_Release(IWshShell3 *iface)
1087 TRACE("()\n");
1088 return 2;
1091 static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinfo)
1093 TRACE("(%p)\n", pctinfo);
1094 *pctinfo = 1;
1095 return S_OK;
1098 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1100 TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
1101 return get_typeinfo(IWshShell3_tid, ppTInfo);
1104 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
1105 UINT cNames, LCID lcid, DISPID *rgDispId)
1107 ITypeInfo *typeinfo;
1108 HRESULT hr;
1110 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1112 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
1113 if(SUCCEEDED(hr))
1115 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1116 ITypeInfo_Release(typeinfo);
1119 return hr;
1122 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1123 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1125 ITypeInfo *typeinfo;
1126 HRESULT hr;
1128 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
1129 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1131 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
1132 if(SUCCEEDED(hr))
1134 hr = ITypeInfo_Invoke(typeinfo, &WshShell3, dispIdMember, wFlags,
1135 pDispParams, pVarResult, pExcepInfo, puArgErr);
1136 ITypeInfo_Release(typeinfo);
1139 return hr;
1142 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
1144 TRACE("(%p)\n", folders);
1145 return WshCollection_Create(folders);
1148 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *type, IWshEnvironment **env)
1150 FIXME("(%s %p): semi-stub\n", debugstr_variant(type), env);
1151 return WshEnvironment_Create(env);
1154 static inline BOOL is_optional_argument(const VARIANT *arg)
1156 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
1159 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *wait, DWORD *exit_code)
1161 SHELLEXECUTEINFOW info;
1162 int waitforprocess;
1163 VARIANT s;
1164 HRESULT hr;
1166 TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(wait), exit_code);
1168 if (!style || !wait || !exit_code)
1169 return E_POINTER;
1171 VariantInit(&s);
1172 hr = VariantChangeType(&s, style, 0, VT_I4);
1173 if (FAILED(hr))
1175 ERR("failed to convert style argument, 0x%08x\n", hr);
1176 return hr;
1179 if (is_optional_argument(wait))
1180 waitforprocess = 0;
1181 else {
1182 VARIANT w;
1184 VariantInit(&w);
1185 hr = VariantChangeType(&w, wait, 0, VT_I4);
1186 if (FAILED(hr))
1187 return hr;
1189 waitforprocess = V_I4(&w);
1192 memset(&info, 0, sizeof(info));
1193 info.cbSize = sizeof(info);
1194 info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
1195 info.lpFile = cmd;
1196 info.nShow = V_I4(&s);
1198 if (!ShellExecuteExW(&info))
1200 TRACE("ShellExecute failed, %d\n", GetLastError());
1201 return HRESULT_FROM_WIN32(GetLastError());
1203 else
1205 if (waitforprocess)
1207 GetExitCodeProcess(info.hProcess, exit_code);
1208 CloseHandle(info.hProcess);
1210 else
1211 *exit_code = 0;
1213 return S_OK;
1217 static HRESULT WINAPI WshShell3_Popup(IWshShell3 *iface, BSTR Text, VARIANT* SecondsToWait, VARIANT *Title, VARIANT *Type, int *button)
1219 FIXME("(%s %s %s %s %p): stub\n", debugstr_w(Text), debugstr_variant(SecondsToWait),
1220 debugstr_variant(Title), debugstr_variant(Type), button);
1221 return E_NOTIMPL;
1224 static HRESULT WINAPI WshShell3_CreateShortcut(IWshShell3 *iface, BSTR PathLink, IDispatch** Shortcut)
1226 TRACE("(%s %p)\n", debugstr_w(PathLink), Shortcut);
1227 return WshShortcut_Create(PathLink, Shortcut);
1230 static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR Src, BSTR* Dst)
1232 DWORD ret;
1234 TRACE("(%s %p)\n", debugstr_w(Src), Dst);
1236 if (!Src || !Dst) return E_POINTER;
1238 ret = ExpandEnvironmentStringsW(Src, NULL, 0);
1239 *Dst = SysAllocStringLen(NULL, ret);
1240 if (!*Dst) return E_OUTOFMEMORY;
1242 if (ExpandEnvironmentStringsW(Src, *Dst, ret))
1243 return S_OK;
1244 else
1246 SysFreeString(*Dst);
1247 *Dst = NULL;
1248 return HRESULT_FROM_WIN32(GetLastError());
1252 static HKEY get_root_key(const WCHAR *path)
1254 static const struct {
1255 const WCHAR full[20];
1256 const WCHAR abbrev[5];
1257 HKEY hkey;
1258 } rootkeys[] = {
1259 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER },
1260 { {'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 },
1261 { {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT },
1262 { {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS },
1263 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG }
1265 int i;
1267 for (i = 0; i < sizeof(rootkeys)/sizeof(rootkeys[0]); i++) {
1268 if (!strncmpW(path, rootkeys[i].full, strlenW(rootkeys[i].full)))
1269 return rootkeys[i].hkey;
1270 if (rootkeys[i].abbrev[0] && !strncmpW(path, rootkeys[i].abbrev, strlenW(rootkeys[i].abbrev)))
1271 return rootkeys[i].hkey;
1274 return NULL;
1277 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
1278 static HRESULT split_reg_path(const WCHAR *path, WCHAR **subkey, WCHAR **value)
1280 *value = NULL;
1282 /* at least one separator should be present */
1283 *subkey = strchrW(path, '\\');
1284 if (!*subkey)
1285 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1287 /* default value or not */
1288 if ((*subkey)[strlenW(*subkey)-1] == '\\') {
1289 (*subkey)++;
1290 *value = NULL;
1292 else {
1293 *value = strrchrW(*subkey, '\\');
1294 if (*value - *subkey > 1) {
1295 unsigned int len = *value - *subkey - 1;
1296 WCHAR *ret;
1298 ret = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
1299 if (!ret)
1300 return E_OUTOFMEMORY;
1302 memcpy(ret, *subkey + 1, len*sizeof(WCHAR));
1303 ret[len] = 0;
1304 *subkey = ret;
1306 (*value)++;
1309 return S_OK;
1312 static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *value)
1314 DWORD type, datalen, ret;
1315 WCHAR *subkey, *val;
1316 HRESULT hr;
1317 HKEY root;
1319 TRACE("(%s %p)\n", debugstr_w(name), value);
1321 if (!name || !value)
1322 return E_POINTER;
1324 root = get_root_key(name);
1325 if (!root)
1326 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1328 hr = split_reg_path(name, &subkey, &val);
1329 if (FAILED(hr))
1330 return hr;
1332 type = REG_NONE;
1333 datalen = 0;
1334 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, NULL, &datalen);
1335 if (ret == ERROR_SUCCESS) {
1336 void *data;
1338 data = HeapAlloc(GetProcessHeap(), 0, datalen);
1339 if (!data) {
1340 hr = E_OUTOFMEMORY;
1341 goto fail;
1344 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, data, &datalen);
1345 if (ret) {
1346 HeapFree(GetProcessHeap(), 0, data);
1347 hr = HRESULT_FROM_WIN32(ret);
1348 goto fail;
1351 switch (type) {
1352 case REG_SZ:
1353 case REG_EXPAND_SZ:
1354 V_VT(value) = VT_BSTR;
1355 V_BSTR(value) = SysAllocStringLen((WCHAR*)data, datalen - sizeof(WCHAR));
1356 if (!V_BSTR(value))
1357 hr = E_OUTOFMEMORY;
1358 break;
1359 case REG_DWORD:
1360 V_VT(value) = VT_I4;
1361 V_I4(value) = *(DWORD*)data;
1362 break;
1363 case REG_BINARY:
1365 BYTE *ptr = (BYTE*)data;
1366 SAFEARRAYBOUND bound;
1367 unsigned int i;
1368 SAFEARRAY *sa;
1369 VARIANT *v;
1371 bound.lLbound = 0;
1372 bound.cElements = datalen;
1373 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1374 if (!sa)
1375 break;
1377 hr = SafeArrayAccessData(sa, (void**)&v);
1378 if (FAILED(hr)) {
1379 SafeArrayDestroy(sa);
1380 break;
1383 for (i = 0; i < datalen; i++) {
1384 V_VT(&v[i]) = VT_UI1;
1385 V_UI1(&v[i]) = ptr[i];
1387 SafeArrayUnaccessData(sa);
1389 V_VT(value) = VT_ARRAY|VT_VARIANT;
1390 V_ARRAY(value) = sa;
1391 break;
1393 case REG_MULTI_SZ:
1395 WCHAR *ptr = (WCHAR*)data;
1396 SAFEARRAYBOUND bound;
1397 SAFEARRAY *sa;
1398 VARIANT *v;
1400 /* get element count first */
1401 bound.lLbound = 0;
1402 bound.cElements = 0;
1403 while (*ptr) {
1404 bound.cElements++;
1405 ptr += strlenW(ptr)+1;
1408 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1409 if (!sa)
1410 break;
1412 hr = SafeArrayAccessData(sa, (void**)&v);
1413 if (FAILED(hr)) {
1414 SafeArrayDestroy(sa);
1415 break;
1418 ptr = (WCHAR*)data;
1419 while (*ptr) {
1420 V_VT(v) = VT_BSTR;
1421 V_BSTR(v) = SysAllocString(ptr);
1422 ptr += strlenW(ptr)+1;
1423 v++;
1426 SafeArrayUnaccessData(sa);
1427 V_VT(value) = VT_ARRAY|VT_VARIANT;
1428 V_ARRAY(value) = sa;
1429 break;
1431 default:
1432 FIXME("value type %d not supported\n", type);
1433 hr = E_FAIL;
1436 HeapFree(GetProcessHeap(), 0, data);
1437 if (FAILED(hr))
1438 VariantInit(value);
1440 else
1441 hr = HRESULT_FROM_WIN32(ret);
1443 fail:
1444 if (val)
1445 HeapFree(GetProcessHeap(), 0, subkey);
1446 return hr;
1449 static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR name, VARIANT *value, VARIANT *type)
1451 static const WCHAR regexpandszW[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
1452 static const WCHAR regszW[] = {'R','E','G','_','S','Z',0};
1453 static const WCHAR regdwordW[] = {'R','E','G','_','D','W','O','R','D',0};
1454 static const WCHAR regbinaryW[] = {'R','E','G','_','B','I','N','A','R','Y',0};
1456 DWORD regtype, data_len;
1457 WCHAR *subkey, *val;
1458 const BYTE *data;
1459 HRESULT hr;
1460 HKEY root;
1461 VARIANT v;
1462 LONG ret;
1464 TRACE("(%s %s %s)\n", debugstr_w(name), debugstr_variant(value), debugstr_variant(type));
1466 if (!name || !value || !type)
1467 return E_POINTER;
1469 root = get_root_key(name);
1470 if (!root)
1471 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1473 /* value type */
1474 if (is_optional_argument(type))
1475 regtype = REG_SZ;
1476 else {
1477 if (V_VT(type) != VT_BSTR)
1478 return E_INVALIDARG;
1480 if (!strcmpW(V_BSTR(type), regszW))
1481 regtype = REG_SZ;
1482 else if (!strcmpW(V_BSTR(type), regdwordW))
1483 regtype = REG_DWORD;
1484 else if (!strcmpW(V_BSTR(type), regexpandszW))
1485 regtype = REG_EXPAND_SZ;
1486 else if (!strcmpW(V_BSTR(type), regbinaryW))
1487 regtype = REG_BINARY;
1488 else {
1489 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type)));
1490 return E_FAIL;
1494 /* it's always a string or a DWORD */
1495 VariantInit(&v);
1496 switch (regtype)
1498 case REG_SZ:
1499 case REG_EXPAND_SZ:
1500 hr = VariantChangeType(&v, value, 0, VT_BSTR);
1501 if (hr == S_OK) {
1502 data = (BYTE*)V_BSTR(&v);
1503 data_len = SysStringByteLen(V_BSTR(&v)) + sizeof(WCHAR);
1505 break;
1506 case REG_DWORD:
1507 case REG_BINARY:
1508 hr = VariantChangeType(&v, value, 0, VT_I4);
1509 data = (BYTE*)&V_I4(&v);
1510 data_len = sizeof(DWORD);
1511 break;
1512 default:
1513 FIXME("unexpected regtype %d\n", regtype);
1514 return E_FAIL;
1517 if (FAILED(hr)) {
1518 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype, hr);
1519 return hr;
1522 hr = split_reg_path(name, &subkey, &val);
1523 if (FAILED(hr))
1524 goto fail;
1526 ret = RegSetKeyValueW(root, subkey, val, regtype, data, data_len);
1527 if (ret)
1528 hr = HRESULT_FROM_WIN32(ret);
1530 fail:
1531 VariantClear(&v);
1532 if (val)
1533 HeapFree(GetProcessHeap(), 0, subkey);
1534 return hr;
1537 static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name)
1539 FIXME("(%s): stub\n", debugstr_w(Name));
1540 return E_NOTIMPL;
1543 static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR Message, BSTR Target, VARIANT_BOOL *out_Success)
1545 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type), debugstr_w(Message), debugstr_w(Target), out_Success);
1546 return E_NOTIMPL;
1549 static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success)
1551 FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success);
1552 return E_NOTIMPL;
1555 static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait)
1557 FIXME("(%s %p): stub\n", debugstr_w(Keys), Wait);
1558 return E_NOTIMPL;
1561 static HRESULT WINAPI WshShell3_Exec(IWshShell3 *iface, BSTR command, IWshExec **ret)
1563 TRACE("(%s %p)\n", debugstr_w(command), ret);
1565 if (!ret)
1566 return E_POINTER;
1568 if (!command)
1569 return DISP_E_EXCEPTION;
1571 return WshExec_create(command, ret);
1574 static HRESULT WINAPI WshShell3_get_CurrentDirectory(IWshShell3 *iface, BSTR *dir)
1576 DWORD ret;
1578 TRACE("(%p)\n", dir);
1580 ret = GetCurrentDirectoryW(0, NULL);
1581 if (!ret)
1582 return HRESULT_FROM_WIN32(GetLastError());
1584 *dir = SysAllocStringLen(NULL, ret-1);
1585 if (!*dir)
1586 return E_OUTOFMEMORY;
1588 ret = GetCurrentDirectoryW(ret, *dir);
1589 if (!ret) {
1590 SysFreeString(*dir);
1591 *dir = NULL;
1592 return HRESULT_FROM_WIN32(GetLastError());
1595 return S_OK;
1598 static HRESULT WINAPI WshShell3_put_CurrentDirectory(IWshShell3 *iface, BSTR dir)
1600 TRACE("(%s)\n", debugstr_w(dir));
1602 if (!dir)
1603 return E_INVALIDARG;
1605 if (!SetCurrentDirectoryW(dir))
1606 return HRESULT_FROM_WIN32(GetLastError());
1608 return S_OK;
1611 static const IWshShell3Vtbl WshShell3Vtbl = {
1612 WshShell3_QueryInterface,
1613 WshShell3_AddRef,
1614 WshShell3_Release,
1615 WshShell3_GetTypeInfoCount,
1616 WshShell3_GetTypeInfo,
1617 WshShell3_GetIDsOfNames,
1618 WshShell3_Invoke,
1619 WshShell3_get_SpecialFolders,
1620 WshShell3_get_Environment,
1621 WshShell3_Run,
1622 WshShell3_Popup,
1623 WshShell3_CreateShortcut,
1624 WshShell3_ExpandEnvironmentStrings,
1625 WshShell3_RegRead,
1626 WshShell3_RegWrite,
1627 WshShell3_RegDelete,
1628 WshShell3_LogEvent,
1629 WshShell3_AppActivate,
1630 WshShell3_SendKeys,
1631 WshShell3_Exec,
1632 WshShell3_get_CurrentDirectory,
1633 WshShell3_put_CurrentDirectory
1636 static IWshShell3 WshShell3 = { &WshShell3Vtbl };
1638 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1640 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
1642 return IWshShell3_QueryInterface(&WshShell3, riid, ppv);