1 /* 2 * Copyright 2008 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 <assert.h> 20 21 #include "jscript.h" 22 #include "engine.h" 23 #include "objsafe.h" 24 25 #include "wine/debug.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(jscript); 28 29 #ifdef _WIN64 30 31 #define CTXARG_T DWORDLONG 32 #define IActiveScriptParseVtbl IActiveScriptParse64Vtbl 33 #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_64Vtbl 34 35 #else 36 37 #define CTXARG_T DWORD 38 #define IActiveScriptParseVtbl IActiveScriptParse32Vtbl 39 #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_32Vtbl 40 41 #endif 42 43 typedef struct { 44 IActiveScript IActiveScript_iface; 45 IActiveScriptParse IActiveScriptParse_iface; 46 IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_iface; 47 IActiveScriptProperty IActiveScriptProperty_iface; 48 IObjectSafety IObjectSafety_iface; 49 IVariantChangeType IVariantChangeType_iface; 50 51 LONG ref; 52 53 DWORD safeopt; 54 script_ctx_t *ctx; 55 LONG thread_id; 56 LCID lcid; 57 DWORD version; 58 BOOL html_mode; 59 BOOL is_encode; 60 61 IActiveScriptSite *site; 62 63 bytecode_t *queue_head; 64 bytecode_t *queue_tail; 65 } JScript; 66 67 void script_release(script_ctx_t *ctx) 68 { 69 if(--ctx->ref) 70 return; 71 72 clear_ei(ctx); 73 if(ctx->cc) 74 release_cc(ctx->cc); 75 heap_pool_free(&ctx->tmp_heap); 76 if(ctx->last_match) 77 jsstr_release(ctx->last_match); 78 assert(!ctx->stack_top); 79 heap_free(ctx->stack); 80 81 ctx->jscaller->ctx = NULL; 82 IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); 83 84 heap_free(ctx); 85 } 86 87 static void change_state(JScript *This, SCRIPTSTATE state) 88 { 89 if(This->ctx->state == state) 90 return; 91 92 This->ctx->state = state; 93 if(This->site) 94 IActiveScriptSite_OnStateChange(This->site, state); 95 } 96 97 static inline BOOL is_started(script_ctx_t *ctx) 98 { 99 return ctx->state == SCRIPTSTATE_STARTED 100 || ctx->state == SCRIPTSTATE_CONNECTED 101 || ctx->state == SCRIPTSTATE_DISCONNECTED; 102 } 103 104 static HRESULT exec_global_code(JScript *This, bytecode_t *code) 105 { 106 HRESULT hres; 107 108 IActiveScriptSite_OnEnterScript(This->site); 109 110 clear_ei(This->ctx); 111 hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, NULL); 112 113 IActiveScriptSite_OnLeaveScript(This->site); 114 return hres; 115 } 116 117 static void clear_script_queue(JScript *This) 118 { 119 bytecode_t *iter, *iter2; 120 121 if(!This->queue_head) 122 return; 123 124 iter = This->queue_head; 125 while(iter) { 126 iter2 = iter->next; 127 iter->next = NULL; 128 release_bytecode(iter); 129 iter = iter2; 130 } 131 132 This->queue_head = This->queue_tail = NULL; 133 } 134 135 static void exec_queued_code(JScript *This) 136 { 137 bytecode_t *iter; 138 139 for(iter = This->queue_head; iter; iter = iter->next) 140 exec_global_code(This, iter); 141 142 clear_script_queue(This); 143 } 144 145 static HRESULT set_ctx_site(JScript *This) 146 { 147 HRESULT hres; 148 149 This->ctx->lcid = This->lcid; 150 151 hres = init_global(This->ctx); 152 if(FAILED(hres)) 153 return hres; 154 155 IActiveScriptSite_AddRef(This->site); 156 This->ctx->site = This->site; 157 158 change_state(This, SCRIPTSTATE_INITIALIZED); 159 return S_OK; 160 } 161 162 static void decrease_state(JScript *This, SCRIPTSTATE state) 163 { 164 if(This->ctx) { 165 switch(This->ctx->state) { 166 case SCRIPTSTATE_CONNECTED: 167 change_state(This, SCRIPTSTATE_DISCONNECTED); 168 if(state == SCRIPTSTATE_DISCONNECTED) 169 return; 170 /* FALLTHROUGH */ 171 case SCRIPTSTATE_STARTED: 172 case SCRIPTSTATE_DISCONNECTED: 173 clear_script_queue(This); 174 175 if(This->ctx->state == SCRIPTSTATE_DISCONNECTED) 176 change_state(This, SCRIPTSTATE_INITIALIZED); 177 if(state == SCRIPTSTATE_INITIALIZED) 178 return; 179 /* FALLTHROUGH */ 180 case SCRIPTSTATE_INITIALIZED: 181 if(This->ctx->host_global) { 182 IDispatch_Release(This->ctx->host_global); 183 This->ctx->host_global = NULL; 184 } 185 186 if(This->ctx->named_items) { 187 named_item_t *iter, *iter2; 188 189 iter = This->ctx->named_items; 190 while(iter) { 191 iter2 = iter->next; 192 193 if(iter->disp) 194 IDispatch_Release(iter->disp); 195 heap_free(iter->name); 196 heap_free(iter); 197 iter = iter2; 198 } 199 200 This->ctx->named_items = NULL; 201 } 202 203 if(This->ctx->secmgr) { 204 IInternetHostSecurityManager_Release(This->ctx->secmgr); 205 This->ctx->secmgr = NULL; 206 } 207 208 if(This->ctx->site) { 209 IActiveScriptSite_Release(This->ctx->site); 210 This->ctx->site = NULL; 211 } 212 213 if(This->ctx->global) { 214 jsdisp_release(This->ctx->global); 215 This->ctx->global = NULL; 216 } 217 /* FALLTHROUGH */ 218 case SCRIPTSTATE_UNINITIALIZED: 219 change_state(This, state); 220 break; 221 default: 222 assert(0); 223 } 224 225 change_state(This, state); 226 }else if(state == SCRIPTSTATE_UNINITIALIZED) { 227 if(This->site) 228 IActiveScriptSite_OnStateChange(This->site, state); 229 }else { 230 FIXME("NULL ctx\n"); 231 } 232 233 if(state == SCRIPTSTATE_UNINITIALIZED) 234 This->thread_id = 0; 235 236 if(This->site) { 237 IActiveScriptSite_Release(This->site); 238 This->site = NULL; 239 } 240 } 241 242 typedef struct { 243 IServiceProvider IServiceProvider_iface; 244 245 LONG ref; 246 247 IServiceProvider *sp; 248 } AXSite; 249 250 static inline AXSite *impl_from_IServiceProvider(IServiceProvider *iface) 251 { 252 return CONTAINING_RECORD(iface, AXSite, IServiceProvider_iface); 253 } 254 255 static HRESULT WINAPI AXSite_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) 256 { 257 AXSite *This = impl_from_IServiceProvider(iface); 258 259 if(IsEqualGUID(&IID_IUnknown, riid)) { 260 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 261 *ppv = &This->IServiceProvider_iface; 262 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { 263 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); 264 *ppv = &This->IServiceProvider_iface; 265 }else { 266 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 267 *ppv = NULL; 268 return E_NOINTERFACE; 269 } 270 271 IUnknown_AddRef((IUnknown*)*ppv); 272 return S_OK; 273 } 274 275 static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface) 276 { 277 AXSite *This = impl_from_IServiceProvider(iface); 278 LONG ref = InterlockedIncrement(&This->ref); 279 280 TRACE("(%p) ref=%d\n", This, ref); 281 282 return ref; 283 } 284 285 static ULONG WINAPI AXSite_Release(IServiceProvider *iface) 286 { 287 AXSite *This = impl_from_IServiceProvider(iface); 288 LONG ref = InterlockedDecrement(&This->ref); 289 290 TRACE("(%p) ref=%d\n", This, ref); 291 292 if(!ref) 293 { 294 if(This->sp) 295 IServiceProvider_Release(This->sp); 296 297 heap_free(This); 298 } 299 300 return ref; 301 } 302 303 static HRESULT WINAPI AXSite_QueryService(IServiceProvider *iface, 304 REFGUID guidService, REFIID riid, void **ppv) 305 { 306 AXSite *This = impl_from_IServiceProvider(iface); 307 308 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); 309 310 if(!This->sp) 311 return E_NOINTERFACE; 312 313 return IServiceProvider_QueryService(This->sp, guidService, riid, ppv); 314 } 315 316 static IServiceProviderVtbl AXSiteVtbl = { 317 AXSite_QueryInterface, 318 AXSite_AddRef, 319 AXSite_Release, 320 AXSite_QueryService 321 }; 322 323 IUnknown *create_ax_site(script_ctx_t *ctx) 324 { 325 IServiceProvider *sp = NULL; 326 AXSite *ret; 327 HRESULT hres; 328 329 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp); 330 if(FAILED(hres)) { 331 TRACE("Could not get IServiceProvider iface: %08x\n", hres); 332 } 333 334 ret = heap_alloc(sizeof(AXSite)); 335 if(!ret) { 336 IServiceProvider_Release(sp); 337 return NULL; 338 } 339 340 ret->IServiceProvider_iface.lpVtbl = &AXSiteVtbl; 341 ret->ref = 1; 342 ret->sp = sp; 343 344 return (IUnknown*)&ret->IServiceProvider_iface; 345 } 346 347 static inline JScript *impl_from_IActiveScript(IActiveScript *iface) 348 { 349 return CONTAINING_RECORD(iface, JScript, IActiveScript_iface); 350 } 351 352 static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv) 353 { 354 JScript *This = impl_from_IActiveScript(iface); 355 356 *ppv = NULL; 357 358 if(IsEqualGUID(riid, &IID_IUnknown)) { 359 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 360 *ppv = &This->IActiveScript_iface; 361 }else if(IsEqualGUID(riid, &IID_IActiveScript)) { 362 TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv); 363 *ppv = &This->IActiveScript_iface; 364 }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) { 365 TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv); 366 *ppv = &This->IActiveScriptParse_iface; 367 }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) { 368 TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv); 369 *ppv = &This->IActiveScriptParseProcedure2_iface; 370 }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) { 371 TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv); 372 *ppv = &This->IActiveScriptParseProcedure2_iface; 373 }else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) { 374 TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv); 375 *ppv = &This->IActiveScriptProperty_iface; 376 }else if(IsEqualGUID(riid, &IID_IObjectSafety)) { 377 TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv); 378 *ppv = &This->IObjectSafety_iface; 379 }else if(IsEqualGUID(riid, &IID_IVariantChangeType)) { 380 TRACE("(%p)->(IID_IVariantChangeType %p)\n", This, ppv); 381 *ppv = &This->IVariantChangeType_iface; 382 } 383 384 if(*ppv) { 385 IUnknown_AddRef((IUnknown*)*ppv); 386 return S_OK; 387 } 388 389 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 390 return E_NOINTERFACE; 391 } 392 393 static ULONG WINAPI JScript_AddRef(IActiveScript *iface) 394 { 395 JScript *This = impl_from_IActiveScript(iface); 396 LONG ref = InterlockedIncrement(&This->ref); 397 398 TRACE("(%p) ref=%d\n", This, ref); 399 400 return ref; 401 } 402 403 static ULONG WINAPI JScript_Release(IActiveScript *iface) 404 { 405 JScript *This = impl_from_IActiveScript(iface); 406 LONG ref = InterlockedDecrement(&This->ref); 407 408 TRACE("(%p) ref=%d\n", iface, ref); 409 410 if(!ref) { 411 if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED) 412 IActiveScript_Close(&This->IActiveScript_iface); 413 if(This->ctx) { 414 This->ctx->active_script = NULL; 415 script_release(This->ctx); 416 } 417 heap_free(This); 418 unlock_module(); 419 } 420 421 return ref; 422 } 423 424 static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface, 425 IActiveScriptSite *pass) 426 { 427 JScript *This = impl_from_IActiveScript(iface); 428 LCID lcid; 429 HRESULT hres; 430 431 TRACE("(%p)->(%p)\n", This, pass); 432 433 if(!pass) 434 return E_POINTER; 435 436 if(This->site) 437 return E_UNEXPECTED; 438 439 if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0)) 440 return E_UNEXPECTED; 441 442 This->site = pass; 443 IActiveScriptSite_AddRef(This->site); 444 445 hres = IActiveScriptSite_GetLCID(This->site, &lcid); 446 if(hres == S_OK) 447 This->lcid = lcid; 448 449 return This->ctx ? set_ctx_site(This) : S_OK; 450 } 451 452 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid, 453 void **ppvObject) 454 { 455 JScript *This = impl_from_IActiveScript(iface); 456 FIXME("(%p)->()\n", This); 457 return E_NOTIMPL; 458 } 459 460 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss) 461 { 462 JScript *This = impl_from_IActiveScript(iface); 463 464 TRACE("(%p)->(%d)\n", This, ss); 465 466 if(This->thread_id && GetCurrentThreadId() != This->thread_id) 467 return E_UNEXPECTED; 468 469 if(ss == SCRIPTSTATE_UNINITIALIZED) { 470 if(This->ctx && This->ctx->state == SCRIPTSTATE_CLOSED) 471 return E_UNEXPECTED; 472 473 decrease_state(This, SCRIPTSTATE_UNINITIALIZED); 474 return S_OK; 475 } 476 477 if(!This->ctx) 478 return E_UNEXPECTED; 479 480 switch(ss) { 481 case SCRIPTSTATE_STARTED: 482 case SCRIPTSTATE_CONNECTED: /* FIXME */ 483 if(This->ctx->state == SCRIPTSTATE_CLOSED) 484 return E_UNEXPECTED; 485 486 exec_queued_code(This); 487 break; 488 case SCRIPTSTATE_INITIALIZED: 489 FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n"); 490 return S_OK; 491 default: 492 FIXME("unimplemented state %d\n", ss); 493 return E_NOTIMPL; 494 } 495 496 change_state(This, ss); 497 return S_OK; 498 } 499 500 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState) 501 { 502 JScript *This = impl_from_IActiveScript(iface); 503 504 TRACE("(%p)->(%p)\n", This, pssState); 505 506 if(!pssState) 507 return E_POINTER; 508 509 if(This->thread_id && This->thread_id != GetCurrentThreadId()) 510 return E_UNEXPECTED; 511 512 *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED; 513 return S_OK; 514 } 515 516 static HRESULT WINAPI JScript_Close(IActiveScript *iface) 517 { 518 JScript *This = impl_from_IActiveScript(iface); 519 520 TRACE("(%p)->()\n", This); 521 522 if(This->thread_id && This->thread_id != GetCurrentThreadId()) 523 return E_UNEXPECTED; 524 525 decrease_state(This, SCRIPTSTATE_CLOSED); 526 return S_OK; 527 } 528 529 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, 530 LPCOLESTR pstrName, DWORD dwFlags) 531 { 532 JScript *This = impl_from_IActiveScript(iface); 533 named_item_t *item; 534 IDispatch *disp = NULL; 535 HRESULT hres; 536 537 TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags); 538 539 if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED) 540 return E_UNEXPECTED; 541 542 if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) { 543 IUnknown *unk; 544 545 hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL); 546 if(FAILED(hres)) { 547 WARN("GetItemInfo failed: %08x\n", hres); 548 return hres; 549 } 550 551 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp); 552 IUnknown_Release(unk); 553 if(FAILED(hres)) { 554 WARN("object does not implement IDispatch\n"); 555 return hres; 556 } 557 558 if(This->ctx->host_global) 559 IDispatch_Release(This->ctx->host_global); 560 IDispatch_AddRef(disp); 561 This->ctx->host_global = disp; 562 } 563 564 item = heap_alloc(sizeof(*item)); 565 if(!item) { 566 if(disp) 567 IDispatch_Release(disp); 568 return E_OUTOFMEMORY; 569 } 570 571 item->disp = disp; 572 item->flags = dwFlags; 573 item->name = heap_strdupW(pstrName); 574 if(!item->name) { 575 if(disp) 576 IDispatch_Release(disp); 577 heap_free(item); 578 return E_OUTOFMEMORY; 579 } 580 581 item->next = This->ctx->named_items; 582 This->ctx->named_items = item; 583 584 return S_OK; 585 } 586 587 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib, 588 DWORD dwMajor, DWORD dwMinor, DWORD dwFlags) 589 { 590 JScript *This = impl_from_IActiveScript(iface); 591 FIXME("(%p)->()\n", This); 592 return E_NOTIMPL; 593 } 594 595 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, 596 IDispatch **ppdisp) 597 { 598 JScript *This = impl_from_IActiveScript(iface); 599 600 TRACE("(%p)->(%p)\n", This, ppdisp); 601 602 if(!ppdisp) 603 return E_POINTER; 604 605 if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) { 606 *ppdisp = NULL; 607 return E_UNEXPECTED; 608 } 609 610 *ppdisp = to_disp(This->ctx->global); 611 IDispatch_AddRef(*ppdisp); 612 return S_OK; 613 } 614 615 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface, 616 SCRIPTTHREADID *pstridThread) 617 { 618 JScript *This = impl_from_IActiveScript(iface); 619 FIXME("(%p)->()\n", This); 620 return E_NOTIMPL; 621 } 622 623 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface, 624 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread) 625 { 626 JScript *This = impl_from_IActiveScript(iface); 627 FIXME("(%p)->()\n", This); 628 return E_NOTIMPL; 629 } 630 631 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface, 632 SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState) 633 { 634 JScript *This = impl_from_IActiveScript(iface); 635 FIXME("(%p)->()\n", This); 636 return E_NOTIMPL; 637 } 638 639 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface, 640 SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags) 641 { 642 JScript *This = impl_from_IActiveScript(iface); 643 FIXME("(%p)->()\n", This); 644 return E_NOTIMPL; 645 } 646 647 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript) 648 { 649 JScript *This = impl_from_IActiveScript(iface); 650 FIXME("(%p)->()\n", This); 651 return E_NOTIMPL; 652 } 653 654 static const IActiveScriptVtbl JScriptVtbl = { 655 JScript_QueryInterface, 656 JScript_AddRef, 657 JScript_Release, 658 JScript_SetScriptSite, 659 JScript_GetScriptSite, 660 JScript_SetScriptState, 661 JScript_GetScriptState, 662 JScript_Close, 663 JScript_AddNamedItem, 664 JScript_AddTypeLib, 665 JScript_GetScriptDispatch, 666 JScript_GetCurrentScriptThreadID, 667 JScript_GetScriptThreadID, 668 JScript_GetScriptThreadState, 669 JScript_InterruptScriptThread, 670 JScript_Clone 671 }; 672 673 static inline JScript *impl_from_IActiveScriptParse(IActiveScriptParse *iface) 674 { 675 return CONTAINING_RECORD(iface, JScript, IActiveScriptParse_iface); 676 } 677 678 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv) 679 { 680 JScript *This = impl_from_IActiveScriptParse(iface); 681 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); 682 } 683 684 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface) 685 { 686 JScript *This = impl_from_IActiveScriptParse(iface); 687 return IActiveScript_AddRef(&This->IActiveScript_iface); 688 } 689 690 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface) 691 { 692 JScript *This = impl_from_IActiveScriptParse(iface); 693 return IActiveScript_Release(&This->IActiveScript_iface); 694 } 695 696 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface) 697 { 698 JScript *This = impl_from_IActiveScriptParse(iface); 699 script_ctx_t *ctx; 700 HRESULT hres; 701 702 TRACE("(%p)\n", This); 703 704 if(This->ctx) 705 return E_UNEXPECTED; 706 707 ctx = heap_alloc_zero(sizeof(script_ctx_t)); 708 if(!ctx) 709 return E_OUTOFMEMORY; 710 711 ctx->ref = 1; 712 ctx->state = SCRIPTSTATE_UNINITIALIZED; 713 ctx->active_script = &This->IActiveScript_iface; 714 ctx->safeopt = This->safeopt; 715 ctx->version = This->version; 716 ctx->html_mode = This->html_mode; 717 ctx->ei.val = jsval_undefined(); 718 heap_pool_init(&ctx->tmp_heap); 719 720 hres = create_jscaller(ctx); 721 if(FAILED(hres)) { 722 heap_free(ctx); 723 return hres; 724 } 725 726 ctx->last_match = jsstr_empty(); 727 728 ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL); 729 if(ctx) { 730 script_release(ctx); 731 return E_UNEXPECTED; 732 } 733 734 return This->site ? set_ctx_site(This) : S_OK; 735 } 736 737 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface, 738 LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName, 739 LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter, 740 CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, 741 BSTR *pbstrName, EXCEPINFO *pexcepinfo) 742 { 743 JScript *This = impl_from_IActiveScriptParse(iface); 744 FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName), 745 debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName), 746 debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie), 747 ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo); 748 return E_NOTIMPL; 749 } 750 751 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, 752 LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext, 753 LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine, 754 DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) 755 { 756 JScript *This = impl_from_IActiveScriptParse(iface); 757 bytecode_t *code; 758 HRESULT hres; 759 760 TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode), 761 debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter), 762 wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo); 763 764 if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) 765 return E_UNEXPECTED; 766 767 hres = compile_script(This->ctx, pstrCode, NULL, pstrDelimiter, (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, 768 This->is_encode, &code); 769 if(FAILED(hres)) 770 return hres; 771 772 if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { 773 jsval_t r; 774 775 IActiveScriptSite_OnEnterScript(This->site); 776 777 clear_ei(This->ctx); 778 hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, &r); 779 if(SUCCEEDED(hres)) { 780 if(pvarResult) 781 hres = jsval_to_variant(r, pvarResult); 782 jsval_release(r); 783 } 784 785 IActiveScriptSite_OnLeaveScript(This->site); 786 return hres; 787 } 788 789 /* 790 * Although pvarResult is not really used without SCRIPTTEXT_ISEXPRESSION flag, if it's not NULL, 791 * script is executed immediately, even if it's not in started state yet. 792 */ 793 if(!pvarResult && !is_started(This->ctx)) { 794 if(This->queue_tail) 795 This->queue_tail = This->queue_tail->next = code; 796 else 797 This->queue_head = This->queue_tail = code; 798 return S_OK; 799 } 800 801 hres = exec_global_code(This, code); 802 release_bytecode(code); 803 if(FAILED(hres)) 804 return hres; 805 806 if(pvarResult) 807 V_VT(pvarResult) = VT_EMPTY; 808 return S_OK; 809 } 810 811 static const IActiveScriptParseVtbl JScriptParseVtbl = { 812 JScriptParse_QueryInterface, 813 JScriptParse_AddRef, 814 JScriptParse_Release, 815 JScriptParse_InitNew, 816 JScriptParse_AddScriptlet, 817 JScriptParse_ParseScriptText 818 }; 819 820 static inline JScript *impl_from_IActiveScriptParseProcedure2(IActiveScriptParseProcedure2 *iface) 821 { 822 return CONTAINING_RECORD(iface, JScript, IActiveScriptParseProcedure2_iface); 823 } 824 825 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv) 826 { 827 JScript *This = impl_from_IActiveScriptParseProcedure2(iface); 828 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); 829 } 830 831 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface) 832 { 833 JScript *This = impl_from_IActiveScriptParseProcedure2(iface); 834 return IActiveScript_AddRef(&This->IActiveScript_iface); 835 } 836 837 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface) 838 { 839 JScript *This = impl_from_IActiveScriptParseProcedure2(iface); 840 return IActiveScript_Release(&This->IActiveScript_iface); 841 } 842 843 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface, 844 LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName, 845 LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter, 846 CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) 847 { 848 JScript *This = impl_from_IActiveScriptParseProcedure2(iface); 849 bytecode_t *code; 850 jsdisp_t *dispex; 851 HRESULT hres; 852 853 TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams), 854 debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter), 855 wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp); 856 857 if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) 858 return E_UNEXPECTED; 859 860 hres = compile_script(This->ctx, pstrCode, pstrFormalParams, pstrDelimiter, FALSE, This->is_encode, &code); 861 if(FAILED(hres)) { 862 WARN("Parse failed %08x\n", hres); 863 return hres; 864 } 865 866 hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex); 867 release_bytecode(code); 868 if(FAILED(hres)) 869 return hres; 870 871 *ppdisp = to_disp(dispex); 872 return S_OK; 873 } 874 875 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = { 876 JScriptParseProcedure_QueryInterface, 877 JScriptParseProcedure_AddRef, 878 JScriptParseProcedure_Release, 879 JScriptParseProcedure_ParseProcedureText, 880 }; 881 882 static inline JScript *impl_from_IActiveScriptProperty(IActiveScriptProperty *iface) 883 { 884 return CONTAINING_RECORD(iface, JScript, IActiveScriptProperty_iface); 885 } 886 887 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv) 888 { 889 JScript *This = impl_from_IActiveScriptProperty(iface); 890 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); 891 } 892 893 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface) 894 { 895 JScript *This = impl_from_IActiveScriptProperty(iface); 896 return IActiveScript_AddRef(&This->IActiveScript_iface); 897 } 898 899 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface) 900 { 901 JScript *This = impl_from_IActiveScriptProperty(iface); 902 return IActiveScript_Release(&This->IActiveScript_iface); 903 } 904 905 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty, 906 VARIANT *pvarIndex, VARIANT *pvarValue) 907 { 908 JScript *This = impl_from_IActiveScriptProperty(iface); 909 FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue); 910 return E_NOTIMPL; 911 } 912 913 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty, 914 VARIANT *pvarIndex, VARIANT *pvarValue) 915 { 916 JScript *This = impl_from_IActiveScriptProperty(iface); 917 918 TRACE("(%p)->(%x %s %s)\n", This, dwProperty, debugstr_variant(pvarIndex), debugstr_variant(pvarValue)); 919 920 if(pvarIndex) 921 FIXME("unsupported pvarIndex\n"); 922 923 switch(dwProperty) { 924 case SCRIPTPROP_INVOKEVERSIONING: 925 if(V_VT(pvarValue) != VT_I4 || V_I4(pvarValue) < 0 926 || (V_I4(pvarValue) > 15 && !(V_I4(pvarValue) & SCRIPTLANGUAGEVERSION_HTML))) { 927 WARN("invalid value %s\n", debugstr_variant(pvarValue)); 928 return E_INVALIDARG; 929 } 930 931 This->version = V_I4(pvarValue) & 0x1ff; 932 This->html_mode = (V_I4(pvarValue) & SCRIPTLANGUAGEVERSION_HTML) != 0; 933 break; 934 default: 935 FIXME("Unimplemented property %x\n", dwProperty); 936 return E_NOTIMPL; 937 } 938 939 return S_OK; 940 } 941 942 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = { 943 JScriptProperty_QueryInterface, 944 JScriptProperty_AddRef, 945 JScriptProperty_Release, 946 JScriptProperty_GetProperty, 947 JScriptProperty_SetProperty 948 }; 949 950 static inline JScript *impl_from_IObjectSafety(IObjectSafety *iface) 951 { 952 return CONTAINING_RECORD(iface, JScript, IObjectSafety_iface); 953 } 954 955 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv) 956 { 957 JScript *This = impl_from_IObjectSafety(iface); 958 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); 959 } 960 961 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface) 962 { 963 JScript *This = impl_from_IObjectSafety(iface); 964 return IActiveScript_AddRef(&This->IActiveScript_iface); 965 } 966 967 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface) 968 { 969 JScript *This = impl_from_IObjectSafety(iface); 970 return IActiveScript_Release(&This->IActiveScript_iface); 971 } 972 973 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER) 974 975 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, 976 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) 977 { 978 JScript *This = impl_from_IObjectSafety(iface); 979 980 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions); 981 982 if(!pdwSupportedOptions || !pdwEnabledOptions) 983 return E_POINTER; 984 985 *pdwSupportedOptions = SUPPORTED_OPTIONS; 986 *pdwEnabledOptions = This->safeopt; 987 988 return S_OK; 989 } 990 991 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, 992 DWORD dwOptionSetMask, DWORD dwEnabledOptions) 993 { 994 JScript *This = impl_from_IObjectSafety(iface); 995 996 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions); 997 998 if(dwOptionSetMask & ~SUPPORTED_OPTIONS) 999 return E_FAIL; 1000 1001 This->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX; 1002 return S_OK; 1003 } 1004 1005 static const IObjectSafetyVtbl JScriptSafetyVtbl = { 1006 JScriptSafety_QueryInterface, 1007 JScriptSafety_AddRef, 1008 JScriptSafety_Release, 1009 JScriptSafety_GetInterfaceSafetyOptions, 1010 JScriptSafety_SetInterfaceSafetyOptions 1011 }; 1012 1013 static inline JScript *impl_from_IVariantChangeType(IVariantChangeType *iface) 1014 { 1015 return CONTAINING_RECORD(iface, JScript, IVariantChangeType_iface); 1016 } 1017 1018 static HRESULT WINAPI VariantChangeType_QueryInterface(IVariantChangeType *iface, REFIID riid, void **ppv) 1019 { 1020 JScript *This = impl_from_IVariantChangeType(iface); 1021 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv); 1022 } 1023 1024 static ULONG WINAPI VariantChangeType_AddRef(IVariantChangeType *iface) 1025 { 1026 JScript *This = impl_from_IVariantChangeType(iface); 1027 return IActiveScript_AddRef(&This->IActiveScript_iface); 1028 } 1029 1030 static ULONG WINAPI VariantChangeType_Release(IVariantChangeType *iface) 1031 { 1032 JScript *This = impl_from_IVariantChangeType(iface); 1033 return IActiveScript_Release(&This->IActiveScript_iface); 1034 } 1035 1036 static HRESULT WINAPI VariantChangeType_ChangeType(IVariantChangeType *iface, VARIANT *dst, VARIANT *src, LCID lcid, VARTYPE vt) 1037 { 1038 JScript *This = impl_from_IVariantChangeType(iface); 1039 VARIANT res; 1040 HRESULT hres; 1041 1042 TRACE("(%p)->(%p %p%s %x %d)\n", This, dst, src, debugstr_variant(src), lcid, vt); 1043 1044 if(!This->ctx) { 1045 FIXME("Object uninitialized\n"); 1046 return E_UNEXPECTED; 1047 } 1048 1049 hres = variant_change_type(This->ctx, &res, src, vt); 1050 if(FAILED(hres)) 1051 return hres; 1052 1053 hres = VariantClear(dst); 1054 if(FAILED(hres)) { 1055 VariantClear(&res); 1056 return hres; 1057 } 1058 1059 *dst = res; 1060 return S_OK; 1061 } 1062 1063 static const IVariantChangeTypeVtbl VariantChangeTypeVtbl = { 1064 VariantChangeType_QueryInterface, 1065 VariantChangeType_AddRef, 1066 VariantChangeType_Release, 1067 VariantChangeType_ChangeType 1068 }; 1069 1070 HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv) 1071 { 1072 JScript *ret; 1073 HRESULT hres; 1074 1075 ret = heap_alloc_zero(sizeof(*ret)); 1076 if(!ret) 1077 return E_OUTOFMEMORY; 1078 1079 lock_module(); 1080 1081 ret->IActiveScript_iface.lpVtbl = &JScriptVtbl; 1082 ret->IActiveScriptParse_iface.lpVtbl = &JScriptParseVtbl; 1083 ret->IActiveScriptParseProcedure2_iface.lpVtbl = &JScriptParseProcedureVtbl; 1084 ret->IActiveScriptProperty_iface.lpVtbl = &JScriptPropertyVtbl; 1085 ret->IObjectSafety_iface.lpVtbl = &JScriptSafetyVtbl; 1086 ret->IVariantChangeType_iface.lpVtbl = &VariantChangeTypeVtbl; 1087 ret->ref = 1; 1088 ret->safeopt = INTERFACE_USES_DISPEX; 1089 ret->is_encode = is_encode; 1090 1091 hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv); 1092 IActiveScript_Release(&ret->IActiveScript_iface); 1093 return hres; 1094 } 1095