jscript: Call SetSite on created ActiveX object.
[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
55     IActiveScriptSite *site;
56
57     parser_ctx_t *queue_head;
58     parser_ctx_t *queue_tail;
59 } JScript;
60
61 #define ACTSCRIPT(x)    ((IActiveScript*) &(x)->lpIActiveScriptVtbl)
62 #define ASPARSE(x)      (&(x)->lpIActiveScriptParseVtbl)
63 #define ASPARSEPROC(x)  (&(x)->lpIActiveScriptParseProcedure2Vtbl)
64 #define ACTSCPPROP(x)   (&(x)->lpIActiveScriptPropertyVtbl)
65 #define OBJSAFETY(x)    (&(x)->lpIObjectSafetyVtbl)
66
67 void script_release(script_ctx_t *ctx)
68 {
69     if(--ctx->ref)
70         return;
71
72     jsheap_free(&ctx->tmp_heap);
73     heap_free(ctx);
74 }
75
76 static void change_state(JScript *This, SCRIPTSTATE state)
77 {
78     if(This->ctx->state == state)
79         return;
80
81     This->ctx->state = state;
82     IActiveScriptSite_OnStateChange(This->site, state);
83 }
84
85 static inline BOOL is_started(script_ctx_t *ctx)
86 {
87     return ctx->state == SCRIPTSTATE_STARTED
88         || ctx->state == SCRIPTSTATE_CONNECTED
89         || ctx->state == SCRIPTSTATE_DISCONNECTED;
90 }
91
92 static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
93 {
94     exec_ctx_t *exec_ctx;
95     jsexcept_t jsexcept;
96     VARIANT var;
97     HRESULT hres;
98
99     hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx);
100     if(FAILED(hres))
101         return hres;
102
103     IActiveScriptSite_OnEnterScript(This->site);
104
105     memset(&jsexcept, 0, sizeof(jsexcept));
106     hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, &jsexcept, &var);
107     VariantClear(&jsexcept.var);
108     exec_release(exec_ctx);
109     if(SUCCEEDED(hres))
110         VariantClear(&var);
111
112     IActiveScriptSite_OnLeaveScript(This->site);
113
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     default:
384         FIXME("unimplemented state %d\n", ss);
385         return E_NOTIMPL;
386     }
387
388     change_state(This, ss);
389     return S_OK;
390 }
391
392 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
393 {
394     JScript *This = ACTSCRIPT_THIS(iface);
395
396     TRACE("(%p)->(%p)\n", This, pssState);
397
398     if(!pssState)
399         return E_POINTER;
400
401     if(!This->thread_id) {
402         *pssState = SCRIPTSTATE_UNINITIALIZED;
403         return S_OK;
404     }
405
406     if(This->thread_id != GetCurrentThreadId())
407         return E_UNEXPECTED;
408
409     *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED;
410     return S_OK;
411 }
412
413 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
414 {
415     JScript *This = ACTSCRIPT_THIS(iface);
416
417     TRACE("(%p)->()\n", This);
418
419     if(This->thread_id != GetCurrentThreadId())
420         return E_UNEXPECTED;
421
422     if(This->ctx) {
423         if(This->ctx->state == SCRIPTSTATE_CONNECTED)
424             change_state(This, SCRIPTSTATE_DISCONNECTED);
425
426         clear_script_queue(This);
427
428         if(This->ctx->state == SCRIPTSTATE_DISCONNECTED)
429             change_state(This, SCRIPTSTATE_INITIALIZED);
430
431         if(This->ctx->host_global) {
432             IDispatch_Release(This->ctx->host_global);
433             This->ctx->host_global = NULL;
434         }
435
436         if(This->ctx->named_items) {
437             named_item_t *iter, *iter2;
438
439             iter = This->ctx->named_items;
440             while(iter) {
441                 iter2 = iter->next;
442
443                 if(iter->disp)
444                     IDispatch_Release(iter->disp);
445                 heap_free(iter->name);
446                 heap_free(iter);
447                 iter = iter2;
448             }
449
450             This->ctx->named_items = NULL;
451         }
452
453         if(This->ctx->secmgr) {
454             IInternetHostSecurityManager_Release(This->ctx->secmgr);
455             This->ctx->secmgr = NULL;
456         }
457
458         if(This->ctx->site) {
459             IActiveScriptSite_Release(This->ctx->site);
460             This->ctx->site = NULL;
461         }
462
463         if (This->site)
464             change_state(This, SCRIPTSTATE_CLOSED);
465
466         if(This->ctx->global) {
467             jsdisp_release(This->ctx->global);
468             This->ctx->global = NULL;
469         }
470     }
471
472     if(This->site) {
473         IActiveScriptSite_Release(This->site);
474         This->site = NULL;
475     }
476
477     return S_OK;
478 }
479
480 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
481                                            LPCOLESTR pstrName, DWORD dwFlags)
482 {
483     JScript *This = ACTSCRIPT_THIS(iface);
484     named_item_t *item;
485     IDispatch *disp = NULL;
486     HRESULT hres;
487
488     TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
489
490     if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->ctx->state == SCRIPTSTATE_CLOSED)
491         return E_UNEXPECTED;
492
493     if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
494         IUnknown *unk;
495
496         hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
497         if(FAILED(hres)) {
498             WARN("GetItemInfo failed: %08x\n", hres);
499             return hres;
500         }
501
502         hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
503         IUnknown_Release(unk);
504         if(FAILED(hres)) {
505             WARN("object does not implement IDispatch\n");
506             return hres;
507         }
508
509         if(This->ctx->host_global)
510             IDispatch_Release(This->ctx->host_global);
511         IDispatch_AddRef(disp);
512         This->ctx->host_global = disp;
513     }
514
515     item = heap_alloc(sizeof(*item));
516     if(!item) {
517         if(disp)
518             IDispatch_Release(disp);
519         return E_OUTOFMEMORY;
520     }
521
522     item->disp = disp;
523     item->flags = dwFlags;
524     item->name = heap_strdupW(pstrName);
525     if(!item->name) {
526         IDispatch_Release(disp);
527         heap_free(item);
528         return E_OUTOFMEMORY;
529     }
530
531     item->next = This->ctx->named_items;
532     This->ctx->named_items = item;
533
534     return S_OK;
535 }
536
537 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
538                                          DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
539 {
540     JScript *This = ACTSCRIPT_THIS(iface);
541     FIXME("(%p)->()\n", This);
542     return E_NOTIMPL;
543 }
544
545 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
546                                                 IDispatch **ppdisp)
547 {
548     JScript *This = ACTSCRIPT_THIS(iface);
549
550     TRACE("(%p)->(%p)\n", This, ppdisp);
551
552     if(!ppdisp)
553         return E_POINTER;
554
555     if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) {
556         *ppdisp = NULL;
557         return E_UNEXPECTED;
558     }
559
560     *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global);
561     IDispatch_AddRef(*ppdisp);
562     return S_OK;
563 }
564
565 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
566                                                        SCRIPTTHREADID *pstridThread)
567 {
568     JScript *This = ACTSCRIPT_THIS(iface);
569     FIXME("(%p)->()\n", This);
570     return E_NOTIMPL;
571 }
572
573 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
574                                                 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
575 {
576     JScript *This = ACTSCRIPT_THIS(iface);
577     FIXME("(%p)->()\n", This);
578     return E_NOTIMPL;
579 }
580
581 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
582         SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
583 {
584     JScript *This = ACTSCRIPT_THIS(iface);
585     FIXME("(%p)->()\n", This);
586     return E_NOTIMPL;
587 }
588
589 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
590         SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
591 {
592     JScript *This = ACTSCRIPT_THIS(iface);
593     FIXME("(%p)->()\n", This);
594     return E_NOTIMPL;
595 }
596
597 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
598 {
599     JScript *This = ACTSCRIPT_THIS(iface);
600     FIXME("(%p)->()\n", This);
601     return E_NOTIMPL;
602 }
603
604 #undef ACTSCRIPT_THIS
605
606 static const IActiveScriptVtbl JScriptVtbl = {
607     JScript_QueryInterface,
608     JScript_AddRef,
609     JScript_Release,
610     JScript_SetScriptSite,
611     JScript_GetScriptSite,
612     JScript_SetScriptState,
613     JScript_GetScriptState,
614     JScript_Close,
615     JScript_AddNamedItem,
616     JScript_AddTypeLib,
617     JScript_GetScriptDispatch,
618     JScript_GetCurrentScriptThreadID,
619     JScript_GetScriptThreadID,
620     JScript_GetScriptThreadState,
621     JScript_InterruptScriptThread,
622     JScript_Clone
623 };
624
625 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
626
627 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
628 {
629     JScript *This = ASPARSE_THIS(iface);
630     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
631 }
632
633 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
634 {
635     JScript *This = ASPARSE_THIS(iface);
636     return IActiveScript_AddRef(ACTSCRIPT(This));
637 }
638
639 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
640 {
641     JScript *This = ASPARSE_THIS(iface);
642     return IActiveScript_Release(ACTSCRIPT(This));
643 }
644
645 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
646 {
647     JScript *This = ASPARSE_THIS(iface);
648     script_ctx_t *ctx;
649
650     TRACE("(%p)\n", This);
651
652     if(This->ctx)
653         return E_UNEXPECTED;
654
655     ctx = heap_alloc_zero(sizeof(script_ctx_t));
656     if(!ctx)
657         return E_OUTOFMEMORY;
658
659     ctx->ref = 1;
660     ctx->state = SCRIPTSTATE_UNINITIALIZED;
661     ctx->safeopt = This->safeopt;
662     jsheap_init(&ctx->tmp_heap);
663
664     ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
665     if(ctx) {
666         script_release(ctx);
667         return E_UNEXPECTED;
668     }
669
670     return This->site ? set_ctx_site(This) : S_OK;
671 }
672
673 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
674         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
675         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
676         CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
677         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
678 {
679     JScript *This = ASPARSE_THIS(iface);
680     FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
681           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
682           debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
683           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
684     return E_NOTIMPL;
685 }
686
687 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
688         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
689         LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
690         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
691 {
692     JScript *This = ASPARSE_THIS(iface);
693     parser_ctx_t *parser_ctx;
694     HRESULT hres;
695
696     TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
697           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
698           wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo);
699
700     if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
701         return E_UNEXPECTED;
702
703     hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx);
704     if(FAILED(hres))
705         return hres;
706
707     if(!is_started(This->ctx)) {
708         if(This->queue_tail)
709             This->queue_tail = This->queue_tail->next = parser_ctx;
710         else
711             This->queue_head = This->queue_tail = parser_ctx;
712         return S_OK;
713     }
714
715     hres = exec_global_code(This, parser_ctx);
716     parser_release(parser_ctx);
717
718     return hres;
719 }
720
721 #undef ASPARSE_THIS
722
723 static const IActiveScriptParseVtbl JScriptParseVtbl = {
724     JScriptParse_QueryInterface,
725     JScriptParse_AddRef,
726     JScriptParse_Release,
727     JScriptParse_InitNew,
728     JScriptParse_AddScriptlet,
729     JScriptParse_ParseScriptText
730 };
731
732 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParseProcedure2, iface)
733
734 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
735 {
736     JScript *This = ASPARSEPROC_THIS(iface);
737     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
738 }
739
740 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
741 {
742     JScript *This = ASPARSEPROC_THIS(iface);
743     return IActiveScript_AddRef(ACTSCRIPT(This));
744 }
745
746 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
747 {
748     JScript *This = ASPARSEPROC_THIS(iface);
749     return IActiveScript_Release(ACTSCRIPT(This));
750 }
751
752 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
753         LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
754         LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
755         CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
756 {
757     JScript *This = ASPARSEPROC_THIS(iface);
758     parser_ctx_t *parser_ctx;
759     DispatchEx *dispex;
760     HRESULT hres;
761
762     TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
763           debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
764           wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp);
765
766     if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
767         return E_UNEXPECTED;
768
769     hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx);
770     if(FAILED(hres)) {
771         WARN("Parse failed %08x\n", hres);
772         return hres;
773     }
774
775     hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex);
776     parser_release(parser_ctx);
777     if(FAILED(hres))
778         return hres;
779
780     *ppdisp = (IDispatch*)_IDispatchEx_(dispex);
781     return S_OK;
782 }
783
784 #undef ASPARSEPROC_THIS
785
786 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
787     JScriptParseProcedure_QueryInterface,
788     JScriptParseProcedure_AddRef,
789     JScriptParseProcedure_Release,
790     JScriptParseProcedure_ParseProcedureText,
791 };
792
793 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
794
795 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
796 {
797     JScript *This = ACTSCPPROP_THIS(iface);
798     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
799 }
800
801 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
802 {
803     JScript *This = ACTSCPPROP_THIS(iface);
804     return IActiveScript_AddRef(ACTSCRIPT(This));
805 }
806
807 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
808 {
809     JScript *This = ACTSCPPROP_THIS(iface);
810     return IActiveScript_Release(ACTSCRIPT(This));
811 }
812
813 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
814         VARIANT *pvarIndex, VARIANT *pvarValue)
815 {
816     JScript *This = ACTSCPPROP_THIS(iface);
817     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
818     return E_NOTIMPL;
819 }
820
821 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
822         VARIANT *pvarIndex, VARIANT *pvarValue)
823 {
824     JScript *This = ACTSCPPROP_THIS(iface);
825     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
826     return E_NOTIMPL;
827 }
828
829 #undef ACTSCPPROP_THIS
830
831 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
832     JScriptProperty_QueryInterface,
833     JScriptProperty_AddRef,
834     JScriptProperty_Release,
835     JScriptProperty_GetProperty,
836     JScriptProperty_SetProperty
837 };
838
839 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
840
841 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
842 {
843     JScript *This = OBJSAFETY_THIS(iface);
844     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
845 }
846
847 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
848 {
849     JScript *This = OBJSAFETY_THIS(iface);
850     return IActiveScript_AddRef(ACTSCRIPT(This));
851 }
852
853 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
854 {
855     JScript *This = OBJSAFETY_THIS(iface);
856     return IActiveScript_Release(ACTSCRIPT(This));
857 }
858
859 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
860
861 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
862         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
863 {
864     JScript *This = OBJSAFETY_THIS(iface);
865
866     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
867
868     if(!pdwSupportedOptions || !pdwEnabledOptions)
869         return E_POINTER;
870
871     *pdwSupportedOptions = SUPPORTED_OPTIONS;
872     *pdwEnabledOptions = This->safeopt;
873
874     return S_OK;
875 }
876
877 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
878         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
879 {
880     JScript *This = OBJSAFETY_THIS(iface);
881
882     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
883
884     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
885         return E_FAIL;
886
887     This->safeopt = dwEnabledOptions & dwEnabledOptions;
888     return S_OK;
889 }
890
891 #undef OBJSAFETY_THIS
892
893 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
894     JScriptSafety_QueryInterface,
895     JScriptSafety_AddRef,
896     JScriptSafety_Release,
897     JScriptSafety_GetInterfaceSafetyOptions,
898     JScriptSafety_SetInterfaceSafetyOptions
899 };
900
901 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
902                                              REFIID riid, void **ppv)
903 {
904     JScript *ret;
905     HRESULT hres;
906
907     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
908
909     lock_module();
910
911     ret = heap_alloc_zero(sizeof(*ret));
912     if(!ret)
913         return E_OUTOFMEMORY;
914
915     ret->lpIActiveScriptVtbl                 = &JScriptVtbl;
916     ret->lpIActiveScriptParseVtbl            = &JScriptParseVtbl;
917     ret->lpIActiveScriptParseProcedure2Vtbl  = &JScriptParseProcedureVtbl;
918     ret->lpIActiveScriptPropertyVtbl         = &JScriptPropertyVtbl;
919     ret->lpIObjectSafetyVtbl                 = &JScriptSafetyVtbl;
920     ret->ref = 1;
921     ret->safeopt = INTERFACE_USES_DISPEX;
922
923     hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
924     IActiveScript_Release(ACTSCRIPT(ret));
925     return hres;
926 }