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