vbscript: Added interp_lt implementation.
[wine] / dlls / vbscript / vbscript.c
1 /*
2  * Copyright 2011 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
20 #include <assert.h>
21
22 #include "vbscript.h"
23 #include "objsafe.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
28
29 #ifdef _WIN64
30
31 #define CTXARG_T DWORDLONG
32 #define IActiveScriptParseVtbl IActiveScriptParse64Vtbl
33
34 #else
35
36 #define CTXARG_T DWORD
37 #define IActiveScriptParseVtbl IActiveScriptParse32Vtbl
38
39 #endif
40
41 struct VBScript {
42     IActiveScript IActiveScript_iface;
43     IActiveScriptParse IActiveScriptParse_iface;
44     IObjectSafety IObjectSafety_iface;
45
46     LONG ref;
47
48     DWORD safeopt;
49     SCRIPTSTATE state;
50     IActiveScriptSite *site;
51     script_ctx_t *ctx;
52     LONG thread_id;
53     LCID lcid;
54 };
55
56 static void change_state(VBScript *This, SCRIPTSTATE state)
57 {
58     if(This->state == state)
59         return;
60
61     This->state = state;
62     if(This->site)
63         IActiveScriptSite_OnStateChange(This->site, state);
64 }
65
66 static inline BOOL is_started(VBScript *This)
67 {
68     return This->state == SCRIPTSTATE_STARTED
69         || This->state == SCRIPTSTATE_CONNECTED
70         || This->state == SCRIPTSTATE_DISCONNECTED;
71 }
72
73 static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code)
74 {
75     HRESULT hres;
76
77     code->global_executed = TRUE;
78
79     IActiveScriptSite_OnEnterScript(ctx->site);
80     hres = exec_script(ctx, &code->global_code, NULL, NULL, NULL);
81     IActiveScriptSite_OnLeaveScript(ctx->site);
82
83     return hres;
84 }
85
86 static void exec_queued_code(script_ctx_t *ctx)
87 {
88     vbscode_t *iter;
89
90     LIST_FOR_EACH_ENTRY(iter, &ctx->code_list, vbscode_t, entry) {
91         if(!iter->global_executed)
92             exec_global_code(ctx, iter);
93     }
94 }
95
96 static HRESULT set_ctx_site(VBScript *This)
97 {
98     HRESULT hres;
99
100     This->ctx->lcid = This->lcid;
101
102     hres = init_global(This->ctx);
103     if(FAILED(hres))
104         return hres;
105
106     IActiveScriptSite_AddRef(This->site);
107     This->ctx->site = This->site;
108
109     change_state(This, SCRIPTSTATE_INITIALIZED);
110     return S_OK;
111 }
112
113 static void destroy_script(script_ctx_t *ctx)
114 {
115     collect_objects(ctx);
116
117     while(!list_empty(&ctx->code_list))
118         release_vbscode(LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry));
119
120     while(!list_empty(&ctx->named_items)) {
121         named_item_t *iter = LIST_ENTRY(list_head(&ctx->named_items), named_item_t, entry);
122
123         list_remove(&iter->entry);
124         if(iter->disp)
125             IDispatch_Release(iter->disp);
126         heap_free(iter->name);
127         heap_free(iter);
128     }
129
130     if(ctx->host_global)
131         IDispatch_Release(ctx->host_global);
132     if(ctx->site)
133         IActiveScriptSite_Release(ctx->site);
134     if(ctx->script_obj)
135         IDispatchEx_Release(&ctx->script_obj->IDispatchEx_iface);
136     heap_free(ctx);
137 }
138
139 static void decrease_state(VBScript *This, SCRIPTSTATE state)
140 {
141     switch(This->state) {
142     case SCRIPTSTATE_CONNECTED:
143         change_state(This, SCRIPTSTATE_DISCONNECTED);
144         if(state == SCRIPTSTATE_DISCONNECTED)
145             return;
146         /* FALLTHROUGH */
147     case SCRIPTSTATE_STARTED:
148     case SCRIPTSTATE_DISCONNECTED:
149         if(This->state == SCRIPTSTATE_DISCONNECTED)
150             change_state(This, SCRIPTSTATE_INITIALIZED);
151         if(state == SCRIPTSTATE_INITIALIZED)
152             break;
153         /* FALLTHROUGH */
154     case SCRIPTSTATE_INITIALIZED:
155     case SCRIPTSTATE_UNINITIALIZED:
156         change_state(This, state);
157
158         if(This->site) {
159             IActiveScriptSite_Release(This->site);
160             This->site = NULL;
161         }
162
163         This->thread_id = 0;
164
165         if(state == SCRIPTSTATE_CLOSED) {
166             destroy_script(This->ctx);
167             This->ctx = NULL;
168         }
169
170         break;
171     default:
172         assert(0);
173     }
174 }
175
176 static inline VBScript *impl_from_IActiveScript(IActiveScript *iface)
177 {
178     return CONTAINING_RECORD(iface, VBScript, IActiveScript_iface);
179 }
180
181 static HRESULT WINAPI VBScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
182 {
183     VBScript *This = impl_from_IActiveScript(iface);
184
185     if(IsEqualGUID(riid, &IID_IUnknown)) {
186         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
187         *ppv = &This->IActiveScript_iface;
188     }else if(IsEqualGUID(riid, &IID_IActiveScript)) {
189         TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
190         *ppv = &This->IActiveScript_iface;
191     }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
192         TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
193         *ppv = &This->IActiveScriptParse_iface;
194     }else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
195         TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
196         *ppv = &This->IObjectSafety_iface;
197     }else {
198         FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
199         *ppv = NULL;
200         return E_NOINTERFACE;
201     }
202
203     IUnknown_AddRef((IUnknown*)*ppv);
204     return S_OK;
205 }
206
207 static ULONG WINAPI VBScript_AddRef(IActiveScript *iface)
208 {
209     VBScript *This = impl_from_IActiveScript(iface);
210     LONG ref = InterlockedIncrement(&This->ref);
211
212     TRACE("(%p) ref=%d\n", This, ref);
213
214     return ref;
215 }
216
217 static ULONG WINAPI VBScript_Release(IActiveScript *iface)
218 {
219     VBScript *This = impl_from_IActiveScript(iface);
220     LONG ref = InterlockedDecrement(&This->ref);
221
222     TRACE("(%p) ref=%d\n", iface, ref);
223
224     if(!ref) {
225         if(This->site)
226             IActiveScriptSite_Release(This->site);
227         heap_free(This);
228     }
229
230     return ref;
231 }
232
233 static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass)
234 {
235     VBScript *This = impl_from_IActiveScript(iface);
236     LCID lcid;
237     HRESULT hres;
238
239     TRACE("(%p)->(%p)\n", This, pass);
240
241     if(!pass)
242         return E_POINTER;
243
244     if(This->site)
245         return E_UNEXPECTED;
246
247     if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
248         return E_UNEXPECTED;
249
250     This->site = pass;
251     IActiveScriptSite_AddRef(This->site);
252
253     hres = IActiveScriptSite_GetLCID(This->site, &lcid);
254     if(hres == S_OK)
255         This->lcid = lcid;
256
257     return This->ctx ? set_ctx_site(This) : S_OK;
258 }
259
260 static HRESULT WINAPI VBScript_GetScriptSite(IActiveScript *iface, REFIID riid,
261                                             void **ppvObject)
262 {
263     VBScript *This = impl_from_IActiveScript(iface);
264     FIXME("(%p)->()\n", This);
265     return E_NOTIMPL;
266 }
267
268 static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
269 {
270     VBScript *This = impl_from_IActiveScript(iface);
271
272     TRACE("(%p)->(%d)\n", This, ss);
273
274     if(This->thread_id && GetCurrentThreadId() != This->thread_id)
275         return E_UNEXPECTED;
276
277     if(ss == SCRIPTSTATE_UNINITIALIZED) {
278         if(This->state == SCRIPTSTATE_CLOSED)
279             return E_UNEXPECTED;
280
281         decrease_state(This, SCRIPTSTATE_UNINITIALIZED);
282         return S_OK;
283     }
284
285     if(!This->ctx)
286         return E_UNEXPECTED;
287
288     switch(ss) {
289     case SCRIPTSTATE_STARTED:
290     case SCRIPTSTATE_CONNECTED: /* FIXME */
291         if(This->state == SCRIPTSTATE_CLOSED)
292             return E_UNEXPECTED;
293
294         exec_queued_code(This->ctx);
295         break;
296     case SCRIPTSTATE_INITIALIZED:
297         FIXME("unimplemented SCRIPTSTATE_INITIALIZED\n");
298         return S_OK;
299     default:
300         FIXME("unimplemented state %d\n", ss);
301         return E_NOTIMPL;
302     }
303
304     change_state(This, ss);
305     return S_OK;
306 }
307
308 static HRESULT WINAPI VBScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
309 {
310     VBScript *This = impl_from_IActiveScript(iface);
311
312     TRACE("(%p)->(%p)\n", This, pssState);
313
314     if(!pssState)
315         return E_POINTER;
316
317     if(This->thread_id && This->thread_id != GetCurrentThreadId())
318         return E_UNEXPECTED;
319
320     *pssState = This->state;
321     return S_OK;
322 }
323
324 static HRESULT WINAPI VBScript_Close(IActiveScript *iface)
325 {
326     VBScript *This = impl_from_IActiveScript(iface);
327
328     TRACE("(%p)->()\n", This);
329
330     if(This->thread_id && This->thread_id != GetCurrentThreadId())
331         return E_UNEXPECTED;
332
333     decrease_state(This, SCRIPTSTATE_CLOSED);
334     return S_OK;
335 }
336
337 static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstrName, DWORD dwFlags)
338 {
339     VBScript *This = impl_from_IActiveScript(iface);
340     named_item_t *item;
341     IDispatch *disp = NULL;
342     HRESULT hres;
343
344     TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
345
346     if(This->thread_id != GetCurrentThreadId() || !This->ctx || This->state == SCRIPTSTATE_CLOSED)
347         return E_UNEXPECTED;
348
349     if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
350         IUnknown *unk;
351
352         hres = IActiveScriptSite_GetItemInfo(This->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
353         if(FAILED(hres)) {
354             WARN("GetItemInfo failed: %08x\n", hres);
355             return hres;
356         }
357
358         hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
359         IUnknown_Release(unk);
360         if(FAILED(hres)) {
361             WARN("object does not implement IDispatch\n");
362             return hres;
363         }
364
365         if(This->ctx->host_global)
366             IDispatch_Release(This->ctx->host_global);
367         IDispatch_AddRef(disp);
368         This->ctx->host_global = disp;
369     }
370
371     item = heap_alloc(sizeof(*item));
372     if(!item) {
373         if(disp)
374             IDispatch_Release(disp);
375         return E_OUTOFMEMORY;
376     }
377
378     item->disp = disp;
379     item->flags = dwFlags;
380     item->name = heap_strdupW(pstrName);
381     if(!item->name) {
382         if(disp)
383             IDispatch_Release(disp);
384         heap_free(item);
385         return E_OUTOFMEMORY;
386     }
387
388     list_add_tail(&This->ctx->named_items, &item->entry);
389     return S_OK;
390 }
391
392 static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
393         DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
394 {
395     VBScript *This = impl_from_IActiveScript(iface);
396     FIXME("(%p)->()\n", This);
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp)
401 {
402     VBScript *This = impl_from_IActiveScript(iface);
403
404     TRACE("(%p)->(%p)\n", This, ppdisp);
405
406     if(!ppdisp)
407         return E_POINTER;
408
409     if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_obj) {
410         *ppdisp = NULL;
411         return E_UNEXPECTED;
412     }
413
414     *ppdisp = (IDispatch*)&This->ctx->script_obj->IDispatchEx_iface;
415     IDispatch_AddRef(*ppdisp);
416     return S_OK;
417 }
418
419 static HRESULT WINAPI VBScript_GetCurrentScriptThreadID(IActiveScript *iface,
420                                                        SCRIPTTHREADID *pstridThread)
421 {
422     VBScript *This = impl_from_IActiveScript(iface);
423     FIXME("(%p)->()\n", This);
424     return E_NOTIMPL;
425 }
426
427 static HRESULT WINAPI VBScript_GetScriptThreadID(IActiveScript *iface,
428                                                 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
429 {
430     VBScript *This = impl_from_IActiveScript(iface);
431     FIXME("(%p)->()\n", This);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI VBScript_GetScriptThreadState(IActiveScript *iface,
436         SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
437 {
438     VBScript *This = impl_from_IActiveScript(iface);
439     FIXME("(%p)->()\n", This);
440     return E_NOTIMPL;
441 }
442
443 static HRESULT WINAPI VBScript_InterruptScriptThread(IActiveScript *iface,
444         SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
445 {
446     VBScript *This = impl_from_IActiveScript(iface);
447     FIXME("(%p)->()\n", This);
448     return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI VBScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
452 {
453     VBScript *This = impl_from_IActiveScript(iface);
454     FIXME("(%p)->()\n", This);
455     return E_NOTIMPL;
456 }
457
458 static const IActiveScriptVtbl VBScriptVtbl = {
459     VBScript_QueryInterface,
460     VBScript_AddRef,
461     VBScript_Release,
462     VBScript_SetScriptSite,
463     VBScript_GetScriptSite,
464     VBScript_SetScriptState,
465     VBScript_GetScriptState,
466     VBScript_Close,
467     VBScript_AddNamedItem,
468     VBScript_AddTypeLib,
469     VBScript_GetScriptDispatch,
470     VBScript_GetCurrentScriptThreadID,
471     VBScript_GetScriptThreadID,
472     VBScript_GetScriptThreadState,
473     VBScript_InterruptScriptThread,
474     VBScript_Clone
475 };
476
477 static inline VBScript *impl_from_IActiveScriptParse(IActiveScriptParse *iface)
478 {
479     return CONTAINING_RECORD(iface, VBScript, IActiveScriptParse_iface);
480 }
481
482 static HRESULT WINAPI VBScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
483 {
484     VBScript *This = impl_from_IActiveScriptParse(iface);
485     return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
486 }
487
488 static ULONG WINAPI VBScriptParse_AddRef(IActiveScriptParse *iface)
489 {
490     VBScript *This = impl_from_IActiveScriptParse(iface);
491     return IActiveScript_AddRef(&This->IActiveScript_iface);
492 }
493
494 static ULONG WINAPI VBScriptParse_Release(IActiveScriptParse *iface)
495 {
496     VBScript *This = impl_from_IActiveScriptParse(iface);
497     return IActiveScript_Release(&This->IActiveScript_iface);
498 }
499
500 static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface)
501 {
502     VBScript *This = impl_from_IActiveScriptParse(iface);
503     script_ctx_t *ctx, *old_ctx;
504
505     TRACE("(%p)\n", This);
506
507     if(This->ctx)
508         return E_UNEXPECTED;
509
510     ctx = heap_alloc_zero(sizeof(script_ctx_t));
511     if(!ctx)
512         return E_OUTOFMEMORY;
513
514     list_init(&ctx->objects);
515     list_init(&ctx->code_list);
516     list_init(&ctx->named_items);
517
518     old_ctx = InterlockedCompareExchangePointer((void**)&This->ctx, ctx, NULL);
519     if(old_ctx) {
520         destroy_script(ctx);
521         return E_UNEXPECTED;
522     }
523
524     return This->site ? set_ctx_site(This) : S_OK;
525 }
526
527 static HRESULT WINAPI VBScriptParse_AddScriptlet(IActiveScriptParse *iface,
528         LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
529         LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
530         CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
531         BSTR *pbstrName, EXCEPINFO *pexcepinfo)
532 {
533     VBScript *This = impl_from_IActiveScriptParse(iface);
534     FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
535           debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
536           debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
537           ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
538     return E_NOTIMPL;
539 }
540
541 static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface,
542         LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
543         LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
544         DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
545 {
546     VBScript *This = impl_from_IActiveScriptParse(iface);
547     vbscode_t *code;
548     HRESULT hres;
549
550     TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
551           debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
552           wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo);
553
554     if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
555         return E_UNEXPECTED;
556
557     hres = compile_script(This->ctx, pstrCode, &code);
558     if(FAILED(hres))
559         return hres;
560
561     return is_started(This) ? exec_global_code(This->ctx, code) : S_OK;
562 }
563
564 static const IActiveScriptParseVtbl VBScriptParseVtbl = {
565     VBScriptParse_QueryInterface,
566     VBScriptParse_AddRef,
567     VBScriptParse_Release,
568     VBScriptParse_InitNew,
569     VBScriptParse_AddScriptlet,
570     VBScriptParse_ParseScriptText
571 };
572
573 static inline VBScript *impl_from_IObjectSafety(IObjectSafety *iface)
574 {
575     return CONTAINING_RECORD(iface, VBScript, IObjectSafety_iface);
576 }
577
578 static HRESULT WINAPI VBScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
579 {
580     VBScript *This = impl_from_IObjectSafety(iface);
581     return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
582 }
583
584 static ULONG WINAPI VBScriptSafety_AddRef(IObjectSafety *iface)
585 {
586     VBScript *This = impl_from_IObjectSafety(iface);
587     return IActiveScript_AddRef(&This->IActiveScript_iface);
588 }
589
590 static ULONG WINAPI VBScriptSafety_Release(IObjectSafety *iface)
591 {
592     VBScript *This = impl_from_IObjectSafety(iface);
593     return IActiveScript_Release(&This->IActiveScript_iface);
594 }
595
596 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
597
598 static HRESULT WINAPI VBScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
599         DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
600 {
601     VBScript *This = impl_from_IObjectSafety(iface);
602
603     TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
604
605     if(!pdwSupportedOptions || !pdwEnabledOptions)
606         return E_POINTER;
607
608     *pdwSupportedOptions = SUPPORTED_OPTIONS;
609     *pdwEnabledOptions = This->safeopt;
610     return S_OK;
611 }
612
613 static HRESULT WINAPI VBScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
614         DWORD dwOptionSetMask, DWORD dwEnabledOptions)
615 {
616     VBScript *This = impl_from_IObjectSafety(iface);
617
618     TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
619
620     if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
621         return E_FAIL;
622
623     This->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX;
624     return S_OK;
625 }
626
627 static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
628     VBScriptSafety_QueryInterface,
629     VBScriptSafety_AddRef,
630     VBScriptSafety_Release,
631     VBScriptSafety_GetInterfaceSafetyOptions,
632     VBScriptSafety_SetInterfaceSafetyOptions
633 };
634
635 HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
636 {
637     VBScript *ret;
638     HRESULT hres;
639
640     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
641
642     ret = heap_alloc_zero(sizeof(*ret));
643     if(!ret)
644         return E_OUTOFMEMORY;
645
646     ret->IActiveScript_iface.lpVtbl = &VBScriptVtbl;
647     ret->IActiveScriptParse_iface.lpVtbl = &VBScriptParseVtbl;
648     ret->IObjectSafety_iface.lpVtbl = &VBScriptSafetyVtbl;
649
650     ret->ref = 1;
651     ret->state = SCRIPTSTATE_UNINITIALIZED;
652     ret->safeopt = INTERFACE_USES_DISPEX;
653
654     hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv);
655     IActiveScript_Release(&ret->IActiveScript_iface);
656     return hres;
657 }