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