Jacek Caban : jscript: Support DISP_E_EXCEPTION InvokeEx result.

Alexandre Julliard julliard at winehq.org
Thu Jan 30 16:10:23 CST 2020


Module: wine
Branch: master
Commit: 274503c839de2a30aef22eab4b9dc879d254a813
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=274503c839de2a30aef22eab4b9dc879d254a813

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Jan 30 15:50:06 2020 +0100

jscript: Support DISP_E_EXCEPTION InvokeEx result.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/dispex.c | 184 +++++++++++++++++++-------------------------------
 1 file changed, 69 insertions(+), 115 deletions(-)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index cd610e4e88..265e84aee8 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -1941,11 +1941,51 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned
     return invoke_prop_func(disp, to_disp(disp), prop, flags, argc, argv, r, NULL);
 }
 
-HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret)
+static HRESULT disp_invoke(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, DISPPARAMS *params, VARIANT *r)
 {
     IDispatchEx *dispex;
-    jsdisp_t *jsdisp;
+    EXCEPINFO ei;
+    HRESULT hres;
+
+    memset(&ei, 0, sizeof(ei));
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    if(SUCCEEDED(hres)) {
+        hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, params, r, &ei, &ctx->jscaller->IServiceProvider_iface);
+        IDispatchEx_Release(dispex);
+    }else {
+        UINT err = 0;
+
+        if(flags == DISPATCH_CONSTRUCT) {
+            WARN("IDispatch cannot be constructor\n");
+            return DISP_E_MEMBERNOTFOUND;
+        }
+
+        if(params->cNamedArgs == 1 && params->rgdispidNamedArgs[0] == DISPID_THIS) {
+            params->cNamedArgs = 0;
+            params->rgdispidNamedArgs = NULL;
+            params->cArgs--;
+            params->rgvarg++;
+        }
+
+        TRACE("using IDispatch\n");
+        hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, params, r, &ei, &err);
+    }
+
+    if(hres == DISP_E_EXCEPTION) {
+        TRACE("DISP_E_EXCEPTION: %08x %s %s\n", ei.scode, debugstr_w(ei.bstrSource), debugstr_w(ei.bstrDescription));
+        hres = SUCCEEDED(ei.scode) ? E_FAIL : ei.scode;
+        SysFreeString(ei.bstrSource);
+        SysFreeString(ei.bstrDescription);
+        SysFreeString(ei.bstrHelpFile);
+    }
+
+    return hres;
+}
+
+HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv, jsval_t *ret)
+{
     VARIANT buf[6], retv;
+    jsdisp_t *jsdisp;
     DISPPARAMS dp;
     unsigned i;
     HRESULT hres;
@@ -1980,7 +2020,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
         dp.rgdispidNamedArgs = NULL;
     }
 
-    if(argc > 6) {
+    if(dp.cArgs > ARRAY_SIZE(buf)) {
         dp.rgvarg = heap_alloc(argc*sizeof(VARIANT));
         if(!dp.rgvarg)
             return E_OUTOFMEMORY;
@@ -2000,48 +2040,29 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
     }
 
     V_VT(&retv) = VT_EMPTY;
-    clear_ei(ctx);
-    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
-    if(SUCCEEDED(hres)) {
-        hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei,
-                &ctx->jscaller->IServiceProvider_iface);
-        IDispatchEx_Release(dispex);
-    }else {
-        UINT err = 0;
-
-        if(flags == DISPATCH_CONSTRUCT) {
-            WARN("IDispatch cannot be constructor\n");
-            return DISP_E_MEMBERNOTFOUND;
-        }
-
-        TRACE("using IDispatch\n");
-        hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ctx->ei.ei, &err);
-    }
+    hres = disp_invoke(ctx, disp, id, flags, &dp, ret ? &retv : NULL);
 
     for(i=0; i<argc; i++)
         VariantClear(dp.rgvarg+argc-i-1);
     if(dp.rgvarg != buf)
         heap_free(dp.rgvarg);
-    if(FAILED(hres))
-        return hres;
 
-    if(ret) {
+    if(SUCCEEDED(hres) && ret)
         hres = variant_to_jsval(&retv, ret);
-        VariantClear(&retv);
-    }
-
+    VariantClear(&retv);
     return hres;
 }
 
 HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv,
         jsval_t *r)
 {
+    VARIANT buf[6], retv, *args = buf;
     jsdisp_t *jsdisp;
-    IDispatchEx *dispex;
-    VARIANT buf[6], retv;
     DISPPARAMS dp;
     unsigned i;
-    HRESULT hres;
+    HRESULT hres = S_OK;
+
+    static DISPID this_id = DISPID_THIS;
 
     assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
 
@@ -2058,17 +2079,8 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
     if(r && argc && flags == DISPATCH_METHOD)
         flags |= DISPATCH_PROPERTYGET;
 
-    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
-    if(FAILED(hres)) {
-        TRACE("using IDispatch\n");
-        dispex = NULL;
-        jsthis = NULL;
-    }
-
     if(jsthis) {
-        static DISPID this_id = DISPID_THIS;
-
-        dp.cArgs = argc+1;
+        dp.cArgs = argc + 1;
         dp.cNamedArgs = 1;
         dp.rgdispidNamedArgs = &this_id;
     }else {
@@ -2077,57 +2089,25 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
         dp.rgdispidNamedArgs = NULL;
     }
 
-    if(dp.cArgs > ARRAY_SIZE(buf)) {
-        dp.rgvarg = heap_alloc(dp.cArgs*sizeof(VARIANT));
-        if(!dp.rgvarg) {
-            if(dispex)
-                IDispatchEx_Release(dispex);
-            return E_OUTOFMEMORY;
-        }
-    }else {
-        dp.rgvarg = buf;
-    }
-
-    for(i=0; i<argc; i++) {
-        hres = jsval_to_variant(argv[i], dp.rgvarg+dp.cArgs-i-1);
-        if(FAILED(hres)) {
-            while(i--)
-                VariantClear(dp.rgvarg+dp.cArgs-i-1);
-            if(dp.rgvarg != buf)
-                heap_free(dp.rgvarg);
-            if(dispex)
-                IDispatchEx_Release(dispex);
-            return hres;
-        }
-    }
-    if(jsthis) {
-        V_VT(dp.rgvarg) = VT_DISPATCH;
-        V_DISPATCH(dp.rgvarg) = jsthis;
-    }
+    if(argc > ARRAY_SIZE(buf) && !(args = heap_alloc(argc * sizeof(VARIANT))))
+        return E_OUTOFMEMORY;
+    dp.rgvarg = args;
 
-    V_VT(&retv) = VT_EMPTY;
-    clear_ei(ctx);
-    if(dispex) {
-        hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei,
-                &ctx->jscaller->IServiceProvider_iface);
-        IDispatchEx_Release(dispex);
-    }else {
-        UINT err = 0;
+    V_VT(dp.rgvarg) = VT_DISPATCH;
+    V_DISPATCH(dp.rgvarg) = jsthis;
 
-        if(flags == DISPATCH_CONSTRUCT) {
-            WARN("IDispatch cannot be constructor\n");
-            return DISP_E_MEMBERNOTFOUND;
-        }
+    for(i=0; SUCCEEDED(hres) && i < argc; i++)
+        hres = jsval_to_variant(argv[i], dp.rgvarg+dp.cArgs-i-1);
 
-        hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, ctx->lcid, flags, &dp, r ? &retv : NULL, &ctx->ei.ei, &err);
+    if(SUCCEEDED(hres)) {
+        V_VT(&retv) = VT_EMPTY;
+        hres = disp_invoke(ctx, disp, DISPID_VALUE, flags, &dp, r ? &retv : NULL);
     }
 
-    for(i=0; i<argc; i++)
-        VariantClear(dp.rgvarg+dp.cArgs-i-1);
-    if(dp.rgvarg != buf)
-        heap_free(dp.rgvarg);
-    if(FAILED(hres))
-        return hres;
+    for(i = 0; i < argc&&0; i++)
+        VariantClear(dp.rgvarg + dp.cArgs - i - 1);
+    if(args != buf)
+        heap_free(args);
 
     if(!r)
         return S_OK;
@@ -2185,7 +2165,6 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
         DWORD flags = DISPATCH_PROPERTYPUT;
         VARIANT var;
         DISPPARAMS dp  = {&var, &dispid, 1, 1};
-        IDispatchEx *dispex;
 
         hres = jsval_to_variant(val, &var);
         if(FAILED(hres))
@@ -2194,19 +2173,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
         if(V_VT(&var) == VT_DISPATCH)
             flags |= DISPATCH_PROPERTYPUTREF;
 
-        clear_ei(ctx);
-        hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
-        if(SUCCEEDED(hres)) {
-            hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, NULL, &ctx->ei.ei,
-                    &ctx->jscaller->IServiceProvider_iface);
-            IDispatchEx_Release(dispex);
-        }else {
-            ULONG err = 0;
-
-            TRACE("using IDispatch\n");
-            hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, NULL, &ctx->ei.ei, &err);
-        }
-
+        hres = disp_invoke(ctx, disp, id, flags, &dp, NULL);
         VariantClear(&var);
     }
 
@@ -2266,7 +2233,6 @@ HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val)
 HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val)
 {
     DISPPARAMS dp  = {NULL,NULL,0,0};
-    IDispatchEx *dispex;
     jsdisp_t *jsdisp;
     VARIANT var;
     HRESULT hres;
@@ -2279,23 +2245,11 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val
     }
 
     V_VT(&var) = VT_EMPTY;
-    clear_ei(ctx);
-    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    hres = disp_invoke(ctx, disp, id, INVOKE_PROPERTYGET, &dp, &var);
     if(SUCCEEDED(hres)) {
-        hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei,
-                &ctx->jscaller->IServiceProvider_iface);
-        IDispatchEx_Release(dispex);
-    }else {
-        ULONG err = 0;
-
-        TRACE("using IDispatch\n");
-        hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ctx->ei.ei, &err);
+        hres = variant_to_jsval(&var, val);
+        VariantClear(&var);
     }
-    if(FAILED(hres))
-        return hres;
-
-    hres = variant_to_jsval(&var, val);
-    VariantClear(&var);
     return hres;
 }
 




More information about the wine-cvs mailing list