Reactos
at master 479 lines 12 kB view raw
1/* 2 * Copyright 2010 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#include <stdarg.h> 20 21#define COBJMACROS 22#define CONST_VTABLE 23 24#include <windef.h> 25#include <winbase.h> 26#include <ole2.h> 27 28#include "wscript.h" 29 30#include <wine/debug.h> 31#include <wine/heap.h> 32 33WINE_DEFAULT_DEBUG_CHANNEL(wscript); 34 35#define BUILDVERSION 16535 36 37static const WCHAR wshNameW[] = {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0}; 38static const WCHAR wshVersionW[] = {'5','.','8'}; 39 40VARIANT_BOOL wshInteractive = 41#ifndef CSCRIPT_BUILD 42 VARIANT_TRUE; 43#else 44 VARIANT_FALSE; 45#endif 46 47static HRESULT to_string(VARIANT *src, BSTR *dst) 48{ 49 VARIANT v; 50 HRESULT hres; 51 52 static const WCHAR nullW[] = {'n','u','l','l',0}; 53 54 if(V_VT(src) == VT_NULL) { 55 *dst = SysAllocString(nullW); 56 return *dst ? S_OK : E_OUTOFMEMORY; 57 } 58 59 V_VT(&v) = VT_EMPTY; 60 hres = VariantChangeType(&v, src, 0, VT_BSTR); 61 if(FAILED(hres)) { 62 WARN("Could not convert argument %s to string\n", debugstr_variant(src)); 63 return hres; 64 } 65 66 *dst = V_BSTR(&v); 67 return S_OK; 68} 69 70static void print_string(const WCHAR *string) 71{ 72 DWORD count, ret, len, lena; 73 char *buf; 74 75 if(wshInteractive) { 76 static const WCHAR windows_script_hostW[] = 77 {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0}; 78 MessageBoxW(NULL, string, windows_script_hostW, MB_OK); 79 return; 80 } 81 82 len = lstrlenW(string); 83 ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), string, len, &count, NULL); 84 if(ret) { 85 static const WCHAR crnlW[] = {'\r','\n'}; 86 WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), crnlW, ARRAY_SIZE(crnlW), &count, NULL); 87 return; 88 } 89 90 lena = WideCharToMultiByte(GetConsoleOutputCP(), 0, string, len, NULL, 0, NULL, NULL); 91 buf = heap_alloc(len); 92 if(!buf) 93 return; 94 95 WideCharToMultiByte(GetConsoleOutputCP(), 0, string, len, buf, lena, NULL, NULL); 96 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, lena, &count, FALSE); 97 heap_free(buf); 98 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\r\n", 2, &count, FALSE); 99} 100 101static HRESULT WINAPI Host_QueryInterface(IHost *iface, REFIID riid, void **ppv) 102{ 103 WINE_TRACE("(%s %p)\n", wine_dbgstr_guid(riid), ppv); 104 105 if(IsEqualGUID(&IID_IUnknown, riid) 106 || IsEqualGUID(&IID_IDispatch, riid) 107 || IsEqualGUID(&IID_IHost, riid)) { 108 *ppv = iface; 109 return S_OK; 110 } 111 112 *ppv = NULL; 113 return E_NOINTERFACE; 114} 115 116static ULONG WINAPI Host_AddRef(IHost *iface) 117{ 118 return 2; 119} 120 121static ULONG WINAPI Host_Release(IHost *iface) 122{ 123 return 1; 124} 125 126static HRESULT WINAPI Host_GetTypeInfoCount(IHost *iface, UINT *pctinfo) 127{ 128 WINE_TRACE("(%p)\n", pctinfo); 129 *pctinfo = 1; 130 return S_OK; 131} 132 133static HRESULT WINAPI Host_GetTypeInfo(IHost *iface, UINT iTInfo, LCID lcid, 134 ITypeInfo **ppTInfo) 135{ 136 WINE_TRACE("(%x %x %p\n", iTInfo, lcid, ppTInfo); 137 138 ITypeInfo_AddRef(host_ti); 139 *ppTInfo = host_ti; 140 return S_OK; 141} 142 143static HRESULT WINAPI Host_GetIDsOfNames(IHost *iface, REFIID riid, LPOLESTR *rgszNames, 144 UINT cNames, LCID lcid, DISPID *rgDispId) 145{ 146 WINE_TRACE("(%s %p %d %x %p)\n", wine_dbgstr_guid(riid), rgszNames, 147 cNames, lcid, rgDispId); 148 149 return ITypeInfo_GetIDsOfNames(host_ti, rgszNames, cNames, rgDispId); 150} 151 152static HRESULT WINAPI Host_Invoke(IHost *iface, DISPID dispIdMember, REFIID riid, 153 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 154 EXCEPINFO *pExcepInfo, UINT *puArgErr) 155{ 156 WINE_TRACE("(%d %p %p)\n", dispIdMember, pDispParams, pVarResult); 157 158 return ITypeInfo_Invoke(host_ti, iface, dispIdMember, wFlags, pDispParams, 159 pVarResult, pExcepInfo, puArgErr); 160} 161 162static HRESULT WINAPI Host_get_Name(IHost *iface, BSTR *out_Name) 163{ 164 WINE_TRACE("(%p)\n", out_Name); 165 166 if(!(*out_Name = SysAllocString(wshNameW))) 167 return E_OUTOFMEMORY; 168 return S_OK; 169} 170 171static HRESULT WINAPI Host_get_Application(IHost *iface, IDispatch **out_Dispatch) 172{ 173 WINE_TRACE("(%p)\n", out_Dispatch); 174 175 *out_Dispatch = (IDispatch*)&host_obj; 176 return S_OK; 177} 178 179static HRESULT WINAPI Host_get_FullName(IHost *iface, BSTR *out_Path) 180{ 181 WCHAR fullPath[MAX_PATH]; 182 183 WINE_TRACE("(%p)\n", out_Path); 184 185 if(GetModuleFileNameW(NULL, fullPath, ARRAY_SIZE(fullPath)) == 0) 186 return E_FAIL; 187 if(!(*out_Path = SysAllocString(fullPath))) 188 return E_OUTOFMEMORY; 189 return S_OK; 190} 191 192static HRESULT WINAPI Host_get_Path(IHost *iface, BSTR *out_Path) 193{ 194 WCHAR path[MAX_PATH]; 195 int howMany; 196 WCHAR *pos; 197 198 WINE_TRACE("(%p)\n", out_Path); 199 200 if(GetModuleFileNameW(NULL, path, ARRAY_SIZE(path)) == 0) 201 return E_FAIL; 202 pos = wcsrchr(path, '\\'); 203 howMany = pos - path; 204 if(!(*out_Path = SysAllocStringLen(path, howMany))) 205 return E_OUTOFMEMORY; 206 return S_OK; 207} 208 209static HRESULT WINAPI Host_get_Interactive(IHost *iface, VARIANT_BOOL *out_Interactive) 210{ 211 WINE_TRACE("(%p)\n", out_Interactive); 212 213 *out_Interactive = wshInteractive; 214 return S_OK; 215} 216 217static HRESULT WINAPI Host_put_Interactive(IHost *iface, VARIANT_BOOL v) 218{ 219 WINE_TRACE("(%x)\n", v); 220 221 wshInteractive = v; 222 return S_OK; 223} 224 225static HRESULT WINAPI Host_Quit(IHost *iface, int ExitCode) 226{ 227 FIXME("(%d) semi-stub: no script engine clean up\n", ExitCode); 228 229 ExitProcess(ExitCode); 230 return S_OK; 231} 232 233static HRESULT WINAPI Host_get_ScriptName(IHost *iface, BSTR *out_ScriptName) 234{ 235 WCHAR *scriptName; 236 237 WINE_TRACE("(%p)\n", out_ScriptName); 238 239 scriptName = wcsrchr(scriptFullName, '\\'); 240 ++scriptName; 241 if(!(*out_ScriptName = SysAllocString(scriptName))) 242 return E_OUTOFMEMORY; 243 return S_OK; 244} 245 246static HRESULT WINAPI Host_get_ScriptFullName(IHost *iface, BSTR *out_ScriptFullName) 247{ 248 WINE_TRACE("(%p)\n", out_ScriptFullName); 249 250 if(!(*out_ScriptFullName = SysAllocString(scriptFullName))) 251 return E_OUTOFMEMORY; 252 return S_OK; 253} 254 255static HRESULT WINAPI Host_get_Arguments(IHost *iface, IArguments2 **out_Arguments) 256{ 257 WINE_TRACE("(%p)\n", out_Arguments); 258 259 *out_Arguments = &arguments_obj; 260 return S_OK; 261} 262 263static HRESULT WINAPI Host_get_Version(IHost *iface, BSTR *out_Version) 264{ 265 WINE_TRACE("(%p)\n", out_Version); 266 267 if(!(*out_Version = SysAllocString(wshVersionW))) 268 return E_OUTOFMEMORY; 269 return S_OK; 270} 271 272static HRESULT WINAPI Host_get_BuildVersion(IHost *iface, int *out_Build) 273{ 274 WINE_TRACE("(%p)\n", out_Build); 275 276 *out_Build = BUILDVERSION; 277 return S_OK; 278} 279 280static HRESULT WINAPI Host_get_Timeout(IHost *iface, LONG *out_Timeout) 281{ 282 WINE_FIXME("(%p)\n", out_Timeout); 283 return E_NOTIMPL; 284} 285 286static HRESULT WINAPI Host_put_Timeout(IHost *iface, LONG v) 287{ 288 WINE_FIXME("(%d)\n", v); 289 return E_NOTIMPL; 290} 291 292static HRESULT WINAPI Host_CreateObject(IHost *iface, BSTR ProgID, BSTR Prefix, 293 IDispatch **out_Dispatch) 294{ 295 IUnknown *unk; 296 GUID guid; 297 HRESULT hres; 298 299 TRACE("(%s %s %p)\n", wine_dbgstr_w(ProgID), wine_dbgstr_w(Prefix), out_Dispatch); 300 301 if(Prefix && *Prefix) { 302 FIXME("Prefix %s not supported\n", debugstr_w(Prefix)); 303 return E_NOTIMPL; 304 } 305 306 hres = CLSIDFromProgID(ProgID, &guid); 307 if(FAILED(hres)) 308 return hres; 309 310 hres = CoCreateInstance(&guid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER, 311 &IID_IUnknown, (void**)&unk); 312 if(FAILED(hres)) 313 return hres; 314 315 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)out_Dispatch); 316 IUnknown_Release(unk); 317 return hres; 318} 319 320static HRESULT WINAPI Host_Echo(IHost *iface, SAFEARRAY *args) 321{ 322 WCHAR *output = NULL, *ptr; 323 unsigned argc, i, len; 324#ifdef __REACTOS__ 325 LONG ubound, lbound; 326#else 327 int ubound, lbound; 328#endif 329 VARIANT *argv; 330 BSTR *strs; 331 HRESULT hres; 332 333 TRACE("(%p)\n", args); 334 335 if(SafeArrayGetDim(args) != 1) { 336 FIXME("Unsupported args dim %d\n", SafeArrayGetDim(args)); 337 return E_NOTIMPL; 338 } 339 340 SafeArrayGetLBound(args, 1, &lbound); 341 SafeArrayGetUBound(args, 1, &ubound); 342 343 hres = SafeArrayAccessData(args, (void**)&argv); 344 if(FAILED(hres)) 345 return hres; 346 347 argc = ubound-lbound+1; 348 strs = heap_alloc_zero(argc*sizeof(*strs)); 349 if(!strs) { 350 SafeArrayUnaccessData(args); 351 return E_OUTOFMEMORY; 352 } 353 354 /* Len of spaces between arguments. */ 355 len = argc-1; 356 357 for(i=0; i < argc; i++) { 358 hres = to_string(argv+i, strs+i); 359 if(FAILED(hres)) 360 break; 361 362 len += SysStringLen(strs[i]); 363 } 364 365 SafeArrayUnaccessData(args); 366 if(SUCCEEDED(hres)) { 367 ptr = output = heap_alloc((len+1)*sizeof(WCHAR)); 368 if(output) { 369 for(i=0; i < argc; i++) { 370 if(i) 371 *ptr++ = ' '; 372 len = SysStringLen(strs[i]); 373 memcpy(ptr, strs[i], len*sizeof(WCHAR)); 374 ptr += len; 375 } 376 *ptr = 0; 377 }else { 378 hres = E_OUTOFMEMORY; 379 } 380 } 381 382 for(i=0; i < argc; i++) 383 SysFreeString(strs[i]); 384 heap_free(strs); 385 if(FAILED(hres)) 386 return hres; 387 388 print_string(output); 389 390 heap_free(output); 391 return S_OK; 392} 393 394static HRESULT WINAPI Host_GetObject(IHost *iface, BSTR Pathname, BSTR ProgID, 395 BSTR Prefix, IDispatch **out_Dispatch) 396{ 397 WINE_FIXME("(%s %s %s %p)\n", wine_dbgstr_w(Pathname), wine_dbgstr_w(ProgID), 398 wine_dbgstr_w(Prefix), out_Dispatch); 399 return E_NOTIMPL; 400} 401 402static HRESULT WINAPI Host_DisconnectObject(IHost *iface, IDispatch *Object) 403{ 404 WINE_FIXME("(%p)\n", Object); 405 return E_NOTIMPL; 406} 407 408static HRESULT WINAPI Host_Sleep(IHost *iface, LONG Time) 409{ 410#ifdef __REACTOS__ 411 UNREFERENCED_PARAMETER(iface); 412 if (Time < 0) 413 return E_INVALIDARG; 414 Sleep(Time); 415 return S_OK; 416#else 417 WINE_FIXME("(%d)\n", Time); 418 return E_NOTIMPL; 419#endif 420} 421 422static HRESULT WINAPI Host_ConnectObject(IHost *iface, IDispatch *Object, BSTR Prefix) 423{ 424 WINE_FIXME("(%p %s)\n", Object, wine_dbgstr_w(Prefix)); 425 return E_NOTIMPL; 426} 427 428static HRESULT WINAPI Host_get_StdIn(IHost *iface, ITextStream **ppts) 429{ 430 WINE_FIXME("(%p)\n", ppts); 431 return E_NOTIMPL; 432} 433 434static HRESULT WINAPI Host_get_StdOut(IHost *iface, ITextStream **ppts) 435{ 436 WINE_FIXME("(%p)\n", ppts); 437 return E_NOTIMPL; 438} 439 440static HRESULT WINAPI Host_get_StdErr(IHost *iface, ITextStream **ppts) 441{ 442 WINE_FIXME("(%p)\n", ppts); 443 return E_NOTIMPL; 444} 445 446static const IHostVtbl HostVtbl = { 447 Host_QueryInterface, 448 Host_AddRef, 449 Host_Release, 450 Host_GetTypeInfoCount, 451 Host_GetTypeInfo, 452 Host_GetIDsOfNames, 453 Host_Invoke, 454 Host_get_Name, 455 Host_get_Application, 456 Host_get_FullName, 457 Host_get_Path, 458 Host_get_Interactive, 459 Host_put_Interactive, 460 Host_Quit, 461 Host_get_ScriptName, 462 Host_get_ScriptFullName, 463 Host_get_Arguments, 464 Host_get_Version, 465 Host_get_BuildVersion, 466 Host_get_Timeout, 467 Host_put_Timeout, 468 Host_CreateObject, 469 Host_Echo, 470 Host_GetObject, 471 Host_DisconnectObject, 472 Host_Sleep, 473 Host_ConnectObject, 474 Host_get_StdIn, 475 Host_get_StdOut, 476 Host_get_StdErr 477}; 478 479IHost host_obj = { &HostVtbl };