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