wined3d: Optimize scanning for changed state in wined3d_stateblock_capture().
[wine.git] / dlls / vbscript / vbscript.c
blob86902d84ea02f36aff21fb12da59ec6365ec5f6c
1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
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.
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.
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
20 #include <assert.h>
22 #include "vbscript.h"
23 #include "objsafe.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
29 #ifdef _WIN64
31 #define CTXARG_T DWORDLONG
32 #define IActiveScriptDebugVtbl IActiveScriptDebug64Vtbl
33 #define IActiveScriptParseVtbl IActiveScriptParse64Vtbl
34 #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_64Vtbl
36 #else
38 #define CTXARG_T DWORD
39 #define IActiveScriptDebugVtbl IActiveScriptDebug32Vtbl
40 #define IActiveScriptParseVtbl IActiveScriptParse32Vtbl
41 #define IActiveScriptParseProcedure2Vtbl IActiveScriptParseProcedure2_32Vtbl
43 #endif
45 struct VBScript {
46 IActiveScript IActiveScript_iface;
47 IActiveScriptDebug IActiveScriptDebug_iface;
48 IActiveScriptParse IActiveScriptParse_iface;
49 IActiveScriptParseProcedure2 IActiveScriptParseProcedure2_iface;
50 IObjectSafety IObjectSafety_iface;
52 LONG ref;
54 SCRIPTSTATE state;
55 script_ctx_t *ctx;
56 LONG thread_id;
57 BOOL is_initialized;
60 typedef struct {
61 IActiveScriptError IActiveScriptError_iface;
62 LONG ref;
63 EXCEPINFO ei;
64 DWORD_PTR cookie;
65 unsigned line;
66 unsigned character;
67 } VBScriptError;
69 static inline WCHAR *heap_pool_strdup(heap_pool_t *heap, const WCHAR *str)
71 size_t size = (lstrlenW(str) + 1) * sizeof(WCHAR);
72 WCHAR *ret = heap_pool_alloc(heap, size);
73 if (ret) memcpy(ret, str, size);
74 return ret;
77 static void change_state(VBScript *This, SCRIPTSTATE state)
79 if(This->state == state)
80 return;
82 This->state = state;
83 if(This->ctx->site)
84 IActiveScriptSite_OnStateChange(This->ctx->site, state);
87 static inline BOOL is_started(VBScript *This)
89 return This->state == SCRIPTSTATE_STARTED
90 || This->state == SCRIPTSTATE_CONNECTED
91 || This->state == SCRIPTSTATE_DISCONNECTED;
94 static HRESULT exec_global_code(script_ctx_t *ctx, vbscode_t *code, VARIANT *res)
96 ScriptDisp *obj = ctx->script_obj;
97 function_t *func_iter, **new_funcs;
98 dynamic_var_t *var, **new_vars;
99 size_t cnt, i;
100 HRESULT hres;
102 if(code->named_item) {
103 if(!code->named_item->script_obj) {
104 hres = create_script_disp(ctx, &code->named_item->script_obj);
105 if(FAILED(hres)) return hres;
107 obj = code->named_item->script_obj;
110 cnt = obj->global_vars_cnt + code->main_code.var_cnt;
111 if (cnt > obj->global_vars_size)
113 if (obj->global_vars)
114 new_vars = heap_realloc(obj->global_vars, cnt * sizeof(*new_vars));
115 else
116 new_vars = heap_alloc(cnt * sizeof(*new_vars));
117 if (!new_vars)
118 return E_OUTOFMEMORY;
119 obj->global_vars = new_vars;
120 obj->global_vars_size = cnt;
123 cnt = obj->global_funcs_cnt;
124 for (func_iter = code->funcs; func_iter; func_iter = func_iter->next)
125 cnt++;
126 if (cnt > obj->global_funcs_size)
128 if (obj->global_funcs)
129 new_funcs = heap_realloc(obj->global_funcs, cnt * sizeof(*new_funcs));
130 else
131 new_funcs = heap_alloc(cnt * sizeof(*new_funcs));
132 if (!new_funcs)
133 return E_OUTOFMEMORY;
134 obj->global_funcs = new_funcs;
135 obj->global_funcs_size = cnt;
138 for (i = 0; i < code->main_code.var_cnt; i++)
140 if (!(var = heap_pool_alloc(&obj->heap, sizeof(*var))))
141 return E_OUTOFMEMORY;
143 var->name = heap_pool_strdup(&obj->heap, code->main_code.vars[i].name);
144 if (!var->name)
145 return E_OUTOFMEMORY;
146 V_VT(&var->v) = VT_EMPTY;
147 var->is_const = FALSE;
148 var->array = NULL;
150 obj->global_vars[obj->global_vars_cnt + i] = var;
153 obj->global_vars_cnt += code->main_code.var_cnt;
155 for (func_iter = code->funcs; func_iter; func_iter = func_iter->next)
157 for (i = 0; i < obj->global_funcs_cnt; i++)
159 if (!wcsicmp(obj->global_funcs[i]->name, func_iter->name))
161 /* global function already exists, replace it */
162 obj->global_funcs[i] = func_iter;
163 break;
166 if (i == obj->global_funcs_cnt)
167 obj->global_funcs[obj->global_funcs_cnt++] = func_iter;
170 if (code->classes)
172 class_desc_t *class = code->classes;
174 while (1)
176 class->ctx = ctx;
177 if (!class->next)
178 break;
179 class = class->next;
182 class->next = obj->classes;
183 obj->classes = code->classes;
184 code->last_class = class;
187 code->pending_exec = FALSE;
188 return exec_script(ctx, TRUE, &code->main_code, NULL, NULL, res);
191 static void exec_queued_code(script_ctx_t *ctx)
193 vbscode_t *iter;
195 LIST_FOR_EACH_ENTRY(iter, &ctx->code_list, vbscode_t, entry) {
196 if(iter->pending_exec)
197 exec_global_code(ctx, iter, NULL);
201 named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *name, unsigned flags)
203 named_item_t *item;
204 HRESULT hres;
206 LIST_FOR_EACH_ENTRY(item, &ctx->named_items, named_item_t, entry) {
207 if((item->flags & flags) == flags && !wcsicmp(item->name, name)) {
208 if(!item->script_obj && !(item->flags & SCRIPTITEM_GLOBALMEMBERS)) {
209 hres = create_script_disp(ctx, &item->script_obj);
210 if(FAILED(hres)) return NULL;
212 if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) {
213 IUnknown *unk;
215 hres = IActiveScriptSite_GetItemInfo(ctx->site, item->name,
216 SCRIPTINFO_IUNKNOWN, &unk, NULL);
217 if(FAILED(hres)) {
218 WARN("GetItemInfo failed: %08x\n", hres);
219 continue;
222 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
223 IUnknown_Release(unk);
224 if(FAILED(hres)) {
225 WARN("object does not implement IDispatch\n");
226 continue;
230 return item;
234 return NULL;
237 static void release_named_item_script_obj(named_item_t *item)
239 if(!item->script_obj) return;
241 item->script_obj->ctx = NULL;
242 IDispatchEx_Release(&item->script_obj->IDispatchEx_iface);
243 item->script_obj = NULL;
246 void release_named_item(named_item_t *item)
248 if(--item->ref) return;
250 heap_free(item->name);
251 heap_free(item);
254 static void release_script(script_ctx_t *ctx)
256 vbscode_t *code, *code_next;
258 collect_objects(ctx);
259 clear_ei(&ctx->ei);
261 LIST_FOR_EACH_ENTRY_SAFE(code, code_next, &ctx->code_list, vbscode_t, entry)
263 if(code->is_persistent)
265 code->pending_exec = TRUE;
266 if(code->last_class) code->last_class->next = NULL;
267 if(code->named_item) release_named_item_script_obj(code->named_item);
269 else
271 list_remove(&code->entry);
272 release_vbscode(code);
276 while(!list_empty(&ctx->named_items)) {
277 named_item_t *iter = LIST_ENTRY(list_head(&ctx->named_items), named_item_t, entry);
279 list_remove(&iter->entry);
280 if(iter->disp)
281 IDispatch_Release(iter->disp);
282 release_named_item_script_obj(iter);
283 release_named_item(iter);
286 if(ctx->secmgr) {
287 IInternetHostSecurityManager_Release(ctx->secmgr);
288 ctx->secmgr = NULL;
291 if(ctx->site) {
292 IActiveScriptSite_Release(ctx->site);
293 ctx->site = NULL;
296 if(ctx->script_obj) {
297 ScriptDisp *script_obj = ctx->script_obj;
299 ctx->script_obj = NULL;
300 script_obj->ctx = NULL;
301 IDispatchEx_Release(&script_obj->IDispatchEx_iface);
305 static void release_code_list(script_ctx_t *ctx)
307 while(!list_empty(&ctx->code_list)) {
308 vbscode_t *iter = LIST_ENTRY(list_head(&ctx->code_list), vbscode_t, entry);
310 list_remove(&iter->entry);
311 release_vbscode(iter);
315 static void decrease_state(VBScript *This, SCRIPTSTATE state)
317 switch(This->state) {
318 case SCRIPTSTATE_CONNECTED:
319 change_state(This, SCRIPTSTATE_DISCONNECTED);
320 if(state == SCRIPTSTATE_DISCONNECTED)
321 return;
322 /* FALLTHROUGH */
323 case SCRIPTSTATE_STARTED:
324 case SCRIPTSTATE_DISCONNECTED:
325 change_state(This, SCRIPTSTATE_INITIALIZED);
326 /* FALLTHROUGH */
327 case SCRIPTSTATE_INITIALIZED:
328 case SCRIPTSTATE_UNINITIALIZED:
329 change_state(This, state);
330 if(state == SCRIPTSTATE_INITIALIZED)
331 break;
332 release_script(This->ctx);
333 This->thread_id = 0;
334 if(state == SCRIPTSTATE_CLOSED)
335 release_code_list(This->ctx);
336 break;
337 case SCRIPTSTATE_CLOSED:
338 break;
339 DEFAULT_UNREACHABLE;
343 static inline VBScriptError *impl_from_IActiveScriptError(IActiveScriptError *iface)
345 return CONTAINING_RECORD(iface, VBScriptError, IActiveScriptError_iface);
348 static HRESULT WINAPI VBScriptError_QueryInterface(IActiveScriptError *iface, REFIID riid, void **ppv)
350 VBScriptError *This = impl_from_IActiveScriptError(iface);
352 if(IsEqualGUID(riid, &IID_IUnknown)) {
353 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
354 *ppv = &This->IActiveScriptError_iface;
355 }else if(IsEqualGUID(riid, &IID_IActiveScriptError)) {
356 TRACE("(%p)->(IID_IActiveScriptError %p)\n", This, ppv);
357 *ppv = &This->IActiveScriptError_iface;
358 }else {
359 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
360 *ppv = NULL;
361 return E_NOINTERFACE;
364 IUnknown_AddRef((IUnknown*)*ppv);
365 return S_OK;
368 static ULONG WINAPI VBScriptError_AddRef(IActiveScriptError *iface)
370 VBScriptError *This = impl_from_IActiveScriptError(iface);
371 LONG ref = InterlockedIncrement(&This->ref);
373 TRACE("(%p) ref=%d\n", This, ref);
375 return ref;
378 static ULONG WINAPI VBScriptError_Release(IActiveScriptError *iface)
380 VBScriptError *This = impl_from_IActiveScriptError(iface);
381 LONG ref = InterlockedDecrement(&This->ref);
383 TRACE("(%p) ref=%d\n", This, ref);
385 if(!ref) {
386 heap_free(This);
389 return ref;
392 static HRESULT WINAPI VBScriptError_GetExceptionInfo(IActiveScriptError *iface, EXCEPINFO *excepinfo)
394 VBScriptError *This = impl_from_IActiveScriptError(iface);
396 TRACE("(%p)->(%p)\n", This, excepinfo);
398 *excepinfo = This->ei;
399 excepinfo->bstrSource = SysAllocString(This->ei.bstrSource);
400 excepinfo->bstrDescription = SysAllocString(This->ei.bstrDescription);
401 excepinfo->bstrHelpFile = SysAllocString(This->ei.bstrHelpFile);
402 return S_OK;
405 static HRESULT WINAPI VBScriptError_GetSourcePosition(IActiveScriptError *iface, DWORD *source_context, ULONG *line, LONG *character)
407 VBScriptError *This = impl_from_IActiveScriptError(iface);
409 TRACE("(%p)->(%p %p %p)\n", This, source_context, line, character);
411 if(source_context)
412 *source_context = This->cookie;
413 if(line)
414 *line = This->line;
415 if(character)
416 *character = This->character;
417 return S_OK;
420 static HRESULT WINAPI VBScriptError_GetSourceLineText(IActiveScriptError *iface, BSTR *source)
422 VBScriptError *This = impl_from_IActiveScriptError(iface);
423 FIXME("(%p)->(%p)\n", This, source);
424 return E_NOTIMPL;
427 static const IActiveScriptErrorVtbl VBScriptErrorVtbl = {
428 VBScriptError_QueryInterface,
429 VBScriptError_AddRef,
430 VBScriptError_Release,
431 VBScriptError_GetExceptionInfo,
432 VBScriptError_GetSourcePosition,
433 VBScriptError_GetSourceLineText
436 HRESULT report_script_error(script_ctx_t *ctx, const vbscode_t *code, unsigned loc)
438 VBScriptError *error;
439 const WCHAR *p, *nl;
440 HRESULT hres, result;
442 if(!(error = heap_alloc(sizeof(*error))))
443 return E_OUTOFMEMORY;
444 error->IActiveScriptError_iface.lpVtbl = &VBScriptErrorVtbl;
446 error->ref = 1;
447 error->ei = ctx->ei;
448 memset(&ctx->ei, 0, sizeof(ctx->ei));
449 result = error->ei.scode;
451 p = code->source;
452 error->cookie = code->cookie;
453 error->line = code->start_line;
454 for(nl = p = code->source; p < code->source + loc; p++) {
455 if(*p != '\n') continue;
456 error->line++;
457 nl = p + 1;
459 error->character = code->source + loc - nl;
461 hres = IActiveScriptSite_OnScriptError(ctx->site, &error->IActiveScriptError_iface);
462 IActiveScriptError_Release(&error->IActiveScriptError_iface);
463 return hres == S_OK ? SCRIPT_E_REPORTED : result;
466 static inline VBScript *impl_from_IActiveScript(IActiveScript *iface)
468 return CONTAINING_RECORD(iface, VBScript, IActiveScript_iface);
471 static HRESULT WINAPI VBScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
473 VBScript *This = impl_from_IActiveScript(iface);
475 if(IsEqualGUID(riid, &IID_IUnknown)) {
476 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
477 *ppv = &This->IActiveScript_iface;
478 }else if(IsEqualGUID(riid, &IID_IActiveScript)) {
479 TRACE("(%p)->(IID_IActiveScript %p)\n", This, ppv);
480 *ppv = &This->IActiveScript_iface;
481 }else if(IsEqualGUID(riid, &IID_IActiveScriptDebug)) {
482 TRACE("(%p)->(IID_IActiveScriptDebug %p)\n", This, ppv);
483 *ppv = &This->IActiveScriptDebug_iface;
484 }else if(IsEqualGUID(riid, &IID_IActiveScriptParse)) {
485 TRACE("(%p)->(IID_IActiveScriptParse %p)\n", This, ppv);
486 *ppv = &This->IActiveScriptParse_iface;
487 }else if(IsEqualGUID(riid, &IID_IActiveScriptParseProcedure2)) {
488 TRACE("(%p)->(IID_IActiveScriptParseProcedure2 %p)\n", This, ppv);
489 *ppv = &This->IActiveScriptParseProcedure2_iface;
490 }else if(IsEqualGUID(riid, &IID_IObjectSafety)) {
491 TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
492 *ppv = &This->IObjectSafety_iface;
493 }else {
494 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
495 *ppv = NULL;
496 return E_NOINTERFACE;
499 IUnknown_AddRef((IUnknown*)*ppv);
500 return S_OK;
503 static ULONG WINAPI VBScript_AddRef(IActiveScript *iface)
505 VBScript *This = impl_from_IActiveScript(iface);
506 LONG ref = InterlockedIncrement(&This->ref);
508 TRACE("(%p) ref=%d\n", This, ref);
510 return ref;
513 static ULONG WINAPI VBScript_Release(IActiveScript *iface)
515 VBScript *This = impl_from_IActiveScript(iface);
516 LONG ref = InterlockedDecrement(&This->ref);
518 TRACE("(%p) ref=%d\n", iface, ref);
520 if(!ref) {
521 decrease_state(This, SCRIPTSTATE_CLOSED);
522 detach_global_objects(This->ctx);
523 heap_free(This->ctx);
524 heap_free(This);
527 return ref;
530 static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScriptSite *pass)
532 VBScript *This = impl_from_IActiveScript(iface);
533 LCID lcid;
534 HRESULT hres;
536 TRACE("(%p)->(%p)\n", This, pass);
538 if(!pass)
539 return E_POINTER;
541 if(This->ctx->site)
542 return E_UNEXPECTED;
544 if(InterlockedCompareExchange(&This->thread_id, GetCurrentThreadId(), 0))
545 return E_UNEXPECTED;
547 hres = create_script_disp(This->ctx, &This->ctx->script_obj);
548 if(FAILED(hres))
549 return hres;
551 This->ctx->site = pass;
552 IActiveScriptSite_AddRef(This->ctx->site);
554 hres = IActiveScriptSite_GetLCID(This->ctx->site, &lcid);
555 if(hres == S_OK)
556 This->ctx->lcid = lcid;
558 if(This->is_initialized)
559 change_state(This, SCRIPTSTATE_INITIALIZED);
560 return S_OK;
563 static HRESULT WINAPI VBScript_GetScriptSite(IActiveScript *iface, REFIID riid,
564 void **ppvObject)
566 VBScript *This = impl_from_IActiveScript(iface);
567 FIXME("(%p)->()\n", This);
568 return E_NOTIMPL;
571 static HRESULT WINAPI VBScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE ss)
573 VBScript *This = impl_from_IActiveScript(iface);
575 TRACE("(%p)->(%d)\n", This, ss);
577 if(This->thread_id && GetCurrentThreadId() != This->thread_id)
578 return E_UNEXPECTED;
580 if(ss == SCRIPTSTATE_UNINITIALIZED) {
581 if(This->state == SCRIPTSTATE_CLOSED)
582 return E_UNEXPECTED;
584 decrease_state(This, SCRIPTSTATE_UNINITIALIZED);
585 return S_OK;
588 if(!This->is_initialized || (!This->ctx->site && ss != SCRIPTSTATE_CLOSED))
589 return E_UNEXPECTED;
591 switch(ss) {
592 case SCRIPTSTATE_STARTED:
593 case SCRIPTSTATE_CONNECTED: /* FIXME */
594 if(This->state == SCRIPTSTATE_CLOSED)
595 return E_UNEXPECTED;
597 exec_queued_code(This->ctx);
598 break;
599 case SCRIPTSTATE_INITIALIZED:
600 decrease_state(This, SCRIPTSTATE_INITIALIZED);
601 return S_OK;
602 case SCRIPTSTATE_CLOSED:
603 decrease_state(This, SCRIPTSTATE_CLOSED);
604 return S_OK;
605 case SCRIPTSTATE_DISCONNECTED:
606 FIXME("unimplemented SCRIPTSTATE_DISCONNECTED\n");
607 return S_OK;
608 default:
609 FIXME("unimplemented state %d\n", ss);
610 return E_NOTIMPL;
613 change_state(This, ss);
614 return S_OK;
617 static HRESULT WINAPI VBScript_GetScriptState(IActiveScript *iface, SCRIPTSTATE *pssState)
619 VBScript *This = impl_from_IActiveScript(iface);
621 TRACE("(%p)->(%p)\n", This, pssState);
623 if(!pssState)
624 return E_POINTER;
626 if(This->thread_id && This->thread_id != GetCurrentThreadId())
627 return E_UNEXPECTED;
629 *pssState = This->state;
630 return S_OK;
633 static HRESULT WINAPI VBScript_Close(IActiveScript *iface)
635 VBScript *This = impl_from_IActiveScript(iface);
637 TRACE("(%p)->()\n", This);
639 if(This->thread_id && This->thread_id != GetCurrentThreadId())
640 return E_UNEXPECTED;
642 decrease_state(This, SCRIPTSTATE_CLOSED);
643 return S_OK;
646 static HRESULT WINAPI VBScript_AddNamedItem(IActiveScript *iface, LPCOLESTR pstrName, DWORD dwFlags)
648 VBScript *This = impl_from_IActiveScript(iface);
649 named_item_t *item;
650 IDispatch *disp = NULL;
651 HRESULT hres;
653 TRACE("(%p)->(%s %x)\n", This, debugstr_w(pstrName), dwFlags);
655 if(This->thread_id != GetCurrentThreadId() || !This->ctx->site)
656 return E_UNEXPECTED;
658 if(dwFlags & SCRIPTITEM_GLOBALMEMBERS) {
659 IUnknown *unk;
661 hres = IActiveScriptSite_GetItemInfo(This->ctx->site, pstrName, SCRIPTINFO_IUNKNOWN, &unk, NULL);
662 if(FAILED(hres)) {
663 WARN("GetItemInfo failed: %08x\n", hres);
664 return hres;
667 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
668 IUnknown_Release(unk);
669 if(FAILED(hres)) {
670 WARN("object does not implement IDispatch\n");
671 return hres;
675 item = heap_alloc(sizeof(*item));
676 if(!item) {
677 if(disp)
678 IDispatch_Release(disp);
679 return E_OUTOFMEMORY;
682 item->ref = 1;
683 item->disp = disp;
684 item->flags = dwFlags;
685 item->script_obj = NULL;
686 item->name = heap_strdupW(pstrName);
687 if(!item->name) {
688 if(disp)
689 IDispatch_Release(disp);
690 heap_free(item);
691 return E_OUTOFMEMORY;
694 list_add_tail(&This->ctx->named_items, &item->entry);
695 return S_OK;
698 static HRESULT WINAPI VBScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
699 DWORD dwMajor, DWORD dwMinor, DWORD dwFlags)
701 VBScript *This = impl_from_IActiveScript(iface);
702 FIXME("(%p)->()\n", This);
703 return E_NOTIMPL;
706 static HRESULT WINAPI VBScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp)
708 VBScript *This = impl_from_IActiveScript(iface);
709 ScriptDisp *script_obj;
711 TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
713 if(!ppdisp)
714 return E_POINTER;
716 if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_obj) {
717 *ppdisp = NULL;
718 return E_UNEXPECTED;
721 script_obj = This->ctx->script_obj;
722 if(pstrItemName) {
723 named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0);
724 if(!item) return E_INVALIDARG;
725 if(item->script_obj) script_obj = item->script_obj;
728 *ppdisp = (IDispatch*)&script_obj->IDispatchEx_iface;
729 IDispatch_AddRef(*ppdisp);
730 return S_OK;
733 static HRESULT WINAPI VBScript_GetCurrentScriptThreadID(IActiveScript *iface,
734 SCRIPTTHREADID *pstridThread)
736 VBScript *This = impl_from_IActiveScript(iface);
737 FIXME("(%p)->()\n", This);
738 return E_NOTIMPL;
741 static HRESULT WINAPI VBScript_GetScriptThreadID(IActiveScript *iface,
742 DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread)
744 VBScript *This = impl_from_IActiveScript(iface);
745 FIXME("(%p)->()\n", This);
746 return E_NOTIMPL;
749 static HRESULT WINAPI VBScript_GetScriptThreadState(IActiveScript *iface,
750 SCRIPTTHREADID stidThread, SCRIPTTHREADSTATE *pstsState)
752 VBScript *This = impl_from_IActiveScript(iface);
753 FIXME("(%p)->()\n", This);
754 return E_NOTIMPL;
757 static HRESULT WINAPI VBScript_InterruptScriptThread(IActiveScript *iface,
758 SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags)
760 VBScript *This = impl_from_IActiveScript(iface);
761 FIXME("(%p)->()\n", This);
762 return E_NOTIMPL;
765 static HRESULT WINAPI VBScript_Clone(IActiveScript *iface, IActiveScript **ppscript)
767 VBScript *This = impl_from_IActiveScript(iface);
768 FIXME("(%p)->()\n", This);
769 return E_NOTIMPL;
772 static const IActiveScriptVtbl VBScriptVtbl = {
773 VBScript_QueryInterface,
774 VBScript_AddRef,
775 VBScript_Release,
776 VBScript_SetScriptSite,
777 VBScript_GetScriptSite,
778 VBScript_SetScriptState,
779 VBScript_GetScriptState,
780 VBScript_Close,
781 VBScript_AddNamedItem,
782 VBScript_AddTypeLib,
783 VBScript_GetScriptDispatch,
784 VBScript_GetCurrentScriptThreadID,
785 VBScript_GetScriptThreadID,
786 VBScript_GetScriptThreadState,
787 VBScript_InterruptScriptThread,
788 VBScript_Clone
791 static inline VBScript *impl_from_IActiveScriptDebug(IActiveScriptDebug *iface)
793 return CONTAINING_RECORD(iface, VBScript, IActiveScriptDebug_iface);
796 static HRESULT WINAPI VBScriptDebug_QueryInterface(IActiveScriptDebug *iface, REFIID riid, void **ppv)
798 VBScript *This = impl_from_IActiveScriptDebug(iface);
799 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
802 static ULONG WINAPI VBScriptDebug_AddRef(IActiveScriptDebug *iface)
804 VBScript *This = impl_from_IActiveScriptDebug(iface);
805 return IActiveScript_AddRef(&This->IActiveScript_iface);
808 static ULONG WINAPI VBScriptDebug_Release(IActiveScriptDebug *iface)
810 VBScript *This = impl_from_IActiveScriptDebug(iface);
811 return IActiveScript_Release(&This->IActiveScript_iface);
814 static HRESULT WINAPI VBScriptDebug_GetScriptTextAttributes(IActiveScriptDebug *iface,
815 LPCOLESTR code, ULONG len, LPCOLESTR delimiter, DWORD flags, SOURCE_TEXT_ATTR *attr)
817 VBScript *This = impl_from_IActiveScriptDebug(iface);
818 FIXME("(%p)->(%s %u %s %#x %p)\n", This, debugstr_w(code), len,
819 debugstr_w(delimiter), flags, attr);
820 return E_NOTIMPL;
823 static HRESULT WINAPI VBScriptDebug_GetScriptletTextAttributes(IActiveScriptDebug *iface,
824 LPCOLESTR code, ULONG len, LPCOLESTR delimiter, DWORD flags, SOURCE_TEXT_ATTR *attr)
826 VBScript *This = impl_from_IActiveScriptDebug(iface);
827 FIXME("(%p)->(%s %u %s %#x %p)\n", This, debugstr_w(code), len,
828 debugstr_w(delimiter), flags, attr);
829 return E_NOTIMPL;
832 static HRESULT WINAPI VBScriptDebug_EnumCodeContextsOfPosition(IActiveScriptDebug *iface,
833 CTXARG_T source, ULONG offset, ULONG len, IEnumDebugCodeContexts **ret)
835 VBScript *This = impl_from_IActiveScriptDebug(iface);
836 FIXME("(%p)->(%s %u %u %p)\n", This, wine_dbgstr_longlong(source), offset, len, ret);
837 return E_NOTIMPL;
840 static const IActiveScriptDebugVtbl VBScriptDebugVtbl = {
841 VBScriptDebug_QueryInterface,
842 VBScriptDebug_AddRef,
843 VBScriptDebug_Release,
844 VBScriptDebug_GetScriptTextAttributes,
845 VBScriptDebug_GetScriptletTextAttributes,
846 VBScriptDebug_EnumCodeContextsOfPosition,
849 static inline VBScript *impl_from_IActiveScriptParse(IActiveScriptParse *iface)
851 return CONTAINING_RECORD(iface, VBScript, IActiveScriptParse_iface);
854 static HRESULT WINAPI VBScriptParse_QueryInterface(IActiveScriptParse *iface, REFIID riid, void **ppv)
856 VBScript *This = impl_from_IActiveScriptParse(iface);
857 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
860 static ULONG WINAPI VBScriptParse_AddRef(IActiveScriptParse *iface)
862 VBScript *This = impl_from_IActiveScriptParse(iface);
863 return IActiveScript_AddRef(&This->IActiveScript_iface);
866 static ULONG WINAPI VBScriptParse_Release(IActiveScriptParse *iface)
868 VBScript *This = impl_from_IActiveScriptParse(iface);
869 return IActiveScript_Release(&This->IActiveScript_iface);
872 static HRESULT WINAPI VBScriptParse_InitNew(IActiveScriptParse *iface)
874 VBScript *This = impl_from_IActiveScriptParse(iface);
876 TRACE("(%p)\n", This);
878 if(This->is_initialized)
879 return E_UNEXPECTED;
880 This->is_initialized = TRUE;
882 if(This->ctx->site)
883 change_state(This, SCRIPTSTATE_INITIALIZED);
884 return S_OK;
887 static HRESULT WINAPI VBScriptParse_AddScriptlet(IActiveScriptParse *iface,
888 LPCOLESTR pstrDefaultName, LPCOLESTR pstrCode, LPCOLESTR pstrItemName,
889 LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName, LPCOLESTR pstrDelimiter,
890 CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags,
891 BSTR *pbstrName, EXCEPINFO *pexcepinfo)
893 VBScript *This = impl_from_IActiveScriptParse(iface);
894 FIXME("(%p)->(%s %s %s %s %s %s %s %u %x %p %p)\n", This, debugstr_w(pstrDefaultName),
895 debugstr_w(pstrCode), debugstr_w(pstrItemName), debugstr_w(pstrSubItemName),
896 debugstr_w(pstrEventName), debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie),
897 ulStartingLineNumber, dwFlags, pbstrName, pexcepinfo);
898 return E_NOTIMPL;
901 static HRESULT WINAPI VBScriptParse_ParseScriptText(IActiveScriptParse *iface,
902 LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
903 LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
904 DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo)
906 VBScript *This = impl_from_IActiveScriptParse(iface);
907 vbscode_t *code;
908 HRESULT hres;
910 TRACE("(%p)->(%s %s %p %s %s %u %x %p %p)\n", This, debugstr_w(pstrCode),
911 debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
912 wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLine, dwFlags, pvarResult, pexcepinfo);
914 if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
915 return E_UNEXPECTED;
917 hres = compile_script(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie,
918 ulStartingLine, dwFlags, &code);
919 if(FAILED(hres))
920 return hres;
922 if(!(dwFlags & SCRIPTTEXT_ISEXPRESSION) && !is_started(This)) {
923 code->pending_exec = TRUE;
924 return S_OK;
927 return exec_global_code(This->ctx, code, pvarResult);
930 static const IActiveScriptParseVtbl VBScriptParseVtbl = {
931 VBScriptParse_QueryInterface,
932 VBScriptParse_AddRef,
933 VBScriptParse_Release,
934 VBScriptParse_InitNew,
935 VBScriptParse_AddScriptlet,
936 VBScriptParse_ParseScriptText
939 static inline VBScript *impl_from_IActiveScriptParseProcedure2(IActiveScriptParseProcedure2 *iface)
941 return CONTAINING_RECORD(iface, VBScript, IActiveScriptParseProcedure2_iface);
944 static HRESULT WINAPI VBScriptParseProcedure_QueryInterface(IActiveScriptParseProcedure2 *iface, REFIID riid, void **ppv)
946 VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
947 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
950 static ULONG WINAPI VBScriptParseProcedure_AddRef(IActiveScriptParseProcedure2 *iface)
952 VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
953 return IActiveScript_AddRef(&This->IActiveScript_iface);
956 static ULONG WINAPI VBScriptParseProcedure_Release(IActiveScriptParseProcedure2 *iface)
958 VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
959 return IActiveScript_Release(&This->IActiveScript_iface);
962 static HRESULT WINAPI VBScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface,
963 LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName,
964 LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter,
965 CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp)
967 VBScript *This = impl_from_IActiveScriptParseProcedure2(iface);
968 class_desc_t *desc;
969 vbdisp_t *vbdisp;
970 HRESULT hres;
972 TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams),
973 debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter),
974 wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp);
976 if(This->thread_id != GetCurrentThreadId() || This->state == SCRIPTSTATE_CLOSED)
977 return E_UNEXPECTED;
979 hres = compile_procedure(This->ctx, pstrCode, pstrItemName, pstrDelimiter, dwSourceContextCookie,
980 ulStartingLineNumber, dwFlags, &desc);
981 if(FAILED(hres))
982 return hres;
984 hres = create_vbdisp(desc, &vbdisp);
985 if(FAILED(hres))
986 return hres;
988 *ppdisp = (IDispatch*)&vbdisp->IDispatchEx_iface;
989 return S_OK;
992 static const IActiveScriptParseProcedure2Vtbl VBScriptParseProcedureVtbl = {
993 VBScriptParseProcedure_QueryInterface,
994 VBScriptParseProcedure_AddRef,
995 VBScriptParseProcedure_Release,
996 VBScriptParseProcedure_ParseProcedureText,
999 static inline VBScript *impl_from_IObjectSafety(IObjectSafety *iface)
1001 return CONTAINING_RECORD(iface, VBScript, IObjectSafety_iface);
1004 static HRESULT WINAPI VBScriptSafety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
1006 VBScript *This = impl_from_IObjectSafety(iface);
1007 return IActiveScript_QueryInterface(&This->IActiveScript_iface, riid, ppv);
1010 static ULONG WINAPI VBScriptSafety_AddRef(IObjectSafety *iface)
1012 VBScript *This = impl_from_IObjectSafety(iface);
1013 return IActiveScript_AddRef(&This->IActiveScript_iface);
1016 static ULONG WINAPI VBScriptSafety_Release(IObjectSafety *iface)
1018 VBScript *This = impl_from_IObjectSafety(iface);
1019 return IActiveScript_Release(&This->IActiveScript_iface);
1022 #define SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER)
1024 static HRESULT WINAPI VBScriptSafety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1025 DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
1027 VBScript *This = impl_from_IObjectSafety(iface);
1029 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), pdwSupportedOptions, pdwEnabledOptions);
1031 if(!pdwSupportedOptions || !pdwEnabledOptions)
1032 return E_POINTER;
1034 *pdwSupportedOptions = SUPPORTED_OPTIONS;
1035 *pdwEnabledOptions = This->ctx->safeopt;
1036 return S_OK;
1039 static HRESULT WINAPI VBScriptSafety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1040 DWORD dwOptionSetMask, DWORD dwEnabledOptions)
1042 VBScript *This = impl_from_IObjectSafety(iface);
1044 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), dwOptionSetMask, dwEnabledOptions);
1046 if(dwOptionSetMask & ~SUPPORTED_OPTIONS)
1047 return E_FAIL;
1049 This->ctx->safeopt = (dwEnabledOptions & dwOptionSetMask) | (This->ctx->safeopt & ~dwOptionSetMask) | INTERFACE_USES_DISPEX;
1050 return S_OK;
1053 static const IObjectSafetyVtbl VBScriptSafetyVtbl = {
1054 VBScriptSafety_QueryInterface,
1055 VBScriptSafety_AddRef,
1056 VBScriptSafety_Release,
1057 VBScriptSafety_GetInterfaceSafetyOptions,
1058 VBScriptSafety_SetInterfaceSafetyOptions
1061 HRESULT WINAPI VBScriptFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv)
1063 script_ctx_t *ctx;
1064 VBScript *ret;
1065 HRESULT hres;
1067 TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppv);
1069 ret = heap_alloc_zero(sizeof(*ret));
1070 if(!ret)
1071 return E_OUTOFMEMORY;
1073 ret->IActiveScript_iface.lpVtbl = &VBScriptVtbl;
1074 ret->IActiveScriptDebug_iface.lpVtbl = &VBScriptDebugVtbl;
1075 ret->IActiveScriptParse_iface.lpVtbl = &VBScriptParseVtbl;
1076 ret->IActiveScriptParseProcedure2_iface.lpVtbl = &VBScriptParseProcedureVtbl;
1077 ret->IObjectSafety_iface.lpVtbl = &VBScriptSafetyVtbl;
1079 ret->ref = 1;
1080 ret->state = SCRIPTSTATE_UNINITIALIZED;
1082 ctx = ret->ctx = heap_alloc_zero(sizeof(*ctx));
1083 if(!ctx) {
1084 heap_free(ret);
1085 return E_OUTOFMEMORY;
1088 ctx->safeopt = INTERFACE_USES_DISPEX;
1089 list_init(&ctx->objects);
1090 list_init(&ctx->code_list);
1091 list_init(&ctx->named_items);
1093 hres = init_global(ctx);
1094 if(FAILED(hres)) {
1095 IActiveScript_Release(&ret->IActiveScript_iface);
1096 return hres;
1099 hres = IActiveScript_QueryInterface(&ret->IActiveScript_iface, riid, ppv);
1100 IActiveScript_Release(&ret->IActiveScript_iface);
1101 return hres;
1104 typedef struct {
1105 IServiceProvider IServiceProvider_iface;
1107 LONG ref;
1109 IServiceProvider *sp;
1110 } AXSite;
1112 static inline AXSite *impl_from_IServiceProvider(IServiceProvider *iface)
1114 return CONTAINING_RECORD(iface, AXSite, IServiceProvider_iface);
1117 static HRESULT WINAPI AXSite_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
1119 AXSite *This = impl_from_IServiceProvider(iface);
1121 if(IsEqualGUID(&IID_IUnknown, riid)) {
1122 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1123 *ppv = &This->IServiceProvider_iface;
1124 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
1125 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
1126 *ppv = &This->IServiceProvider_iface;
1127 }else {
1128 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1129 *ppv = NULL;
1130 return E_NOINTERFACE;
1133 IUnknown_AddRef((IUnknown*)*ppv);
1134 return S_OK;
1137 static ULONG WINAPI AXSite_AddRef(IServiceProvider *iface)
1139 AXSite *This = impl_from_IServiceProvider(iface);
1140 LONG ref = InterlockedIncrement(&This->ref);
1142 TRACE("(%p) ref=%d\n", This, ref);
1144 return ref;
1147 static ULONG WINAPI AXSite_Release(IServiceProvider *iface)
1149 AXSite *This = impl_from_IServiceProvider(iface);
1150 LONG ref = InterlockedDecrement(&This->ref);
1152 TRACE("(%p) ref=%d\n", This, ref);
1154 if(!ref)
1155 heap_free(This);
1157 return ref;
1160 static HRESULT WINAPI AXSite_QueryService(IServiceProvider *iface,
1161 REFGUID guidService, REFIID riid, void **ppv)
1163 AXSite *This = impl_from_IServiceProvider(iface);
1165 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
1167 return IServiceProvider_QueryService(This->sp, guidService, riid, ppv);
1170 static IServiceProviderVtbl AXSiteVtbl = {
1171 AXSite_QueryInterface,
1172 AXSite_AddRef,
1173 AXSite_Release,
1174 AXSite_QueryService
1177 IUnknown *create_ax_site(script_ctx_t *ctx)
1179 IServiceProvider *sp;
1180 AXSite *ret;
1181 HRESULT hres;
1183 hres = IActiveScriptSite_QueryInterface(ctx->site, &IID_IServiceProvider, (void**)&sp);
1184 if(FAILED(hres)) {
1185 ERR("Could not get IServiceProvider iface: %08x\n", hres);
1186 return NULL;
1189 ret = heap_alloc(sizeof(*ret));
1190 if(!ret) {
1191 IServiceProvider_Release(sp);
1192 return NULL;
1195 ret->IServiceProvider_iface.lpVtbl = &AXSiteVtbl;
1196 ret->ref = 1;
1197 ret->sp = sp;
1199 return (IUnknown*)&ret->IServiceProvider_iface;