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 #ifdef __REACTOS__ 23 #define CONST_VTABLE 24 #endif 25 26 #include <windef.h> 27 #include <winbase.h> 28 #include <winreg.h> 29 #include <ole2.h> 30 #include <shellapi.h> 31 #include <activscp.h> 32 #include <initguid.h> 33 34 #include "wscript.h" 35 36 #include <wine/debug.h> 37 38 #ifdef _WIN64 39 40 #define IActiveScriptParse_Release IActiveScriptParse64_Release 41 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew 42 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText 43 44 #else 45 46 #define IActiveScriptParse_Release IActiveScriptParse32_Release 47 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew 48 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText 49 50 #endif 51 52 WINE_DEFAULT_DEBUG_CHANNEL(wscript); 53 54 static const WCHAR wscriptW[] = {'W','S','c','r','i','p','t',0}; 55 static const WCHAR wshW[] = {'W','S','H',0}; 56 WCHAR scriptFullName[MAX_PATH]; 57 58 ITypeInfo *host_ti; 59 ITypeInfo *arguments_ti; 60 61 static HRESULT query_interface(REFIID,void**); 62 63 #ifdef __REACTOS__ 64 #include <commctrl.h> 65 66 typedef struct { 67 UINT itemsize, count; 68 void *mem; 69 } SIMPLEVECTOR; 70 71 static void SVect_Free(SIMPLEVECTOR *pV) 72 { 73 if (pV->mem) 74 LocalFree(pV->mem); 75 pV->mem = NULL; 76 } 77 78 static void* SVect_Add(SIMPLEVECTOR *pV) 79 { 80 void *p = NULL; 81 if (pV->mem) 82 { 83 p = LocalReAlloc(pV->mem, pV->itemsize * (pV->count + 1), LMEM_FIXED | LMEM_MOVEABLE); 84 if (p) 85 { 86 pV->mem = p; 87 p = (char*)p + (pV->count * pV->itemsize); 88 pV->count++; 89 } 90 } 91 else 92 { 93 p = pV->mem = LocalAlloc(LMEM_FIXED, pV->itemsize); 94 if (p) 95 { 96 pV->count = 1; 97 } 98 } 99 return p; 100 } 101 102 #define SVect_Delete(pV, pItem) ( (pV), (pItem) ) /* Should not be required for global items */ 103 104 static void* SVect_Get(SIMPLEVECTOR *pV, UINT i) 105 { 106 return pV->mem && i < pV->count ? (char*)pV->mem + (i * pV->itemsize) : NULL; 107 } 108 109 typedef struct { 110 BSTR name; 111 IUnknown *punk; 112 } GLOBAL_ITEM; 113 114 SIMPLEVECTOR g_global_items = { sizeof(GLOBAL_ITEM) }; 115 116 static void free_globals(void) 117 { 118 UINT i; 119 for (i = 0;; ++i) 120 { 121 GLOBAL_ITEM *p = (GLOBAL_ITEM*)SVect_Get(&g_global_items, i); 122 if (!p) 123 break; 124 IUnknown_Release(p->punk); 125 SysFreeString(p->name); 126 } 127 SVect_Free(&g_global_items); 128 } 129 130 static HRESULT add_globalitem(IActiveScript *script, BSTR name, IUnknown *punk, DWORD siflags) 131 { 132 GLOBAL_ITEM *item; 133 HRESULT hr; 134 135 name = SysAllocString(name); 136 if (!name) 137 return E_OUTOFMEMORY; 138 139 item = SVect_Add(&g_global_items); 140 if (item) 141 { 142 item->name = name; 143 item->punk = punk; 144 hr = IActiveScript_AddNamedItem(script, name, siflags); 145 if (SUCCEEDED(hr)) 146 { 147 IUnknown_AddRef(punk); 148 return hr; 149 } 150 SVect_Delete(&g_global_items, item); 151 } 152 SysFreeString(name); 153 return E_OUTOFMEMORY; 154 } 155 156 static HRESULT add_globalitem_from_clsid(IActiveScript *script, BSTR name, REFCLSID clsid, DWORD siflags) 157 { 158 IUnknown *punk; 159 HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk); 160 if (SUCCEEDED(hr)) 161 { 162 hr = add_globalitem(script, name, punk, siflags); 163 IUnknown_Release(punk); 164 } 165 return hr; 166 } 167 168 static HRESULT get_globalitem_info(LPCOLESTR Name, DWORD Mask, IUnknown **ppunk, ITypeInfo **ppti, BOOL *pHandled) 169 { 170 HRESULT hr = S_FALSE; 171 UINT i; 172 for (i = 0;; ++i) 173 { 174 GLOBAL_ITEM *p = (GLOBAL_ITEM*)SVect_Get(&g_global_items, i); 175 if (!p) 176 break; 177 if (!lstrcmpiW(Name, p->name)) 178 { 179 if (ppti) 180 *ppti = NULL; 181 if (Mask & SCRIPTINFO_IUNKNOWN) 182 { 183 *ppunk = p->punk; 184 if (p->punk) 185 { 186 IUnknown_AddRef(p->punk); 187 *pHandled = TRUE; 188 } 189 return S_OK; 190 } 191 break; 192 } 193 } 194 return hr; 195 } 196 #endif 197 198 static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, 199 REFIID riid, void **ppv) 200 { 201 return query_interface(riid, ppv); 202 } 203 204 static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) 205 { 206 return 2; 207 } 208 209 static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) 210 { 211 return 1; 212 } 213 214 static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) 215 { 216 WINE_TRACE("()\n"); 217 218 *plcid = GetUserDefaultLCID(); 219 return S_OK; 220 } 221 222 static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, 223 LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) 224 { 225 WINE_TRACE("(%s %x %p %p)\n", wine_dbgstr_w(pstrName), dwReturnMask, ppunkItem, ppti); 226 227 #ifdef __REACTOS__ 228 { 229 BOOL handled = FALSE; 230 HRESULT hr = get_globalitem_info(pstrName, dwReturnMask, ppunkItem, ppti, &handled); 231 if (handled) 232 return hr; 233 } 234 #endif 235 236 if(lstrcmpW(pstrName, wshW) && lstrcmpW(pstrName, wscriptW)) 237 return E_FAIL; 238 239 if(dwReturnMask & SCRIPTINFO_ITYPEINFO) { 240 ITypeInfo_AddRef(host_ti); 241 *ppti = host_ti; 242 } 243 244 if(dwReturnMask & SCRIPTINFO_IUNKNOWN) { 245 IHost_AddRef(&host_obj); 246 *ppunkItem = (IUnknown*)&host_obj; 247 } 248 249 return S_OK; 250 } 251 252 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, 253 BSTR *pbstrVersion) 254 { 255 WINE_FIXME("()\n"); 256 return E_NOTIMPL; 257 } 258 259 static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, 260 const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) 261 { 262 WINE_FIXME("()\n"); 263 return E_NOTIMPL; 264 } 265 266 static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, 267 SCRIPTSTATE ssScriptState) 268 { 269 WINE_TRACE("(%x)\n", ssScriptState); 270 return S_OK; 271 } 272 273 static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, 274 IActiveScriptError *pscripterror) 275 { 276 WINE_FIXME("()\n"); 277 return E_NOTIMPL; 278 } 279 280 static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) 281 { 282 WINE_TRACE("()\n"); 283 return S_OK; 284 } 285 286 static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) 287 { 288 WINE_TRACE("()\n"); 289 return S_OK; 290 } 291 292 static IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { 293 ActiveScriptSite_QueryInterface, 294 ActiveScriptSite_AddRef, 295 ActiveScriptSite_Release, 296 ActiveScriptSite_GetLCID, 297 ActiveScriptSite_GetItemInfo, 298 ActiveScriptSite_GetDocVersionString, 299 ActiveScriptSite_OnScriptTerminate, 300 ActiveScriptSite_OnStateChange, 301 ActiveScriptSite_OnScriptError, 302 ActiveScriptSite_OnEnterScript, 303 ActiveScriptSite_OnLeaveScript 304 }; 305 306 static IActiveScriptSite script_site = { &ActiveScriptSiteVtbl }; 307 308 static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface, REFIID riid, void **ppv) 309 { 310 return query_interface(riid, ppv); 311 } 312 313 static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface) 314 { 315 return 2; 316 } 317 318 static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface) 319 { 320 return 1; 321 } 322 323 static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *phwnd) 324 { 325 TRACE("(%p)\n", phwnd); 326 327 *phwnd = NULL; 328 return S_OK; 329 } 330 331 static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL fEnable) 332 { 333 TRACE("(%x)\n", fEnable); 334 return S_OK; 335 } 336 337 static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = { 338 ActiveScriptSiteWindow_QueryInterface, 339 ActiveScriptSiteWindow_AddRef, 340 ActiveScriptSiteWindow_Release, 341 ActiveScriptSiteWindow_GetWindow, 342 ActiveScriptSiteWindow_EnableModeless 343 }; 344 345 static IActiveScriptSiteWindow script_site_window = { &ActiveScriptSiteWindowVtbl }; 346 347 static HRESULT query_interface(REFIID riid, void **ppv) 348 { 349 if(IsEqualGUID(riid, &IID_IUnknown)) { 350 TRACE("(IID_IUnknown %p)\n", ppv); 351 *ppv = &script_site; 352 }else if(IsEqualGUID(riid, &IID_IActiveScriptSite)) { 353 TRACE("(IID_IActiveScriptSite %p)\n", ppv); 354 *ppv = &script_site; 355 }else if(IsEqualGUID(riid, &IID_IActiveScriptSiteWindow)) { 356 TRACE("(IID_IActiveScriptSiteWindow %p)\n", ppv); 357 *ppv = &script_site_window; 358 }else { 359 *ppv = NULL; 360 TRACE("(%s %p)\n", wine_dbgstr_guid(riid), ppv); 361 return E_NOINTERFACE; 362 } 363 364 IUnknown_AddRef((IUnknown*)*ppv); 365 return S_OK; 366 } 367 368 static BOOL load_typelib(void) 369 { 370 ITypeLib *typelib; 371 HRESULT hres; 372 373 static const WCHAR wscript_exeW[] = {'w','s','c','r','i','p','t','.','e','x','e',0}; 374 375 hres = LoadTypeLib(wscript_exeW, &typelib); 376 if(FAILED(hres)) 377 return FALSE; 378 379 hres = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IHost, &host_ti); 380 if(SUCCEEDED(hres)) 381 hres = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IArguments2, &arguments_ti); 382 383 ITypeLib_Release(typelib); 384 return SUCCEEDED(hres); 385 } 386 387 static BOOL get_engine_clsid(const WCHAR *ext, CLSID *clsid) 388 { 389 WCHAR fileid[64], progid[64]; 390 DWORD res; 391 LONG size; 392 HKEY hkey; 393 HRESULT hres; 394 395 static const WCHAR script_engineW[] = 396 {'\\','S','c','r','i','p','t','E','n','g','i','n','e',0}; 397 398 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ext, &hkey); 399 if(res != ERROR_SUCCESS) 400 return FALSE; 401 402 size = ARRAY_SIZE(fileid); 403 res = RegQueryValueW(hkey, NULL, fileid, &size); 404 RegCloseKey(hkey); 405 if(res != ERROR_SUCCESS) 406 return FALSE; 407 408 WINE_TRACE("fileid is %s\n", wine_dbgstr_w(fileid)); 409 410 lstrcatW(fileid, script_engineW); 411 res = RegOpenKeyW(HKEY_CLASSES_ROOT, fileid, &hkey); 412 if(res != ERROR_SUCCESS) 413 return FALSE; 414 415 size = ARRAY_SIZE(progid); 416 res = RegQueryValueW(hkey, NULL, progid, &size); 417 RegCloseKey(hkey); 418 if(res != ERROR_SUCCESS) 419 return FALSE; 420 421 WINE_TRACE("ProgID is %s\n", wine_dbgstr_w(progid)); 422 423 hres = CLSIDFromProgID(progid, clsid); 424 return SUCCEEDED(hres); 425 } 426 427 static BOOL create_engine(CLSID *clsid, IActiveScript **script_ret, 428 IActiveScriptParse **parser) 429 { 430 IActiveScript *script; 431 IUnknown *unk; 432 HRESULT hres; 433 434 hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 435 &IID_IUnknown, (void**)&unk); 436 if(FAILED(hres)) 437 return FALSE; 438 439 hres = IUnknown_QueryInterface(unk, &IID_IActiveScript, (void**)&script); 440 IUnknown_Release(unk); 441 if(FAILED(hres)) 442 return FALSE; 443 444 hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)parser); 445 if(FAILED(hres)) { 446 IActiveScript_Release(script); 447 return FALSE; 448 } 449 450 *script_ret = script; 451 return TRUE; 452 } 453 454 static BOOL init_engine(IActiveScript *script, IActiveScriptParse *parser) 455 { 456 HRESULT hres; 457 458 if(!load_typelib()) 459 return FALSE; 460 461 hres = IActiveScript_SetScriptSite(script, &script_site); 462 if(FAILED(hres)) 463 return FALSE; 464 465 hres = IActiveScriptParse_InitNew(parser); 466 if(FAILED(hres)) 467 return FALSE; 468 469 hres = IActiveScript_AddNamedItem(script, wscriptW, SCRIPTITEM_ISVISIBLE); 470 if(FAILED(hres)) 471 return FALSE; 472 473 hres = IActiveScript_AddNamedItem(script, wshW, SCRIPTITEM_ISVISIBLE); 474 if(FAILED(hres)) 475 return FALSE; 476 477 hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_INITIALIZED); 478 return SUCCEEDED(hres); 479 } 480 481 static BSTR get_script_str(const WCHAR *filename) 482 { 483 const char *file_map; 484 HANDLE file, map; 485 DWORD size, len; 486 BSTR ret; 487 488 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 489 if(file == INVALID_HANDLE_VALUE) 490 return NULL; 491 492 size = GetFileSize(file, NULL); 493 map = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); 494 CloseHandle(file); 495 if(map == INVALID_HANDLE_VALUE) 496 return NULL; 497 498 file_map = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); 499 CloseHandle(map); 500 if(!file_map) 501 return NULL; 502 503 len = MultiByteToWideChar(CP_ACP, 0, file_map, size, NULL, 0); 504 ret = SysAllocStringLen(NULL, len); 505 MultiByteToWideChar(CP_ACP, 0, file_map, size, ret, len); 506 507 UnmapViewOfFile(file_map); 508 return ret; 509 } 510 511 static void run_script(const WCHAR *filename, IActiveScript *script, IActiveScriptParse *parser) 512 { 513 BSTR text; 514 HRESULT hres; 515 516 text = get_script_str(filename); 517 if(!text) { 518 WINE_FIXME("Could not get script text\n"); 519 return; 520 } 521 522 hres = IActiveScriptParse_ParseScriptText(parser, text, NULL, NULL, NULL, 1, 1, 523 SCRIPTTEXT_HOSTMANAGESSOURCE|SCRIPTITEM_ISVISIBLE, NULL, NULL); 524 SysFreeString(text); 525 if(FAILED(hres)) { 526 WINE_FIXME("ParseScriptText failed: %08x\n", hres); 527 return; 528 } 529 530 hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); 531 if(FAILED(hres)) 532 WINE_FIXME("SetScriptState failed: %08x\n", hres); 533 } 534 535 #ifdef __REACTOS__ 536 #include <msxml2.h> 537 #include <shlwapi.h> 538 539 static HRESULT xmldomnode_getattributevalue(IXMLDOMNode *pnode, LPCWSTR name, BSTR *pout) 540 { 541 IXMLDOMNamedNodeMap *pmap; 542 HRESULT hr = E_OUTOFMEMORY; 543 BSTR bsname = SysAllocString(name); 544 *pout = NULL; 545 if (bsname && SUCCEEDED(hr = IXMLDOMNode_get_attributes(pnode, &pmap))) 546 { 547 if (SUCCEEDED(hr = IXMLDOMNamedNodeMap_getNamedItem(pmap, bsname, &pnode))) 548 { 549 hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); 550 if (pnode) 551 { 552 hr = IXMLDOMNode_get_text(pnode, pout); 553 if (SUCCEEDED(hr) && !*pout) 554 hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); 555 IXMLDOMNode_Release(pnode); 556 } 557 } 558 IXMLDOMNamedNodeMap_Release(pmap); 559 } 560 SysFreeString(bsname); 561 return hr; 562 } 563 564 static HRESULT xmldomelem_getelembytag(IXMLDOMElement *pelem, LPCWSTR name, long index, IXMLDOMNode**ppout) 565 { 566 HRESULT hr = E_OUTOFMEMORY; 567 IXMLDOMNodeList *pnl; 568 BSTR bsname = SysAllocString(name); 569 *ppout = NULL; 570 if (bsname && SUCCEEDED(hr = IXMLDOMElement_getElementsByTagName(pelem, bsname, &pnl))) 571 { 572 hr = IXMLDOMNodeList_get_item(pnl, index, ppout); 573 if (SUCCEEDED(hr) && !*ppout) 574 hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); 575 IUnknown_Release(pnl); 576 } 577 SysFreeString(bsname); 578 return hr; 579 } 580 581 static HRESULT xmldomelem_getelembytagasdomelem(IXMLDOMElement *pelem, LPCWSTR name, long index, IXMLDOMElement**ppout) 582 { 583 IXMLDOMNode *pnode; 584 HRESULT hr = xmldomelem_getelembytag(pelem, name, index, &pnode); 585 *ppout = NULL; 586 if (SUCCEEDED(hr)) 587 { 588 hr = IUnknown_QueryInterface(pnode, &IID_IXMLDOMElement, (void**)ppout); 589 IUnknown_Release(pnode); 590 } 591 return hr; 592 } 593 594 static void wsf_addobjectfromnode(IActiveScript *script, IXMLDOMNode *obj) 595 { 596 BSTR bsid, bsclsid = NULL; 597 if (SUCCEEDED(xmldomnode_getattributevalue(obj, L"id", &bsid))) 598 { 599 CLSID clsid; 600 HRESULT hr; 601 hr = xmldomnode_getattributevalue(obj, L"clsid", &bsclsid); 602 if (FAILED(hr) || FAILED(CLSIDFromString(bsclsid, &clsid))) 603 { 604 SysFreeString(bsclsid); 605 if (SUCCEEDED(hr = xmldomnode_getattributevalue(obj, L"progid", &bsclsid))) 606 { 607 hr = CLSIDFromProgID(bsclsid, &clsid); 608 SysFreeString(bsclsid); 609 } 610 } 611 if (SUCCEEDED(hr)) 612 { 613 hr = add_globalitem_from_clsid(script, bsid, &clsid, SCRIPTITEM_ISVISIBLE); 614 } 615 SysFreeString(bsid); 616 } 617 } 618 619 static HRESULT run_wsfjob(IXMLDOMElement *jobtag) 620 { 621 // FIXME: We are supposed to somehow handle multiple languages in the same IActiveScript. 622 IActiveScript *script; 623 LPCWSTR deflang = L"JScript"; 624 IXMLDOMNode *scripttag; 625 HRESULT hr = S_OK; 626 if (SUCCEEDED(xmldomelem_getelembytag(jobtag, L"script", 0, &scripttag))) 627 { 628 CLSID clsid; 629 IActiveScriptParse *parser; 630 BSTR lang, code; 631 if (FAILED(xmldomnode_getattributevalue(scripttag, L"language", &lang))) 632 lang = NULL; 633 hr = CLSIDFromProgID(lang ? lang : deflang, &clsid); 634 SysFreeString(lang); 635 636 if (SUCCEEDED(hr)) 637 { 638 hr = E_FAIL; 639 if (create_engine(&clsid, &script, &parser)) 640 { 641 if (init_engine(script, parser)) 642 { 643 long index; 644 for (index = 0; index < 0x7fffffff; ++index) 645 { 646 IXMLDOMNode *obj; 647 if (SUCCEEDED(xmldomelem_getelembytag(jobtag, L"object", index, &obj))) 648 { 649 wsf_addobjectfromnode(script, obj); 650 IUnknown_Release(obj); 651 } 652 else 653 { 654 break; 655 } 656 } 657 658 if (SUCCEEDED(hr = IXMLDOMNode_get_text(scripttag, &code))) 659 { 660 hr = IActiveScriptParse_ParseScriptText(parser, code, NULL, NULL, NULL, 1, 1, 661 SCRIPTTEXT_HOSTMANAGESSOURCE|SCRIPTITEM_ISVISIBLE, 662 NULL, NULL); 663 if (SUCCEEDED(hr)) 664 { 665 hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); 666 IActiveScript_Close(script); 667 } 668 SysFreeString(code); 669 } 670 ITypeInfo_Release(host_ti); 671 } 672 IUnknown_Release(parser); 673 IUnknown_Release(script); 674 } 675 } 676 IUnknown_Release(scripttag); 677 } 678 return hr; 679 } 680 681 /* 682 .WSF files can contain a single job, or multiple jobs if contained in a package. 683 Jobs are identified by their id and if no id is specified, the first job is used. 684 Each job can contain multiple script tags and all scripts are merged into one. 685 686 <job><script language="JScript">WScript.Echo("JS");</script></job> 687 or 688 <package> 689 <job><script language="JScript">WScript.Echo("JS");</script></job> 690 </package> 691 or 692 <?xml version="1.0" ?> 693 <job> 694 <script language="JScript"><![CDATA[function JS(s) {WScript.Echo(s)}]]></script> 695 <script language="VBScript">JS "VB2JS"</script> 696 </job> 697 */ 698 static HRESULT run_wsf(LPCWSTR xmlpath) 699 { 700 WCHAR url[ARRAY_SIZE("file://") + max(ARRAY_SIZE(scriptFullName), MAX_PATH)]; 701 DWORD cch = ARRAY_SIZE(url); 702 IXMLDOMDocument *pdoc; 703 HRESULT hr = UrlCreateFromPathW(xmlpath, url, &cch, 0), hrCom; 704 if (FAILED(hr)) 705 return hr; 706 707 hrCom = CoInitialize(NULL); 708 hr = CoCreateInstance(&CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER, 709 &IID_IXMLDOMDocument, (void**)&pdoc); 710 if (SUCCEEDED(hr)) 711 { 712 VARIANT_BOOL succ = VARIANT_FALSE; 713 IXMLDOMElement *pdocelm; 714 BSTR bsurl = SysAllocString(url); 715 VARIANT v; 716 V_VT(&v) = VT_BSTR; 717 V_BSTR(&v) = bsurl; 718 if (!bsurl || (hr = IXMLDOMDocument_load(pdoc, v, &succ)) > 0 || (SUCCEEDED(hr) && !succ)) 719 { 720 hr = E_FAIL; 721 } 722 if (SUCCEEDED(hr) && SUCCEEDED(hr = IXMLDOMDocument_get_documentElement(pdoc, &pdocelm))) 723 { 724 BSTR tagName = NULL; 725 if (SUCCEEDED(hr = IXMLDOMElement_get_tagName(pdocelm, &tagName))) 726 { 727 if (lstrcmpiW(tagName, L"package") == 0) 728 { 729 // FIXME: Accept job id as a function parameter and find the job here 730 IXMLDOMElement *p; 731 if (SUCCEEDED(hr = xmldomelem_getelembytagasdomelem(pdocelm, L"job", 0, &p))) 732 { 733 IUnknown_Release(pdocelm); 734 pdocelm = p; 735 } 736 } 737 else if (lstrcmpiW(tagName, L"job") != 0) 738 { 739 hr = 0x800400C0ul; 740 } 741 SysFreeString(tagName); 742 } 743 if (SUCCEEDED(hr)) 744 { 745 // FIXME: Only support CDATA blocks if the xml tag is present? 746 hr = run_wsfjob(pdocelm); 747 } 748 IUnknown_Release(pdocelm); 749 } 750 VariantClear(&v); 751 IUnknown_Release(pdoc); 752 } 753 free_globals(); 754 if (SUCCEEDED(hrCom)) 755 CoUninitialize(); 756 return hr; 757 } 758 #endif 759 760 static BOOL set_host_properties(const WCHAR *prop) 761 { 762 static const WCHAR nologoW[] = {'n','o','l','o','g','o',0}; 763 static const WCHAR iactive[] = {'i',0}; 764 static const WCHAR batch[] = {'b',0}; 765 766 if(*prop == '/') { 767 ++prop; 768 if(*prop == '/') 769 ++prop; 770 } 771 else 772 ++prop; 773 774 if(wcsicmp(prop, iactive) == 0) 775 wshInteractive = VARIANT_TRUE; 776 else if(wcsicmp(prop, batch) == 0) 777 wshInteractive = VARIANT_FALSE; 778 else if(wcsicmp(prop, nologoW) == 0) 779 WINE_FIXME("ignored %s switch\n", debugstr_w(nologoW)); 780 else 781 { 782 WINE_FIXME("unsupported switch %s\n", debugstr_w(prop)); 783 return FALSE; 784 } 785 return TRUE; 786 } 787 788 int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cmdshow) 789 { 790 WCHAR *ext, *filepart, *filename = NULL; 791 IActiveScriptParse *parser; 792 IActiveScript *script; 793 WCHAR **argv; 794 CLSID clsid; 795 int argc, i; 796 DWORD res; 797 798 WINE_TRACE("(%p %p %s %x)\n", hInst, hPrevInst, wine_dbgstr_w(cmdline), cmdshow); 799 800 argv = CommandLineToArgvW(GetCommandLineW(), &argc); 801 if(!argv) 802 return 1; 803 804 for(i=1; i<argc; i++) { 805 if(*argv[i] == '/' || *argv[i] == '-') { 806 if(!set_host_properties(argv[i])) 807 return 1; 808 }else { 809 filename = argv[i]; 810 argums = argv+i+1; 811 numOfArgs = argc-i-1; 812 break; 813 } 814 } 815 816 if(!filename) { 817 WINE_FIXME("No file name specified\n"); 818 return 1; 819 } 820 res = GetFullPathNameW(filename, ARRAY_SIZE(scriptFullName), scriptFullName, &filepart); 821 if(!res || res > ARRAY_SIZE(scriptFullName)) 822 return 1; 823 824 ext = wcsrchr(filepart, '.'); 825 #ifdef __REACTOS__ 826 if (ext && !lstrcmpiW(ext, L".wsf")) { 827 return run_wsf(scriptFullName); 828 } 829 #endif 830 if(!ext || !get_engine_clsid(ext, &clsid)) { 831 WINE_FIXME("Could not find engine for %s\n", wine_dbgstr_w(ext)); 832 return 1; 833 } 834 835 CoInitialize(NULL); 836 837 if(!create_engine(&clsid, &script, &parser)) { 838 WINE_FIXME("Could not create script engine\n"); 839 CoUninitialize(); 840 return 1; 841 } 842 843 if(init_engine(script, parser)) { 844 run_script(filename, script, parser); 845 IActiveScript_Close(script); 846 ITypeInfo_Release(host_ti); 847 }else { 848 WINE_FIXME("Script initialization failed\n"); 849 } 850 851 IActiveScript_Release(script); 852 IActiveScriptParse_Release(parser); 853 854 #ifdef __REACTOS__ 855 free_globals(); 856 #endif 857 858 CoUninitialize(); 859 860 return 0; 861 } 862