jscript: Added IActiveScript::ParseScriptText implementation.
[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 typedef struct {
28     const IActiveScriptVtbl                 *lpIActiveScriptVtbl;
29     const IActiveScriptParseVtbl            *lpIActiveScriptParseVtbl;
30     const IActiveScriptParseProcedure2Vtbl  *lpIActiveScriptParseProcedure2Vtbl;
31     const IActiveScriptPropertyVtbl         *lpIActiveScriptPropertyVtbl;
32     const IObjectSafetyVtbl                 *lpIObjectSafetyVtbl;
33
34     LONG ref;
35
36     DWORD safeopt;
37     script_ctx_t *ctx;
38     LONG thread_id;
39
40     IActiveScriptSite *site;
41
42     parser_ctx_t *queue_head;
43     parser_ctx_t *queue_tail;
44 } JScript;
45
46 #define ACTSCRIPT(x)    ((IActiveScript*)                 &(x)->lpIActiveScriptVtbl)
47 #define ASPARSE(x)      ((IActiveScriptParse*)            &(x)->lpIActiveScriptParseVtbl)
48 #define ASPARSEPROC(x)  ((IActiveScriptParseProcedure2*)  &(x)->lpIActiveScriptParseProcedure2Vtbl)
49 #define ACTSCPPROP(x)   ((IActiveScriptProperty*)         &(x)->lpIActiveScriptPropertyVtbl)
50 #define OBJSAFETY(x)    ((IObjectSafety*)                 &(x)->lpIObjectSafetyVtbl)
51
52 void script_release(script_ctx_t *ctx)
53 {
54     if(--ctx->ref)
55         return;
56
57     heap_free(ctx);
58 }
59
60 static void change_state(JScript *This, SCRIPTSTATE state)
61 {
62     if(This->ctx->state == state)
63         return;
64
65     This->ctx->state = state;
66     IActiveScriptSite_OnStateChange(This->site, state);
67 }
68
69 static inline BOOL is_started(script_ctx_t *ctx)
70 {
71     return ctx->state == SCRIPTSTATE_STARTED
72         || ctx->state == SCRIPTSTATE_CONNECTED
73         || ctx->state == SCRIPTSTATE_DISCONNECTED;
74 }
75
76 static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx)
77 {
78     exec_ctx_t *exec_ctx;
79     jsexcept_t jsexcept;
80     VARIANT var;
81     HRESULT hres;
82
83     hres = create_exec_ctx(&exec_ctx);
84     if(FAILED(hres))
85         return hres;
86
87     IActiveScriptSite_OnEnterScript(This->site);
88
89     memset(&jsexcept, 0, sizeof(jsexcept));
90     hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, &jsexcept, &var);
91     VariantClear(&jsexcept.var);
92     exec_release(exec_ctx);
93     if(SUCCEEDED(hres))
94         VariantClear(&var);
95
96     IActiveScriptSite_OnLeaveScript(This->site);
97
98     return hres;
99 }
100
101 static void clear_script_queue(JScript *This)
102 {
103     parser_ctx_t *iter, *iter2;
104
105     if(!This->queue_head)
106         return;
107
108     iter = This->queue_head;
109     while(iter) {
110         iter2 = iter->next;
111         iter->next = NULL;
112         parser_release(iter);
113         iter = iter2;
114     }
115
116     This->queue_head = This->queue_tail = NULL;
117 }
118
119 #define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface)
120
121 static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
122 {
123     JScript *This = ACTSCRIPT_THIS(iface);
124
125     *ppv = NULL;
126
127     if(IsEqualGUID(riid, &IID_IUnknown)) {
128         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
129         *ppv = ACTSCRIPT(This);
130     }else if(IsEqualGUID(riid, &IID_IActiveScript)) {
131         TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
132         *ppv = ACTSCRIPT(This);
133     }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
134         TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
135         *ppv = ASPARSE(This);
136     }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure)) {
137         TRACE("(%p)->(IID_IActiveScriptParseProcedure %p)\n", This, ppv);
138         *ppv = ASPARSEPROC(This);
139     }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) {
140         TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv);
141         *ppv = ASPARSEPROC(This);
142     }else if(IsEqualGUID(riid, &IID_IActiveScriptProperty)) {
143         TRACE("(%p)->(IID_IActiveScriptProperty %p)\n", This, ppv);
144         *ppv = ACTSCPPROP(This);
145     }else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
146         TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
147         *ppv = OBJSAFETY(This);
148     }
149
150     if(*ppv) {
151         IUnknown_AddRef((IUnknown*)*ppv);
152         return S_OK;
153     }
154
155     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
156     return E_NOINTERFACE;
157 }
158
159 static ULONG WINAPI JScript_AddRef(IActiveScript *iface)
160 {
161     JScript *This = ACTSCRIPT_THIS(iface);
162     LONG ref = InterlockedIncrement(&This->ref);
163
164     TRACE("(%p) ref=%d\n", This, ref);
165
166     return ref;
167 }
168
169 static ULONG WINAPI JScript_Release(IActiveScript *iface)
170 {
171     JScript *This = ACTSCRIPT_THIS(iface);
172     LONG ref = InterlockedDecrement(&This->ref);
173
174     TRACE("(%p) ref=%d\n", iface, ref);
175
176     if(!ref) {
177         if(This->ctx && This->ctx->state != SCRIPTSTATE_CLOSED)
178             IActiveScript_Close(ACTSCRIPT(This));
179         if(This->ctx)
180             script_release(This->ctx);
181         heap_free(This);
182         unlock_module();
183     }
184
185     return ref;
186 }
187
188 static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
189                                             IActiveScriptSite *pass)
190 {
191     JScript *This = ACTSCRIPT_THIS(iface);
192     LCID lcid;
193     HRESULT hres;
194
195     TRACE("(%p)->(%p)\n", This, pass);
196
197     if(!pass)
198         return E_POINTER;
199
200     if(This->site)
201         return E_UNEXPECTED;
202
203     if(!This->ctx) {
204         hres = IActiveScriptParse_InitNew(ASPARSE(This));
205         if(FAILED(hres))
206             return hres;
207     }
208
209     hres = create_dispex(This->ctx, &This->ctx->script_disp);
210     if(FAILED(hres))
211         return hres;
212
213     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
214         return E_UNEXPECTED;
215
216     This->site = pass;
217     IActiveScriptSite_AddRef(This->site);
218
219     hres = IActiveScriptSite_GetLCID(This->site, &lcid);
220     if(hres == S_OK)
221         This->ctx->lcid = lcid;
222
223     change_state(This, SCRIPTSTATE_INITIALIZED);
224     return S_OK;
225 }
226
227 static HRESULT WINAPI JScript_GetScriptSite(IActiveScript *iface, REFIID riid,
228                                             void **ppvObject)
229 {
230     JScript *This = ACTSCRIPT_THIS(iface);
231     FIXME("(%p)->()\n", This);
232     return E_NOTIMPL;
233 }
234
235 static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
236 {
237     JScript *This = ACTSCRIPT_THIS(iface);
238     FIXME("(%p)->(%d)\n", This, ss);
239     return E_NOTIMPL;
240 }
241
242 static HRESULT WINAPI JScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
243 {
244     JScript *This = ACTSCRIPT_THIS(iface);
245
246     TRACE("(%p)->(%p)\n", This, pssState);
247
248     if(!pssState)
249         return E_POINTER;
250
251     if(!This->thread_id) {
252         *pssState = SCRIPTSTATE_UNINITIALIZED;
253         return S_OK;
254     }
255
256     if(This->thread_id != GetCurrentThreadId())
257         return E_UNEXPECTED;
258
259     *pssState = This->ctx ? This->ctx->state : SCRIPTSTATE_UNINITIALIZED;
260     return S_OK;
261 }
262
263 static HRESULT WINAPI JScript_Close(IActiveScript *iface)
264 {
265     JScript *This = ACTSCRIPT_THIS(iface);
266
267     TRACE("(%p)->()\n", This);
268
269     if(This->thread_id != GetCurrentThreadId())
270         return E_UNEXPECTED;
271
272     clear_script_queue(This);
273
274     if(This->ctx) {
275         change_state(This, SCRIPTSTATE_CLOSED);
276
277         if(This->ctx->script_disp) {
278             IDispatchEx_Release(_IDispatchEx_(This->ctx->script_disp));
279             This->ctx->script_disp = NULL;
280         }
281     }
282
283     if(This->site) {
284         IActiveScriptSite_Release(This->site);
285         This->site = NULL;
286     }
287
288     return S_OK;
289 }
290
291 static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface,
292                                            LPCOLESTR pstrName, DWORD dwFlags)
293 {
294     JScript *This = ACTSCRIPT_THIS(iface);
295     FIXME("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI JScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
300                                          DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
301 {
302     JScript *This = ACTSCRIPT_THIS(iface);
303     FIXME("(%p)->()\n", This);
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
308                                                 IDispatch **ppdisp)
309 {
310     JScript *This = ACTSCRIPT_THIS(iface);
311
312     TRACE("(%p)->(%p)\n", This, ppdisp);
313
314     if(!ppdisp)
315         return E_POINTER;
316
317     if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
318         *ppdisp = NULL;
319         return E_UNEXPECTED;
320     }
321
322     *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
323     IDispatch_AddRef(*ppdisp);
324     return S_OK;
325 }
326
327 static HRESULT WINAPI JScript_GetCurrentScriptThreadID(IActiveScript *iface,
328                                                        SCRIPTTHREADID *pstridThread)
329 {
330     JScript *This = ACTSCRIPT_THIS(iface);
331     FIXME("(%p)->()\n", This);
332     return E_NOTIMPL;
333 }
334
335 static HRESULT WINAPI JScript_GetScriptThreadID(IActiveScript *iface,
336                                                 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
337 {
338     JScript *This = ACTSCRIPT_THIS(iface);
339     FIXME("(%p)->()\n", This);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI JScript_GetScriptThreadState(IActiveScript *iface,
344         SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
345 {
346     JScript *This = ACTSCRIPT_THIS(iface);
347     FIXME("(%p)->()\n", This);
348     return E_NOTIMPL;
349 }
350
351 static HRESULT WINAPI JScript_InterruptScriptThread(IActiveScript *iface,
352         SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
353 {
354     JScript *This = ACTSCRIPT_THIS(iface);
355     FIXME("(%p)->()\n", This);
356     return E_NOTIMPL;
357 }
358
359 static HRESULT WINAPI JScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
360 {
361     JScript *This = ACTSCRIPT_THIS(iface);
362     FIXME("(%p)->()\n", This);
363     return E_NOTIMPL;
364 }
365
366 #undef ACTSCRIPT_THIS
367
368 static const IActiveScriptVtbl JScriptVtbl = {
369     JScript_QueryInterface,
370     JScript_AddRef,
371     JScript_Release,
372     JScript_SetScriptSite,
373     JScript_GetScriptSite,
374     JScript_SetScriptState,
375     JScript_GetScriptState,
376     JScript_Close,
377     JScript_AddNamedItem,
378     JScript_AddTypeLib,
379     JScript_GetScriptDispatch,
380     JScript_GetCurrentScriptThreadID,
381     JScript_GetScriptThreadID,
382     JScript_GetScriptThreadState,
383     JScript_InterruptScriptThread,
384     JScript_Clone
385 };
386
387 #define ASPARSE_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
388
389 static HRESULT WINAPI JScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
390 {
391     JScript *This = ASPARSE_THIS(iface);
392     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
393 }
394
395 static ULONG WINAPI JScriptParse_AddRef(IActiveScriptParse *iface)
396 {
397     JScript *This = ASPARSE_THIS(iface);
398     return IActiveScript_AddRef(ACTSCRIPT(This));
399 }
400
401 static ULONG WINAPI JScriptParse_Release(IActiveScriptParse *iface)
402 {
403     JScript *This = ASPARSE_THIS(iface);
404     return IActiveScript_Release(ACTSCRIPT(This));
405 }
406
407 static HRESULT WINAPI JScriptParse_InitNew(IActiveScriptParse *iface)
408 {
409     JScript *This = ASPARSE_THIS(iface);
410     script_ctx_t *ctx;
411
412     TRACE("(%p)\n", This);
413
414     if(This->ctx)
415         return E_UNEXPECTED;
416
417     ctx = heap_alloc_zero(sizeof(script_ctx_t));
418     if(!ctx)
419         return E_OUTOFMEMORY;
420
421     ctx->ref = 1;
422     ctx->state = SCRIPTSTATE_UNINITIALIZED;
423
424     ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
425     if(ctx) {
426         script_release(ctx);
427         return E_UNEXPECTED;
428     }
429
430     return S_OK;
431 }
432
433 static HRESULT WINAPI JScriptParse_AddScriptlet(IActiveScriptParse *iface,
434         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
435         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
436         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
437         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
438 {
439     JScript *This = ASPARSE_THIS(iface);
440     FIXME("(%p)->(%s %s %s %s %s %s %x %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
441           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
442           debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), dwSourceContextCookie,
443           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
444     return E_NOTIMPL;
445 }
446
447 static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
448         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
449         LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLine,
450         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
451 {
452     JScript *This = ASPARSE_THIS(iface);
453     parser_ctx_t *parser_ctx;
454     HRESULT hres;
455
456     TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode),
457           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
458           dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo);
459
460     if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED)
461         return E_UNEXPECTED;
462
463     hres = script_parse(This->ctx, pstrCode, &parser_ctx);
464     if(FAILED(hres))
465         return hres;
466
467     if(!is_started(This->ctx)) {
468         if(This->queue_tail)
469             This->queue_tail = This->queue_tail->next = parser_ctx;
470         else
471             This->queue_head = This->queue_tail = parser_ctx;
472         return S_OK;
473     }
474
475     hres = exec_global_code(This, parser_ctx);
476     parser_release(parser_ctx);
477
478     return hres;
479 }
480
481 #undef ASPARSE_THIS
482
483 static const IActiveScriptParseVtbl JScriptParseVtbl = {
484     JScriptParse_QueryInterface,
485     JScriptParse_AddRef,
486     JScriptParse_Release,
487     JScriptParse_InitNew,
488     JScriptParse_AddScriptlet,
489     JScriptParse_ParseScriptText
490 };
491
492 #define ASPARSEPROC_THIS(iface) DEFINE_THIS(JScript, IActiveScriptParse, iface)
493
494 static HRESULT WINAPI JScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
495 {
496     JScript *This = ASPARSEPROC_THIS(iface);
497     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
498 }
499
500 static ULONG WINAPI JScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
501 {
502     JScript *This = ASPARSEPROC_THIS(iface);
503     return IActiveScript_AddRef(ACTSCRIPT(This));
504 }
505
506 static ULONG WINAPI JScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
507 {
508     JScript *This = ASPARSEPROC_THIS(iface);
509     return IActiveScript_Release(ACTSCRIPT(This));
510 }
511
512 static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
513         LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
514         LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
515         DWORD dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
516 {
517     JScript *This = ASPARSEPROC_THIS(iface);
518     FIXME("(%p)->()\n", This);
519     return E_NOTIMPL;
520 }
521
522 #undef ASPARSEPROC_THIS
523
524 static const IActiveScriptParseProcedure2Vtbl JScriptParseProcedureVtbl = {
525     JScriptParseProcedure_QueryInterface,
526     JScriptParseProcedure_AddRef,
527     JScriptParseProcedure_Release,
528     JScriptParseProcedure_ParseProcedureText,
529 };
530
531 #define ACTSCPPROP_THIS(iface) DEFINE_THIS(JScript, IActiveScriptProperty, iface)
532
533 static HRESULT WINAPI JScriptProperty_QueryInterface(IActiveScriptProperty *iface, REFIID riid, void **ppv)
534 {
535     JScript *This = ACTSCPPROP_THIS(iface);
536     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
537 }
538
539 static ULONG WINAPI JScriptProperty_AddRef(IActiveScriptProperty *iface)
540 {
541     JScript *This = ACTSCPPROP_THIS(iface);
542     return IActiveScript_AddRef(ACTSCRIPT(This));
543 }
544
545 static ULONG WINAPI JScriptProperty_Release(IActiveScriptProperty *iface)
546 {
547     JScript *This = ACTSCPPROP_THIS(iface);
548     return IActiveScript_Release(ACTSCRIPT(This));
549 }
550
551 static HRESULT WINAPI JScriptProperty_GetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
552         VARIANT *pvarIndex, VARIANT *pvarValue)
553 {
554     JScript *This = ACTSCPPROP_THIS(iface);
555     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
556     return E_NOTIMPL;
557 }
558
559 static HRESULT WINAPI JScriptProperty_SetProperty(IActiveScriptProperty *iface, DWORD dwProperty,
560         VARIANT *pvarIndex, VARIANT *pvarValue)
561 {
562     JScript *This = ACTSCPPROP_THIS(iface);
563     FIXME("(%p)->(%x %p %p)\n", This, dwProperty, pvarIndex, pvarValue);
564     return E_NOTIMPL;
565 }
566
567 #undef ACTSCPPROP_THIS
568
569 static const IActiveScriptPropertyVtbl JScriptPropertyVtbl = {
570     JScriptProperty_QueryInterface,
571     JScriptProperty_AddRef,
572     JScriptProperty_Release,
573     JScriptProperty_GetProperty,
574     JScriptProperty_SetProperty
575 };
576
577 #define OBJSAFETY_THIS(iface) DEFINE_THIS(JScript, IObjectSafety, iface)
578
579 static HRESULT WINAPI JScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
580 {
581     JScript *This = OBJSAFETY_THIS(iface);
582     return IActiveScript_QueryInterface(ACTSCRIPT(This), riid, ppv);
583 }
584
585 static ULONG WINAPI JScriptSafety_AddRef(IObjectSafety *iface)
586 {
587     JScript *This = OBJSAFETY_THIS(iface);
588     return IActiveScript_AddRef(ACTSCRIPT(This));
589 }
590
591 static ULONG WINAPI JScriptSafety_Release(IObjectSafety *iface)
592 {
593     JScript *This = OBJSAFETY_THIS(iface);
594     return IActiveScript_Release(ACTSCRIPT(This));
595 }
596
597 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
598
599 static HRESULT WINAPI JScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
600         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
601 {
602     JScript *This = OBJSAFETY_THIS(iface);
603
604     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
605
606     if(!pdwSupportedOptions || !pdwEnabledOptions)
607         return E_POINTER;
608
609     *pdwSupportedOptions = SUPPORTED_OPTIONS;
610     *pdwEnabledOptions = This->safeopt;
611
612     return S_OK;
613 }
614
615 static HRESULT WINAPI JScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
616         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
617 {
618     JScript *This = OBJSAFETY_THIS(iface);
619
620     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
621
622     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
623         return E_FAIL;
624
625     This->safeopt = dwEnabledOptions & dwEnabledOptions;
626     return S_OK;
627 }
628
629 #undef OBJSAFETY_THIS
630
631 static const IObjectSafetyVtbl JScriptSafetyVtbl = {
632     JScriptSafety_QueryInterface,
633     JScriptSafety_AddRef,
634     JScriptSafety_Release,
635     JScriptSafety_GetInterfaceSafetyOptions,
636     JScriptSafety_SetInterfaceSafetyOptions
637 };
638
639 HRESULT WINAPI JScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
640                                              REFIID riid, void **ppv)
641 {
642     JScript *ret;
643     HRESULT hres;
644
645     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
646
647     lock_module();
648
649     ret = heap_alloc_zero(sizeof(*ret));
650
651     ret->lpIActiveScriptVtbl                 = &JScriptVtbl;
652     ret->lpIActiveScriptParseVtbl            = &JScriptParseVtbl;
653     ret->lpIActiveScriptParseProcedure2Vtbl  = &JScriptParseProcedureVtbl;
654     ret->lpIActiveScriptPropertyVtbl         = &JScriptPropertyVtbl;
655     ret->lpIObjectSafetyVtbl                 = &JScriptSafetyVtbl;
656     ret->ref = 1;
657     ret->safeopt = INTERFACE_USES_DISPEX;
658
659     hres = IActiveScript_QueryInterface(ACTSCRIPT(ret), riid, ppv);
660     IActiveScript_Release(ACTSCRIPT(ret));
661     return hres;
662 }