Jacek Caban : mshtml: Allow setting function properties to any VARIANT type.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Nov 28 12:49:04 CST 2014


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Nov 28 16:18:53 2014 +0100

mshtml: Allow setting function properties to any VARIANT type.

---

 dlls/mshtml/dispex.c       | 63 +++++++++++++++++++++-------------------------
 dlls/mshtml/tests/script.c |  2 +-
 2 files changed, 29 insertions(+), 36 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index f294d91..1f1204a 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -87,7 +87,7 @@ typedef struct {
 
 typedef struct {
     func_disp_t *func_obj;
-    IDispatch *val;
+    VARIANT val;
 } func_obj_entry_t;
 
 struct dispex_dynamic_data_t {
@@ -833,6 +833,7 @@ static HRESULT invoke_disp_value(DispatchEx *This, IDispatch *func_disp, LCID lc
 static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_entry_t **ret)
 {
     dispex_dynamic_data_t *dynamic_data;
+    func_obj_entry_t *entry;
 
     dynamic_data = get_dynamic_data(This);
     if(!dynamic_data)
@@ -844,20 +845,18 @@ static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_
             return E_OUTOFMEMORY;
     }
 
-    if(!dynamic_data->func_disps[func->func_disp_idx].func_obj) {
-        func_disp_t *func_obj;
-
-        func_obj = create_func_disp(This, func);
-        if(!func_obj)
+    entry = dynamic_data->func_disps + func->func_disp_idx;
+    if(!entry->func_obj) {
+        entry->func_obj = create_func_disp(This, func);
+        if(!entry->func_obj)
             return E_OUTOFMEMORY;
 
-        dynamic_data->func_disps[func->func_disp_idx].func_obj = func_obj;
-
-        IDispatchEx_AddRef(&func_obj->dispex.IDispatchEx_iface);
-        dynamic_data->func_disps[func->func_disp_idx].val = (IDispatch*)&func_obj->dispex.IDispatchEx_iface;
+        IDispatchEx_AddRef(&entry->func_obj->dispex.IDispatchEx_iface);
+        V_VT(&entry->val) = VT_DISPATCH;
+        V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface;
     }
 
-    *ret = dynamic_data->func_disps+func->func_disp_idx;
+    *ret = entry;
     return S_OK;
 }
 
@@ -1131,13 +1130,18 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
            && This->dynamic_data->func_disps[func->func_disp_idx].func_obj) {
             func_obj_entry_t *entry = This->dynamic_data->func_disps + func->func_disp_idx;
 
-            if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != entry->val) {
-                if(!entry->val) {
+            if(V_VT(&entry->val) != VT_DISPATCH) {
+                FIXME("calling %s not supported\n", debugstr_variant(&entry->val));
+                return E_NOTIMPL;
+            }
+
+            if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != V_DISPATCH(&entry->val)) {
+                if(!V_DISPATCH(&entry->val)) {
                     FIXME("Calling null\n");
                     return E_FAIL;
                 }
 
-                hres = invoke_disp_value(This, entry->val, 0, flags, dp, res, ei, NULL);
+                hres = invoke_disp_value(This, V_DISPATCH(&entry->val), 0, flags, dp, res, ei, NULL);
                 break;
             }
         }
@@ -1166,16 +1170,11 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
         if(FAILED(hres))
             return hres;
 
-        V_VT(res) = VT_DISPATCH;
-        V_DISPATCH(res) = entry->val;
-        if(V_DISPATCH(res))
-            IDispatch_AddRef(V_DISPATCH(res));
-        hres = S_OK;
-        break;
+        V_VT(res) = VT_EMPTY;
+        return VariantCopy(res, &entry->val);
     }
     case DISPATCH_PROPERTYPUT: {
         func_obj_entry_t *entry;
-        VARIANT *v;
 
         if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT)
            || dp->cNamedArgs > 1) {
@@ -1183,22 +1182,17 @@ static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags,
             return E_INVALIDARG;
         }
 
-        v = dp->rgvarg;
-        /* FIXME: not exactly right */
-        if(V_VT(v) != VT_DISPATCH)
-            return E_NOTIMPL;
-
+        /*
+         * NOTE: Although we have IDispatchEx tests showing, that it's not allowed to set
+         * function property using InvokeEx, it's possible to do that from jscript.
+         * Native probably uses some undocumented interface in this case, but it should
+         * be fine for us to allow IDispatchEx handle that.
+         */
         hres = get_func_obj_entry(This, func, &entry);
         if(FAILED(hres))
             return hres;
 
-        if(entry->val)
-            IDispatch_Release(entry->val);
-        entry->val = V_DISPATCH(v);
-        if(entry->val)
-            IDispatch_AddRef(entry->val);
-        hres = S_OK;
-        break;
+        return VariantCopy(&entry->val, dp->rgvarg);
     }
     default:
         FIXME("Unimplemented flags %x\n", flags);
@@ -1722,8 +1716,7 @@ void release_dispex(DispatchEx *This)
                 iter->func_obj->obj = NULL;
                 IDispatchEx_Release(&iter->func_obj->dispex.IDispatchEx_iface);
             }
-            if(iter->val)
-                IDispatch_Release(iter->val);
+            VariantClear(&iter->val);
         }
 
         heap_free(This->dynamic_data->func_disps);
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index c9b9eb5..9681fd6 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -1915,7 +1915,7 @@ static void test_func(IDispatchEx *obj)
     V_VT(&var) = VT_I4;
     V_I4(&var) = 100;
     hres = dispex_propput(obj, id, 0, &var, NULL);
-    ok(hres == E_NOTIMPL, "InvokeEx failed: %08x\n", hres);
+    todo_wine ok(hres == E_NOTIMPL, "InvokeEx failed: %08x\n", hres);
 
     hres = dispex_propget(dispex, DISPID_VALUE, &var, NULL);
     ok(hres == E_ACCESSDENIED, "InvokeEx returned: %08x, expected E_ACCESSDENIED\n", hres);




More information about the wine-cvs mailing list