Jacek Caban : vbscript: Convert VT_DISPATCH propput value to trivial value if DISPATCH_PROPERTYPUTREF is not set.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Mar 3 09:42:11 CST 2015


Module: wine
Branch: master
Commit: 4bca1665c4dcd6e1c58322b8cb4e0b0ca9915033
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4bca1665c4dcd6e1c58322b8cb4e0b0ca9915033

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Mar  3 14:40:51 2015 +0100

vbscript: Convert VT_DISPATCH propput value to trivial value if DISPATCH_PROPERTYPUTREF is not set.

---

 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) {




More information about the wine-cvs mailing list