From: Jacek Caban Subject: [PATCH 3/7] vbscript: Convert VT_DISPATCH propput value to trivial value if DISPATCH_PROPERTYPUTREF is not set. Message-Id: <54F5B9E3.6040801@codeweavers.com> Date: Tue, 03 Mar 2015 14:40:51 +0100 --- dlls/vbscript/vbdisp.c | 73 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c index 18ba966..a07020b 100644 --- a/dlls/vbscript/vbdisp.c +++ b/dlls/vbscript/vbdisp.c @@ -85,19 +85,43 @@ HRESULT vbdisp_get_id(vbdisp_t *This, BSTR name, vbdisp_invoke_type_t invoke_typ return DISP_E_UNKNOWNNAME; } -static VARIANT *get_propput_arg(const DISPPARAMS *dp) +static HRESULT get_propput_arg(script_ctx_t *ctx, const DISPPARAMS *dp, WORD flags, VARIANT *v, BOOL *is_owned) { unsigned i; for(i=0; i < dp->cNamedArgs; i++) { if(dp->rgdispidNamedArgs[i] == DISPID_PROPERTYPUT) - return dp->rgvarg+i; + break; + } + if(i == dp->cNamedArgs) { + WARN("no value to set\n"); + return DISP_E_PARAMNOTOPTIONAL; + } + + *v = dp->rgvarg[i]; + if(V_VT(v) == (VT_VARIANT|VT_BYREF)) + *v = *V_VARIANTREF(v); + *is_owned = FALSE; + + if(V_VT(v) == VT_DISPATCH) { + if(!(flags & DISPATCH_PROPERTYPUTREF)) { + DISPPARAMS val_dp = {NULL}; + VARIANT value; + HRESULT hres; + + hres = disp_call(ctx, V_DISPATCH(v), DISPID_VALUE, &val_dp, &value); + if(FAILED(hres)) + return hres; + + *v = value; + *is_owned = TRUE; + } } - return NULL; + return S_OK; } -static HRESULT invoke_variant_prop(VARIANT *v, WORD flags, DISPPARAMS *dp, VARIANT *res) +static HRESULT invoke_variant_prop(script_ctx_t *ctx, VARIANT *v, WORD flags, DISPPARAMS *dp, VARIANT *res) { HRESULT hres; @@ -115,13 +139,12 @@ static HRESULT invoke_variant_prop(VARIANT *v, WORD flags, DISPPARAMS *dp, VARIA case DISPATCH_PROPERTYPUT: case DISPATCH_PROPERTYPUTREF: case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: { - VARIANT *put_val; + VARIANT put_val; + BOOL own_val; - put_val = get_propput_arg(dp); - if(!put_val) { - WARN("no value to set\n"); - return DISP_E_PARAMNOTOPTIONAL; - } + hres = get_propput_arg(ctx, dp, flags, &put_val, &own_val); + if(FAILED(hres)) + return hres; if(arg_cnt(dp)) { FIXME("Arguments not supported\n"); @@ -131,7 +154,10 @@ static HRESULT invoke_variant_prop(VARIANT *v, WORD flags, DISPPARAMS *dp, VARIA if(res) V_VT(res) = VT_EMPTY; - hres = VariantCopyInd(v, put_val); + if(own_val) + *v = put_val; + else + hres = VariantCopyInd(v, &put_val); break; } @@ -414,28 +440,31 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc case DISPATCH_PROPERTYPUT: case DISPATCH_PROPERTYPUTREF: case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: { - VARIANT *put_val; DISPPARAMS dp = {NULL, NULL, 1, 0}; + BOOL needs_release; + VARIANT put_val; + HRESULT hres; if(arg_cnt(pdp)) { FIXME("arguments not implemented\n"); return E_NOTIMPL; } - put_val = get_propput_arg(pdp); - if(!put_val) { - WARN("no value to set\n"); - return DISP_E_PARAMNOTOPTIONAL; - } + hres = get_propput_arg(This->desc->ctx, pdp, wFlags, &put_val, &needs_release); + if(FAILED(hres)) + return hres; - dp.rgvarg = put_val; - func = This->desc->funcs[id].entries[V_VT(put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET]; + dp.rgvarg = &put_val; + func = This->desc->funcs[id].entries[V_VT(&put_val) == VT_DISPATCH ? VBDISP_SET : VBDISP_LET]; if(!func) { FIXME("no letter/setter\n"); return DISP_E_MEMBERNOTFOUND; } - return exec_script(This->desc->ctx, func, This, &dp, NULL); + hres = exec_script(This->desc->ctx, func, This, &dp, NULL); + if(needs_release) + VariantClear(&put_val); + return hres; } default: FIXME("flags %x\n", wFlags); @@ -444,7 +473,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc } if(id < This->desc->prop_cnt + This->desc->func_cnt) - return invoke_variant_prop(This->props+(id-This->desc->func_cnt), wFlags, pdp, pvarRes); + return invoke_variant_prop(This->desc->ctx, This->props+(id-This->desc->func_cnt), wFlags, pdp, pvarRes); if(This->desc->builtin_prop_cnt) { unsigned min = 0, max = This->desc->builtin_prop_cnt-1, i; @@ -849,7 +878,7 @@ static HRESULT WINAPI ScriptDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc return E_NOTIMPL; } - return invoke_variant_prop(&ident->u.var->v, wFlags, pdp, pvarRes); + return invoke_variant_prop(This->ctx, &ident->u.var->v, wFlags, pdp, pvarRes); } switch(wFlags) {