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 33 WINE_DEFAULT_DEBUG_CHANNEL(wscript); 34 35 #define BUILDVERSION 16535 36 37 static const WCHAR wshNameW[] = {'W','i','n','d','o','w','s',' ','S','c','r','i','p','t',' ','H','o','s','t',0}; 38 static const WCHAR wshVersionW[] = {'5','.','8'}; 39 40 VARIANT_BOOL wshInteractive = 41 #ifndef CSCRIPT_BUILD 42 VARIANT_TRUE; 43 #else 44 VARIANT_FALSE; 45 #endif 46 47 static 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 70 static 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 101 static 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 116 static ULONG WINAPI Host_AddRef(IHost *iface) 117 { 118 return 2; 119 } 120 121 static ULONG WINAPI Host_Release(IHost *iface) 122 { 123 return 1; 124 } 125 126 static HRESULT WINAPI Host_GetTypeInfoCount(IHost *iface, UINT *pctinfo) 127 { 128 WINE_TRACE("(%p)\n", pctinfo); 129 *pctinfo = 1; 130 return S_OK; 131 } 132 133 static 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 143 static 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 152 static 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 162 static 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 171 static 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 179 static 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 192 static 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 209 static 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 217 static 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 225 static 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 233 static 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 246 static 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 255 static 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 263 static 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 272 static 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 280 static HRESULT WINAPI Host_get_Timeout(IHost *iface, LONG *out_Timeout) 281 { 282 WINE_FIXME("(%p)\n", out_Timeout); 283 return E_NOTIMPL; 284 } 285 286 static HRESULT WINAPI Host_put_Timeout(IHost *iface, LONG v) 287 { 288 WINE_FIXME("(%d)\n", v); 289 return E_NOTIMPL; 290 } 291 292 static 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 320 static 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 394 static 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 402 static HRESULT WINAPI Host_DisconnectObject(IHost *iface, IDispatch *Object) 403 { 404 WINE_FIXME("(%p)\n", Object); 405 return E_NOTIMPL; 406 } 407 408 static HRESULT WINAPI Host_Sleep(IHost *iface, LONG Time) 409 { 410 WINE_FIXME("(%d)\n", Time); 411 return E_NOTIMPL; 412 } 413 414 static HRESULT WINAPI Host_ConnectObject(IHost *iface, IDispatch *Object, BSTR Prefix) 415 { 416 WINE_FIXME("(%p %s)\n", Object, wine_dbgstr_w(Prefix)); 417 return E_NOTIMPL; 418 } 419 420 static HRESULT WINAPI Host_get_StdIn(IHost *iface, ITextStream **ppts) 421 { 422 WINE_FIXME("(%p)\n", ppts); 423 return E_NOTIMPL; 424 } 425 426 static HRESULT WINAPI Host_get_StdOut(IHost *iface, ITextStream **ppts) 427 { 428 WINE_FIXME("(%p)\n", ppts); 429 return E_NOTIMPL; 430 } 431 432 static HRESULT WINAPI Host_get_StdErr(IHost *iface, ITextStream **ppts) 433 { 434 WINE_FIXME("(%p)\n", ppts); 435 return E_NOTIMPL; 436 } 437 438 static const IHostVtbl HostVtbl = { 439 Host_QueryInterface, 440 Host_AddRef, 441 Host_Release, 442 Host_GetTypeInfoCount, 443 Host_GetTypeInfo, 444 Host_GetIDsOfNames, 445 Host_Invoke, 446 Host_get_Name, 447 Host_get_Application, 448 Host_get_FullName, 449 Host_get_Path, 450 Host_get_Interactive, 451 Host_put_Interactive, 452 Host_Quit, 453 Host_get_ScriptName, 454 Host_get_ScriptFullName, 455 Host_get_Arguments, 456 Host_get_Version, 457 Host_get_BuildVersion, 458 Host_get_Timeout, 459 Host_put_Timeout, 460 Host_CreateObject, 461 Host_Echo, 462 Host_GetObject, 463 Host_DisconnectObject, 464 Host_Sleep, 465 Host_ConnectObject, 466 Host_get_StdIn, 467 Host_get_StdOut, 468 Host_get_StdErr 469 }; 470 471 IHost host_obj = { &HostVtbl }; 472