[PATCH 3/3] msscript.ocx/tests: Add tests for IScriptControl::Run.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Sep 26 09:43:45 CDT 2019


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/msscript.ocx/tests/msscript.c | 560 ++++++++++++++++++++++++++++-
 1 file changed, 558 insertions(+), 2 deletions(-)

diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c
index 95b2a69..091d882 100644
--- a/dlls/msscript.ocx/tests/msscript.c
+++ b/dlls/msscript.ocx/tests/msscript.c
@@ -29,6 +29,7 @@
 
 #include "msscript.h"
 #include "wine/test.h"
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 #define TESTSCRIPT_CLSID "{178fc164-f585-4e24-9c13-4bb7faf80746}"
 static const GUID CLSID_TestScript =
@@ -92,12 +93,17 @@ DEFINE_EXPECT(CreateInstance);
 DEFINE_EXPECT(SetInterfaceSafetyOptions);
 DEFINE_EXPECT(InitNew);
 DEFINE_EXPECT(Close);
+DEFINE_EXPECT(QI_IDispatchEx);
+DEFINE_EXPECT(GetIDsOfNames);
+DEFINE_EXPECT(Invoke);
+DEFINE_EXPECT(InvokeEx);
 DEFINE_EXPECT(SetScriptSite);
 DEFINE_EXPECT(QI_IActiveScriptParse);
 DEFINE_EXPECT(SetScriptState_INITIALIZED);
 DEFINE_EXPECT(SetScriptState_STARTED);
 DEFINE_EXPECT(ParseScriptText);
 DEFINE_EXPECT(AddNamedItem);
+DEFINE_EXPECT(GetScriptDispatch);
 
 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
@@ -226,6 +232,317 @@ static const IObjectSafetyVtbl ObjectSafetyVtbl = {
 
 static IObjectSafety ObjectSafety = { &ObjectSafetyVtbl };
 
+static void dispparams_release(DISPPARAMS *dp)
+{
+    while (dp->cArgs--)
+        VariantClear(&dp->rgvarg[dp->cArgs]);
+    HeapFree(GetProcessHeap(), 0, dp->rgvarg);
+}
+
+static HRESULT safearray_to_dispparams(SAFEARRAY *sa, DISPPARAMS *out)
+{
+    DISPPARAMS dp;
+    HRESULT hr;
+    UINT i;
+
+    if (sa->cDims == 0 || !(sa->fFeatures & FADF_VARIANT))
+        return E_FAIL;
+
+    dp.cArgs = sa->rgsabound[0].cElements;
+    dp.rgdispidNamedArgs = NULL;
+    dp.cNamedArgs = 0;
+
+    dp.rgvarg = HeapAlloc(GetProcessHeap(), 0, dp.cArgs * sizeof(*dp.rgvarg));
+    if (!dp.rgvarg) return E_OUTOFMEMORY;
+
+    hr = SafeArrayLock(sa);
+    if (FAILED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, dp.rgvarg);
+        return hr;
+    }
+
+    for (i = 0; i < dp.cArgs; i++)
+    {
+        /* The DISPPARAMS are stored in reverse order */
+        VARIANT *src = (VARIANT*)((char*)(sa->pvData) + (dp.cArgs - i - 1) * sa->cbElements);
+
+        V_VT(&dp.rgvarg[i]) = VT_EMPTY;
+        hr = VariantCopy(&dp.rgvarg[i], src);
+        if (FAILED(hr))
+        {
+            dp.cArgs = i;
+            dispparams_release(&dp);
+            goto err;
+        }
+    }
+    *out = dp;
+
+err:
+    SafeArrayUnlock(sa);
+    return hr;
+}
+
+static struct
+{
+    UINT line;
+    const WCHAR *name;
+    DISPPARAMS dp;
+} Dispatch_expect;
+
+#define set_Dispatch_expect(n,sa) do { \
+    Dispatch_expect.line = __LINE__; \
+    Dispatch_expect.name = (n); \
+    ok(safearray_to_dispparams((sa), &Dispatch_expect.dp) == S_OK, "safearray_to_dispparams failed.\n"); \
+} while(0)
+
+static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+    ok(0, "unexpected call\n");
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames,
+        UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+        WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags,
+        DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
+{
+    UINT line = Dispatch_expect.line, i;
+
+    CHECK_EXPECT(InvokeEx);
+    ok_(__FILE__,line)(lcid == LOCALE_USER_DEFAULT, "unexpected lcid %u\n", lcid);
+    ok_(__FILE__,line)(wFlags == DISPATCH_METHOD, "unexpected wFlags %u\n", wFlags);
+    ok_(__FILE__,line)(id == 0xdeadbeef, "unexpected id %d\n", id);
+    ok_(__FILE__,line)(pdp->cNamedArgs == Dispatch_expect.dp.cNamedArgs,
+        "unexpected number of named args %u (expected %u)\n", pdp->cNamedArgs, Dispatch_expect.dp.cNamedArgs);
+    ok_(__FILE__,line)(!pdp->rgdispidNamedArgs,
+        "unexpected (non-NULL) named args array %p\n", pdp->rgdispidNamedArgs);
+    ok_(__FILE__,line)(pdp->cArgs == Dispatch_expect.dp.cArgs,
+        "unexpected number of args %u (expected %u)\n", pdp->cArgs, Dispatch_expect.dp.cArgs);
+    if (pdp->rgvarg)
+    {
+        if (pdp->cArgs == Dispatch_expect.dp.cArgs)
+            for (i = 0; i < Dispatch_expect.dp.cArgs; i++)
+            {
+                VARIANT *v1 = pdp->rgvarg + i, *v2 = Dispatch_expect.dp.rgvarg + i;
+
+                ok_(__FILE__,line)(V_VT(v1) == V_VT(v2) && VarCmp(v1, v2, lcid, 0) == VARCMP_EQ,
+                    "unexpected arg %u: V_VT = %d, V_I4 = %d (expected V_VT = %d, V_I4 = %d)\n", i,
+                    V_VT(v1), V_I4(v1), V_VT(v2), V_I4(v2));
+            }
+    }
+    else if (Dispatch_expect.dp.rgvarg)
+        ok_(__FILE__,line)(0, "unexpected NULL args array\n");
+
+    V_VT(pvarRes) = VT_I2;
+    V_I2(pvarRes) = 42;
+    return S_OK;
+}
+
+static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch,
+        DWORD *pgrfdex)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static const IDispatchExVtbl DispatchExVtbl = {
+    DispatchEx_QueryInterface,
+    DispatchEx_AddRef,
+    DispatchEx_Release,
+    DispatchEx_GetTypeInfoCount,
+    DispatchEx_GetTypeInfo,
+    DispatchEx_GetIDsOfNames,
+    DispatchEx_Invoke,
+    DispatchEx_GetDispID,
+    DispatchEx_InvokeEx,
+    DispatchEx_DeleteMemberByName,
+    DispatchEx_DeleteMemberByDispID,
+    DispatchEx_GetMemberProperties,
+    DispatchEx_GetMemberName,
+    DispatchEx_GetNextDispID,
+    DispatchEx_GetNameSpaceParent
+};
+
+static IDispatchEx DispatchEx = { &DispatchExVtbl };
+
+static BOOL DispatchEx_available = FALSE;
+static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+
+    if (IsEqualGUID(&IID_IDispatchEx, riid))
+    {
+        CHECK_EXPECT(QI_IDispatchEx);
+        if (DispatchEx_available)
+        {
+            *ppv = &DispatchEx;
+            return S_OK;
+        }
+        return E_NOINTERFACE;
+    }
+
+    ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Dispatch_AddRef(IDispatch *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI Dispatch_Release(IDispatch *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
+        UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    UINT line = Dispatch_expect.line;
+
+    CHECK_EXPECT(GetIDsOfNames);
+    ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
+    ok_(__FILE__,line)(lcid == LOCALE_USER_DEFAULT, "unexpected lcid %u\n", lcid);
+    ok_(__FILE__,line)(cNames == 1, "unexpected cNames %u\n", cNames);
+    ok_(__FILE__,line)(!lstrcmpW(rgszNames[0], Dispatch_expect.name),
+        "unexpected name: %s\n", wine_dbgstr_w(rgszNames[0]));
+
+    *rgDispId = 0xdeadbeef;
+    return S_OK;
+}
+
+static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+        WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    UINT line = Dispatch_expect.line, i;
+
+    CHECK_EXPECT(Invoke);
+    ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
+    ok_(__FILE__,line)(lcid == LOCALE_USER_DEFAULT, "unexpected lcid %u\n", lcid);
+    ok_(__FILE__,line)(wFlags == DISPATCH_METHOD, "unexpected wFlags %u\n", wFlags);
+    ok_(__FILE__,line)(dispIdMember == 0xdeadbeef, "unexpected dispIdMember %d\n", dispIdMember);
+    ok_(__FILE__,line)(pDispParams->cNamedArgs == Dispatch_expect.dp.cNamedArgs,
+        "unexpected number of named args %u (expected %u)\n", pDispParams->cNamedArgs, Dispatch_expect.dp.cNamedArgs);
+    ok_(__FILE__,line)(!pDispParams->rgdispidNamedArgs,
+        "unexpected (non-NULL) named args array %p\n", pDispParams->rgdispidNamedArgs);
+    ok_(__FILE__,line)(pDispParams->cArgs == Dispatch_expect.dp.cArgs,
+        "unexpected number of args %u (expected %u)\n", pDispParams->cArgs, Dispatch_expect.dp.cArgs);
+    if (pDispParams->rgvarg)
+    {
+        if (pDispParams->cArgs == Dispatch_expect.dp.cArgs)
+            for (i = 0; i < Dispatch_expect.dp.cArgs; i++)
+            {
+                VARIANT *v1 = pDispParams->rgvarg + i, *v2 = Dispatch_expect.dp.rgvarg + i;
+
+                ok_(__FILE__,line)(V_VT(v1) == V_VT(v2) && VarCmp(v1, v2, lcid, 0) == VARCMP_EQ,
+                    "unexpected arg %u: V_VT = %d, V_I4 = %d (expected V_VT = %d, V_I4 = %d)\n", i,
+                    V_VT(v1), V_I4(v1), V_VT(v2), V_I4(v2));
+            }
+    }
+    else if (Dispatch_expect.dp.rgvarg)
+        ok_(__FILE__,line)(0, "unexpected NULL args array\n");
+
+    V_VT(pVarResult) = VT_R8;
+    V_R8(pVarResult) = 4.2;
+    return S_OK;
+}
+
+static const IDispatchVtbl DispatchVtbl = {
+    Dispatch_QueryInterface,
+    Dispatch_AddRef,
+    Dispatch_Release,
+    Dispatch_GetTypeInfoCount,
+    Dispatch_GetTypeInfo,
+    Dispatch_GetIDsOfNames,
+    Dispatch_Invoke
+};
+
+static IDispatch Dispatch = { &DispatchVtbl };
+
 static HRESULT WINAPI ActiveScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv)
 {
     *ppv = NULL;
@@ -362,8 +679,12 @@ static HRESULT WINAPI ActiveScript_AddTypeLib(IActiveScript *iface, REFGUID rgui
 static HRESULT WINAPI ActiveScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName,
                                                 IDispatch **ppdisp)
 {
-    ok(0, "unexpected call\n");
-    return E_NOTIMPL;
+    CHECK_EXPECT(GetScriptDispatch);
+    ok(!pstrItemName, "pstrItemName not NULL, got %s.\n", wine_dbgstr_w(pstrItemName));
+
+    *ppdisp = &Dispatch;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI ActiveScript_GetCurrentScriptThreadID(IActiveScript *iface,
@@ -1757,6 +2078,240 @@ static void test_IScriptControl_ExecuteStatement(void)
     }
 }
 
+static void test_IScriptControl_Run(void)
+{
+    SAFEARRAYBOUND bnd[] = { { 2, 0 }, { 2, 0 } };
+    LONG idx0_0[] = { 0, 0 };
+    LONG idx0_1[] = { 1, 0 };
+    LONG idx1_0[] = { 0, 1 };
+    LONG idx1_1[] = { 1, 1 };
+    IScriptControl *sc;
+    SAFEARRAY *params;
+    VARIANT var;
+    HRESULT hr;
+    BSTR str;
+
+    hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
+                          &IID_IScriptControl, (void**)&sc);
+    ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr);
+
+    params = NULL;
+    str = a2bstr("identifier");
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == E_POINTER, "IScriptControl_Run returned: 0x%08x.\n", hr);
+
+    params = SafeArrayCreate(VT_VARIANT, 1, bnd);
+    ok(params != NULL, "Failed to create SafeArray.\n");
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = 10;
+    SafeArrayPutElement(params, idx0_0, &var);
+    V_I4(&var) = 3;
+    SafeArrayPutElement(params, idx0_1, &var);
+
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == E_FAIL, "IScriptControl_Run returned: 0x%08x.\n", hr);
+
+    hr = IScriptControl_Run(sc, str, NULL, &var);
+    ok(hr == E_POINTER, "IScriptControl_Run returned: 0x%08x.\n", hr);
+
+    hr = IScriptControl_Run(sc, str, &params, NULL);
+    ok(hr == E_POINTER, "IScriptControl_Run returned: 0x%08x.\n", hr);
+    SysFreeString(str);
+
+    hr = IScriptControl_Run(sc, NULL, &params, &var);
+    ok(hr == E_FAIL, "IScriptControl_Run returned: 0x%08x.\n", hr);
+
+    str = a2bstr("jscript");
+    hr = IScriptControl_put_Language(sc, str);
+    ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr);
+    SysFreeString(str);
+
+    str = a2bstr("foobar");
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == DISP_E_UNKNOWNNAME, "IScriptControl_Run failed: 0x%08x.\n", hr);
+    todo_wine CHECK_ERROR(sc, 0);
+    SysFreeString(str);
+
+    str = a2bstr("function subtract(a, b) { return a - b; }\n");
+    hr = IScriptControl_AddCode(sc, str);
+    ok(hr == S_OK, "IScriptControl_AddCode failed: 0x%08x.\n", hr);
+    todo_wine CHECK_ERROR(sc, 0);
+    SysFreeString(str);
+
+    str = a2bstr("Subtract");
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == DISP_E_UNKNOWNNAME, "IScriptControl_Run failed: 0x%08x.\n", hr);
+    SysFreeString(str);
+
+    str = a2bstr("subtract");
+    hr = IScriptControl_Run(sc, str, &params, NULL);
+    ok(hr == E_POINTER, "IScriptControl_Run failed: 0x%08x.\n", hr);
+    todo_wine CHECK_ERROR(sc, 0);
+
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+    ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 7), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var));
+    todo_wine CHECK_ERROR(sc, 0);
+    VariantClear(&var);
+    SafeArrayDestroy(params);
+
+    /* The array must be of VT_VARIANT type, else it either
+       crashes on Windows, or returns DISP_E_BADVARTYPE. */
+    if (!broken(1))
+    {
+        params = SafeArrayCreate(VT_I4, 1, bnd);
+        ok(params != NULL, "Failed to create SafeArray.\n");
+
+        V_I4(&var) = 10;
+        SafeArrayPutElement(params, idx0_0, &V_I4(&var));
+        V_I4(&var) = 3;
+        SafeArrayPutElement(params, idx0_1, &V_I4(&var));
+
+        V_VT(&var) = VT_EMPTY;
+        hr = IScriptControl_Run(sc, str, &params, &var);
+        ok(hr == DISP_E_BADVARTYPE, "IScriptControl_Run returned: 0x%08x.\n", hr);
+        ok(V_VT(&var) == VT_EMPTY, "V_VT(var) = %d.\n", V_VT(&var));
+        SafeArrayDestroy(params);
+    }
+
+    /* The array's other dimensions are ignored */
+    params = SafeArrayCreate(VT_VARIANT, 2, bnd);
+    ok(params != NULL, "Failed to create SafeArray.\n");
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = 10;
+    SafeArrayPutElement(params, idx0_0, &var);
+    V_I4(&var) = 3;
+    SafeArrayPutElement(params, idx0_1, &var);
+    V_I4(&var) = 90;
+    SafeArrayPutElement(params, idx1_0, &var);
+    V_I4(&var) = 80;
+    SafeArrayPutElement(params, idx1_1, &var);
+
+    VariantClear(&var);
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+    ok((V_VT(&var) == VT_I4) && (V_I4(&var) == 7), "V_VT(var) = %d, V_I4(var) = %d.\n", V_VT(&var), V_I4(&var));
+
+    /* Hack the array's dimensions to 0 */
+    VariantClear(&var);
+    params->cDims = 0;
+    hr = IScriptControl_Run(sc, str, &params, &var);
+    ok(hr == DISP_E_BADINDEX, "IScriptControl_Run returned: 0x%08x.\n", hr);
+    ok(V_VT(&var) == VT_EMPTY, "V_VT(var) = %d.\n", V_VT(&var));
+    params->cDims = 2;
+    VariantClear(&var);
+    SysFreeString(str);
+    IScriptControl_Release(sc);
+
+    /* custom script engine */
+    if (have_custom_engine)
+    {
+        hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
+                              &IID_IScriptControl, (void**)&sc);
+        ok(hr == S_OK, "Failed to create IScriptControl interface: 0x%08x.\n", hr);
+
+        SET_EXPECT(CreateInstance);
+        SET_EXPECT(SetInterfaceSafetyOptions);
+        SET_EXPECT(SetScriptSite);
+        SET_EXPECT(QI_IActiveScriptParse);
+        SET_EXPECT(InitNew);
+
+        str = a2bstr("testscript");
+        hr = IScriptControl_put_Language(sc, str);
+        ok(hr == S_OK, "IScriptControl_put_Language failed: 0x%08x.\n", hr);
+        SysFreeString(str);
+
+        CHECK_CALLED(CreateInstance);
+        CHECK_CALLED(SetInterfaceSafetyOptions);
+        CHECK_CALLED(SetScriptSite);
+        CHECK_CALLED(QI_IActiveScriptParse);
+        CHECK_CALLED(InitNew);
+
+        SET_EXPECT(SetScriptState_STARTED);
+        SET_EXPECT(GetScriptDispatch);
+        SET_EXPECT(QI_IDispatchEx);
+        SET_EXPECT(GetIDsOfNames);
+        SET_EXPECT(Invoke);
+        str = a2bstr("function");
+        set_Dispatch_expect(str, params);
+        hr = IScriptControl_Run(sc, str, &params, &var);
+        ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+        ok((V_VT(&var) == VT_R8) && (V_R8(&var) == 4.2), "V_VT(var) = %d, V_R8(var) = %lf.\n", V_VT(&var), V_R8(&var));
+        VariantClear(&var);
+        SysFreeString(str);
+        dispparams_release(&Dispatch_expect.dp);
+        CHECK_CALLED(SetScriptState_STARTED);
+        CHECK_CALLED(GetScriptDispatch);
+        CHECK_CALLED(QI_IDispatchEx);
+        CHECK_CALLED(GetIDsOfNames);
+        CHECK_CALLED(Invoke);
+
+        /* GetScriptDispatch is cached and not called again */
+        CLEAR_CALLED(GetScriptDispatch);
+        SET_EXPECT(QI_IDispatchEx);
+        SET_EXPECT(GetIDsOfNames);
+        SET_EXPECT(Invoke);
+        str = a2bstr("BarFoo");
+        set_Dispatch_expect(str, params);
+        hr = IScriptControl_Run(sc, str, &params, &var);
+        ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+        VariantClear(&var);
+        SysFreeString(str);
+        dispparams_release(&Dispatch_expect.dp);
+        CHECK_NOT_CALLED(GetScriptDispatch);
+        CHECK_CALLED(QI_IDispatchEx);
+        CHECK_CALLED(GetIDsOfNames);
+        CHECK_CALLED(Invoke);
+
+        /* Make DispatchEx available */
+        DispatchEx_available = TRUE;
+        CLEAR_CALLED(GetScriptDispatch);
+        SET_EXPECT(QI_IDispatchEx);
+        SET_EXPECT(GetIDsOfNames);
+        SET_EXPECT(InvokeEx);
+        str = a2bstr("FooBar");
+        set_Dispatch_expect(str, params);
+        hr = IScriptControl_Run(sc, str, &params, &var);
+        ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+        ok((V_VT(&var) == VT_I2) && (V_I2(&var) == 42), "V_VT(var) = %d, V_I2(var) = %d.\n", V_VT(&var), V_I2(&var));
+        VariantClear(&var);
+        SysFreeString(str);
+        dispparams_release(&Dispatch_expect.dp);
+        CHECK_NOT_CALLED(GetScriptDispatch);
+        CHECK_CALLED(QI_IDispatchEx);
+        CHECK_CALLED(GetIDsOfNames);
+        CHECK_CALLED(InvokeEx);
+
+        /* QueryInterface for IDispatchEx is always called and not cached */
+        CLEAR_CALLED(GetScriptDispatch);
+        SET_EXPECT(QI_IDispatchEx);
+        SET_EXPECT(GetIDsOfNames);
+        SET_EXPECT(InvokeEx);
+        str = a2bstr("FooBar");
+        set_Dispatch_expect(str, params);
+        hr = IScriptControl_Run(sc, str, &params, &var);
+        ok(hr == S_OK, "IScriptControl_Run failed: 0x%08x.\n", hr);
+        VariantClear(&var);
+        SysFreeString(str);
+        dispparams_release(&Dispatch_expect.dp);
+        CHECK_NOT_CALLED(GetScriptDispatch);
+        CHECK_CALLED(QI_IDispatchEx);
+        CHECK_CALLED(GetIDsOfNames);
+        CHECK_CALLED(InvokeEx);
+        DispatchEx_available = FALSE;
+
+        IActiveScriptSite_Release(site);
+
+        SET_EXPECT(Close);
+        IScriptControl_Release(sc);
+        CHECK_CALLED(Close);
+    }
+
+    SafeArrayDestroy(params);
+}
+
 START_TEST(msscript)
 {
     IUnknown *unk;
@@ -1793,6 +2348,7 @@ START_TEST(msscript)
     test_IScriptControl_Eval();
     test_IScriptControl_AddCode();
     test_IScriptControl_ExecuteStatement();
+    test_IScriptControl_Run();
 
     init_registry(FALSE);
 
-- 
2.21.0




More information about the wine-devel mailing list