wininet: Don't update *lpdwIndex if HttpQueryInfoW fails with ERROR_INSUFFICIENT_BUFFER.
[wine/wine-gecko.git] / dlls / vbscript / interp.c
blob10641dbbf5cd898459b4e8a9c5c0f5f217a2e4fa
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
19 #include <assert.h>
21 #include "vbscript.h"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(vbscript);
27 static DISPID propput_dispid = DISPID_PROPERTYPUT;
29 typedef struct {
30 vbscode_t *code;
31 instr_t *instr;
32 script_ctx_t *script;
33 function_t *func;
34 IDispatch *this_obj;
35 vbdisp_t *vbthis;
37 VARIANT *args;
38 VARIANT *vars;
39 SAFEARRAY **arrays;
41 dynamic_var_t *dynamic_vars;
42 heap_pool_t heap;
44 BOOL resume_next;
46 unsigned stack_size;
47 unsigned top;
48 VARIANT *stack;
50 VARIANT ret_val;
51 } exec_ctx_t;
53 typedef HRESULT (*instr_func_t)(exec_ctx_t*);
55 typedef enum {
56 REF_NONE,
57 REF_DISP,
58 REF_VAR,
59 REF_OBJ,
60 REF_CONST,
61 REF_FUNC
62 } ref_type_t;
64 typedef struct {
65 ref_type_t type;
66 union {
67 struct {
68 IDispatch *disp;
69 DISPID id;
70 } d;
71 VARIANT *v;
72 function_t *f;
73 IDispatch *obj;
74 } u;
75 } ref_t;
77 typedef struct {
78 VARIANT *v;
79 VARIANT store;
80 BOOL owned;
81 } variant_val_t;
83 static BOOL lookup_dynamic_vars(dynamic_var_t *var, const WCHAR *name, ref_t *ref)
85 while(var) {
86 if(!strcmpiW(var->name, name)) {
87 ref->type = var->is_const ? REF_CONST : REF_VAR;
88 ref->u.v = &var->v;
89 return TRUE;
92 var = var->next;
95 return FALSE;
98 static HRESULT lookup_identifier(exec_ctx_t *ctx, BSTR name, vbdisp_invoke_type_t invoke_type, ref_t *ref)
100 named_item_t *item;
101 function_t *func;
102 unsigned i;
103 DISPID id;
104 HRESULT hres;
106 static const WCHAR errW[] = {'e','r','r',0};
108 if(invoke_type == VBDISP_LET
109 && (ctx->func->type == FUNC_FUNCTION || ctx->func->type == FUNC_PROPGET || ctx->func->type == FUNC_DEFGET)
110 && !strcmpiW(name, ctx->func->name)) {
111 ref->type = REF_VAR;
112 ref->u.v = &ctx->ret_val;
113 return S_OK;
116 for(i=0; i < ctx->func->var_cnt; i++) {
117 if(!strcmpiW(ctx->func->vars[i].name, name)) {
118 ref->type = REF_VAR;
119 ref->u.v = ctx->vars+i;
120 return TRUE;
124 for(i=0; i < ctx->func->arg_cnt; i++) {
125 if(!strcmpiW(ctx->func->args[i].name, name)) {
126 ref->type = REF_VAR;
127 ref->u.v = ctx->args+i;
128 return S_OK;
132 if(lookup_dynamic_vars(ctx->func->type == FUNC_GLOBAL ? ctx->script->global_vars : ctx->dynamic_vars, name, ref))
133 return S_OK;
135 if(ctx->func->type != FUNC_GLOBAL) {
136 if(ctx->vbthis) {
137 /* FIXME: Bind such identifier while generating bytecode. */
138 for(i=0; i < ctx->vbthis->desc->prop_cnt; i++) {
139 if(!strcmpiW(ctx->vbthis->desc->props[i].name, name)) {
140 ref->type = REF_VAR;
141 ref->u.v = ctx->vbthis->props+i;
142 return S_OK;
147 hres = disp_get_id(ctx->this_obj, name, invoke_type, TRUE, &id);
148 if(SUCCEEDED(hres)) {
149 ref->type = REF_DISP;
150 ref->u.d.disp = ctx->this_obj;
151 ref->u.d.id = id;
152 return S_OK;
156 if(ctx->func->type != FUNC_GLOBAL && lookup_dynamic_vars(ctx->script->global_vars, name, ref))
157 return S_OK;
159 for(func = ctx->script->global_funcs; func; func = func->next) {
160 if(!strcmpiW(func->name, name)) {
161 ref->type = REF_FUNC;
162 ref->u.f = func;
163 return S_OK;
167 if(!strcmpiW(name, errW)) {
168 ref->type = REF_OBJ;
169 ref->u.obj = (IDispatch*)&ctx->script->err_obj->IDispatchEx_iface;
170 return S_OK;
173 hres = vbdisp_get_id(ctx->script->global_obj, name, invoke_type, TRUE, &id);
174 if(SUCCEEDED(hres)) {
175 ref->type = REF_DISP;
176 ref->u.d.disp = (IDispatch*)&ctx->script->global_obj->IDispatchEx_iface;
177 ref->u.d.id = id;
178 return S_OK;
181 LIST_FOR_EACH_ENTRY(item, &ctx->script->named_items, named_item_t, entry) {
182 if((item->flags & SCRIPTITEM_ISVISIBLE) && !strcmpiW(item->name, name)) {
183 if(!item->disp) {
184 IUnknown *unk;
186 hres = IActiveScriptSite_GetItemInfo(ctx->script->site, name, SCRIPTINFO_IUNKNOWN, &unk, NULL);
187 if(FAILED(hres)) {
188 WARN("GetItemInfo failed: %08x\n", hres);
189 continue;
192 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&item->disp);
193 IUnknown_Release(unk);
194 if(FAILED(hres)) {
195 WARN("object does not implement IDispatch\n");
196 continue;
200 ref->type = REF_OBJ;
201 ref->u.obj = item->disp;
202 return S_OK;
206 LIST_FOR_EACH_ENTRY(item, &ctx->script->named_items, named_item_t, entry) {
207 if((item->flags & SCRIPTITEM_GLOBALMEMBERS)) {
208 hres = disp_get_id(item->disp, name, invoke_type, FALSE, &id);
209 if(SUCCEEDED(hres)) {
210 ref->type = REF_DISP;
211 ref->u.d.disp = item->disp;
212 ref->u.d.id = id;
213 return S_OK;
218 ref->type = REF_NONE;
219 return S_OK;
222 static HRESULT add_dynamic_var(exec_ctx_t *ctx, const WCHAR *name,
223 BOOL is_const, VARIANT *val, BOOL own_val, VARIANT **out_var)
225 dynamic_var_t *new_var;
226 heap_pool_t *heap;
227 WCHAR *str;
228 unsigned size;
229 HRESULT hres;
231 heap = ctx->func->type == FUNC_GLOBAL ? &ctx->script->heap : &ctx->heap;
233 new_var = heap_pool_alloc(heap, sizeof(*new_var));
234 if(!new_var)
235 return E_OUTOFMEMORY;
237 size = (strlenW(name)+1)*sizeof(WCHAR);
238 str = heap_pool_alloc(heap, size);
239 if(!str)
240 return E_OUTOFMEMORY;
241 memcpy(str, name, size);
242 new_var->name = str;
243 new_var->is_const = is_const;
245 if(own_val) {
246 new_var->v = *val;
247 }else {
248 V_VT(&new_var->v) = VT_EMPTY;
249 hres = VariantCopy(&new_var->v, val);
250 if(FAILED(hres))
251 return hres;
254 if(ctx->func->type == FUNC_GLOBAL) {
255 new_var->next = ctx->script->global_vars;
256 ctx->script->global_vars = new_var;
257 }else {
258 new_var->next = ctx->dynamic_vars;
259 ctx->dynamic_vars = new_var;
262 if(out_var)
263 *out_var = &new_var->v;
265 return S_OK;
268 static inline VARIANT *stack_pop(exec_ctx_t *ctx)
270 assert(ctx->top);
271 return ctx->stack + --ctx->top;
274 static inline VARIANT *stack_top(exec_ctx_t *ctx, unsigned n)
276 assert(ctx->top >= n);
277 return ctx->stack + (ctx->top-n-1);
280 static HRESULT stack_push(exec_ctx_t *ctx, VARIANT *v)
282 if(ctx->stack_size == ctx->top) {
283 VARIANT *new_stack;
285 new_stack = heap_realloc(ctx->stack, ctx->stack_size*2*sizeof(*ctx->stack));
286 if(!new_stack) {
287 VariantClear(v);
288 return E_OUTOFMEMORY;
291 ctx->stack = new_stack;
292 ctx->stack_size *= 2;
295 ctx->stack[ctx->top++] = *v;
296 return S_OK;
299 static inline HRESULT stack_push_null(exec_ctx_t *ctx)
301 VARIANT v;
302 V_VT(&v) = VT_NULL;
303 return stack_push(ctx, &v);
306 static void stack_popn(exec_ctx_t *ctx, unsigned n)
308 while(n--)
309 VariantClear(stack_pop(ctx));
312 static void stack_pop_deref(exec_ctx_t *ctx, variant_val_t *r)
314 VARIANT *v;
316 v = stack_pop(ctx);
317 if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
318 r->owned = FALSE;
319 r->v = V_VARIANTREF(v);
320 }else {
321 r->owned = TRUE;
322 r->v = v;
326 static inline void release_val(variant_val_t *v)
328 if(v->owned)
329 VariantClear(v->v);
332 static HRESULT stack_pop_val(exec_ctx_t *ctx, variant_val_t *r)
334 stack_pop_deref(ctx, r);
336 if(V_VT(r->v) == VT_DISPATCH) {
337 DISPPARAMS dp = {0};
338 HRESULT hres;
340 hres = disp_call(ctx->script, V_DISPATCH(r->v), DISPID_VALUE, &dp, &r->store);
341 if(r->owned)
342 IDispatch_Release(V_DISPATCH(r->v));
343 if(FAILED(hres))
344 return hres;
346 r->owned = TRUE;
347 r->v = &r->store;
350 return S_OK;
353 static HRESULT stack_assume_val(exec_ctx_t *ctx, unsigned n)
355 VARIANT *v = stack_top(ctx, n);
356 HRESULT hres;
358 if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
359 VARIANT *ref = V_VARIANTREF(v);
361 V_VT(v) = VT_EMPTY;
362 hres = VariantCopy(v, ref);
363 if(FAILED(hres))
364 return hres;
367 if(V_VT(v) == VT_DISPATCH) {
368 DISPPARAMS dp = {0};
369 IDispatch *disp;
371 disp = V_DISPATCH(v);
372 V_VT(v) = VT_EMPTY;
373 hres = disp_call(ctx->script, disp, DISPID_VALUE, &dp, v);
374 IDispatch_Release(disp);
375 if(FAILED(hres))
376 return hres;
379 return S_OK;
382 static int stack_pop_bool(exec_ctx_t *ctx, BOOL *b)
384 variant_val_t val;
385 HRESULT hres;
387 hres = stack_pop_val(ctx, &val);
388 if(FAILED(hres))
389 return hres;
391 switch (V_VT(val.v))
393 case VT_BOOL:
394 *b = V_BOOL(val.v);
395 break;
396 case VT_NULL:
397 *b = FALSE;
398 break;
399 case VT_I2:
400 *b = V_I2(val.v);
401 break;
402 case VT_I4:
403 *b = V_I4(val.v);
404 break;
405 default:
406 FIXME("unsupported for %s\n", debugstr_variant(val.v));
407 release_val(&val);
408 return E_NOTIMPL;
410 return S_OK;
413 static HRESULT stack_pop_disp(exec_ctx_t *ctx, IDispatch **ret)
415 VARIANT *v = stack_pop(ctx);
417 if(V_VT(v) == VT_DISPATCH) {
418 *ret = V_DISPATCH(v);
419 return S_OK;
422 if(V_VT(v) != (VT_VARIANT|VT_BYREF)) {
423 FIXME("not supported type: %s\n", debugstr_variant(v));
424 VariantClear(v);
425 return E_FAIL;
428 v = V_BYREF(v);
429 if(V_VT(v) != VT_DISPATCH) {
430 FIXME("not disp %s\n", debugstr_variant(v));
431 return E_FAIL;
434 if(V_DISPATCH(v))
435 IDispatch_AddRef(V_DISPATCH(v));
436 *ret = V_DISPATCH(v);
437 return S_OK;
440 static HRESULT stack_assume_disp(exec_ctx_t *ctx, unsigned n, IDispatch **disp)
442 VARIANT *v = stack_top(ctx, n), *ref;
444 if(V_VT(v) != VT_DISPATCH) {
445 if(V_VT(v) != (VT_VARIANT|VT_BYREF)) {
446 FIXME("not supported type: %s\n", debugstr_variant(v));
447 return E_FAIL;
450 ref = V_VARIANTREF(v);
451 if(V_VT(ref) != VT_DISPATCH) {
452 FIXME("not disp %s\n", debugstr_variant(ref));
453 return E_FAIL;
456 V_VT(v) = VT_DISPATCH;
457 V_DISPATCH(v) = V_DISPATCH(ref);
458 if(V_DISPATCH(v))
459 IDispatch_AddRef(V_DISPATCH(v));
462 if(disp)
463 *disp = V_DISPATCH(v);
464 return S_OK;
467 static inline void instr_jmp(exec_ctx_t *ctx, unsigned addr)
469 ctx->instr = ctx->code->instrs + addr;
472 static void vbstack_to_dp(exec_ctx_t *ctx, unsigned arg_cnt, BOOL is_propput, DISPPARAMS *dp)
474 dp->cNamedArgs = is_propput ? 1 : 0;
475 dp->cArgs = arg_cnt + dp->cNamedArgs;
476 dp->rgdispidNamedArgs = is_propput ? &propput_dispid : NULL;
478 if(arg_cnt) {
479 VARIANT tmp;
480 unsigned i;
482 assert(ctx->top >= arg_cnt);
484 for(i=1; i*2 <= arg_cnt; i++) {
485 tmp = ctx->stack[ctx->top-i];
486 ctx->stack[ctx->top-i] = ctx->stack[ctx->top-arg_cnt+i-1];
487 ctx->stack[ctx->top-arg_cnt+i-1] = tmp;
490 dp->rgvarg = ctx->stack + ctx->top-dp->cArgs;
491 }else {
492 dp->rgvarg = is_propput ? ctx->stack+ctx->top-1 : NULL;
496 static HRESULT array_access(exec_ctx_t *ctx, SAFEARRAY *array, DISPPARAMS *dp, VARIANT **ret)
498 unsigned cell_off = 0, dim_size = 1, i;
499 unsigned argc = arg_cnt(dp);
500 VARIANT *data;
501 LONG idx;
502 HRESULT hres;
504 if(!array) {
505 FIXME("NULL array\n");
506 return E_FAIL;
509 if(array->cDims != argc) {
510 FIXME("argc %d does not match cDims %d\n", dp->cArgs, array->cDims);
511 return E_FAIL;
514 for(i=0; i < argc; i++) {
515 hres = to_int(get_arg(dp, i), &idx);
516 if(FAILED(hres))
517 return hres;
519 idx -= array->rgsabound[i].lLbound;
520 if(idx >= array->rgsabound[i].cElements) {
521 FIXME("out of bound element %d in dim %d of size %d\n", idx, i+1, array->rgsabound[i].cElements);
522 return E_FAIL;
525 cell_off += idx*dim_size;
526 dim_size *= array->rgsabound[i].cElements;
529 hres = SafeArrayAccessData(array, (void**)&data);
530 if(FAILED(hres))
531 return hres;
533 *ret = data+cell_off;
535 SafeArrayUnaccessData(array);
536 return S_OK;
539 static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res)
541 BSTR identifier = ctx->instr->arg1.bstr;
542 const unsigned arg_cnt = ctx->instr->arg2.uint;
543 DISPPARAMS dp;
544 ref_t ref;
545 HRESULT hres;
547 hres = lookup_identifier(ctx, identifier, VBDISP_CALLGET, &ref);
548 if(FAILED(hres))
549 return hres;
551 switch(ref.type) {
552 case REF_VAR:
553 case REF_CONST: {
554 VARIANT *v;
556 if(!res) {
557 FIXME("REF_VAR no res\n");
558 return E_NOTIMPL;
561 v = V_VT(ref.u.v) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(ref.u.v) : ref.u.v;
563 if(arg_cnt) {
564 SAFEARRAY *array;
566 switch(V_VT(v)) {
567 case VT_ARRAY|VT_BYREF|VT_VARIANT:
568 array = *V_ARRAYREF(ref.u.v);
569 break;
570 case VT_ARRAY|VT_VARIANT:
571 array = V_ARRAY(ref.u.v);
572 break;
573 default:
574 FIXME("arguments not implemented\n");
575 return E_NOTIMPL;
578 vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
579 hres = array_access(ctx, array, &dp, &v);
580 if(FAILED(hres))
581 return hres;
584 V_VT(res) = VT_BYREF|VT_VARIANT;
585 V_BYREF(res) = v;
586 break;
588 case REF_DISP:
589 vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
590 hres = disp_call(ctx->script, ref.u.d.disp, ref.u.d.id, &dp, res);
591 if(FAILED(hres))
592 return hres;
593 break;
594 case REF_FUNC:
595 vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
596 hres = exec_script(ctx->script, ref.u.f, NULL, &dp, res);
597 if(FAILED(hres))
598 return hres;
599 break;
600 case REF_OBJ:
601 if(arg_cnt) {
602 FIXME("arguments on object\n");
603 return E_NOTIMPL;
606 if(res) {
607 IDispatch_AddRef(ref.u.obj);
608 V_VT(res) = VT_DISPATCH;
609 V_DISPATCH(res) = ref.u.obj;
611 break;
612 case REF_NONE:
613 if(res && !ctx->func->code_ctx->option_explicit && arg_cnt == 0) {
614 VARIANT v, *new;
615 VariantInit(&v);
616 hres = add_dynamic_var(ctx, identifier, FALSE, &v, FALSE, &new);
617 if(FAILED(hres))
618 return hres;
619 V_VT(res) = VT_BYREF|VT_VARIANT;
620 V_BYREF(res) = new;
621 break;
623 FIXME("%s not found\n", debugstr_w(identifier));
624 return DISP_E_UNKNOWNNAME;
627 stack_popn(ctx, arg_cnt);
628 return S_OK;
631 static HRESULT interp_icall(exec_ctx_t *ctx)
633 VARIANT v;
634 HRESULT hres;
636 TRACE("\n");
638 hres = do_icall(ctx, &v);
639 if(FAILED(hres))
640 return hres;
642 return stack_push(ctx, &v);
645 static HRESULT interp_icallv(exec_ctx_t *ctx)
647 TRACE("\n");
648 return do_icall(ctx, NULL);
651 static HRESULT do_mcall(exec_ctx_t *ctx, VARIANT *res)
653 const BSTR identifier = ctx->instr->arg1.bstr;
654 const unsigned arg_cnt = ctx->instr->arg2.uint;
655 IDispatch *obj;
656 DISPPARAMS dp;
657 DISPID id;
658 HRESULT hres;
660 hres = stack_pop_disp(ctx, &obj);
661 if(FAILED(hres))
662 return hres;
664 if(!obj) {
665 FIXME("NULL obj\n");
666 return E_FAIL;
669 vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
671 hres = disp_get_id(obj, identifier, VBDISP_CALLGET, FALSE, &id);
672 if(SUCCEEDED(hres))
673 hres = disp_call(ctx->script, obj, id, &dp, res);
674 IDispatch_Release(obj);
675 if(FAILED(hres))
676 return hres;
678 stack_popn(ctx, arg_cnt);
679 return S_OK;
682 static HRESULT interp_mcall(exec_ctx_t *ctx)
684 VARIANT res;
685 HRESULT hres;
687 TRACE("\n");
689 hres = do_mcall(ctx, &res);
690 if(FAILED(hres))
691 return hres;
693 return stack_push(ctx, &res);
696 static HRESULT interp_mcallv(exec_ctx_t *ctx)
698 TRACE("\n");
700 return do_mcall(ctx, NULL);
703 static HRESULT assign_ident(exec_ctx_t *ctx, BSTR name, DISPPARAMS *dp)
705 ref_t ref;
706 HRESULT hres;
708 hres = lookup_identifier(ctx, name, VBDISP_LET, &ref);
709 if(FAILED(hres))
710 return hres;
712 switch(ref.type) {
713 case REF_VAR: {
714 VARIANT *v = ref.u.v;
716 if(V_VT(v) == (VT_VARIANT|VT_BYREF))
717 v = V_VARIANTREF(v);
719 if(arg_cnt(dp)) {
720 SAFEARRAY *array;
722 if(!(V_VT(v) & VT_ARRAY)) {
723 FIXME("array assign on type %d\n", V_VT(v));
724 return E_FAIL;
727 switch(V_VT(v)) {
728 case VT_ARRAY|VT_BYREF|VT_VARIANT:
729 array = *V_ARRAYREF(v);
730 break;
731 case VT_ARRAY|VT_VARIANT:
732 array = V_ARRAY(v);
733 break;
734 default:
735 FIXME("Unsupported array type %x\n", V_VT(v));
736 return E_NOTIMPL;
739 if(!array) {
740 FIXME("null array\n");
741 return E_FAIL;
744 hres = array_access(ctx, array, dp, &v);
745 if(FAILED(hres))
746 return hres;
747 }else if(V_VT(v) == (VT_ARRAY|VT_BYREF|VT_VARIANT)) {
748 FIXME("non-array assign\n");
749 return E_NOTIMPL;
752 hres = VariantCopyInd(v, dp->rgvarg);
753 break;
755 case REF_DISP:
756 hres = disp_propput(ctx->script, ref.u.d.disp, ref.u.d.id, dp);
757 break;
758 case REF_FUNC:
759 FIXME("functions not implemented\n");
760 return E_NOTIMPL;
761 case REF_OBJ:
762 FIXME("REF_OBJ\n");
763 return E_NOTIMPL;
764 case REF_CONST:
765 FIXME("REF_CONST\n");
766 return E_NOTIMPL;
767 case REF_NONE:
768 if(ctx->func->code_ctx->option_explicit) {
769 FIXME("throw exception\n");
770 hres = E_FAIL;
771 }else {
772 if(arg_cnt(dp)) {
773 FIXME("arg_cnt %d not supported\n", arg_cnt(dp));
774 return E_NOTIMPL;
777 TRACE("creating variable %s\n", debugstr_w(name));
778 hres = add_dynamic_var(ctx, name, FALSE, dp->rgvarg, FALSE, NULL);
782 return hres;
785 static HRESULT interp_assign_ident(exec_ctx_t *ctx)
787 const BSTR arg = ctx->instr->arg1.bstr;
788 const unsigned arg_cnt = ctx->instr->arg2.uint;
789 DISPPARAMS dp;
790 HRESULT hres;
792 TRACE("%s\n", debugstr_w(arg));
794 hres = stack_assume_val(ctx, arg_cnt);
795 if(FAILED(hres))
796 return hres;
798 vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
799 hres = assign_ident(ctx, arg, &dp);
800 if(FAILED(hres))
801 return hres;
803 stack_popn(ctx, arg_cnt+1);
804 return S_OK;
807 static HRESULT interp_set_ident(exec_ctx_t *ctx)
809 const BSTR arg = ctx->instr->arg1.bstr;
810 const unsigned arg_cnt = ctx->instr->arg2.uint;
811 DISPPARAMS dp;
812 HRESULT hres;
814 TRACE("%s\n", debugstr_w(arg));
816 if(arg_cnt) {
817 FIXME("arguments not supported\n");
818 return E_NOTIMPL;
821 hres = stack_assume_disp(ctx, 0, NULL);
822 if(FAILED(hres))
823 return hres;
825 vbstack_to_dp(ctx, 0, TRUE, &dp);
826 hres = assign_ident(ctx, ctx->instr->arg1.bstr, &dp);
827 if(FAILED(hres))
828 return hres;
830 stack_popn(ctx, 1);
831 return S_OK;
834 static HRESULT interp_assign_member(exec_ctx_t *ctx)
836 BSTR identifier = ctx->instr->arg1.bstr;
837 const unsigned arg_cnt = ctx->instr->arg2.uint;
838 IDispatch *obj;
839 DISPPARAMS dp;
840 DISPID id;
841 HRESULT hres;
843 TRACE("%s\n", debugstr_w(identifier));
845 hres = stack_assume_disp(ctx, arg_cnt+1, &obj);
846 if(FAILED(hres))
847 return hres;
849 if(!obj) {
850 FIXME("NULL obj\n");
851 return E_FAIL;
854 hres = stack_assume_val(ctx, arg_cnt);
855 if(FAILED(hres))
856 return hres;
858 hres = disp_get_id(obj, identifier, VBDISP_LET, FALSE, &id);
859 if(SUCCEEDED(hres)) {
860 vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
861 hres = disp_propput(ctx->script, obj, id, &dp);
863 if(FAILED(hres))
864 return hres;
866 stack_popn(ctx, arg_cnt+2);
867 return S_OK;
870 static HRESULT interp_set_member(exec_ctx_t *ctx)
872 BSTR identifier = ctx->instr->arg1.bstr;
873 const unsigned arg_cnt = ctx->instr->arg2.uint;
874 IDispatch *obj;
875 DISPPARAMS dp;
876 DISPID id;
877 HRESULT hres;
879 TRACE("%s\n", debugstr_w(identifier));
881 if(arg_cnt) {
882 FIXME("arguments not supported\n");
883 return E_NOTIMPL;
886 hres = stack_assume_disp(ctx, 1, &obj);
887 if(FAILED(hres))
888 return hres;
890 if(!obj) {
891 FIXME("NULL obj\n");
892 return E_FAIL;
895 hres = stack_assume_disp(ctx, 0, NULL);
896 if(FAILED(hres))
897 return hres;
899 hres = disp_get_id(obj, identifier, VBDISP_SET, FALSE, &id);
900 if(SUCCEEDED(hres)) {
901 vbstack_to_dp(ctx, arg_cnt, TRUE, &dp);
902 hres = disp_propput(ctx->script, obj, id, &dp);
904 if(FAILED(hres))
905 return hres;
907 stack_popn(ctx, 2);
908 return S_OK;
911 static HRESULT interp_const(exec_ctx_t *ctx)
913 BSTR arg = ctx->instr->arg1.bstr;
914 variant_val_t val;
915 ref_t ref;
916 HRESULT hres;
918 TRACE("%s\n", debugstr_w(arg));
920 assert(ctx->func->type == FUNC_GLOBAL);
922 hres = lookup_identifier(ctx, arg, VBDISP_CALLGET, &ref);
923 if(FAILED(hres))
924 return hres;
926 if(ref.type != REF_NONE) {
927 FIXME("%s already defined\n", debugstr_w(arg));
928 return E_FAIL;
931 hres = stack_pop_val(ctx, &val);
932 if(FAILED(hres))
933 return hres;
935 return add_dynamic_var(ctx, arg, TRUE, val.v, val.owned, NULL);
938 static HRESULT interp_val(exec_ctx_t *ctx)
940 variant_val_t val;
941 VARIANT v;
942 HRESULT hres;
944 TRACE("\n");
946 hres = stack_pop_val(ctx, &val);
947 if(FAILED(hres))
948 return hres;
950 if(!val.owned) {
951 V_VT(&v) = VT_EMPTY;
952 hres = VariantCopy(&v, val.v);
953 if(FAILED(hres))
954 return hres;
957 return stack_push(ctx, val.owned ? val.v : &v);
960 static HRESULT interp_pop(exec_ctx_t *ctx)
962 const unsigned n = ctx->instr->arg1.uint;
964 TRACE("%u\n", n);
966 stack_popn(ctx, n);
967 return S_OK;
970 static HRESULT interp_new(exec_ctx_t *ctx)
972 const WCHAR *arg = ctx->instr->arg1.bstr;
973 class_desc_t *class_desc;
974 vbdisp_t *obj;
975 VARIANT v;
976 HRESULT hres;
978 static const WCHAR regexpW[] = {'r','e','g','e','x','p',0};
980 TRACE("%s\n", debugstr_w(arg));
982 if(!strcmpiW(arg, regexpW)) {
983 V_VT(&v) = VT_DISPATCH;
984 hres = create_regexp(&V_DISPATCH(&v));
985 if(FAILED(hres))
986 return hres;
988 return stack_push(ctx, &v);
991 for(class_desc = ctx->script->classes; class_desc; class_desc = class_desc->next) {
992 if(!strcmpiW(class_desc->name, arg))
993 break;
995 if(!class_desc) {
996 FIXME("Class %s not found\n", debugstr_w(arg));
997 return E_FAIL;
1000 hres = create_vbdisp(class_desc, &obj);
1001 if(FAILED(hres))
1002 return hres;
1004 V_VT(&v) = VT_DISPATCH;
1005 V_DISPATCH(&v) = (IDispatch*)&obj->IDispatchEx_iface;
1006 return stack_push(ctx, &v);
1009 static HRESULT interp_dim(exec_ctx_t *ctx)
1011 const BSTR ident = ctx->instr->arg1.bstr;
1012 const unsigned array_id = ctx->instr->arg2.uint;
1013 const array_desc_t *array_desc;
1014 ref_t ref;
1015 HRESULT hres;
1017 TRACE("%s\n", debugstr_w(ident));
1019 assert(array_id < ctx->func->array_cnt);
1020 if(!ctx->arrays) {
1021 ctx->arrays = heap_alloc_zero(ctx->func->array_cnt * sizeof(SAFEARRAY*));
1022 if(!ctx->arrays)
1023 return E_OUTOFMEMORY;
1026 hres = lookup_identifier(ctx, ident, VBDISP_LET, &ref);
1027 if(FAILED(hres)) {
1028 FIXME("lookup %s failed: %08x\n", debugstr_w(ident), hres);
1029 return hres;
1032 if(ref.type != REF_VAR) {
1033 FIXME("got ref.type = %d\n", ref.type);
1034 return E_FAIL;
1037 if(ctx->arrays[array_id]) {
1038 FIXME("Array already initialized\n");
1039 return E_FAIL;
1042 array_desc = ctx->func->array_descs + array_id;
1043 if(array_desc->dim_cnt) {
1044 ctx->arrays[array_id] = SafeArrayCreate(VT_VARIANT, array_desc->dim_cnt, array_desc->bounds);
1045 if(!ctx->arrays[array_id])
1046 return E_OUTOFMEMORY;
1049 V_VT(ref.u.v) = VT_ARRAY|VT_BYREF|VT_VARIANT;
1050 V_ARRAYREF(ref.u.v) = ctx->arrays+array_id;
1051 return S_OK;
1054 static HRESULT interp_step(exec_ctx_t *ctx)
1056 const BSTR ident = ctx->instr->arg2.bstr;
1057 BOOL gteq_zero;
1058 VARIANT zero;
1059 ref_t ref;
1060 HRESULT hres;
1062 TRACE("%s\n", debugstr_w(ident));
1064 V_VT(&zero) = VT_I2;
1065 V_I2(&zero) = 0;
1066 hres = VarCmp(stack_top(ctx, 0), &zero, ctx->script->lcid, 0);
1067 if(FAILED(hres))
1068 return hres;
1070 gteq_zero = hres == VARCMP_GT || hres == VARCMP_EQ;
1072 hres = lookup_identifier(ctx, ident, VBDISP_ANY, &ref);
1073 if(FAILED(hres))
1074 return hres;
1076 if(ref.type != REF_VAR) {
1077 FIXME("%s is not REF_VAR\n", debugstr_w(ident));
1078 return E_FAIL;
1081 hres = VarCmp(ref.u.v, stack_top(ctx, 1), ctx->script->lcid, 0);
1082 if(FAILED(hres))
1083 return hres;
1085 if(hres == VARCMP_EQ || hres == (gteq_zero ? VARCMP_LT : VARCMP_GT)) {
1086 ctx->instr++;
1087 }else {
1088 stack_popn(ctx, 2);
1089 instr_jmp(ctx, ctx->instr->arg1.uint);
1091 return S_OK;
1094 static HRESULT interp_newenum(exec_ctx_t *ctx)
1096 variant_val_t v;
1097 VARIANT *r;
1098 HRESULT hres;
1100 TRACE("\n");
1102 stack_pop_deref(ctx, &v);
1103 assert(V_VT(stack_top(ctx, 0)) == VT_EMPTY);
1104 r = stack_top(ctx, 0);
1106 switch(V_VT(v.v)) {
1107 case VT_DISPATCH|VT_BYREF:
1108 case VT_DISPATCH: {
1109 IEnumVARIANT *iter;
1110 DISPPARAMS dp = {0};
1111 VARIANT iterv;
1113 hres = disp_call(ctx->script, V_ISBYREF(v.v) ? *V_DISPATCHREF(v.v) : V_DISPATCH(v.v), DISPID_NEWENUM, &dp, &iterv);
1114 release_val(&v);
1115 if(FAILED(hres))
1116 return hres;
1118 if(V_VT(&iterv) != VT_UNKNOWN && V_VT(&iterv) != VT_DISPATCH) {
1119 FIXME("Unsupported iterv %s\n", debugstr_variant(&iterv));
1120 VariantClear(&iterv);
1121 return hres;
1124 hres = IUnknown_QueryInterface(V_UNKNOWN(&iterv), &IID_IEnumVARIANT, (void**)&iter);
1125 IUnknown_Release(V_UNKNOWN(&iterv));
1126 if(FAILED(hres)) {
1127 FIXME("Could not get IEnumVARIANT iface: %08x\n", hres);
1128 return hres;
1131 V_VT(r) = VT_UNKNOWN;
1132 V_UNKNOWN(r) = (IUnknown*)iter;
1133 break;
1135 default:
1136 FIXME("Unsupported for %s\n", debugstr_variant(v.v));
1137 release_val(&v);
1138 return E_NOTIMPL;
1141 return S_OK;
1144 static HRESULT interp_enumnext(exec_ctx_t *ctx)
1146 const unsigned loop_end = ctx->instr->arg1.uint;
1147 const BSTR ident = ctx->instr->arg2.bstr;
1148 VARIANT v;
1149 DISPPARAMS dp = {&v, &propput_dispid, 1, 1};
1150 IEnumVARIANT *iter;
1151 BOOL do_continue;
1152 HRESULT hres;
1154 TRACE("\n");
1156 if(V_VT(stack_top(ctx, 0)) == VT_EMPTY) {
1157 FIXME("uninitialized\n");
1158 return E_FAIL;
1161 assert(V_VT(stack_top(ctx, 0)) == VT_UNKNOWN);
1162 iter = (IEnumVARIANT*)V_UNKNOWN(stack_top(ctx, 0));
1164 V_VT(&v) = VT_EMPTY;
1165 hres = IEnumVARIANT_Next(iter, 1, &v, NULL);
1166 if(FAILED(hres))
1167 return hres;
1169 do_continue = hres == S_OK;
1170 hres = assign_ident(ctx, ident, &dp);
1171 VariantClear(&v);
1172 if(FAILED(hres))
1173 return hres;
1175 if(do_continue) {
1176 ctx->instr++;
1177 }else {
1178 stack_pop(ctx);
1179 instr_jmp(ctx, loop_end);
1181 return S_OK;
1184 static HRESULT interp_jmp(exec_ctx_t *ctx)
1186 const unsigned arg = ctx->instr->arg1.uint;
1188 TRACE("%u\n", arg);
1190 instr_jmp(ctx, arg);
1191 return S_OK;
1194 static HRESULT interp_jmp_false(exec_ctx_t *ctx)
1196 const unsigned arg = ctx->instr->arg1.uint;
1197 HRESULT hres;
1198 BOOL b;
1200 TRACE("%u\n", arg);
1202 hres = stack_pop_bool(ctx, &b);
1203 if(FAILED(hres))
1204 return hres;
1206 if(b)
1207 ctx->instr++;
1208 else
1209 instr_jmp(ctx, ctx->instr->arg1.uint);
1210 return S_OK;
1213 static HRESULT interp_jmp_true(exec_ctx_t *ctx)
1215 const unsigned arg = ctx->instr->arg1.uint;
1216 HRESULT hres;
1217 BOOL b;
1219 TRACE("%u\n", arg);
1221 hres = stack_pop_bool(ctx, &b);
1222 if(FAILED(hres))
1223 return hres;
1225 if(b)
1226 instr_jmp(ctx, ctx->instr->arg1.uint);
1227 else
1228 ctx->instr++;
1229 return S_OK;
1232 static HRESULT interp_ret(exec_ctx_t *ctx)
1234 TRACE("\n");
1236 ctx->instr = NULL;
1237 return S_OK;
1240 static HRESULT interp_stop(exec_ctx_t *ctx)
1242 WARN("\n");
1244 /* NOTE: this should have effect in debugging mode (that we don't support yet) */
1245 return S_OK;
1248 static HRESULT interp_me(exec_ctx_t *ctx)
1250 VARIANT v;
1252 TRACE("\n");
1254 IDispatch_AddRef(ctx->this_obj);
1255 V_VT(&v) = VT_DISPATCH;
1256 V_DISPATCH(&v) = ctx->this_obj;
1257 return stack_push(ctx, &v);
1260 static HRESULT interp_bool(exec_ctx_t *ctx)
1262 const VARIANT_BOOL arg = ctx->instr->arg1.lng;
1263 VARIANT v;
1265 TRACE("%s\n", arg ? "true" : "false");
1267 V_VT(&v) = VT_BOOL;
1268 V_BOOL(&v) = arg;
1269 return stack_push(ctx, &v);
1272 static HRESULT interp_errmode(exec_ctx_t *ctx)
1274 const int err_mode = ctx->instr->arg1.uint;
1276 TRACE("%d\n", err_mode);
1278 ctx->resume_next = err_mode;
1279 ctx->script->err_number = S_OK;
1280 return S_OK;
1283 static HRESULT interp_string(exec_ctx_t *ctx)
1285 VARIANT v;
1287 TRACE("\n");
1289 V_VT(&v) = VT_BSTR;
1290 V_BSTR(&v) = SysAllocString(ctx->instr->arg1.str);
1291 if(!V_BSTR(&v))
1292 return E_OUTOFMEMORY;
1294 return stack_push(ctx, &v);
1297 static HRESULT interp_long(exec_ctx_t *ctx)
1299 const LONG arg = ctx->instr->arg1.lng;
1300 VARIANT v;
1302 TRACE("%d\n", arg);
1304 V_VT(&v) = VT_I4;
1305 V_I4(&v) = arg;
1306 return stack_push(ctx, &v);
1309 static HRESULT interp_short(exec_ctx_t *ctx)
1311 const LONG arg = ctx->instr->arg1.lng;
1312 VARIANT v;
1314 TRACE("%d\n", arg);
1316 V_VT(&v) = VT_I2;
1317 V_I2(&v) = arg;
1318 return stack_push(ctx, &v);
1321 static HRESULT interp_double(exec_ctx_t *ctx)
1323 const DOUBLE *arg = ctx->instr->arg1.dbl;
1324 VARIANT v;
1326 TRACE("%lf\n", *arg);
1328 V_VT(&v) = VT_R8;
1329 V_R8(&v) = *arg;
1330 return stack_push(ctx, &v);
1333 static HRESULT interp_empty(exec_ctx_t *ctx)
1335 VARIANT v;
1337 TRACE("\n");
1339 V_VT(&v) = VT_EMPTY;
1340 return stack_push(ctx, &v);
1343 static HRESULT interp_null(exec_ctx_t *ctx)
1345 TRACE("\n");
1346 return stack_push_null(ctx);
1349 static HRESULT interp_nothing(exec_ctx_t *ctx)
1351 VARIANT v;
1353 TRACE("\n");
1355 V_VT(&v) = VT_DISPATCH;
1356 V_DISPATCH(&v) = NULL;
1357 return stack_push(ctx, &v);
1360 static HRESULT interp_not(exec_ctx_t *ctx)
1362 variant_val_t val;
1363 VARIANT v;
1364 HRESULT hres;
1366 TRACE("\n");
1368 hres = stack_pop_val(ctx, &val);
1369 if(FAILED(hres))
1370 return hres;
1372 hres = VarNot(val.v, &v);
1373 release_val(&val);
1374 if(FAILED(hres))
1375 return hres;
1377 return stack_push(ctx, &v);
1380 static HRESULT interp_and(exec_ctx_t *ctx)
1382 variant_val_t r, l;
1383 VARIANT v;
1384 HRESULT hres;
1386 TRACE("\n");
1388 hres = stack_pop_val(ctx, &r);
1389 if(FAILED(hres))
1390 return hres;
1392 hres = stack_pop_val(ctx, &l);
1393 if(SUCCEEDED(hres)) {
1394 hres = VarAnd(l.v, r.v, &v);
1395 release_val(&l);
1397 release_val(&r);
1398 if(FAILED(hres))
1399 return hres;
1401 return stack_push(ctx, &v);
1404 static HRESULT interp_or(exec_ctx_t *ctx)
1406 variant_val_t r, l;
1407 VARIANT v;
1408 HRESULT hres;
1410 TRACE("\n");
1412 hres = stack_pop_val(ctx, &r);
1413 if(FAILED(hres))
1414 return hres;
1416 hres = stack_pop_val(ctx, &l);
1417 if(SUCCEEDED(hres)) {
1418 hres = VarOr(l.v, r.v, &v);
1419 release_val(&l);
1421 release_val(&r);
1422 if(FAILED(hres))
1423 return hres;
1425 return stack_push(ctx, &v);
1428 static HRESULT interp_xor(exec_ctx_t *ctx)
1430 variant_val_t r, l;
1431 VARIANT v;
1432 HRESULT hres;
1434 TRACE("\n");
1436 hres = stack_pop_val(ctx, &r);
1437 if(FAILED(hres))
1438 return hres;
1440 hres = stack_pop_val(ctx, &l);
1441 if(SUCCEEDED(hres)) {
1442 hres = VarXor(l.v, r.v, &v);
1443 release_val(&l);
1445 release_val(&r);
1446 if(FAILED(hres))
1447 return hres;
1449 return stack_push(ctx, &v);
1452 static HRESULT interp_eqv(exec_ctx_t *ctx)
1454 variant_val_t r, l;
1455 VARIANT v;
1456 HRESULT hres;
1458 TRACE("\n");
1460 hres = stack_pop_val(ctx, &r);
1461 if(FAILED(hres))
1462 return hres;
1464 hres = stack_pop_val(ctx, &l);
1465 if(SUCCEEDED(hres)) {
1466 hres = VarEqv(l.v, r.v, &v);
1467 release_val(&l);
1469 release_val(&r);
1470 if(FAILED(hres))
1471 return hres;
1473 return stack_push(ctx, &v);
1476 static HRESULT interp_imp(exec_ctx_t *ctx)
1478 variant_val_t r, l;
1479 VARIANT v;
1480 HRESULT hres;
1482 TRACE("\n");
1484 hres = stack_pop_val(ctx, &r);
1485 if(FAILED(hres))
1486 return hres;
1488 hres = stack_pop_val(ctx, &l);
1489 if(SUCCEEDED(hres)) {
1490 hres = VarImp(l.v, r.v, &v);
1491 release_val(&l);
1493 release_val(&r);
1494 if(FAILED(hres))
1495 return hres;
1497 return stack_push(ctx, &v);
1500 static HRESULT var_cmp(exec_ctx_t *ctx, VARIANT *l, VARIANT *r)
1502 TRACE("%s %s\n", debugstr_variant(l), debugstr_variant(r));
1504 /* FIXME: Fix comparing string to number */
1506 return VarCmp(l, r, ctx->script->lcid, 0);
1509 static HRESULT cmp_oper(exec_ctx_t *ctx)
1511 variant_val_t l, r;
1512 HRESULT hres;
1514 hres = stack_pop_val(ctx, &r);
1515 if(FAILED(hres))
1516 return hres;
1518 hres = stack_pop_val(ctx, &l);
1519 if(SUCCEEDED(hres)) {
1520 hres = var_cmp(ctx, l.v, r.v);
1521 release_val(&l);
1524 release_val(&r);
1525 return hres;
1528 static HRESULT interp_equal(exec_ctx_t *ctx)
1530 VARIANT v;
1531 HRESULT hres;
1533 TRACE("\n");
1535 hres = cmp_oper(ctx);
1536 if(FAILED(hres))
1537 return hres;
1538 if(hres == VARCMP_NULL)
1539 return stack_push_null(ctx);
1541 V_VT(&v) = VT_BOOL;
1542 V_BOOL(&v) = hres == VARCMP_EQ ? VARIANT_TRUE : VARIANT_FALSE;
1543 return stack_push(ctx, &v);
1546 static HRESULT interp_nequal(exec_ctx_t *ctx)
1548 VARIANT v;
1549 HRESULT hres;
1551 TRACE("\n");
1553 hres = cmp_oper(ctx);
1554 if(FAILED(hres))
1555 return hres;
1556 if(hres == VARCMP_NULL)
1557 return stack_push_null(ctx);
1559 V_VT(&v) = VT_BOOL;
1560 V_BOOL(&v) = hres != VARCMP_EQ ? VARIANT_TRUE : VARIANT_FALSE;
1561 return stack_push(ctx, &v);
1564 static HRESULT interp_gt(exec_ctx_t *ctx)
1566 VARIANT v;
1567 HRESULT hres;
1569 TRACE("\n");
1571 hres = cmp_oper(ctx);
1572 if(FAILED(hres))
1573 return hres;
1574 if(hres == VARCMP_NULL)
1575 return stack_push_null(ctx);
1577 V_VT(&v) = VT_BOOL;
1578 V_BOOL(&v) = hres == VARCMP_GT ? VARIANT_TRUE : VARIANT_FALSE;
1579 return stack_push(ctx, &v);
1582 static HRESULT interp_gteq(exec_ctx_t *ctx)
1584 VARIANT v;
1585 HRESULT hres;
1587 TRACE("\n");
1589 hres = cmp_oper(ctx);
1590 if(FAILED(hres))
1591 return hres;
1592 if(hres == VARCMP_NULL)
1593 return stack_push_null(ctx);
1595 V_VT(&v) = VT_BOOL;
1596 V_BOOL(&v) = hres == VARCMP_GT || hres == VARCMP_EQ ? VARIANT_TRUE : VARIANT_FALSE;
1597 return stack_push(ctx, &v);
1600 static HRESULT interp_lt(exec_ctx_t *ctx)
1602 VARIANT v;
1603 HRESULT hres;
1605 TRACE("\n");
1607 hres = cmp_oper(ctx);
1608 if(FAILED(hres))
1609 return hres;
1610 if(hres == VARCMP_NULL)
1611 return stack_push_null(ctx);
1613 V_VT(&v) = VT_BOOL;
1614 V_BOOL(&v) = hres == VARCMP_LT ? VARIANT_TRUE : VARIANT_FALSE;
1615 return stack_push(ctx, &v);
1618 static HRESULT interp_lteq(exec_ctx_t *ctx)
1620 VARIANT v;
1621 HRESULT hres;
1623 TRACE("\n");
1625 hres = cmp_oper(ctx);
1626 if(FAILED(hres))
1627 return hres;
1628 if(hres == VARCMP_NULL)
1629 return stack_push_null(ctx);
1631 V_VT(&v) = VT_BOOL;
1632 V_BOOL(&v) = hres == VARCMP_LT || hres == VARCMP_EQ ? VARIANT_TRUE : VARIANT_FALSE;
1633 return stack_push(ctx, &v);
1636 static HRESULT interp_case(exec_ctx_t *ctx)
1638 const unsigned arg = ctx->instr->arg1.uint;
1639 variant_val_t v;
1640 HRESULT hres;
1642 TRACE("%d\n", arg);
1644 hres = stack_pop_val(ctx, &v);
1645 if(FAILED(hres))
1646 return hres;
1648 hres = var_cmp(ctx, stack_top(ctx, 0), v.v);
1649 release_val(&v);
1650 if(FAILED(hres))
1651 return hres;
1653 if(hres == VARCMP_EQ) {
1654 stack_popn(ctx, 1);
1655 instr_jmp(ctx, arg);
1656 }else {
1657 ctx->instr++;
1660 return S_OK;
1663 static HRESULT disp_cmp(IDispatch *disp1, IDispatch *disp2, VARIANT_BOOL *ret)
1665 IObjectIdentity *identity;
1666 IUnknown *unk1, *unk2;
1667 HRESULT hres;
1669 if(disp1 == disp2) {
1670 *ret = VARIANT_TRUE;
1671 return S_OK;
1674 if(!disp1 || !disp2) {
1675 *ret = VARIANT_FALSE;
1676 return S_OK;
1679 hres = IDispatch_QueryInterface(disp1, &IID_IUnknown, (void**)&unk1);
1680 if(FAILED(hres))
1681 return hres;
1683 hres = IDispatch_QueryInterface(disp2, &IID_IUnknown, (void**)&unk2);
1684 if(FAILED(hres)) {
1685 IUnknown_Release(unk1);
1686 return hres;
1689 if(unk1 == unk2) {
1690 *ret = VARIANT_TRUE;
1691 }else {
1692 hres = IUnknown_QueryInterface(unk1, &IID_IObjectIdentity, (void**)&identity);
1693 if(SUCCEEDED(hres)) {
1694 hres = IObjectIdentity_IsEqualObject(identity, unk2);
1695 IObjectIdentity_Release(identity);
1696 *ret = hres == S_OK ? VARIANT_TRUE : VARIANT_FALSE;
1697 }else {
1698 *ret = VARIANT_FALSE;
1702 IUnknown_Release(unk1);
1703 IUnknown_Release(unk2);
1704 return S_OK;
1707 static HRESULT interp_is(exec_ctx_t *ctx)
1709 IDispatch *l, *r;
1710 VARIANT v;
1711 HRESULT hres;
1713 TRACE("\n");
1715 hres = stack_pop_disp(ctx, &r);
1716 if(FAILED(hres))
1717 return hres;
1719 hres = stack_pop_disp(ctx, &l);
1720 if(SUCCEEDED(hres)) {
1721 V_VT(&v) = VT_BOOL;
1722 hres = disp_cmp(l, r, &V_BOOL(&v));
1723 if(l)
1724 IDispatch_Release(l);
1726 if(r)
1727 IDispatch_Release(r);
1728 if(FAILED(hres))
1729 return hres;
1731 return stack_push(ctx, &v);
1734 static HRESULT interp_concat(exec_ctx_t *ctx)
1736 variant_val_t r, l;
1737 VARIANT v;
1738 HRESULT hres;
1740 TRACE("\n");
1742 hres = stack_pop_val(ctx, &r);
1743 if(FAILED(hres))
1744 return hres;
1746 hres = stack_pop_val(ctx, &l);
1747 if(SUCCEEDED(hres)) {
1748 hres = VarCat(l.v, r.v, &v);
1749 release_val(&l);
1751 release_val(&r);
1752 if(FAILED(hres))
1753 return hres;
1755 return stack_push(ctx, &v);
1758 static HRESULT interp_add(exec_ctx_t *ctx)
1760 variant_val_t r, l;
1761 VARIANT v;
1762 HRESULT hres;
1764 TRACE("\n");
1766 hres = stack_pop_val(ctx, &r);
1767 if(FAILED(hres))
1768 return hres;
1770 hres = stack_pop_val(ctx, &l);
1771 if(SUCCEEDED(hres)) {
1772 hres = VarAdd(l.v, r.v, &v);
1773 release_val(&l);
1775 release_val(&r);
1776 if(FAILED(hres))
1777 return hres;
1779 return stack_push(ctx, &v);
1782 static HRESULT interp_sub(exec_ctx_t *ctx)
1784 variant_val_t r, l;
1785 VARIANT v;
1786 HRESULT hres;
1788 TRACE("\n");
1790 hres = stack_pop_val(ctx, &r);
1791 if(FAILED(hres))
1792 return hres;
1794 hres = stack_pop_val(ctx, &l);
1795 if(SUCCEEDED(hres)) {
1796 hres = VarSub(l.v, r.v, &v);
1797 release_val(&l);
1799 release_val(&r);
1800 if(FAILED(hres))
1801 return hres;
1803 return stack_push(ctx, &v);
1806 static HRESULT interp_mod(exec_ctx_t *ctx)
1808 variant_val_t r, l;
1809 VARIANT v;
1810 HRESULT hres;
1812 TRACE("\n");
1814 hres = stack_pop_val(ctx, &r);
1815 if(FAILED(hres))
1816 return hres;
1818 hres = stack_pop_val(ctx, &l);
1819 if(SUCCEEDED(hres)) {
1820 hres = VarMod(l.v, r.v, &v);
1821 release_val(&l);
1823 release_val(&r);
1824 if(FAILED(hres))
1825 return hres;
1827 return stack_push(ctx, &v);
1830 static HRESULT interp_idiv(exec_ctx_t *ctx)
1832 variant_val_t r, l;
1833 VARIANT v;
1834 HRESULT hres;
1836 TRACE("\n");
1838 hres = stack_pop_val(ctx, &r);
1839 if(FAILED(hres))
1840 return hres;
1842 hres = stack_pop_val(ctx, &l);
1843 if(SUCCEEDED(hres)) {
1844 hres = VarIdiv(l.v, r.v, &v);
1845 release_val(&l);
1847 release_val(&r);
1848 if(FAILED(hres))
1849 return hres;
1851 return stack_push(ctx, &v);
1854 static HRESULT interp_div(exec_ctx_t *ctx)
1856 variant_val_t r, l;
1857 VARIANT v;
1858 HRESULT hres;
1860 TRACE("\n");
1862 hres = stack_pop_val(ctx, &r);
1863 if(FAILED(hres))
1864 return hres;
1866 hres = stack_pop_val(ctx, &l);
1867 if(SUCCEEDED(hres)) {
1868 hres = VarDiv(l.v, r.v, &v);
1869 release_val(&l);
1871 release_val(&r);
1872 if(FAILED(hres))
1873 return hres;
1875 return stack_push(ctx, &v);
1878 static HRESULT interp_mul(exec_ctx_t *ctx)
1880 variant_val_t r, l;
1881 VARIANT v;
1882 HRESULT hres;
1884 TRACE("\n");
1886 hres = stack_pop_val(ctx, &r);
1887 if(FAILED(hres))
1888 return hres;
1890 hres = stack_pop_val(ctx, &l);
1891 if(SUCCEEDED(hres)) {
1892 hres = VarMul(l.v, r.v, &v);
1893 release_val(&l);
1895 release_val(&r);
1896 if(FAILED(hres))
1897 return hres;
1899 return stack_push(ctx, &v);
1902 static HRESULT interp_exp(exec_ctx_t *ctx)
1904 variant_val_t r, l;
1905 VARIANT v;
1906 HRESULT hres;
1908 TRACE("\n");
1910 hres = stack_pop_val(ctx, &r);
1911 if(FAILED(hres))
1912 return hres;
1914 hres = stack_pop_val(ctx, &l);
1915 if(SUCCEEDED(hres)) {
1916 hres = VarPow(l.v, r.v, &v);
1917 release_val(&l);
1919 release_val(&r);
1920 if(FAILED(hres))
1921 return hres;
1923 return stack_push(ctx, &v);
1926 static HRESULT interp_neg(exec_ctx_t *ctx)
1928 variant_val_t val;
1929 VARIANT v;
1930 HRESULT hres;
1932 hres = stack_pop_val(ctx, &val);
1933 if(FAILED(hres))
1934 return hres;
1936 hres = VarNeg(val.v, &v);
1937 release_val(&val);
1938 if(FAILED(hres))
1939 return hres;
1941 return stack_push(ctx, &v);
1944 static HRESULT interp_incc(exec_ctx_t *ctx)
1946 const BSTR ident = ctx->instr->arg1.bstr;
1947 VARIANT v;
1948 ref_t ref;
1949 HRESULT hres;
1951 TRACE("\n");
1953 hres = lookup_identifier(ctx, ident, VBDISP_LET, &ref);
1954 if(FAILED(hres))
1955 return hres;
1957 if(ref.type != REF_VAR) {
1958 FIXME("ref.type is not REF_VAR\n");
1959 return E_FAIL;
1962 hres = VarAdd(stack_top(ctx, 0), ref.u.v, &v);
1963 if(FAILED(hres))
1964 return hres;
1966 VariantClear(ref.u.v);
1967 *ref.u.v = v;
1968 return S_OK;
1971 static HRESULT interp_catch(exec_ctx_t *ctx)
1973 /* Nothing to do here, the OP is for unwinding only. */
1974 return S_OK;
1977 static const instr_func_t op_funcs[] = {
1978 #define X(x,n,a,b) interp_ ## x,
1979 OP_LIST
1980 #undef X
1983 static const unsigned op_move[] = {
1984 #define X(x,n,a,b) n,
1985 OP_LIST
1986 #undef X
1989 void release_dynamic_vars(dynamic_var_t *var)
1991 while(var) {
1992 VariantClear(&var->v);
1993 var = var->next;
1997 static void release_exec(exec_ctx_t *ctx)
1999 unsigned i;
2001 VariantClear(&ctx->ret_val);
2002 release_dynamic_vars(ctx->dynamic_vars);
2004 if(ctx->this_obj)
2005 IDispatch_Release(ctx->this_obj);
2007 if(ctx->args) {
2008 for(i=0; i < ctx->func->arg_cnt; i++)
2009 VariantClear(ctx->args+i);
2012 if(ctx->vars) {
2013 for(i=0; i < ctx->func->var_cnt; i++)
2014 VariantClear(ctx->vars+i);
2017 if(ctx->arrays) {
2018 for(i=0; i < ctx->func->var_cnt; i++) {
2019 if(ctx->arrays[i])
2020 SafeArrayDestroy(ctx->arrays[i]);
2022 heap_free(ctx->arrays);
2025 heap_pool_free(&ctx->heap);
2026 heap_free(ctx->args);
2027 heap_free(ctx->vars);
2028 heap_free(ctx->stack);
2031 HRESULT exec_script(script_ctx_t *ctx, function_t *func, vbdisp_t *vbthis, DISPPARAMS *dp, VARIANT *res)
2033 exec_ctx_t exec = {func->code_ctx};
2034 vbsop_t op;
2035 HRESULT hres = S_OK;
2037 exec.code = func->code_ctx;
2039 if(dp ? func->arg_cnt != arg_cnt(dp) : func->arg_cnt) {
2040 FIXME("wrong arg_cnt %d, expected %d\n", dp ? arg_cnt(dp) : 0, func->arg_cnt);
2041 return E_FAIL;
2044 heap_pool_init(&exec.heap);
2046 if(func->arg_cnt) {
2047 VARIANT *v;
2048 unsigned i;
2050 exec.args = heap_alloc_zero(func->arg_cnt * sizeof(VARIANT));
2051 if(!exec.args) {
2052 release_exec(&exec);
2053 return E_OUTOFMEMORY;
2056 for(i=0; i < func->arg_cnt; i++) {
2057 v = get_arg(dp, i);
2058 if(V_VT(v) == (VT_VARIANT|VT_BYREF)) {
2059 if(func->args[i].by_ref)
2060 exec.args[i] = *v;
2061 else
2062 hres = VariantCopyInd(exec.args+i, V_VARIANTREF(v));
2063 }else {
2064 hres = VariantCopyInd(exec.args+i, v);
2066 if(FAILED(hres)) {
2067 release_exec(&exec);
2068 return hres;
2071 }else {
2072 exec.args = NULL;
2075 if(func->var_cnt) {
2076 exec.vars = heap_alloc_zero(func->var_cnt * sizeof(VARIANT));
2077 if(!exec.vars) {
2078 release_exec(&exec);
2079 return E_OUTOFMEMORY;
2081 }else {
2082 exec.vars = NULL;
2085 exec.stack_size = 16;
2086 exec.top = 0;
2087 exec.stack = heap_alloc(exec.stack_size * sizeof(VARIANT));
2088 if(!exec.stack) {
2089 release_exec(&exec);
2090 return E_OUTOFMEMORY;
2093 if(vbthis) {
2094 exec.this_obj = (IDispatch*)&vbthis->IDispatchEx_iface;
2095 exec.vbthis = vbthis;
2096 }else if (ctx->host_global) {
2097 exec.this_obj = ctx->host_global;
2098 }else {
2099 exec.this_obj = (IDispatch*)&ctx->script_obj->IDispatchEx_iface;
2101 IDispatch_AddRef(exec.this_obj);
2103 exec.instr = exec.code->instrs + func->code_off;
2104 exec.script = ctx;
2105 exec.func = func;
2107 while(exec.instr) {
2108 op = exec.instr->op;
2109 hres = op_funcs[op](&exec);
2110 if(FAILED(hres)) {
2111 ctx->err_number = hres = map_hres(hres);
2113 if(exec.resume_next) {
2114 unsigned stack_off;
2116 WARN("Failed %08x in resume next mode\n", hres);
2119 * Unwinding here is simple. We need to find the next OP_catch, which contains
2120 * information about expected stack size and jump offset on error. Generated
2121 * bytecode needs to guarantee, that simple jump and stack adjustment will
2122 * guarantee proper execution continuation.
2124 while((++exec.instr)->op != OP_catch);
2126 TRACE("unwind jmp %d stack_off %d\n", exec.instr->arg1.uint, exec.instr->arg2.uint);
2128 stack_off = exec.instr->arg2.uint;
2129 instr_jmp(&exec, exec.instr->arg1.uint);
2131 if(exec.top > stack_off) {
2132 stack_popn(&exec, exec.top-stack_off);
2133 }else if(exec.top < stack_off) {
2134 VARIANT v;
2136 V_VT(&v) = VT_EMPTY;
2137 while(exec.top < stack_off) {
2138 hres = stack_push(&exec, &v);
2139 if(FAILED(hres))
2140 break;
2144 continue;
2145 }else {
2146 WARN("Failed %08x\n", hres);
2147 stack_popn(&exec, exec.top);
2148 break;
2152 exec.instr += op_move[op];
2155 assert(!exec.top);
2156 if(func->type != FUNC_FUNCTION && func->type != FUNC_PROPGET && func->type != FUNC_DEFGET)
2157 assert(V_VT(&exec.ret_val) == VT_EMPTY);
2159 if(SUCCEEDED(hres) && res) {
2160 *res = exec.ret_val;
2161 V_VT(&exec.ret_val) = VT_EMPTY;
2164 release_exec(&exec);
2165 return hres;