[VBSCRIPT_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
[reactos.git] / rostests / winetests / vbscript / run.c
index e471b44..3ae85ee 100644 (file)
@@ -94,10 +94,12 @@ DEFINE_EXPECT(testobj_propget_d);
 DEFINE_EXPECT(testobj_propget_i);
 DEFINE_EXPECT(testobj_propput_d);
 DEFINE_EXPECT(testobj_propput_i);
+DEFINE_EXPECT(testobj_value_i);
 DEFINE_EXPECT(global_propargput_d);
 DEFINE_EXPECT(global_propargput_i);
 DEFINE_EXPECT(global_propargput1_d);
 DEFINE_EXPECT(global_propargput1_i);
+DEFINE_EXPECT(global_testoptionalarg_i);
 DEFINE_EXPECT(collectionobj_newenum_i);
 DEFINE_EXPECT(Next);
 DEFINE_EXPECT(GetWindow);
@@ -119,12 +121,18 @@ DEFINE_EXPECT(EnableModeless);
 #define DISPID_GLOBAL_PROPARGPUT1   1012
 #define DISPID_GLOBAL_COLLOBJ       1013
 #define DISPID_GLOBAL_DOUBLEASSTRING 1014
+#define DISPID_GLOBAL_TESTARRAY     1015
+#define DISPID_GLOBAL_THROWINT      1016
+#define DISPID_GLOBAL_TESTOPTIONALARG 1017
 
 #define DISPID_TESTOBJ_PROPGET      2000
 #define DISPID_TESTOBJ_PROPPUT      2001
 
 #define DISPID_COLLOBJ_RESET        3000
 
+#define FACILITY_VBS 0xa
+#define MAKE_VBSERROR(code) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_VBS, code)
+
 static const WCHAR testW[] = {'t','e','s','t',0};
 static const WCHAR emptyW[] = {0};
 
@@ -152,18 +160,6 @@ static int strcmp_wa(LPCWSTR strw, const char *stra)
     return lstrcmpA(buf, stra);
 }
 
-static const char *debugstr_guid(REFIID riid)
-{
-    static char buf[50];
-
-    sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-            riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
-            riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
-            riid->Data4[5], riid->Data4[6], riid->Data4[7]);
-
-    return buf;
-}
-
 static const char *vt2a(VARIANT *v)
 {
     if(V_VT(v) == (VT_BYREF|VT_VARIANT)) {
@@ -181,8 +177,12 @@ static const char *vt2a(VARIANT *v)
         return "VT_I2";
     case VT_I4:
         return "VT_I4";
+    case VT_R4:
+        return "VT_R4";
     case VT_R8:
         return "VT_R8";
+    case VT_CY:
+        return "VT_CY";
     case VT_DATE:
         return "VT_DATE";
     case VT_BSTR:
@@ -193,6 +193,10 @@ static const char *vt2a(VARIANT *v)
         return "VT_BOOL";
     case VT_ARRAY|VT_VARIANT:
         return "VT_ARRAY|VT_VARIANT";
+    case VT_ARRAY|VT_BYREF|VT_VARIANT:
+        return "VT_ARRAY|VT_BYREF|VT_VARIANT";
+    case VT_UI1:
+        return "VT_UI1";
     default:
         ok(0, "unknown vt %d\n", V_VT(v));
         return NULL;
@@ -241,7 +245,7 @@ static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
         REFIID riid, void **ppv)
 {
-    ok(0, "unexpected service %s\n", debugstr_guid(guidService));
+    ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService));
     return E_NOINTERFACE;
 }
 
@@ -256,7 +260,7 @@ static IServiceProvider caller_sp = { &ServiceProviderVtbl };
 
 static void test_disp(IDispatch *disp)
 {
-    DISPID id, public_prop_id, public_prop2_id, public_func_id, public_sub_id, defvalget_id;
+    DISPID id, public_prop_id, public_prop2_id, public_func_id, public_sub_id, defvalget_id, gs_getter_id;
     DISPID named_args[5] = {DISPID_PROPERTYPUT};
     VARIANT v, args[5];
     DISPPARAMS dp = {args, named_args};
@@ -319,6 +323,12 @@ static void test_disp(IDispatch *disp)
     ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v));
     ok(V_BOOL(&v), "V_BOOL(v) = %x\n", V_BOOL(&v));
 
+    dp.cArgs = dp.cNamedArgs = 0;
+    hres = IDispatchEx_Invoke(dispex, public_prop_id, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&v) == VT_BOOL, "V_VT(v) = %d\n", V_VT(&v));
+    ok(V_BOOL(&v), "V_BOOL(v) = %x\n", V_BOOL(&v));
+
     dp.cArgs = dp.cNamedArgs = 0;
     hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL);
     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
@@ -399,6 +409,12 @@ static void test_disp(IDispatch *disp)
     ok(V_VT(&v) == VT_I2, "V_VT(v) = %d\n", V_VT(&v));
     ok(V_I2(&v) == 4, "V_I2(v) = %d\n", V_I2(&v));
 
+    dp.cArgs = dp.cNamedArgs = 0;
+    hres = IDispatchEx_Invoke(dispex, public_func_id, &IID_NULL, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&v) == VT_I2, "V_VT(v) = %d\n", V_VT(&v));
+    ok(V_I2(&v) == 4, "V_I2(v) = %d\n", V_I2(&v));
+
     dp.cArgs = dp.cNamedArgs = 0;
     hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL);
     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
@@ -443,9 +459,63 @@ static void test_disp(IDispatch *disp)
     ok(hres == S_OK, "GetDispID(publicProp) failed: %08x\n", hres);
     ok(id == public_prop_id, "id = %d, expected %d\n", id, public_prop_id);
 
+    str = a2bstr("gsGetProp");
+    hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &gs_getter_id);
+    SysFreeString(str);
+    ok(hres == S_OK, "GetDispID(publicFunction) failed: %08x\n", hres);
+    ok(gs_getter_id != -1, "gs_getter_id = -1\n");
+
+    V_VT(args) = VT_BOOL;
+    V_BOOL(args) = VARIANT_TRUE;
+    dp.cNamedArgs = 0;
+    dp.cArgs = 1;
+    V_VT(&v) = VT_I8;
+    hres = IDispatchEx_InvokeEx(dispex, gs_getter_id, 0, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&v) == VT_BOOL && V_BOOL(&v), "V_VT(v) = %d\n", V_VT(&v));
+
+    hres = IDispatchEx_InvokeEx(dispex, gs_getter_id, 0, DISPATCH_PROPERTYGET, &dp, NULL, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+
+    V_VT(args) = VT_BOOL;
+    V_BOOL(args) = VARIANT_FALSE;
+    dp.cArgs = 1;
+    V_VT(&v) = VT_I8;
+    hres = IDispatchEx_InvokeEx(dispex, gs_getter_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&v) == VT_BOOL && !V_BOOL(&v), "V_VT(v) = %d\n", V_VT(&v));
+
+    V_VT(args) = VT_BOOL;
+    V_BOOL(args) = VARIANT_TRUE;
+    V_VT(&v) = VT_I8;
+    dp.cArgs = 1;
+    hres = IDispatchEx_InvokeEx(dispex, gs_getter_id, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL);
+    ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+    ok(V_VT(&v) == VT_BOOL && V_BOOL(&v), "V_VT(v) = %d\n", V_VT(&v));
+
     IDispatchEx_Release(dispex);
 }
 
+static void test_safearray(SAFEARRAY *safearray, unsigned indims)
+{
+    int i, exdims = indims;
+
+    if(!exdims)
+        exdims = 1;
+    ok(safearray->cDims == exdims, "safearray->cDims = %d, expected %d\n", safearray->cDims, exdims);
+    todo_wine
+    ok(safearray->fFeatures == (FADF_VARIANT|FADF_HAVEVARTYPE|FADF_FIXEDSIZE|FADF_STATIC),
+       "safearray->fFeatures = %x\n", safearray->fFeatures);
+    ok(safearray->cbElements == sizeof(VARIANT), "safearray->cbElements = %x\n", safearray->cbElements);
+    ok(!safearray->cLocks, "safearray->cLocks = %x\n", safearray->cLocks);
+
+    for(i=0; i < safearray->cDims; i++) {
+        ok(safearray->rgsabound[i].cElements == indims ? i+4 : 1, "safearray->rgsabound[%d].cElements = %d\n", i,
+           safearray->rgsabound[i].cElements);
+        ok(!safearray->rgsabound[i].lLbound, "safearray->rgsabound[%d].lLbound = %d\n", i, safearray->rgsabound[i].lLbound);
+    }
+}
+
 #define test_grfdex(a,b) _test_grfdex(__LINE__,a,b)
 static void _test_grfdex(unsigned line, DWORD grfdex, DWORD expect)
 {
@@ -466,7 +536,7 @@ static HRESULT WINAPI EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID rii
         return S_OK;
     }
 
-    ok(0, "unexpected call %s\n", debugstr_guid(riid));
+    ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
     return E_NOINTERFACE;
 }
 
@@ -539,7 +609,7 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
        || IsEqualGUID(riid, &IID_IDispatchEx))
         *ppv = iface;
     else {
-        trace("QI %s\n", debugstr_guid(riid));
+        trace("QI %s\n", wine_dbgstr_guid(riid));
         return E_NOINTERFACE;
     }
 
@@ -658,6 +728,29 @@ static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
 {
     switch(id) {
+    case DISPID_VALUE: {
+        VARIANT *arg;
+        int i;
+
+        CHECK_EXPECT(testobj_value_i);
+
+        ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(pvarRes != NULL, "pvarRes == NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+
+        for(i=0; i<pdp->cArgs; i++) {
+            arg = pdp->rgvarg+pdp->cArgs-i-1;
+            ok(V_VT(arg) == VT_I2, "V_VT(arg) = %d\n", V_VT(arg));
+            ok(V_I2(arg) == i+1, "V_I2(arg) = %d\n", V_I2(arg));
+        }
+
+        V_VT(pvarRes) = VT_I2;
+        V_I2(pvarRes) = pdp->cArgs;
+        return S_OK;
+    }
     case DISPID_TESTOBJ_PROPGET:
         CHECK_EXPECT(testobj_propget_i);
 
@@ -913,6 +1006,21 @@ static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD
         *pid = DISPID_GLOBAL_DOUBLEASSTRING;
         return S_OK;
     }
+    if(!strcmp_wa(bstrName, "testArray")) {
+        test_grfdex(grfdex, fdexNameCaseInsensitive);
+        *pid = DISPID_GLOBAL_TESTARRAY;
+        return S_OK;
+    }
+    if(!strcmp_wa(bstrName, "throwInt")) {
+        test_grfdex(grfdex, fdexNameCaseInsensitive);
+        *pid = DISPID_GLOBAL_THROWINT;
+        return S_OK;
+    }
+    if(!strcmp_wa(bstrName, "testOptionalArg")) {
+        test_grfdex(grfdex, fdexNameCaseInsensitive);
+        *pid = DISPID_GLOBAL_TESTOPTIONALARG;
+        return S_OK;
+    }
 
     if(strict_dispid_check && strcmp_wa(bstrName, "x"))
         ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
@@ -950,7 +1058,7 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
         return S_OK;
     }
 
-     case DISPID_GLOBAL_TRACE:
+    case DISPID_GLOBAL_TRACE:
         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
         ok(pdp != NULL, "pdp == NULL\n");
         ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
@@ -1171,6 +1279,85 @@ static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid,
 
         V_VT(pvarRes) = VT_BSTR;
         return VarBstrFromR8(V_R8(pdp->rgvarg), 0, 0, &V_BSTR(pvarRes));
+
+    case DISPID_GLOBAL_TESTARRAY:
+        ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(!pvarRes, "pvarRes != NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+
+        ok(V_VT(pdp->rgvarg+1) == VT_I2, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg+1));
+        ok(V_VT(pdp->rgvarg) == (VT_BYREF|VT_VARIANT), "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
+        ok(V_VT(V_VARIANTREF(pdp->rgvarg)) == (VT_ARRAY|VT_BYREF|VT_VARIANT),
+           "V_VT(V_VARIANTREF(psp->rgvargs)) = %d\n", V_VT(V_VARIANTREF(pdp->rgvarg)));
+        if(V_I2(pdp->rgvarg+1) == -1)
+            ok(!*V_ARRAYREF(V_VARIANTREF(pdp->rgvarg)), "*V_ARRAYREF(V_VARIANTREF(pdp->rgvarg)) != NULL\n");
+        else
+            test_safearray(*V_ARRAYREF(V_VARIANTREF(pdp->rgvarg)), V_I2(pdp->rgvarg+1));
+        return S_OK;
+
+    case DISPID_GLOBAL_THROWINT: {
+        VARIANT *v = pdp->rgvarg;
+        HRESULT hres;
+
+        ok((wFlags & ~INVOKE_PROPERTYGET) == INVOKE_FUNC, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(pei != NULL, "pei == NULL\n");
+        if(pvarRes) {
+            ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
+            V_VT(pvarRes) = VT_BOOL;
+            V_BOOL(pvarRes) = VARIANT_FALSE;
+        }
+
+        if(V_VT(v) == (VT_VARIANT|VT_BYREF))
+            v = V_VARIANTREF(v);
+
+        switch(V_VT(v)) {
+        case VT_I2:
+            hres = V_I2(v);
+            break;
+        case VT_I4:
+            hres = V_I4(v);
+            break;
+        default:
+            ok(0, "unexpected vt %d\n", V_VT(v));
+            return E_INVALIDARG;
+        }
+
+        return hres;
+    }
+
+    case DISPID_GLOBAL_TESTOPTIONALARG: {
+        VARIANT *v;
+        int opt;
+
+        CHECK_EXPECT(global_testoptionalarg_i);
+
+        ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
+        ok(pdp != NULL, "pdp == NULL\n");
+        ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+        ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+        ok(pdp->cArgs == 3, "cArgs = %d\n", pdp->cArgs);
+        ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+        ok(!pvarRes, "pvarRes != NULL\n");
+        ok(pei != NULL, "pei == NULL\n");
+
+        ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
+        opt = V_I2(pdp->rgvarg);
+        ok(opt == 1 || opt == 2, "opt = %d\n", opt);
+        v = pdp->rgvarg+pdp->cArgs-opt;
+        ok(V_VT(v) == VT_ERROR, "V_VT(v) = %d\n", V_VT(v));
+        ok(V_ERROR(v) == DISP_E_PARAMNOTFOUND, "V_ERROR(v) = %08x\n", V_ERROR(v));
+        return S_OK;
+    }
     }
 
     ok(0, "unexpected call %d\n", id);
@@ -1733,7 +1920,7 @@ static BSTR get_script_from_file(const char *filename)
 
     size = GetFileSize(file, NULL);
 
-    map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
+    map = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
     CloseHandle(file);
     if(map == INVALID_HANDLE_VALUE) {
         trace("Could not create file mapping: %u\n", GetLastError());
@@ -1912,8 +2099,42 @@ static void run_tests(void)
     test_global_vars_ref(TRUE);
     test_global_vars_ref(FALSE);
 
+    hres = parse_script_ar("throwInt(&h80080008&)");
+    ok(hres == 0x80080008, "hres = %08x\n", hres);
+
+    /* DISP_E_BADINDEX */
+    hres = parse_script_ar("throwInt(&h8002000b&)");
+    ok(hres == MAKE_VBSERROR(9), "hres = %08x\n", hres);
+
+    hres = parse_script_ar("throwInt(&h800a0009&)");
+    ok(hres == MAKE_VBSERROR(9), "hres = %08x\n", hres);
+
+    /* E_NOTIMPL */
+    hres = parse_script_ar("throwInt(&h80004001&)");
+    ok(hres == MAKE_VBSERROR(445), "hres = %08x\n", hres);
+
+    SET_EXPECT(global_testoptionalarg_i);
+    parse_script_a("call testOptionalArg(1,,2)");
+    CHECK_CALLED(global_testoptionalarg_i);
+
+    SET_EXPECT(global_testoptionalarg_i);
+    parse_script_a("call testOptionalArg(,1,1)");
+    CHECK_CALLED(global_testoptionalarg_i);
+
+    SET_EXPECT(global_testoptionalarg_i);
+    parse_script_a("testOptionalArg 1,,2");
+    CHECK_CALLED(global_testoptionalarg_i);
+
     strict_dispid_check = FALSE;
 
+    SET_EXPECT(testobj_value_i);
+    parse_script_a("dim n,o\n set o = testObj\n n = o(1,2)\n call ok(n=2, \"n = \" & n)\n");
+    CHECK_CALLED(testobj_value_i);
+
+    SET_EXPECT(testobj_value_i);
+    parse_script_a("dim n,o\n set o = testObj\n n = o\n call ok(n=0, \"n = \" & n)\n");
+    CHECK_CALLED(testobj_value_i);
+
     parse_script_a("Sub testsub\n"
                    "x = 1\n"
                    "Call ok(x = 1, \"x = \" & x)\n"
@@ -1931,6 +2152,7 @@ static void run_tests(void)
     run_from_res("lang.vbs");
     run_from_res("api.vbs");
     run_from_res("regexp.vbs");
+    run_from_res("error.vbs");
 
     test_procedures();
     test_gc();