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