1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #ifdef __REACTOS__
20 #include <wchar.h>
21 #endif
22
23 #include "wshom_private.h"
24 #include "wshom.h"
25
26 #include "shellapi.h"
27 #include "shlobj.h"
28 #include "dispex.h"
29
30 #include "wine/debug.h"
31 #include "wine/heap.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(wshom);
34
35 typedef struct
36 {
37 struct provideclassinfo classinfo;
38 IWshShell3 IWshShell3_iface;
39 } WshShellImpl;
40 static WshShellImpl WshShell3;
41
42 typedef struct
43 {
44 struct provideclassinfo classinfo;
45 IWshCollection IWshCollection_iface;
46 LONG ref;
47 } WshCollection;
48
49 typedef struct
50 {
51 struct provideclassinfo classinfo;
52 IWshShortcut IWshShortcut_iface;
53 LONG ref;
54
55 IShellLinkW *link;
56 BSTR path_link;
57 } WshShortcut;
58
59 typedef struct
60 {
61 struct provideclassinfo classinfo;
62 IWshEnvironment IWshEnvironment_iface;
63 LONG ref;
64 } WshEnvironment;
65
66 typedef struct
67 {
68 struct provideclassinfo classinfo;
69 IWshExec IWshExec_iface;
70 LONG ref;
71 PROCESS_INFORMATION info;
72 } WshExecImpl;
73
impl_from_IWshCollection(IWshCollection * iface)74 static inline WshCollection *impl_from_IWshCollection( IWshCollection *iface )
75 {
76 return CONTAINING_RECORD(iface, WshCollection, IWshCollection_iface);
77 }
78
impl_from_IWshShortcut(IWshShortcut * iface)79 static inline WshShortcut *impl_from_IWshShortcut( IWshShortcut *iface )
80 {
81 return CONTAINING_RECORD(iface, WshShortcut, IWshShortcut_iface);
82 }
83
impl_from_IWshEnvironment(IWshEnvironment * iface)84 static inline WshEnvironment *impl_from_IWshEnvironment( IWshEnvironment *iface )
85 {
86 return CONTAINING_RECORD(iface, WshEnvironment, IWshEnvironment_iface);
87 }
88
impl_from_IWshExec(IWshExec * iface)89 static inline WshExecImpl *impl_from_IWshExec( IWshExec *iface )
90 {
91 return CONTAINING_RECORD(iface, WshExecImpl, IWshExec_iface);
92 }
93
WshExec_QueryInterface(IWshExec * iface,REFIID riid,void ** obj)94 static HRESULT WINAPI WshExec_QueryInterface(IWshExec *iface, REFIID riid, void **obj)
95 {
96 WshExecImpl *This = impl_from_IWshExec(iface);
97
98 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
99
100 if (IsEqualGUID(riid, &IID_IDispatch) ||
101 IsEqualGUID(riid, &IID_IWshExec) ||
102 IsEqualGUID(riid, &IID_IUnknown))
103 {
104 *obj = iface;
105 }
106 else if (IsEqualIID(riid, &IID_IProvideClassInfo))
107 {
108 *obj = &This->classinfo.IProvideClassInfo_iface;
109 }
110 else {
111 FIXME("Unknown iface %s\n", debugstr_guid(riid));
112 *obj = NULL;
113 return E_NOINTERFACE;
114 }
115
116 IUnknown_AddRef((IUnknown *)*obj);
117 return S_OK;
118 }
119
WshExec_AddRef(IWshExec * iface)120 static ULONG WINAPI WshExec_AddRef(IWshExec *iface)
121 {
122 WshExecImpl *This = impl_from_IWshExec(iface);
123 LONG ref = InterlockedIncrement(&This->ref);
124 TRACE("(%p) ref = %d\n", This, ref);
125 return ref;
126 }
127
WshExec_Release(IWshExec * iface)128 static ULONG WINAPI WshExec_Release(IWshExec *iface)
129 {
130 WshExecImpl *This = impl_from_IWshExec(iface);
131 LONG ref = InterlockedDecrement(&This->ref);
132 TRACE("(%p) ref = %d\n", This, ref);
133
134 if (!ref) {
135 CloseHandle(This->info.hThread);
136 CloseHandle(This->info.hProcess);
137 heap_free(This);
138 }
139
140 return ref;
141 }
142
WshExec_GetTypeInfoCount(IWshExec * iface,UINT * pctinfo)143 static HRESULT WINAPI WshExec_GetTypeInfoCount(IWshExec *iface, UINT *pctinfo)
144 {
145 WshExecImpl *This = impl_from_IWshExec(iface);
146 TRACE("(%p)->(%p)\n", This, pctinfo);
147 *pctinfo = 1;
148 return S_OK;
149 }
150
WshExec_GetTypeInfo(IWshExec * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)151 static HRESULT WINAPI WshExec_GetTypeInfo(IWshExec *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
152 {
153 WshExecImpl *This = impl_from_IWshExec(iface);
154 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
155 return get_typeinfo(IWshExec_tid, ppTInfo);
156 }
157
WshExec_GetIDsOfNames(IWshExec * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)158 static HRESULT WINAPI WshExec_GetIDsOfNames(IWshExec *iface, REFIID riid, LPOLESTR *rgszNames,
159 UINT cNames, LCID lcid, DISPID *rgDispId)
160 {
161 WshExecImpl *This = impl_from_IWshExec(iface);
162 ITypeInfo *typeinfo;
163 HRESULT hr;
164
165 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
166
167 hr = get_typeinfo(IWshExec_tid, &typeinfo);
168 if(SUCCEEDED(hr))
169 {
170 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
171 ITypeInfo_Release(typeinfo);
172 }
173
174 return hr;
175 }
176
WshExec_Invoke(IWshExec * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)177 static HRESULT WINAPI WshExec_Invoke(IWshExec *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
178 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
179 {
180 WshExecImpl *This = impl_from_IWshExec(iface);
181 ITypeInfo *typeinfo;
182 HRESULT hr;
183
184 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
185 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
186
187 hr = get_typeinfo(IWshExec_tid, &typeinfo);
188 if(SUCCEEDED(hr))
189 {
190 hr = ITypeInfo_Invoke(typeinfo, &This->IWshExec_iface, dispIdMember, wFlags,
191 pDispParams, pVarResult, pExcepInfo, puArgErr);
192 ITypeInfo_Release(typeinfo);
193 }
194
195 return hr;
196 }
197
WshExec_get_Status(IWshExec * iface,WshExecStatus * status)198 static HRESULT WINAPI WshExec_get_Status(IWshExec *iface, WshExecStatus *status)
199 {
200 WshExecImpl *This = impl_from_IWshExec(iface);
201 DWORD code;
202
203 TRACE("(%p)->(%p)\n", This, status);
204
205 if (!status)
206 return E_INVALIDARG;
207
208 if (!GetExitCodeProcess(This->info.hProcess, &code))
209 return HRESULT_FROM_WIN32(GetLastError());
210
211 switch (code)
212 {
213 case 0:
214 *status = WshFinished;
215 break;
216 case STILL_ACTIVE:
217 *status = WshRunning;
218 break;
219 default:
220 *status = WshFailed;
221 }
222
223 return S_OK;
224 }
225
WshExec_get_StdIn(IWshExec * iface,ITextStream ** stream)226 static HRESULT WINAPI WshExec_get_StdIn(IWshExec *iface, ITextStream **stream)
227 {
228 WshExecImpl *This = impl_from_IWshExec(iface);
229
230 FIXME("(%p)->(%p): stub\n", This, stream);
231
232 return E_NOTIMPL;
233 }
234
WshExec_get_StdOut(IWshExec * iface,ITextStream ** stream)235 static HRESULT WINAPI WshExec_get_StdOut(IWshExec *iface, ITextStream **stream)
236 {
237 WshExecImpl *This = impl_from_IWshExec(iface);
238
239 FIXME("(%p)->(%p): stub\n", This, stream);
240
241 return E_NOTIMPL;
242 }
243
WshExec_get_StdErr(IWshExec * iface,ITextStream ** stream)244 static HRESULT WINAPI WshExec_get_StdErr(IWshExec *iface, ITextStream **stream)
245 {
246 WshExecImpl *This = impl_from_IWshExec(iface);
247
248 FIXME("(%p)->(%p): stub\n", This, stream);
249
250 return E_NOTIMPL;
251 }
252
WshExec_get_ProcessID(IWshExec * iface,DWORD * pid)253 static HRESULT WINAPI WshExec_get_ProcessID(IWshExec *iface, DWORD *pid)
254 {
255 WshExecImpl *This = impl_from_IWshExec(iface);
256
257 TRACE("(%p)->(%p)\n", This, pid);
258
259 if (!pid)
260 return E_INVALIDARG;
261
262 *pid = This->info.dwProcessId;
263 return S_OK;
264 }
265
WshExec_get_ExitCode(IWshExec * iface,DWORD * code)266 static HRESULT WINAPI WshExec_get_ExitCode(IWshExec *iface, DWORD *code)
267 {
268 WshExecImpl *This = impl_from_IWshExec(iface);
269
270 FIXME("(%p)->(%p): stub\n", This, code);
271
272 return E_NOTIMPL;
273 }
274
enum_thread_wnd_proc(HWND hwnd,LPARAM lParam)275 static BOOL CALLBACK enum_thread_wnd_proc(HWND hwnd, LPARAM lParam)
276 {
277 INT *count = (INT*)lParam;
278
279 (*count)++;
280 PostMessageW(hwnd, WM_CLOSE, 0, 0);
281 /* try to send it to all windows, even if failed for some */
282 return TRUE;
283 }
284
WshExec_Terminate(IWshExec * iface)285 static HRESULT WINAPI WshExec_Terminate(IWshExec *iface)
286 {
287 WshExecImpl *This = impl_from_IWshExec(iface);
288 BOOL ret, kill = FALSE;
289 INT count = 0;
290
291 TRACE("(%p)\n", This);
292
293 ret = EnumThreadWindows(This->info.dwThreadId, enum_thread_wnd_proc, (LPARAM)&count);
294 if (ret && count) {
295 /* manual testing shows that it waits 2 seconds before forcing termination */
296 if (WaitForSingleObject(This->info.hProcess, 2000) != WAIT_OBJECT_0)
297 kill = TRUE;
298 }
299 else
300 kill = TRUE;
301
302 if (kill)
303 TerminateProcess(This->info.hProcess, 0);
304
305 return S_OK;
306 }
307
308 static const IWshExecVtbl WshExecVtbl = {
309 WshExec_QueryInterface,
310 WshExec_AddRef,
311 WshExec_Release,
312 WshExec_GetTypeInfoCount,
313 WshExec_GetTypeInfo,
314 WshExec_GetIDsOfNames,
315 WshExec_Invoke,
316 WshExec_get_Status,
317 WshExec_get_StdIn,
318 WshExec_get_StdOut,
319 WshExec_get_StdErr,
320 WshExec_get_ProcessID,
321 WshExec_get_ExitCode,
322 WshExec_Terminate
323 };
324
WshExec_create(BSTR command,IWshExec ** ret)325 static HRESULT WshExec_create(BSTR command, IWshExec **ret)
326 {
327 STARTUPINFOW si = {0};
328 WshExecImpl *This;
329
330 *ret = NULL;
331
332 This = heap_alloc(sizeof(*This));
333 if (!This)
334 return E_OUTOFMEMORY;
335
336 This->IWshExec_iface.lpVtbl = &WshExecVtbl;
337 This->ref = 1;
338
339 if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &This->info)) {
340 heap_free(This);
341 return HRESULT_FROM_WIN32(GetLastError());
342 }
343
344 init_classinfo(&CLSID_WshExec, (IUnknown *)&This->IWshExec_iface, &This->classinfo);
345 *ret = &This->IWshExec_iface;
346 return S_OK;
347 }
348
WshEnvironment_QueryInterface(IWshEnvironment * iface,REFIID riid,void ** obj)349 static HRESULT WINAPI WshEnvironment_QueryInterface(IWshEnvironment *iface, REFIID riid, void **obj)
350 {
351 WshEnvironment *This = impl_from_IWshEnvironment(iface);
352
353 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
354
355 if (IsEqualGUID(riid, &IID_IUnknown) ||
356 IsEqualGUID(riid, &IID_IDispatch) ||
357 IsEqualGUID(riid, &IID_IWshEnvironment))
358 {
359 *obj = iface;
360 }
361 else if (IsEqualIID(riid, &IID_IProvideClassInfo))
362 {
363 *obj = &This->classinfo.IProvideClassInfo_iface;
364 }
365 else {
366 FIXME("Unknown iface %s\n", debugstr_guid(riid));
367 *obj = NULL;
368 return E_NOINTERFACE;
369 }
370
371 IUnknown_AddRef((IUnknown*)*obj);
372 return S_OK;
373 }
374
WshEnvironment_AddRef(IWshEnvironment * iface)375 static ULONG WINAPI WshEnvironment_AddRef(IWshEnvironment *iface)
376 {
377 WshEnvironment *This = impl_from_IWshEnvironment(iface);
378 LONG ref = InterlockedIncrement(&This->ref);
379 TRACE("(%p) ref = %d\n", This, ref);
380 return ref;
381 }
382
WshEnvironment_Release(IWshEnvironment * iface)383 static ULONG WINAPI WshEnvironment_Release(IWshEnvironment *iface)
384 {
385 WshEnvironment *This = impl_from_IWshEnvironment(iface);
386 LONG ref = InterlockedDecrement(&This->ref);
387 TRACE("(%p) ref = %d\n", This, ref);
388
389 if (!ref)
390 heap_free(This);
391
392 return ref;
393 }
394
WshEnvironment_GetTypeInfoCount(IWshEnvironment * iface,UINT * pctinfo)395 static HRESULT WINAPI WshEnvironment_GetTypeInfoCount(IWshEnvironment *iface, UINT *pctinfo)
396 {
397 WshEnvironment *This = impl_from_IWshEnvironment(iface);
398 TRACE("(%p)->(%p)\n", This, pctinfo);
399 *pctinfo = 1;
400 return S_OK;
401 }
402
WshEnvironment_GetTypeInfo(IWshEnvironment * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)403 static HRESULT WINAPI WshEnvironment_GetTypeInfo(IWshEnvironment *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
404 {
405 WshEnvironment *This = impl_from_IWshEnvironment(iface);
406 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
407 return get_typeinfo(IWshEnvironment_tid, ppTInfo);
408 }
409
WshEnvironment_GetIDsOfNames(IWshEnvironment * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)410 static HRESULT WINAPI WshEnvironment_GetIDsOfNames(IWshEnvironment *iface, REFIID riid, LPOLESTR *rgszNames,
411 UINT cNames, LCID lcid, DISPID *rgDispId)
412 {
413 WshEnvironment *This = impl_from_IWshEnvironment(iface);
414 ITypeInfo *typeinfo;
415 HRESULT hr;
416
417 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
418
419 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
420 if(SUCCEEDED(hr))
421 {
422 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
423 ITypeInfo_Release(typeinfo);
424 }
425
426 return hr;
427 }
428
WshEnvironment_Invoke(IWshEnvironment * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)429 static HRESULT WINAPI WshEnvironment_Invoke(IWshEnvironment *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
430 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
431 {
432 WshEnvironment *This = impl_from_IWshEnvironment(iface);
433 ITypeInfo *typeinfo;
434 HRESULT hr;
435
436 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
437 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
438
439 hr = get_typeinfo(IWshEnvironment_tid, &typeinfo);
440 if(SUCCEEDED(hr))
441 {
442 hr = ITypeInfo_Invoke(typeinfo, &This->IWshEnvironment_iface, dispIdMember, wFlags,
443 pDispParams, pVarResult, pExcepInfo, puArgErr);
444 ITypeInfo_Release(typeinfo);
445 }
446
447 return hr;
448 }
449
WshEnvironment_get_Item(IWshEnvironment * iface,BSTR name,BSTR * value)450 static HRESULT WINAPI WshEnvironment_get_Item(IWshEnvironment *iface, BSTR name, BSTR *value)
451 {
452 WshEnvironment *This = impl_from_IWshEnvironment(iface);
453 DWORD len;
454
455 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), value);
456
457 if (!value)
458 return E_POINTER;
459
460 len = GetEnvironmentVariableW(name, NULL, 0);
461 if (len)
462 {
463 *value = SysAllocStringLen(NULL, len - 1);
464 if (*value)
465 GetEnvironmentVariableW(name, *value, len);
466 }
467 else
468 *value = SysAllocStringLen(NULL, 0);
469
470 return *value ? S_OK : E_OUTOFMEMORY;
471 }
472
WshEnvironment_put_Item(IWshEnvironment * iface,BSTR name,BSTR value)473 static HRESULT WINAPI WshEnvironment_put_Item(IWshEnvironment *iface, BSTR name, BSTR value)
474 {
475 WshEnvironment *This = impl_from_IWshEnvironment(iface);
476 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(name), debugstr_w(value));
477 return E_NOTIMPL;
478 }
479
WshEnvironment_Count(IWshEnvironment * iface,LONG * count)480 static HRESULT WINAPI WshEnvironment_Count(IWshEnvironment *iface, LONG *count)
481 {
482 WshEnvironment *This = impl_from_IWshEnvironment(iface);
483 FIXME("(%p)->(%p): stub\n", This, count);
484 return E_NOTIMPL;
485 }
486
WshEnvironment_get_length(IWshEnvironment * iface,LONG * len)487 static HRESULT WINAPI WshEnvironment_get_length(IWshEnvironment *iface, LONG *len)
488 {
489 WshEnvironment *This = impl_from_IWshEnvironment(iface);
490 FIXME("(%p)->(%p): stub\n", This, len);
491 return E_NOTIMPL;
492 }
493
WshEnvironment__NewEnum(IWshEnvironment * iface,IUnknown ** penum)494 static HRESULT WINAPI WshEnvironment__NewEnum(IWshEnvironment *iface, IUnknown **penum)
495 {
496 WshEnvironment *This = impl_from_IWshEnvironment(iface);
497 FIXME("(%p)->(%p): stub\n", This, penum);
498 return E_NOTIMPL;
499 }
500
WshEnvironment_Remove(IWshEnvironment * iface,BSTR name)501 static HRESULT WINAPI WshEnvironment_Remove(IWshEnvironment *iface, BSTR name)
502 {
503 WshEnvironment *This = impl_from_IWshEnvironment(iface);
504 FIXME("(%p)->(%s): stub\n", This, debugstr_w(name));
505 return E_NOTIMPL;
506 }
507
508 static const IWshEnvironmentVtbl WshEnvironmentVtbl = {
509 WshEnvironment_QueryInterface,
510 WshEnvironment_AddRef,
511 WshEnvironment_Release,
512 WshEnvironment_GetTypeInfoCount,
513 WshEnvironment_GetTypeInfo,
514 WshEnvironment_GetIDsOfNames,
515 WshEnvironment_Invoke,
516 WshEnvironment_get_Item,
517 WshEnvironment_put_Item,
518 WshEnvironment_Count,
519 WshEnvironment_get_length,
520 WshEnvironment__NewEnum,
521 WshEnvironment_Remove
522 };
523
WshEnvironment_Create(IWshEnvironment ** env)524 static HRESULT WshEnvironment_Create(IWshEnvironment **env)
525 {
526 WshEnvironment *This;
527
528 This = heap_alloc(sizeof(*This));
529 if (!This) return E_OUTOFMEMORY;
530
531 This->IWshEnvironment_iface.lpVtbl = &WshEnvironmentVtbl;
532 This->ref = 1;
533
534 init_classinfo(&IID_IWshEnvironment, (IUnknown *)&This->IWshEnvironment_iface, &This->classinfo);
535 *env = &This->IWshEnvironment_iface;
536
537 return S_OK;
538 }
539
WshCollection_QueryInterface(IWshCollection * iface,REFIID riid,void ** ppv)540 static HRESULT WINAPI WshCollection_QueryInterface(IWshCollection *iface, REFIID riid, void **ppv)
541 {
542 WshCollection *This = impl_from_IWshCollection(iface);
543
544 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
545
546 if (IsEqualGUID(riid, &IID_IUnknown) ||
547 IsEqualGUID(riid, &IID_IDispatch) ||
548 IsEqualGUID(riid, &IID_IWshCollection))
549 {
550 *ppv = iface;
551 }
552 else if (IsEqualIID(riid, &IID_IProvideClassInfo))
553 {
554 *ppv = &This->classinfo.IProvideClassInfo_iface;
555 }
556 else {
557 FIXME("Unknown iface %s\n", debugstr_guid(riid));
558 *ppv = NULL;
559 return E_NOINTERFACE;
560 }
561
562 IUnknown_AddRef((IUnknown*)*ppv);
563 return S_OK;
564 }
565
WshCollection_AddRef(IWshCollection * iface)566 static ULONG WINAPI WshCollection_AddRef(IWshCollection *iface)
567 {
568 WshCollection *This = impl_from_IWshCollection(iface);
569 LONG ref = InterlockedIncrement(&This->ref);
570 TRACE("(%p) ref = %d\n", This, ref);
571 return ref;
572 }
573
WshCollection_Release(IWshCollection * iface)574 static ULONG WINAPI WshCollection_Release(IWshCollection *iface)
575 {
576 WshCollection *This = impl_from_IWshCollection(iface);
577 LONG ref = InterlockedDecrement(&This->ref);
578 TRACE("(%p) ref = %d\n", This, ref);
579
580 if (!ref)
581 heap_free(This);
582
583 return ref;
584 }
585
WshCollection_GetTypeInfoCount(IWshCollection * iface,UINT * pctinfo)586 static HRESULT WINAPI WshCollection_GetTypeInfoCount(IWshCollection *iface, UINT *pctinfo)
587 {
588 WshCollection *This = impl_from_IWshCollection(iface);
589 TRACE("(%p)->(%p)\n", This, pctinfo);
590 *pctinfo = 1;
591 return S_OK;
592 }
593
WshCollection_GetTypeInfo(IWshCollection * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)594 static HRESULT WINAPI WshCollection_GetTypeInfo(IWshCollection *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
595 {
596 WshCollection *This = impl_from_IWshCollection(iface);
597 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
598 return get_typeinfo(IWshCollection_tid, ppTInfo);
599 }
600
WshCollection_GetIDsOfNames(IWshCollection * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)601 static HRESULT WINAPI WshCollection_GetIDsOfNames(IWshCollection *iface, REFIID riid, LPOLESTR *rgszNames,
602 UINT cNames, LCID lcid, DISPID *rgDispId)
603 {
604 WshCollection *This = impl_from_IWshCollection(iface);
605 ITypeInfo *typeinfo;
606 HRESULT hr;
607
608 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
609
610 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
611 if(SUCCEEDED(hr))
612 {
613 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
614 ITypeInfo_Release(typeinfo);
615 }
616
617 return hr;
618 }
619
WshCollection_Invoke(IWshCollection * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)620 static HRESULT WINAPI WshCollection_Invoke(IWshCollection *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
621 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
622 {
623 WshCollection *This = impl_from_IWshCollection(iface);
624 ITypeInfo *typeinfo;
625 HRESULT hr;
626
627 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
628 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
629
630 hr = get_typeinfo(IWshCollection_tid, &typeinfo);
631 if(SUCCEEDED(hr))
632 {
633 hr = ITypeInfo_Invoke(typeinfo, &This->IWshCollection_iface, dispIdMember, wFlags,
634 pDispParams, pVarResult, pExcepInfo, puArgErr);
635 ITypeInfo_Release(typeinfo);
636 }
637
638 return hr;
639 }
640
WshCollection_Item(IWshCollection * iface,VARIANT * index,VARIANT * value)641 static HRESULT WINAPI WshCollection_Item(IWshCollection *iface, VARIANT *index, VARIANT *value)
642 {
643 WshCollection *This = impl_from_IWshCollection(iface);
644 static const WCHAR allusersdesktopW[] = {'A','l','l','U','s','e','r','s','D','e','s','k','t','o','p',0};
645 static const WCHAR allusersprogramsW[] = {'A','l','l','U','s','e','r','s','P','r','o','g','r','a','m','s',0};
646 static const WCHAR desktopW[] = {'D','e','s','k','t','o','p',0};
647 PIDLIST_ABSOLUTE pidl;
648 WCHAR pathW[MAX_PATH];
649 int kind = 0;
650 BSTR folder;
651 HRESULT hr;
652
653 TRACE("(%p)->(%s %p)\n", This, debugstr_variant(index), value);
654
655 if (V_VT(index) != VT_BSTR)
656 {
657 FIXME("only BSTR index supported, got %d\n", V_VT(index));
658 return E_NOTIMPL;
659 }
660
661 folder = V_BSTR(index);
662 if (!wcsicmp(folder, desktopW))
663 kind = CSIDL_DESKTOP;
664 else if (!wcsicmp(folder, allusersdesktopW))
665 kind = CSIDL_COMMON_DESKTOPDIRECTORY;
666 else if (!wcsicmp(folder, allusersprogramsW))
667 kind = CSIDL_COMMON_PROGRAMS;
668 else
669 {
670 FIXME("folder kind %s not supported\n", debugstr_w(folder));
671 return E_NOTIMPL;
672 }
673
674 hr = SHGetSpecialFolderLocation(NULL, kind, &pidl);
675 if (hr != S_OK) return hr;
676
677 if (SHGetPathFromIDListW(pidl, pathW))
678 {
679 V_VT(value) = VT_BSTR;
680 V_BSTR(value) = SysAllocString(pathW);
681 hr = V_BSTR(value) ? S_OK : E_OUTOFMEMORY;
682 }
683 else
684 hr = E_FAIL;
685
686 CoTaskMemFree(pidl);
687
688 return hr;
689 }
690
WshCollection_Count(IWshCollection * iface,LONG * count)691 static HRESULT WINAPI WshCollection_Count(IWshCollection *iface, LONG *count)
692 {
693 WshCollection *This = impl_from_IWshCollection(iface);
694 FIXME("(%p)->(%p): stub\n", This, count);
695 return E_NOTIMPL;
696 }
697
WshCollection_get_length(IWshCollection * iface,LONG * count)698 static HRESULT WINAPI WshCollection_get_length(IWshCollection *iface, LONG *count)
699 {
700 WshCollection *This = impl_from_IWshCollection(iface);
701 FIXME("(%p)->(%p): stub\n", This, count);
702 return E_NOTIMPL;
703 }
704
WshCollection__NewEnum(IWshCollection * iface,IUnknown ** Enum)705 static HRESULT WINAPI WshCollection__NewEnum(IWshCollection *iface, IUnknown **Enum)
706 {
707 WshCollection *This = impl_from_IWshCollection(iface);
708 FIXME("(%p)->(%p): stub\n", This, Enum);
709 return E_NOTIMPL;
710 }
711
712 static const IWshCollectionVtbl WshCollectionVtbl = {
713 WshCollection_QueryInterface,
714 WshCollection_AddRef,
715 WshCollection_Release,
716 WshCollection_GetTypeInfoCount,
717 WshCollection_GetTypeInfo,
718 WshCollection_GetIDsOfNames,
719 WshCollection_Invoke,
720 WshCollection_Item,
721 WshCollection_Count,
722 WshCollection_get_length,
723 WshCollection__NewEnum
724 };
725
WshCollection_Create(IWshCollection ** collection)726 static HRESULT WshCollection_Create(IWshCollection **collection)
727 {
728 WshCollection *This;
729
730 This = heap_alloc(sizeof(*This));
731 if (!This) return E_OUTOFMEMORY;
732
733 This->IWshCollection_iface.lpVtbl = &WshCollectionVtbl;
734 This->ref = 1;
735
736 init_classinfo(&IID_IWshCollection, (IUnknown *)&This->IWshCollection_iface, &This->classinfo);
737 *collection = &This->IWshCollection_iface;
738
739 return S_OK;
740 }
741
742 /* IWshShortcut */
WshShortcut_QueryInterface(IWshShortcut * iface,REFIID riid,void ** ppv)743 static HRESULT WINAPI WshShortcut_QueryInterface(IWshShortcut *iface, REFIID riid, void **ppv)
744 {
745 WshShortcut *This = impl_from_IWshShortcut(iface);
746
747 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
748
749 if (IsEqualGUID(riid, &IID_IUnknown) ||
750 IsEqualGUID(riid, &IID_IDispatch) ||
751 IsEqualGUID(riid, &IID_IWshShortcut))
752 {
753 *ppv = iface;
754 }
755 else if (IsEqualIID(riid, &IID_IProvideClassInfo))
756 {
757 *ppv = &This->classinfo.IProvideClassInfo_iface;
758 }
759 else {
760 FIXME("Unknown iface %s\n", debugstr_guid(riid));
761 *ppv = NULL;
762 return E_NOINTERFACE;
763 }
764
765 IUnknown_AddRef((IUnknown*)*ppv);
766 return S_OK;
767 }
768
WshShortcut_AddRef(IWshShortcut * iface)769 static ULONG WINAPI WshShortcut_AddRef(IWshShortcut *iface)
770 {
771 WshShortcut *This = impl_from_IWshShortcut(iface);
772 LONG ref = InterlockedIncrement(&This->ref);
773 TRACE("(%p) ref = %d\n", This, ref);
774 return ref;
775 }
776
WshShortcut_Release(IWshShortcut * iface)777 static ULONG WINAPI WshShortcut_Release(IWshShortcut *iface)
778 {
779 WshShortcut *This = impl_from_IWshShortcut(iface);
780 LONG ref = InterlockedDecrement(&This->ref);
781 TRACE("(%p) ref = %d\n", This, ref);
782
783 if (!ref)
784 {
785 SysFreeString(This->path_link);
786 IShellLinkW_Release(This->link);
787 heap_free(This);
788 }
789
790 return ref;
791 }
792
WshShortcut_GetTypeInfoCount(IWshShortcut * iface,UINT * pctinfo)793 static HRESULT WINAPI WshShortcut_GetTypeInfoCount(IWshShortcut *iface, UINT *pctinfo)
794 {
795 WshShortcut *This = impl_from_IWshShortcut(iface);
796 TRACE("(%p)->(%p)\n", This, pctinfo);
797 *pctinfo = 1;
798 return S_OK;
799 }
800
WshShortcut_GetTypeInfo(IWshShortcut * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)801 static HRESULT WINAPI WshShortcut_GetTypeInfo(IWshShortcut *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
802 {
803 WshShortcut *This = impl_from_IWshShortcut(iface);
804 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
805 return get_typeinfo(IWshShortcut_tid, ppTInfo);
806 }
807
WshShortcut_GetIDsOfNames(IWshShortcut * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)808 static HRESULT WINAPI WshShortcut_GetIDsOfNames(IWshShortcut *iface, REFIID riid, LPOLESTR *rgszNames,
809 UINT cNames, LCID lcid, DISPID *rgDispId)
810 {
811 WshShortcut *This = impl_from_IWshShortcut(iface);
812 ITypeInfo *typeinfo;
813 HRESULT hr;
814
815 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
816
817 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
818 if(SUCCEEDED(hr))
819 {
820 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
821 ITypeInfo_Release(typeinfo);
822 }
823
824 return hr;
825 }
826
WshShortcut_Invoke(IWshShortcut * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)827 static HRESULT WINAPI WshShortcut_Invoke(IWshShortcut *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
828 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
829 {
830 WshShortcut *This = impl_from_IWshShortcut(iface);
831 ITypeInfo *typeinfo;
832 HRESULT hr;
833
834 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
835 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
836
837 hr = get_typeinfo(IWshShortcut_tid, &typeinfo);
838 if(SUCCEEDED(hr))
839 {
840 hr = ITypeInfo_Invoke(typeinfo, &This->IWshShortcut_iface, dispIdMember, wFlags,
841 pDispParams, pVarResult, pExcepInfo, puArgErr);
842 ITypeInfo_Release(typeinfo);
843 }
844
845 return hr;
846 }
847
WshShortcut_get_FullName(IWshShortcut * iface,BSTR * name)848 static HRESULT WINAPI WshShortcut_get_FullName(IWshShortcut *iface, BSTR *name)
849 {
850 WshShortcut *This = impl_from_IWshShortcut(iface);
851 FIXME("(%p)->(%p): stub\n", This, name);
852 return E_NOTIMPL;
853 }
854
WshShortcut_get_Arguments(IWshShortcut * iface,BSTR * Arguments)855 static HRESULT WINAPI WshShortcut_get_Arguments(IWshShortcut *iface, BSTR *Arguments)
856 {
857 WshShortcut *This = impl_from_IWshShortcut(iface);
858 WCHAR buffW[INFOTIPSIZE];
859 HRESULT hr;
860
861 TRACE("(%p)->(%p)\n", This, Arguments);
862
863 if (!Arguments)
864 return E_POINTER;
865
866 *Arguments = NULL;
867
868 hr = IShellLinkW_GetArguments(This->link, buffW, ARRAY_SIZE(buffW));
869 if (FAILED(hr))
870 return hr;
871
872 *Arguments = SysAllocString(buffW);
873 return *Arguments ? S_OK : E_OUTOFMEMORY;
874 }
875
WshShortcut_put_Arguments(IWshShortcut * iface,BSTR Arguments)876 static HRESULT WINAPI WshShortcut_put_Arguments(IWshShortcut *iface, BSTR Arguments)
877 {
878 WshShortcut *This = impl_from_IWshShortcut(iface);
879
880 TRACE("(%p)->(%s)\n", This, debugstr_w(Arguments));
881
882 return IShellLinkW_SetArguments(This->link, Arguments);
883 }
884
WshShortcut_get_Description(IWshShortcut * iface,BSTR * Description)885 static HRESULT WINAPI WshShortcut_get_Description(IWshShortcut *iface, BSTR *Description)
886 {
887 WshShortcut *This = impl_from_IWshShortcut(iface);
888 FIXME("(%p)->(%p): stub\n", This, Description);
889 return E_NOTIMPL;
890 }
891
WshShortcut_put_Description(IWshShortcut * iface,BSTR Description)892 static HRESULT WINAPI WshShortcut_put_Description(IWshShortcut *iface, BSTR Description)
893 {
894 WshShortcut *This = impl_from_IWshShortcut(iface);
895 TRACE("(%p)->(%s)\n", This, debugstr_w(Description));
896 return IShellLinkW_SetDescription(This->link, Description);
897 }
898
WshShortcut_get_Hotkey(IWshShortcut * iface,BSTR * Hotkey)899 static HRESULT WINAPI WshShortcut_get_Hotkey(IWshShortcut *iface, BSTR *Hotkey)
900 {
901 WshShortcut *This = impl_from_IWshShortcut(iface);
902 FIXME("(%p)->(%p): stub\n", This, Hotkey);
903 return E_NOTIMPL;
904 }
905
WshShortcut_put_Hotkey(IWshShortcut * iface,BSTR Hotkey)906 static HRESULT WINAPI WshShortcut_put_Hotkey(IWshShortcut *iface, BSTR Hotkey)
907 {
908 WshShortcut *This = impl_from_IWshShortcut(iface);
909 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Hotkey));
910 return E_NOTIMPL;
911 }
912
WshShortcut_get_IconLocation(IWshShortcut * iface,BSTR * IconPath)913 static HRESULT WINAPI WshShortcut_get_IconLocation(IWshShortcut *iface, BSTR *IconPath)
914 {
915 static const WCHAR fmtW[] = {'%','s',',',' ','%','d',0};
916 WshShortcut *This = impl_from_IWshShortcut(iface);
917 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
918 INT icon = 0;
919 HRESULT hr;
920
921 TRACE("(%p)->(%p)\n", This, IconPath);
922
923 if (!IconPath)
924 return E_POINTER;
925
926 hr = IShellLinkW_GetIconLocation(This->link, buffW, ARRAY_SIZE(buffW), &icon);
927 if (FAILED(hr)) return hr;
928
929 swprintf(pathW, fmtW, buffW, icon);
930 *IconPath = SysAllocString(pathW);
931 if (!*IconPath) return E_OUTOFMEMORY;
932
933 return S_OK;
934 }
935
WshShortcut_put_IconLocation(IWshShortcut * iface,BSTR IconPath)936 static HRESULT WINAPI WshShortcut_put_IconLocation(IWshShortcut *iface, BSTR IconPath)
937 {
938 WshShortcut *This = impl_from_IWshShortcut(iface);
939 HRESULT hr;
940 WCHAR *ptr;
941 BSTR path;
942 INT icon;
943
944 TRACE("(%p)->(%s)\n", This, debugstr_w(IconPath));
945
946 /* scan for icon id */
947 ptr = wcsrchr(IconPath, ',');
948 if (!ptr)
949 {
950 WARN("icon index not found\n");
951 return E_FAIL;
952 }
953
954 path = SysAllocStringLen(IconPath, ptr-IconPath);
955
956 /* skip spaces if any */
957 while (iswspace(*++ptr))
958 ;
959
960 icon = wcstol(ptr, NULL, 10);
961
962 hr = IShellLinkW_SetIconLocation(This->link, path, icon);
963 SysFreeString(path);
964
965 return hr;
966 }
967
WshShortcut_put_RelativePath(IWshShortcut * iface,BSTR rhs)968 static HRESULT WINAPI WshShortcut_put_RelativePath(IWshShortcut *iface, BSTR rhs)
969 {
970 WshShortcut *This = impl_from_IWshShortcut(iface);
971 FIXME("(%p)->(%s): stub\n", This, debugstr_w(rhs));
972 return E_NOTIMPL;
973 }
974
WshShortcut_get_TargetPath(IWshShortcut * iface,BSTR * Path)975 static HRESULT WINAPI WshShortcut_get_TargetPath(IWshShortcut *iface, BSTR *Path)
976 {
977 WshShortcut *This = impl_from_IWshShortcut(iface);
978 FIXME("(%p)->(%p): stub\n", This, Path);
979 return E_NOTIMPL;
980 }
981
WshShortcut_put_TargetPath(IWshShortcut * iface,BSTR Path)982 static HRESULT WINAPI WshShortcut_put_TargetPath(IWshShortcut *iface, BSTR Path)
983 {
984 WshShortcut *This = impl_from_IWshShortcut(iface);
985 TRACE("(%p)->(%s)\n", This, debugstr_w(Path));
986 return IShellLinkW_SetPath(This->link, Path);
987 }
988
WshShortcut_get_WindowStyle(IWshShortcut * iface,int * ShowCmd)989 static HRESULT WINAPI WshShortcut_get_WindowStyle(IWshShortcut *iface, int *ShowCmd)
990 {
991 WshShortcut *This = impl_from_IWshShortcut(iface);
992 TRACE("(%p)->(%p)\n", This, ShowCmd);
993 return IShellLinkW_GetShowCmd(This->link, ShowCmd);
994 }
995
WshShortcut_put_WindowStyle(IWshShortcut * iface,int ShowCmd)996 static HRESULT WINAPI WshShortcut_put_WindowStyle(IWshShortcut *iface, int ShowCmd)
997 {
998 WshShortcut *This = impl_from_IWshShortcut(iface);
999 TRACE("(%p)->(%d)\n", This, ShowCmd);
1000 return IShellLinkW_SetShowCmd(This->link, ShowCmd);
1001 }
1002
WshShortcut_get_WorkingDirectory(IWshShortcut * iface,BSTR * WorkingDirectory)1003 static HRESULT WINAPI WshShortcut_get_WorkingDirectory(IWshShortcut *iface, BSTR *WorkingDirectory)
1004 {
1005 WshShortcut *This = impl_from_IWshShortcut(iface);
1006 WCHAR buffW[MAX_PATH];
1007 HRESULT hr;
1008
1009 TRACE("(%p)->(%p)\n", This, WorkingDirectory);
1010
1011 if (!WorkingDirectory)
1012 return E_POINTER;
1013
1014 *WorkingDirectory = NULL;
1015 hr = IShellLinkW_GetWorkingDirectory(This->link, buffW, ARRAY_SIZE(buffW));
1016 if (FAILED(hr)) return hr;
1017
1018 *WorkingDirectory = SysAllocString(buffW);
1019 return *WorkingDirectory ? S_OK : E_OUTOFMEMORY;
1020 }
1021
WshShortcut_put_WorkingDirectory(IWshShortcut * iface,BSTR WorkingDirectory)1022 static HRESULT WINAPI WshShortcut_put_WorkingDirectory(IWshShortcut *iface, BSTR WorkingDirectory)
1023 {
1024 WshShortcut *This = impl_from_IWshShortcut(iface);
1025 TRACE("(%p)->(%s)\n", This, debugstr_w(WorkingDirectory));
1026 return IShellLinkW_SetWorkingDirectory(This->link, WorkingDirectory);
1027 }
1028
WshShortcut_Load(IWshShortcut * iface,BSTR PathLink)1029 static HRESULT WINAPI WshShortcut_Load(IWshShortcut *iface, BSTR PathLink)
1030 {
1031 WshShortcut *This = impl_from_IWshShortcut(iface);
1032 FIXME("(%p)->(%s): stub\n", This, debugstr_w(PathLink));
1033 return E_NOTIMPL;
1034 }
1035
WshShortcut_Save(IWshShortcut * iface)1036 static HRESULT WINAPI WshShortcut_Save(IWshShortcut *iface)
1037 {
1038 WshShortcut *This = impl_from_IWshShortcut(iface);
1039 IPersistFile *file;
1040 HRESULT hr;
1041
1042 TRACE("(%p)\n", This);
1043
1044 IShellLinkW_QueryInterface(This->link, &IID_IPersistFile, (void**)&file);
1045 hr = IPersistFile_Save(file, This->path_link, TRUE);
1046 IPersistFile_Release(file);
1047
1048 return hr;
1049 }
1050
1051 static const IWshShortcutVtbl WshShortcutVtbl = {
1052 WshShortcut_QueryInterface,
1053 WshShortcut_AddRef,
1054 WshShortcut_Release,
1055 WshShortcut_GetTypeInfoCount,
1056 WshShortcut_GetTypeInfo,
1057 WshShortcut_GetIDsOfNames,
1058 WshShortcut_Invoke,
1059 WshShortcut_get_FullName,
1060 WshShortcut_get_Arguments,
1061 WshShortcut_put_Arguments,
1062 WshShortcut_get_Description,
1063 WshShortcut_put_Description,
1064 WshShortcut_get_Hotkey,
1065 WshShortcut_put_Hotkey,
1066 WshShortcut_get_IconLocation,
1067 WshShortcut_put_IconLocation,
1068 WshShortcut_put_RelativePath,
1069 WshShortcut_get_TargetPath,
1070 WshShortcut_put_TargetPath,
1071 WshShortcut_get_WindowStyle,
1072 WshShortcut_put_WindowStyle,
1073 WshShortcut_get_WorkingDirectory,
1074 WshShortcut_put_WorkingDirectory,
1075 WshShortcut_Load,
1076 WshShortcut_Save
1077 };
1078
WshShortcut_Create(const WCHAR * path,IDispatch ** shortcut)1079 static HRESULT WshShortcut_Create(const WCHAR *path, IDispatch **shortcut)
1080 {
1081 WshShortcut *This;
1082 HRESULT hr;
1083
1084 *shortcut = NULL;
1085
1086 This = heap_alloc(sizeof(*This));
1087 if (!This) return E_OUTOFMEMORY;
1088
1089 This->IWshShortcut_iface.lpVtbl = &WshShortcutVtbl;
1090 This->ref = 1;
1091
1092 hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
1093 &IID_IShellLinkW, (void**)&This->link);
1094 if (FAILED(hr))
1095 {
1096 heap_free(This);
1097 return hr;
1098 }
1099
1100 This->path_link = SysAllocString(path);
1101 if (!This->path_link)
1102 {
1103 IShellLinkW_Release(This->link);
1104 heap_free(This);
1105 return E_OUTOFMEMORY;
1106 }
1107
1108 init_classinfo(&IID_IWshShortcut, (IUnknown *)&This->IWshShortcut_iface, &This->classinfo);
1109 *shortcut = (IDispatch*)&This->IWshShortcut_iface;
1110
1111 return S_OK;
1112 }
1113
WshShell3_QueryInterface(IWshShell3 * iface,REFIID riid,void ** ppv)1114 static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
1115 {
1116 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1117
1118 *ppv = NULL;
1119
1120 if (IsEqualGUID(riid, &IID_IDispatch) ||
1121 IsEqualGUID(riid, &IID_IWshShell3) ||
1122 IsEqualGUID(riid, &IID_IWshShell2) ||
1123 IsEqualGUID(riid, &IID_IWshShell) ||
1124 IsEqualGUID(riid, &IID_IUnknown))
1125 {
1126 *ppv = iface;
1127 }
1128 else if (IsEqualGUID(riid, &IID_IDispatchEx))
1129 {
1130 return E_NOINTERFACE;
1131 }
1132 else if (IsEqualIID(riid, &IID_IProvideClassInfo))
1133 {
1134 *ppv = &WshShell3.classinfo.IProvideClassInfo_iface;
1135 }
1136 else
1137 {
1138 WARN("unknown iface %s\n", debugstr_guid(riid));
1139 return E_NOINTERFACE;
1140 }
1141
1142 IUnknown_AddRef((IUnknown *)*ppv);
1143 return S_OK;
1144 }
1145
WshShell3_AddRef(IWshShell3 * iface)1146 static ULONG WINAPI WshShell3_AddRef(IWshShell3 *iface)
1147 {
1148 TRACE("()\n");
1149 return 2;
1150 }
1151
WshShell3_Release(IWshShell3 * iface)1152 static ULONG WINAPI WshShell3_Release(IWshShell3 *iface)
1153 {
1154 TRACE("()\n");
1155 return 2;
1156 }
1157
WshShell3_GetTypeInfoCount(IWshShell3 * iface,UINT * pctinfo)1158 static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinfo)
1159 {
1160 TRACE("(%p)\n", pctinfo);
1161 *pctinfo = 1;
1162 return S_OK;
1163 }
1164
WshShell3_GetTypeInfo(IWshShell3 * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)1165 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1166 {
1167 TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
1168 return get_typeinfo(IWshShell3_tid, ppTInfo);
1169 }
1170
WshShell3_GetIDsOfNames(IWshShell3 * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)1171 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
1172 UINT cNames, LCID lcid, DISPID *rgDispId)
1173 {
1174 ITypeInfo *typeinfo;
1175 HRESULT hr;
1176
1177 TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
1178
1179 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
1180 if(SUCCEEDED(hr))
1181 {
1182 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1183 ITypeInfo_Release(typeinfo);
1184 }
1185
1186 return hr;
1187 }
1188
WshShell3_Invoke(IWshShell3 * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)1189 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1190 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1191 {
1192 ITypeInfo *typeinfo;
1193 HRESULT hr;
1194
1195 TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
1196 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1197
1198 hr = get_typeinfo(IWshShell3_tid, &typeinfo);
1199 if(SUCCEEDED(hr))
1200 {
1201 hr = ITypeInfo_Invoke(typeinfo, &WshShell3.IWshShell3_iface, dispIdMember, wFlags,
1202 pDispParams, pVarResult, pExcepInfo, puArgErr);
1203 ITypeInfo_Release(typeinfo);
1204 }
1205
1206 return hr;
1207 }
1208
WshShell3_get_SpecialFolders(IWshShell3 * iface,IWshCollection ** folders)1209 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **folders)
1210 {
1211 TRACE("(%p)\n", folders);
1212 return WshCollection_Create(folders);
1213 }
1214
WshShell3_get_Environment(IWshShell3 * iface,VARIANT * type,IWshEnvironment ** env)1215 static HRESULT WINAPI WshShell3_get_Environment(IWshShell3 *iface, VARIANT *type, IWshEnvironment **env)
1216 {
1217 FIXME("(%s %p): semi-stub\n", debugstr_variant(type), env);
1218 return WshEnvironment_Create(env);
1219 }
1220
is_optional_argument(const VARIANT * arg)1221 static inline BOOL is_optional_argument(const VARIANT *arg)
1222 {
1223 return V_VT(arg) == VT_ERROR && V_ERROR(arg) == DISP_E_PARAMNOTFOUND;
1224 }
1225
split_command(BSTR cmd,WCHAR ** params)1226 static WCHAR *split_command( BSTR cmd, WCHAR **params )
1227 {
1228 WCHAR *ret, *ptr;
1229 BOOL in_quotes = FALSE;
1230
1231 if (!(ret = heap_alloc((lstrlenW(cmd) + 1) * sizeof(WCHAR)))) return NULL;
1232 lstrcpyW( ret, cmd );
1233
1234 *params = NULL;
1235 for (ptr = ret; *ptr; ptr++)
1236 {
1237 if (*ptr == '"') in_quotes = !in_quotes;
1238 else if (*ptr == ' ' && !in_quotes)
1239 {
1240 *ptr = 0;
1241 *params = ptr + 1;
1242 break;
1243 }
1244 }
1245
1246 return ret;
1247 }
1248
WshShell3_Run(IWshShell3 * iface,BSTR cmd,VARIANT * style,VARIANT * wait,DWORD * exit_code)1249 static HRESULT WINAPI WshShell3_Run(IWshShell3 *iface, BSTR cmd, VARIANT *style, VARIANT *wait, DWORD *exit_code)
1250 {
1251 SHELLEXECUTEINFOW info;
1252 int waitforprocess;
1253 WCHAR *file, *params;
1254 VARIANT s;
1255 HRESULT hr;
1256 BOOL ret;
1257
1258 TRACE("(%s %s %s %p)\n", debugstr_w(cmd), debugstr_variant(style), debugstr_variant(wait), exit_code);
1259
1260 if (!style || !wait || !exit_code)
1261 return E_POINTER;
1262
1263 VariantInit(&s);
1264 #ifdef __REACTOS__
1265 if (is_optional_argument(style))
1266 {
1267 V_VT(&s) = VT_I4;
1268 V_I4(&s) = SW_SHOW;
1269 hr = S_OK;
1270 }
1271 else
1272 #endif
1273 hr = VariantChangeType(&s, style, 0, VT_I4);
1274 if (FAILED(hr))
1275 {
1276 ERR("failed to convert style argument, 0x%08x\n", hr);
1277 return hr;
1278 }
1279
1280 if (is_optional_argument(wait))
1281 waitforprocess = 0;
1282 else {
1283 VARIANT w;
1284
1285 VariantInit(&w);
1286 hr = VariantChangeType(&w, wait, 0, VT_I4);
1287 if (FAILED(hr))
1288 return hr;
1289
1290 waitforprocess = V_I4(&w);
1291 }
1292
1293 if (!(file = split_command(cmd, ¶ms))) return E_OUTOFMEMORY;
1294
1295 memset(&info, 0, sizeof(info));
1296 info.cbSize = sizeof(info);
1297 info.fMask = waitforprocess ? SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
1298 info.lpFile = file;
1299 info.lpParameters = params;
1300 info.nShow = V_I4(&s);
1301
1302 ret = ShellExecuteExW(&info);
1303 heap_free( file );
1304 if (!ret)
1305 {
1306 TRACE("ShellExecute failed, %d\n", GetLastError());
1307 return HRESULT_FROM_WIN32(GetLastError());
1308 }
1309 else
1310 {
1311 if (waitforprocess)
1312 {
1313 WaitForSingleObject(info.hProcess, INFINITE);
1314 GetExitCodeProcess(info.hProcess, exit_code);
1315 CloseHandle(info.hProcess);
1316 }
1317 else
1318 *exit_code = 0;
1319
1320 return S_OK;
1321 }
1322 }
1323
1324 struct popup_thread_param
1325 {
1326 WCHAR *text;
1327 VARIANT title;
1328 VARIANT type;
1329 INT button;
1330 };
1331
popup_thread_proc(void * arg)1332 static DWORD WINAPI popup_thread_proc(void *arg)
1333 {
1334 static const WCHAR defaulttitleW[] = {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0};
1335 struct popup_thread_param *param = (struct popup_thread_param *)arg;
1336
1337 param->button = MessageBoxW(NULL, param->text, is_optional_argument(¶m->title) ?
1338 defaulttitleW : V_BSTR(¶m->title), V_I4(¶m->type));
1339 return 0;
1340 }
1341
WshShell3_Popup(IWshShell3 * iface,BSTR text,VARIANT * seconds_to_wait,VARIANT * title,VARIANT * type,int * button)1342 static HRESULT WINAPI WshShell3_Popup(IWshShell3 *iface, BSTR text, VARIANT *seconds_to_wait, VARIANT *title,
1343 VARIANT *type, int *button)
1344 {
1345 struct popup_thread_param param;
1346 DWORD tid, status;
1347 VARIANT timeout;
1348 HANDLE hthread;
1349 HRESULT hr;
1350
1351 TRACE("(%s %s %s %s %p)\n", debugstr_w(text), debugstr_variant(seconds_to_wait), debugstr_variant(title),
1352 debugstr_variant(type), button);
1353
1354 if (!seconds_to_wait || !title || !type || !button)
1355 return E_POINTER;
1356
1357 VariantInit(&timeout);
1358 if (!is_optional_argument(seconds_to_wait))
1359 {
1360 hr = VariantChangeType(&timeout, seconds_to_wait, 0, VT_I4);
1361 if (FAILED(hr))
1362 return hr;
1363 }
1364 #ifdef __REACTOS__
1365 else
1366 {
1367 VariantChangeType(&timeout, &timeout, 0, VT_I4);
1368 }
1369 #endif
1370
1371 VariantInit(¶m.type);
1372 if (!is_optional_argument(type))
1373 {
1374 hr = VariantChangeType(¶m.type, type, 0, VT_I4);
1375 if (FAILED(hr))
1376 return hr;
1377 }
1378 #ifdef __REACTOS__
1379 else
1380 {
1381 VariantChangeType(¶m.type, ¶m.type, 0, VT_I4);
1382 }
1383 #endif
1384
1385 if (is_optional_argument(title))
1386 param.title = *title;
1387 else
1388 {
1389 VariantInit(¶m.title);
1390 hr = VariantChangeType(¶m.title, title, 0, VT_BSTR);
1391 if (FAILED(hr))
1392 return hr;
1393 }
1394
1395 param.text = text;
1396 param.button = -1;
1397 hthread = CreateThread(NULL, 0, popup_thread_proc, ¶m, 0, &tid);
1398 status = MsgWaitForMultipleObjects(1, &hthread, FALSE, V_I4(&timeout) ? V_I4(&timeout) * 1000: INFINITE, 0);
1399 if (status == WAIT_TIMEOUT)
1400 {
1401 PostThreadMessageW(tid, WM_QUIT, 0, 0);
1402 MsgWaitForMultipleObjects(1, &hthread, FALSE, INFINITE, 0);
1403 param.button = -1;
1404 }
1405 *button = param.button;
1406
1407 VariantClear(¶m.title);
1408 CloseHandle(hthread);
1409
1410 return S_OK;
1411 }
1412
WshShell3_CreateShortcut(IWshShell3 * iface,BSTR PathLink,IDispatch ** Shortcut)1413 static HRESULT WINAPI WshShell3_CreateShortcut(IWshShell3 *iface, BSTR PathLink, IDispatch** Shortcut)
1414 {
1415 TRACE("(%s %p)\n", debugstr_w(PathLink), Shortcut);
1416 return WshShortcut_Create(PathLink, Shortcut);
1417 }
1418
WshShell3_ExpandEnvironmentStrings(IWshShell3 * iface,BSTR Src,BSTR * Dst)1419 static HRESULT WINAPI WshShell3_ExpandEnvironmentStrings(IWshShell3 *iface, BSTR Src, BSTR* Dst)
1420 {
1421 DWORD ret;
1422
1423 TRACE("(%s %p)\n", debugstr_w(Src), Dst);
1424
1425 if (!Src || !Dst) return E_POINTER;
1426
1427 ret = ExpandEnvironmentStringsW(Src, NULL, 0);
1428 *Dst = SysAllocStringLen(NULL, ret);
1429 if (!*Dst) return E_OUTOFMEMORY;
1430
1431 if (ExpandEnvironmentStringsW(Src, *Dst, ret))
1432 return S_OK;
1433 else
1434 {
1435 SysFreeString(*Dst);
1436 *Dst = NULL;
1437 return HRESULT_FROM_WIN32(GetLastError());
1438 }
1439 }
1440
get_root_key(const WCHAR * path)1441 static HKEY get_root_key(const WCHAR *path)
1442 {
1443 static const struct {
1444 const WCHAR full[20];
1445 const WCHAR abbrev[5];
1446 HKEY hkey;
1447 } rootkeys[] = {
1448 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, {'H','K','C','U',0}, HKEY_CURRENT_USER },
1449 { {'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 },
1450 { {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, {'H','K','C','R',0}, HKEY_CLASSES_ROOT },
1451 { {'H','K','E','Y','_','U','S','E','R','S',0}, {0}, HKEY_USERS },
1452 { {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, {0}, HKEY_CURRENT_CONFIG }
1453 };
1454 int i;
1455
1456 for (i = 0; i < ARRAY_SIZE(rootkeys); i++) {
1457 if (!wcsncmp(path, rootkeys[i].full, lstrlenW(rootkeys[i].full)))
1458 return rootkeys[i].hkey;
1459 if (rootkeys[i].abbrev[0] && !wcsncmp(path, rootkeys[i].abbrev, lstrlenW(rootkeys[i].abbrev)))
1460 return rootkeys[i].hkey;
1461 }
1462
1463 return NULL;
1464 }
1465
1466 /* Caller is responsible to free 'subkey' if 'value' is not NULL */
split_reg_path(const WCHAR * path,WCHAR ** subkey,WCHAR ** value)1467 static HRESULT split_reg_path(const WCHAR *path, WCHAR **subkey, WCHAR **value)
1468 {
1469 *value = NULL;
1470
1471 /* at least one separator should be present */
1472 *subkey = wcschr(path, '\\');
1473 if (!*subkey)
1474 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1475
1476 /* default value or not */
1477 if ((*subkey)[lstrlenW(*subkey)-1] == '\\') {
1478 (*subkey)++;
1479 *value = NULL;
1480 }
1481 else {
1482 *value = wcsrchr(*subkey, '\\');
1483 if (*value - *subkey > 1) {
1484 unsigned int len = *value - *subkey - 1;
1485 WCHAR *ret;
1486
1487 ret = heap_alloc((len + 1)*sizeof(WCHAR));
1488 if (!ret)
1489 return E_OUTOFMEMORY;
1490
1491 memcpy(ret, *subkey + 1, len*sizeof(WCHAR));
1492 ret[len] = 0;
1493 *subkey = ret;
1494 }
1495 (*value)++;
1496 }
1497
1498 return S_OK;
1499 }
1500
WshShell3_RegRead(IWshShell3 * iface,BSTR name,VARIANT * value)1501 static HRESULT WINAPI WshShell3_RegRead(IWshShell3 *iface, BSTR name, VARIANT *value)
1502 {
1503 DWORD type, datalen, ret;
1504 WCHAR *subkey, *val;
1505 HRESULT hr;
1506 HKEY root;
1507
1508 TRACE("(%s %p)\n", debugstr_w(name), value);
1509
1510 if (!name || !value)
1511 return E_POINTER;
1512
1513 root = get_root_key(name);
1514 if (!root)
1515 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1516
1517 hr = split_reg_path(name, &subkey, &val);
1518 if (FAILED(hr))
1519 return hr;
1520
1521 type = REG_NONE;
1522 datalen = 0;
1523 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, NULL, &datalen);
1524 if (ret == ERROR_SUCCESS) {
1525 void *data;
1526
1527 data = heap_alloc(datalen);
1528 if (!data) {
1529 hr = E_OUTOFMEMORY;
1530 goto fail;
1531 }
1532
1533 ret = RegGetValueW(root, subkey, val, RRF_RT_ANY, &type, data, &datalen);
1534 if (ret) {
1535 heap_free(data);
1536 hr = HRESULT_FROM_WIN32(ret);
1537 goto fail;
1538 }
1539
1540 switch (type) {
1541 case REG_SZ:
1542 case REG_EXPAND_SZ:
1543 V_VT(value) = VT_BSTR;
1544 V_BSTR(value) = SysAllocString((WCHAR*)data);
1545 if (!V_BSTR(value))
1546 hr = E_OUTOFMEMORY;
1547 break;
1548 case REG_DWORD:
1549 V_VT(value) = VT_I4;
1550 V_I4(value) = *(DWORD*)data;
1551 break;
1552 case REG_BINARY:
1553 {
1554 BYTE *ptr = (BYTE*)data;
1555 SAFEARRAYBOUND bound;
1556 unsigned int i;
1557 SAFEARRAY *sa;
1558 VARIANT *v;
1559
1560 bound.lLbound = 0;
1561 bound.cElements = datalen;
1562 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1563 if (!sa)
1564 break;
1565
1566 hr = SafeArrayAccessData(sa, (void**)&v);
1567 if (FAILED(hr)) {
1568 SafeArrayDestroy(sa);
1569 break;
1570 }
1571
1572 for (i = 0; i < datalen; i++) {
1573 V_VT(&v[i]) = VT_UI1;
1574 V_UI1(&v[i]) = ptr[i];
1575 }
1576 SafeArrayUnaccessData(sa);
1577
1578 V_VT(value) = VT_ARRAY|VT_VARIANT;
1579 V_ARRAY(value) = sa;
1580 break;
1581 }
1582 case REG_MULTI_SZ:
1583 {
1584 WCHAR *ptr = (WCHAR*)data;
1585 SAFEARRAYBOUND bound;
1586 SAFEARRAY *sa;
1587 VARIANT *v;
1588
1589 /* get element count first */
1590 bound.lLbound = 0;
1591 bound.cElements = 0;
1592 while (*ptr) {
1593 bound.cElements++;
1594 ptr += lstrlenW(ptr)+1;
1595 }
1596
1597 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1598 if (!sa)
1599 break;
1600
1601 hr = SafeArrayAccessData(sa, (void**)&v);
1602 if (FAILED(hr)) {
1603 SafeArrayDestroy(sa);
1604 break;
1605 }
1606
1607 ptr = (WCHAR*)data;
1608 while (*ptr) {
1609 V_VT(v) = VT_BSTR;
1610 V_BSTR(v) = SysAllocString(ptr);
1611 ptr += lstrlenW(ptr)+1;
1612 v++;
1613 }
1614
1615 SafeArrayUnaccessData(sa);
1616 V_VT(value) = VT_ARRAY|VT_VARIANT;
1617 V_ARRAY(value) = sa;
1618 break;
1619 }
1620 default:
1621 FIXME("value type %d not supported\n", type);
1622 hr = E_FAIL;
1623 };
1624
1625 heap_free(data);
1626 if (FAILED(hr))
1627 VariantInit(value);
1628 }
1629 else
1630 hr = HRESULT_FROM_WIN32(ret);
1631
1632 fail:
1633 if (val)
1634 heap_free(subkey);
1635 return hr;
1636 }
1637
WshShell3_RegWrite(IWshShell3 * iface,BSTR name,VARIANT * value,VARIANT * type)1638 static HRESULT WINAPI WshShell3_RegWrite(IWshShell3 *iface, BSTR name, VARIANT *value, VARIANT *type)
1639 {
1640 static const WCHAR regexpandszW[] = {'R','E','G','_','E','X','P','A','N','D','_','S','Z',0};
1641 static const WCHAR regszW[] = {'R','E','G','_','S','Z',0};
1642 static const WCHAR regdwordW[] = {'R','E','G','_','D','W','O','R','D',0};
1643 static const WCHAR regbinaryW[] = {'R','E','G','_','B','I','N','A','R','Y',0};
1644
1645 DWORD regtype, data_len;
1646 WCHAR *subkey, *val;
1647 const BYTE *data;
1648 HRESULT hr;
1649 HKEY root;
1650 VARIANT v;
1651 LONG ret;
1652
1653 TRACE("(%s %s %s)\n", debugstr_w(name), debugstr_variant(value), debugstr_variant(type));
1654
1655 if (!name || !value || !type)
1656 return E_POINTER;
1657
1658 root = get_root_key(name);
1659 if (!root)
1660 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
1661
1662 /* value type */
1663 if (is_optional_argument(type))
1664 regtype = REG_SZ;
1665 else {
1666 if (V_VT(type) != VT_BSTR)
1667 return E_INVALIDARG;
1668
1669 if (!wcscmp(V_BSTR(type), regszW))
1670 regtype = REG_SZ;
1671 else if (!wcscmp(V_BSTR(type), regdwordW))
1672 regtype = REG_DWORD;
1673 else if (!wcscmp(V_BSTR(type), regexpandszW))
1674 regtype = REG_EXPAND_SZ;
1675 else if (!wcscmp(V_BSTR(type), regbinaryW))
1676 regtype = REG_BINARY;
1677 else {
1678 FIXME("unrecognized value type %s\n", debugstr_w(V_BSTR(type)));
1679 return E_FAIL;
1680 }
1681 }
1682
1683 /* it's always a string or a DWORD */
1684 VariantInit(&v);
1685 switch (regtype)
1686 {
1687 case REG_SZ:
1688 case REG_EXPAND_SZ:
1689 hr = VariantChangeType(&v, value, 0, VT_BSTR);
1690 if (hr == S_OK) {
1691 data = (BYTE*)V_BSTR(&v);
1692 data_len = SysStringByteLen(V_BSTR(&v)) + sizeof(WCHAR);
1693 }
1694 break;
1695 case REG_DWORD:
1696 case REG_BINARY:
1697 hr = VariantChangeType(&v, value, 0, VT_I4);
1698 data = (BYTE*)&V_I4(&v);
1699 data_len = sizeof(DWORD);
1700 break;
1701 default:
1702 FIXME("unexpected regtype %d\n", regtype);
1703 return E_FAIL;
1704 };
1705
1706 if (FAILED(hr)) {
1707 FIXME("failed to convert value, regtype %d, 0x%08x\n", regtype, hr);
1708 return hr;
1709 }
1710
1711 hr = split_reg_path(name, &subkey, &val);
1712 if (FAILED(hr))
1713 goto fail;
1714
1715 ret = RegSetKeyValueW(root, subkey, val, regtype, data, data_len);
1716 if (ret)
1717 hr = HRESULT_FROM_WIN32(ret);
1718
1719 fail:
1720 VariantClear(&v);
1721 if (val)
1722 heap_free(subkey);
1723 return hr;
1724 }
1725
WshShell3_RegDelete(IWshShell3 * iface,BSTR Name)1726 static HRESULT WINAPI WshShell3_RegDelete(IWshShell3 *iface, BSTR Name)
1727 {
1728 FIXME("(%s): stub\n", debugstr_w(Name));
1729 return E_NOTIMPL;
1730 }
1731
WshShell3_LogEvent(IWshShell3 * iface,VARIANT * Type,BSTR Message,BSTR Target,VARIANT_BOOL * out_Success)1732 static HRESULT WINAPI WshShell3_LogEvent(IWshShell3 *iface, VARIANT *Type, BSTR Message, BSTR Target, VARIANT_BOOL *out_Success)
1733 {
1734 FIXME("(%s %s %s %p): stub\n", debugstr_variant(Type), debugstr_w(Message), debugstr_w(Target), out_Success);
1735 return E_NOTIMPL;
1736 }
1737
WshShell3_AppActivate(IWshShell3 * iface,VARIANT * App,VARIANT * Wait,VARIANT_BOOL * out_Success)1738 static HRESULT WINAPI WshShell3_AppActivate(IWshShell3 *iface, VARIANT *App, VARIANT *Wait, VARIANT_BOOL *out_Success)
1739 {
1740 FIXME("(%s %s %p): stub\n", debugstr_variant(App), debugstr_variant(Wait), out_Success);
1741 return E_NOTIMPL;
1742 }
1743
WshShell3_SendKeys(IWshShell3 * iface,BSTR Keys,VARIANT * Wait)1744 static HRESULT WINAPI WshShell3_SendKeys(IWshShell3 *iface, BSTR Keys, VARIANT *Wait)
1745 {
1746 FIXME("(%s %p): stub\n", debugstr_w(Keys), Wait);
1747 return E_NOTIMPL;
1748 }
1749
WshShell3_Exec(IWshShell3 * iface,BSTR command,IWshExec ** ret)1750 static HRESULT WINAPI WshShell3_Exec(IWshShell3 *iface, BSTR command, IWshExec **ret)
1751 {
1752 TRACE("(%s %p)\n", debugstr_w(command), ret);
1753
1754 if (!ret)
1755 return E_POINTER;
1756
1757 if (!command)
1758 return DISP_E_EXCEPTION;
1759
1760 return WshExec_create(command, ret);
1761 }
1762
WshShell3_get_CurrentDirectory(IWshShell3 * iface,BSTR * dir)1763 static HRESULT WINAPI WshShell3_get_CurrentDirectory(IWshShell3 *iface, BSTR *dir)
1764 {
1765 DWORD ret;
1766
1767 TRACE("(%p)\n", dir);
1768
1769 ret = GetCurrentDirectoryW(0, NULL);
1770 if (!ret)
1771 return HRESULT_FROM_WIN32(GetLastError());
1772
1773 *dir = SysAllocStringLen(NULL, ret-1);
1774 if (!*dir)
1775 return E_OUTOFMEMORY;
1776
1777 ret = GetCurrentDirectoryW(ret, *dir);
1778 if (!ret) {
1779 SysFreeString(*dir);
1780 *dir = NULL;
1781 return HRESULT_FROM_WIN32(GetLastError());
1782 }
1783
1784 return S_OK;
1785 }
1786
WshShell3_put_CurrentDirectory(IWshShell3 * iface,BSTR dir)1787 static HRESULT WINAPI WshShell3_put_CurrentDirectory(IWshShell3 *iface, BSTR dir)
1788 {
1789 TRACE("(%s)\n", debugstr_w(dir));
1790
1791 if (!dir)
1792 return E_INVALIDARG;
1793
1794 if (!SetCurrentDirectoryW(dir))
1795 return HRESULT_FROM_WIN32(GetLastError());
1796
1797 return S_OK;
1798 }
1799
1800 static const IWshShell3Vtbl WshShell3Vtbl = {
1801 WshShell3_QueryInterface,
1802 WshShell3_AddRef,
1803 WshShell3_Release,
1804 WshShell3_GetTypeInfoCount,
1805 WshShell3_GetTypeInfo,
1806 WshShell3_GetIDsOfNames,
1807 WshShell3_Invoke,
1808 WshShell3_get_SpecialFolders,
1809 WshShell3_get_Environment,
1810 WshShell3_Run,
1811 WshShell3_Popup,
1812 WshShell3_CreateShortcut,
1813 WshShell3_ExpandEnvironmentStrings,
1814 WshShell3_RegRead,
1815 WshShell3_RegWrite,
1816 WshShell3_RegDelete,
1817 WshShell3_LogEvent,
1818 WshShell3_AppActivate,
1819 WshShell3_SendKeys,
1820 WshShell3_Exec,
1821 WshShell3_get_CurrentDirectory,
1822 WshShell3_put_CurrentDirectory
1823 };
1824
WshShellFactory_CreateInstance(IClassFactory * iface,IUnknown * outer,REFIID riid,void ** ppv)1825 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1826 {
1827 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
1828
1829 WshShell3.IWshShell3_iface.lpVtbl = &WshShell3Vtbl;
1830 init_classinfo(&IID_IWshShell3, (IUnknown *)&WshShell3.IWshShell3_iface, &WshShell3.classinfo);
1831 return IWshShell3_QueryInterface(&WshShell3.IWshShell3_iface, riid, ppv);
1832 }
1833