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