https://bugs.winehq.org/show_bug.cgi?id=54221
--- Comment #10 from Jason Millard jsm174@gmail.com --- So this is probably the worst hack ever, but I leveraged VARIANT's wReserved2 to store the function index.
static HRESULT Global_GetRef(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) { BSTR str; HRESULT hres;
hres = to_string(arg, &str);
if(FAILED(hres)) return hres;
function_t **funcs = This->ctx->script_obj->global_funcs; size_t i, cnt = This->ctx->script_obj->global_funcs_cnt;
for(i = 0; i < cnt; i++) { if(!wcsicmp(funcs[i]->name, str)) { IDispatch* disp = (IDispatch*) &This->ctx->script_obj->IDispatchEx_iface;
DISPID dispid; hres = disp->lpVtbl->GetIDsOfNames(disp, 0, (LPOLESTR*)&funcs[i]->name, 1, 0, &dispid);
if(FAILED(hres)) return hres;
V_VT(res) = VT_DISPATCH; V_DISPATCH(res) = disp; res->n1.n2.wReserved1 = 0xFF; res->n1.n2.wReserved2 = i;
IDispatch_AddRef(disp); return hres; } }
return DISP_E_UNKNOWNNAME; }
Then in do_icall:
static HRESULT do_icall(exec_ctx_t *ctx, VARIANT *res, BSTR identifier, unsigned arg_cnt) { DISPPARAMS dp; ref_t ref; HRESULT hres;
TRACE("%s %u\n", debugstr_w(identifier), arg_cnt);
hres = lookup_identifier(ctx, identifier, VBDISP_CALLGET, &ref); if(FAILED(hres)) return hres;
switch(ref.type) { case REF_VAR: case REF_CONST: if (V_VT(ref.u.v) == VT_DISPATCH && ref.u.v->n1.n2.wReserved1 == 0xFF) { vbstack_to_dp(ctx, arg_cnt, FALSE, &dp);
ref.type = REF_FUNC; ref.u.f = ctx->script->script_obj->global_funcs[ref.u.v->n1.n2.wReserved2];
hres = exec_script(ctx->script, FALSE, ref.u.f, NULL, &dp, res); if(FAILED(hres)) return hres;
break; }
if(arg_cnt) return variant_call(ctx, ref.u.v, arg_cnt, res);
This allows the following code to work:
Sub test Debug.print "test call" End Sub
Dim funcAlias set funcAlias = GetRef("test")
If Not IsObject(GetRef("test")) Then Debug.print "getref test not object"
funcAlias