From 0af75befc5e7a9a3bb7d03a06cdee4571e1f9731 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Wed, 15 May 2013 17:33:58 +0000 Subject: [PATCH] [VBSCRIPT_WINETEST] * Import from Wine 1.5.26. svn path=/trunk/; revision=59018 --- rostests/winetests/CMakeLists.txt | 1 + rostests/winetests/vbscript/CMakeLists.txt | 24 + rostests/winetests/vbscript/api.vbs | 427 ++++ rostests/winetests/vbscript/createobj.c | 1125 +++++++++++ rostests/winetests/vbscript/lang.vbs | 975 +++++++++ rostests/winetests/vbscript/regexp.vbs | 171 ++ rostests/winetests/vbscript/rsrc.rc | 26 + rostests/winetests/vbscript/run.c | 1985 +++++++++++++++++++ rostests/winetests/vbscript/testlist.c | 16 + rostests/winetests/vbscript/vbscript.c | 968 +++++++++ rostests/winetests/vbscript/vbscript_defs.h | 33 + rostests/winetests/vbscript/vbsregexp55.idl | 270 +++ 12 files changed, 6021 insertions(+) create mode 100644 rostests/winetests/vbscript/CMakeLists.txt create mode 100644 rostests/winetests/vbscript/api.vbs create mode 100644 rostests/winetests/vbscript/createobj.c create mode 100644 rostests/winetests/vbscript/lang.vbs create mode 100644 rostests/winetests/vbscript/regexp.vbs create mode 100644 rostests/winetests/vbscript/rsrc.rc create mode 100644 rostests/winetests/vbscript/run.c create mode 100644 rostests/winetests/vbscript/testlist.c create mode 100644 rostests/winetests/vbscript/vbscript.c create mode 100644 rostests/winetests/vbscript/vbscript_defs.h create mode 100644 rostests/winetests/vbscript/vbsregexp55.idl diff --git a/rostests/winetests/CMakeLists.txt b/rostests/winetests/CMakeLists.txt index 7e46e0284d8..450fd38269d 100644 --- a/rostests/winetests/CMakeLists.txt +++ b/rostests/winetests/CMakeLists.txt @@ -88,6 +88,7 @@ add_subdirectory(user32) add_subdirectory(userenv) add_subdirectory(usp10) add_subdirectory(uxtheme) +add_subdirectory(vbscript) add_subdirectory(version) add_subdirectory(windowscodecs) add_subdirectory(winhttp) diff --git a/rostests/winetests/vbscript/CMakeLists.txt b/rostests/winetests/vbscript/CMakeLists.txt new file mode 100644 index 00000000000..fc6e85c80a3 --- /dev/null +++ b/rostests/winetests/vbscript/CMakeLists.txt @@ -0,0 +1,24 @@ + +add_definitions(-D__ROS_LONG64__) +add_idl_headers(vbscript_wine_test_idlheader vbsregexp55.idl) + +list(APPEND SOURCE + createobj.c + run.c + vbscript.c + testlist.c + rsrc.rc) + +list(APPEND vbscript_winetest_rc_deps + ${CMAKE_CURRENT_SOURCE_DIR}/api.vbs + ${CMAKE_CURRENT_SOURCE_DIR}/lang.vbs + ${CMAKE_CURRENT_SOURCE_DIR}/regexp.vbs) + +set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS "${vbscript_winetest_rc_deps}") + +add_executable(vbscript_winetest ${SOURCE}) +target_link_libraries(vbscript_winetest wine) +set_module_type(vbscript_winetest win32cui) +add_importlibs(vbscript_winetest ole32 oleaut32 advapi32 msvcrt kernel32 ntdll) +add_dependencies(vbscript_winetest vbscript_wine_test_idlheader) +add_cd_file(TARGET vbscript_winetest DESTINATION reactos/bin FOR all) diff --git a/rostests/winetests/vbscript/api.vbs b/rostests/winetests/vbscript/api.vbs new file mode 100644 index 00000000000..0aaeefbd79d --- /dev/null +++ b/rostests/winetests/vbscript/api.vbs @@ -0,0 +1,427 @@ +' +' Copyright 2011 Jacek Caban for CodeWeavers +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +' + +Option Explicit + +Dim x + +Class EmptyClass +End Class + +Call ok(vbSunday = 1, "vbSunday = " & vbSunday) +Call ok(getVT(vbSunday) = "VT_I2", "getVT(vbSunday) = " & getVT(vbSunday)) +Call ok(vbMonday = 2, "vbMonday = " & vbMonday) +Call ok(getVT(vbMonday) = "VT_I2", "getVT(vbMonday) = " & getVT(vbMonday)) +Call ok(vbTuesday = 3, "vbTuesday = " & vbTuesday) +Call ok(getVT(vbTuesday) = "VT_I2", "getVT(vbTuesday) = " & getVT(vbTuesday)) +Call ok(vbWednesday = 4, "vbWednesday = " & vbWednesday) +Call ok(getVT(vbWednesday) = "VT_I2", "getVT(vbWednesday) = " & getVT(vbWednesday)) +Call ok(vbThursday = 5, "vbThursday = " & vbThursday) +Call ok(getVT(vbThursday) = "VT_I2", "getVT(vbThursday) = " & getVT(vbThursday)) +Call ok(vbFriday = 6, "vbFriday = " & vbFriday) +Call ok(getVT(vbFriday) = "VT_I2", "getVT(vbFriday) = " & getVT(vbFriday)) +Call ok(vbSaturday = 7, "vbSaturday = " & vbSaturday) +Call ok(getVT(vbSaturday) = "VT_I2", "getVT(vbSaturday) = " & getVT(vbSaturday)) + +Sub TestConstant(name, val, exval) + Call ok(val = exval, name & " = " & val & " expected " & exval) + Call ok(getVT(val) = "VT_I2*", "getVT(" & name & ") = " & getVT(val)) +End Sub + +Sub TestConstantI4(name, val, exval) + Call ok(val = exval, name & " = " & val & " expected " & exval) + Call ok(getVT(val) = "VT_I4*", "getVT(" & name & ") = " & getVT(val)) +End Sub + +Sub TestConstantBSTR(name, val, exval) + Call ok(val = exval, name & " = " & val & " expected " & exval) + Call ok(getVT(val) = "VT_BSTR*", "getVT(" & name & ") = " & getVT(val)) +End Sub + +TestConstant "vbEmpty", vbEmpty, 0 +TestConstant "vbNull", vbNull, 1 +TestConstant "vbLong", vbLong, 3 +TestConstant "vbSingle", vbSingle, 4 +TestConstant "vbDouble", vbDouble, 5 +TestConstant "vbCurrency", vbCurrency, 6 +TestConstant "vbDate", vbDate, 7 +TestConstant "vbString", vbString, 8 +TestConstant "vbObject", vbObject, 9 +TestConstant "vbError", vbError, 10 +TestConstant "vbBoolean", vbBoolean, 11 +TestConstant "vbVariant", vbVariant, 12 +TestConstant "vbDataObject", vbDataObject, 13 +TestConstant "vbDecimal", vbDecimal, 14 +TestConstant "vbByte", vbByte, 17 +TestConstant "vbArray", vbArray, 8192 +TestConstant "vbCritical", vbCritical, 16 +TestConstant "vbQuestion", vbQuestion, 32 +TestConstant "vbExclamation", vbExclamation, 48 +TestConstant "vbInformation", vbInformation, 64 +TestConstant "vbDefaultButton1", vbDefaultButton1, 0 +TestConstant "vbDefaultButton2", vbDefaultButton2, 256 +TestConstant "vbDefaultButton3", vbDefaultButton3, 512 +TestConstant "vbDefaultButton4", vbDefaultButton4, 768 +TestConstant "vbApplicationModal", vbApplicationModal, 0 +TestConstant "vbSystemModal", vbSystemModal, 4096 +TestConstant "vbUseSystem", vbUseSystem, 0 +TestConstant "vbUseSystemDayOfWeek", vbUseSystemDayOfWeek, 0 +TestConstant "vbFirstJan1", vbFirstJan1, 1 +TestConstant "vbFirstFourDays", vbFirstFourDays, 2 +TestConstant "vbFirstFullWeek", vbFirstFullWeek, 3 +TestConstant "vbTrue", vbTrue, -1 +TestConstant "vbFalse", vbFalse, 0 +TestConstantI4 "vbMsgBoxHelpButton", vbMsgBoxHelpButton, 16384 +TestConstantI4 "vbMsgBoxSetForeground", vbMsgBoxSetForeground, 65536 +TestConstantI4 "vbMsgBoxRight", vbMsgBoxRight, 524288 +TestConstantI4 "vbMsgBoxRtlReading", vbMsgBoxRtlReading, 1048576 +TestConstant "vbUseDefault", vbUseDefault, -2 +TestConstant "vbBinaryCompare", vbBinaryCompare, 0 +TestConstant "vbTextCompare", vbTextCompare, 1 +TestConstant "vbDatabaseCompare", vbDatabaseCompare, 2 +TestConstant "vbGeneralDate", vbGeneralDate, 0 +TestConstant "vbLongDate", vbLongDate, 1 +TestConstant "vbShortDate", vbShortDate, 2 +TestConstant "vbLongTime", vbLongTime, 3 +TestConstant "vbShortTime", vbShortTime, 4 +TestConstantI4 "vbObjectError", vbObjectError, &h80040000& +TestConstantI4 "vbBlack", vbBlack, 0 +TestConstantI4 "vbBlue", vbBlue, &hff0000& +TestConstantI4 "vbCyan", vbCyan, &hffff00& +TestConstantI4 "vbGreen", vbGreen, &h00ff00& +TestConstantI4 "vbMagenta", vbMagenta, &hff00ff& +TestConstantI4 "vbRed", vbRed, &h0000ff& +TestConstantI4 "vbWhite", vbWhite, &hffffff& +TestConstantI4 "vbYellow", vbYellow, &h00ffff& +TestConstantBSTR "vbCr", vbCr, Chr(13) +TestConstantBSTR "vbCrLf", vbCrLf, Chr(13)&Chr(10) +TestConstantBSTR "vbNewLine", vbNewLine, Chr(13)&Chr(10) +TestConstantBSTR "vbFormFeed", vbFormFeed, Chr(12) +TestConstantBSTR "vbLf", vbLf, Chr(10) +TestConstantBSTR "vbNullChar", vbNullChar, Chr(0) +TestConstantBSTR "vbNullString", vbNullString, "" +TestConstantBSTR "vbTab", vbTab, chr(9) +TestConstantBSTR "vbVerticalTab", vbVerticalTab, chr(11) + +Sub TestCStr(arg, exval) + dim x + x = CStr(arg) + Call ok(getVT(x) = "VT_BSTR*", "getVT(x) = " & getVT(x)) + Call ok(x = exval, "CStr(" & arg & ") = " & x) +End Sub + +TestCStr "test", "test" +TestCStr 3, "3" +if isEnglishLang then TestCStr 3.5, "3.5" +if isEnglishLang then TestCStr true, "True" + +Call ok(getVT(Chr(120)) = "VT_BSTR", "getVT(Chr(120)) = " & getVT(Chr(120))) +Call ok(getVT(Chr(255)) = "VT_BSTR", "getVT(Chr(255)) = " & getVT(Chr(255))) +Call ok(Chr(120) = "x", "Chr(120) = " & Chr(120)) +Call ok(Chr(0) <> "", "Chr(0) = """"") + +Call ok(isObject(new EmptyClass), "isObject(new EmptyClass) is not true?") +Set x = new EmptyClass +Call ok(isObject(x), "isObject(x) is not true?") +Call ok(isObject(Nothing), "isObject(Nothing) is not true?") +Call ok(not isObject(true), "isObject(true) is true?") +Call ok(not isObject(4), "isObject(4) is true?") +Call ok(not isObject("x"), "isObject(""x"") is true?") +Call ok(not isObject(Null), "isObject(Null) is true?") + +Call ok(not isEmpty(new EmptyClass), "isEmpty(new EmptyClass) is true?") +Set x = new EmptyClass +Call ok(not isEmpty(x), "isEmpty(x) is true?") +x = empty +Call ok(isEmpty(x), "isEmpty(x) is not true?") +Call ok(isEmpty(empty), "isEmpty(empty) is not true?") +Call ok(not isEmpty(Nothing), "isEmpty(Nothing) is not true?") +Call ok(not isEmpty(true), "isEmpty(true) is true?") +Call ok(not isEmpty(4), "isEmpty(4) is true?") +Call ok(not isEmpty("x"), "isEmpty(""x"") is true?") +Call ok(not isEmpty(Null), "isEmpty(Null) is true?") + +Call ok(not isNull(new EmptyClass), "isNull(new EmptyClass) is true?") +Set x = new EmptyClass +Call ok(not isNull(x), "isNull(x) is true?") +x = null +Call ok(isNull(x), "isNull(x) is not true?") +Call ok(not isNull(empty), "isNull(empty) is true?") +Call ok(not isNull(Nothing), "isNull(Nothing) is true?") +Call ok(not isNull(true), "isNull(true) is true?") +Call ok(not isNull(4), "isNull(4) is true?") +Call ok(not isNull("x"), "isNull(""x"") is true?") +Call ok(isNull(Null), "isNull(Null) is not true?") + +Call ok(getVT(err) = "VT_DISPATCH", "getVT(err) = " & getVT(err)) + +Sub TestHex(x, ex) + Call ok(hex(x) = ex, "hex(" & x & ") = " & hex(x) & " expected " & ex) +End Sub + +TestHex 0, "0" +TestHex 6, "6" +TestHex 16, "10" +TestHex &hdeadbeef&, "DEADBEEF" +TestHex -1, "FFFF" +TestHex -16, "FFF0" +TestHex -934859845, "C8472BBB" +TestHex empty, "0" + +Call ok(getVT(hex(null)) = "VT_NULL", "getVT(hex(null)) = " & getVT(hex(null))) +Call ok(getVT(hex(empty)) = "VT_BSTR", "getVT(hex(empty)) = " & getVT(hex(empty))) + +x = InStr(1, "abcd", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr("abcd", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr("abc", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr("abcbc", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr("bcabc", "bc") +Call ok(x = 1, "InStr returned " & x) + +x = InStr(3, "abcd", "bc") +Call ok(x = 0, "InStr returned " & x) + +x = InStr("abcd", "bcx") +Call ok(x = 0, "InStr returned " & x) + +x = InStr(5, "abcd", "bc") +Call ok(x = 0, "InStr returned " & x) + +x = "abcd" +x = InStr(x, "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr("abcd", null) +Call ok(isNull(x), "InStr returned " & x) +x = InStr(null, "abcd") +Call ok(isNull(x), "InStr returned " & x) +x = InStr(2, null, "abcd") +Call ok(isNull(x), "InStr returned " & x) + +x = InStr(1.3, "abcd", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr(2.3, "abcd", "bc") +Call ok(x = 2, "InStr returned " & x) + +x = InStr(2.6, "abcd", "bc") +Call ok(x = 0, "InStr returned " & x) + +Sub TestMid(str, start, len, ex) + x = Mid(str, start, len) + Call ok(x = ex, "Mid(" & str & ", " & start & ", " & len & ") = " & x & " expected " & ex) +End Sub + +Sub TestMid2(str, start, ex) + x = Mid(str, start) + Call ok(x = ex, "Mid(" & str & ", " & start & ") = " & x & " expected " & ex) +End Sub + +TestMid "test", 2, 2, "es" +TestMid "test", 2, 4, "est" +TestMid "test", 1, 2, "te" +TestMid "test", 1, 0, "" +TestMid "test", 1, 0, "" +TestMid "test", 5, 2, "" +TestMid2 "test", 1, "test" +TestMid2 "test", 2, "est" +TestMid2 "test", 4, "t" +TestMid2 "test", 5, "" + +Sub TestUCase(str, ex) + x = UCase(str) + Call ok(x = ex, "UCase(" & str & ") = " & x & " expected " & ex) +End Sub + +TestUCase "test", "TEST" +TestUCase "123aBC?", "123ABC?" +TestUCase "", "" +TestUCase 1, "1" +if isEnglishLang then TestUCase true, "TRUE" +TestUCase 0.123, doubleAsString(0.123) +TestUCase Empty, "" +Call ok(getVT(UCase(Null)) = "VT_NULL", "getVT(UCase(Null)) = " & getVT(UCase(Null))) + +Sub TestLCase(str, ex) + x = LCase(str) + Call ok(x = ex, "LCase(" & str & ") = " & x & " expected " & ex) +End Sub + +TestLCase "test", "test" +TestLCase "123aBC?", "123abc?" +TestLCase "", "" +TestLCase 1, "1" +if isEnglishLang then TestLCase true, "true" +TestLCase 0.123, doubleAsString(0.123) +TestLCase Empty, "" +Call ok(getVT(LCase(Null)) = "VT_NULL", "getVT(LCase(Null)) = " & getVT(LCase(Null))) + +Call ok(Len("abc") = 3, "Len(abc) = " & Len("abc")) +Call ok(Len("") = 0, "Len() = " & Len("")) +Call ok(Len(1) = 1, "Len(1) = " & Len(1)) +Call ok(isNull(Len(null)), "Len(null) = " & Len(null)) +Call ok(Len(empty) = 0, "Len(empty) = " & Len(empty)) + +Call ok(Space(1) = " ", "Space(1) = " & Space(1) & """") +Call ok(Space(0) = "", "Space(0) = " & Space(0) & """") +Call ok(Space(false) = "", "Space(false) = " & Space(false) & """") +Call ok(Space(5) = " ", "Space(5) = " & Space(5) & """") +Call ok(Space(5.2) = " ", "Space(5.2) = " & Space(5.2) & """") +Call ok(Space(5.8) = " ", "Space(5.8) = " & Space(5.8) & """") +Call ok(Space(5.5) = " ", "Space(5.5) = " & Space(5.5) & """") + +Sub TestStrReverse(str, ex) + Call ok(StrReverse(str) = ex, "StrReverse(" & str & ") = " & StrReverse(str)) +End Sub + +TestStrReverse "test", "tset" +TestStrReverse "", "" +TestStrReverse 123, "321" +if isEnglishLang then TestStrReverse true, "eurT" + +Sub TestLeft(str, len, ex) + Call ok(Left(str, len) = ex, "Left(" & str & ", " & len & ") = " & Left(str, len)) +End Sub + +TestLeft "test", 2, "te" +TestLeft "test", 5, "test" +TestLeft "test", 0, "" +TestLeft 123, 2, "12" +if isEnglishLang then TestLeft true, 2, "Tr" + +Sub TestRight(str, len, ex) + Call ok(Right(str, len) = ex, "Right(" & str & ", " & len & ") = " & Right(str, len)) +End Sub + +TestRight "test", 2, "st" +TestRight "test", 5, "test" +TestRight "test", 0, "" +TestRight 123, 2, "23" +if isEnglishLang then TestRight true, 2, "ue" + +Sub TestTrim(str, exstr) + Call ok(Trim(str) = exstr, "Trim(" & str & ") = " & Trim(str)) +End Sub + +TestTrim " test ", "test" +TestTrim "test ", "test" +TestTrim " test", "test" +TestTrim "test", "test" +TestTrim "", "" +TestTrim 123, "123" +if isEnglishLang then TestTrim true, "True" + +Sub TestLTrim(str, exstr) + Call ok(LTrim(str) = exstr, "LTrim(" & str & ") = " & LTrim(str)) +End Sub + +TestLTrim " test ", "test " +TestLTrim "test ", "test " +TestLTrim " test", "test" +TestLTrim "test", "test" +TestLTrim "", "" +TestLTrim 123, "123" +if isEnglishLang then TestLTrim true, "True" + +Sub TestRound(val, exval, vt) + Call ok(Round(val) = exval, "Round(" & val & ") = " & Round(val)) + Call ok(getVT(Round(val)) = vt, "getVT(Round(" & val & ")) = " & getVT(Round(val))) +End Sub + +Sub TestRTrim(str, exstr) + Call ok(RTrim(str) = exstr, "RTrim(" & str & ") = " & RTrim(str)) +End Sub + +TestRTrim " test ", " test" +TestRTrim "test ", "test" +TestRTrim " test", " test" +TestRTrim "test", "test" +TestRTrim "", "" +TestRTrim 123, "123" +if isEnglishLang then TestRTrim true, "True" + +TestRound 3, 3, "VT_I2" +TestRound 3.3, 3, "VT_R8" +TestRound 3.8, 4, "VT_R8" +TestRound 3.5, 4, "VT_R8" +TestRound -3.3, -3, "VT_R8" +TestRound -3.5, -4, "VT_R8" +TestRound "2", 2, "VT_R8" +TestRound true, true, "VT_BOOL" +TestRound false, false, "VT_BOOL" + +if isEnglishLang then + Call ok(WeekDayName(1) = "Sunday", "WeekDayName(1) = " & WeekDayName(1)) + Call ok(WeekDayName(3) = "Tuesday", "WeekDayName(3) = " & WeekDayName(3)) + Call ok(WeekDayName(7) = "Saturday", "WeekDayName(7) = " & WeekDayName(7)) + Call ok(WeekDayName(1.1) = "Sunday", "WeekDayName(1.1) = " & WeekDayName(1.1)) + Call ok(WeekDayName(1, false) = "Sunday", "WeekDayName(1, false) = " & WeekDayName(1, false)) + Call ok(WeekDayName(1, true) = "Sun", "WeekDayName(1, true) = " & WeekDayName(1, true)) + Call ok(WeekDayName(1, 10) = "Sun", "WeekDayName(1, 10) = " & WeekDayName(1, 10)) + Call ok(WeekDayName(1, true, 0) = "Sun", "WeekDayName(1, true, 0) = " & WeekDayName(1, true, 0)) + Call ok(WeekDayName(1, true, 2) = "Mon", "WeekDayName(1, true, 2) = " & WeekDayName(1, true, 2)) + Call ok(WeekDayName(1, true, 7) = "Sat", "WeekDayName(1, true, 7) = " & WeekDayName(1, true, 7)) + Call ok(WeekDayName(1, true, 7.1) = "Sat", "WeekDayName(1, true, 7.1) = " & WeekDayName(1, true, 7.1)) + + Call ok(MonthName(1) = "January", "MonthName(1) = " & MonthName(1)) + Call ok(MonthName(12) = "December", "MonthName(12) = " & MonthName(12)) + Call ok(MonthName(1, 0) = "January", "MonthName(1, 0) = " & MonthName(1, 0)) + Call ok(MonthName(12, false) = "December", "MonthName(12, false) = " & MonthName(12, false)) + Call ok(MonthName(1, 10) = "Jan", "MonthName(1, 10) = " & MonthName(1, 10)) + Call ok(MonthName(12, true) = "Dec", "MonthName(12, true) = " & MonthName(12, true)) +end if + +Call ok(getVT(Now()) = "VT_DATE", "getVT(Now()) = " & getVT(Now())) + +Call ok(vbOKOnly = 0, "vbOKOnly = " & vbOKOnly) +Call ok(getVT(vbOKOnly) = "VT_I2", "getVT(vbOKOnly) = " & getVT(vbOKOnly)) +Call ok(vbOKCancel = 1, "vbOKCancel = " & vbOKCancel) +Call ok(getVT(vbOKCancel) = "VT_I2", "getVT(vbOKCancel) = " & getVT(vbOKCancel)) +Call ok(vbAbortRetryIgnore = 2, "vbAbortRetryIgnore = " & vbAbortRetryIgnore) +Call ok(getVT(vbAbortRetryIgnore) = "VT_I2", "getVT(vbAbortRetryIgnore) = " & getVT(vbAbortRetryIgnore)) +Call ok(vbYesNoCancel = 3, "vbYesNoCancel = " & vbYesNoCancel) +Call ok(getVT(vbYesNoCancel) = "VT_I2", "getVT(vbYesNoCancel) = " & getVT(vbYesNoCancel)) +Call ok(vbYesNo = 4, "vbYesNo = " & vbYesNo) +Call ok(getVT(vbYesNo) = "VT_I2", "getVT(vbYesNo) = " & getVT(vbYesNo)) +Call ok(vbRetryCancel = 5, "vbRetryCancel = " & vbRetryCancel) +Call ok(getVT(vbRetryCancel) = "VT_I2", "getVT(vbRetryCancel) = " & getVT(vbRetryCancel)) + +Call ok(vbOK = 1, "vbOK = " & vbOK) +Call ok(getVT(vbOK) = "VT_I2", "getVT(vbOK) = " & getVT(vbOK)) +Call ok(vbCancel = 2, "vbCancel = " & vbCancel) +Call ok(getVT(vbCancel) = "VT_I2", "getVT(vbCancel) = " & getVT(vbCancel)) +Call ok(vbAbort = 3, "vbAbort = " & vbAbort) +Call ok(getVT(vbAbort) = "VT_I2", "getVT(vbAbort) = " & getVT(vbAbort)) +Call ok(vbRetry = 4, "vbRetry = " & vbRetry) +Call ok(getVT(vbRetry) = "VT_I2", "getVT(vbRetry) = " & getVT(vbRetry)) +Call ok(vbIgnore = 5, "vbIgnore = " & vbIgnore) +Call ok(getVT(vbIgnore) = "VT_I2", "getVT(vbIgnore) = " & getVT(vbIgnore)) +Call ok(vbYes = 6, "vbYes = " & vbYes) +Call ok(getVT(vbYes) = "VT_I2", "getVT(vbYes) = " & getVT(vbYes)) +Call ok(vbNo = 7, "vbNo = " & vbNo) +Call ok(getVT(vbNo) = "VT_I2", "getVT(vbNo) = " & getVT(vbNo)) + +Call reportSuccess() diff --git a/rostests/winetests/vbscript/createobj.c b/rostests/winetests/vbscript/createobj.c new file mode 100644 index 00000000000..bdb9cd69a7c --- /dev/null +++ b/rostests/winetests/vbscript/createobj.c @@ -0,0 +1,1125 @@ +/* + * Copyright 2009,2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + +#define COBJMACROS +#define CONST_VTABLE + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release + +#endif + +extern const CLSID CLSID_VBScript; + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + +DEFINE_EXPECT(CreateInstance); +DEFINE_EXPECT(ProcessUrlAction); +DEFINE_EXPECT(QueryCustomPolicy); +DEFINE_EXPECT(reportSuccess); +DEFINE_EXPECT(Host_QS_SecMgr); +DEFINE_EXPECT(Caller_QS_SecMgr); +DEFINE_EXPECT(QI_IObjectWithSite); +DEFINE_EXPECT(SetSite); + +static const WCHAR testW[] = {'t','e','s','t',0}; + +static HRESULT QS_SecMgr_hres; +static HRESULT ProcessUrlAction_hres; +static DWORD ProcessUrlAction_policy; +static HRESULT CreateInstance_hres; +static HRESULT QueryCustomPolicy_hres; +static DWORD QueryCustomPolicy_psize; +static DWORD QueryCustomPolicy_policy; +static HRESULT QI_IDispatch_hres; +static HRESULT QI_IObjectWithSite_hres; +static HRESULT SetSite_hres; + +#define TESTOBJ_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80646}" +#define TESTOBJINST_CLSID "{178fc163-f585-4e24-9c13-4bb7faf80647}" + +static const GUID CLSID_TestObj = + {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}}; +static const GUID CLSID_TestObjInst = + {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x47}}; + +/* Defined as extern in urlmon.idl, but not exported by uuid.lib */ +const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY = + {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}}; + +#define DISPID_TEST_REPORTSUCCESS 0x1000 + +#define DISPID_GLOBAL_OK 0x2000 + +#define VB_E_CANNOT_CREATE_OBJ 0x800a01ad + +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 BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len-1); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + +static int strcmp_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), 0, 0); + return lstrcmpA(buf, stra); +} + +static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface) +{ + return 2; +} + +static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite) +{ + IServiceProvider *sp; + HRESULT hres; + + + CHECK_EXPECT(SetSite); + ok(pUnkSite != NULL, "pUnkSite == NULL\n"); + + hres = IUnknown_QueryInterface(pUnkSite, &IID_IServiceProvider, (void**)&sp); + ok(hres == S_OK, "Could not get IServiceProvider iface: %08x\n", hres); + IServiceProvider_Release(sp); + + return SetSite_hres; +} + +static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IObjectWithSiteVtbl ObjectWithSiteVtbl = { + ObjectWithSite_QueryInterface, + ObjectWithSite_AddRef, + ObjectWithSite_Release, + ObjectWithSite_SetSite, + ObjectWithSite_GetSite +}; + +static IObjectWithSite ObjectWithSite = { &ObjectWithSiteVtbl }; + +static IObjectWithSite *object_with_site; + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = iface; + }else if(IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IDispatchEx)) { + if(FAILED(QI_IDispatch_hres)) + return QI_IDispatch_hres; + *ppv = iface; + }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) { + CHECK_EXPECT(QI_IObjectWithSite); + if(FAILED(QI_IObjectWithSite_hres)) + return QI_IObjectWithSite_hres; + *ppv = object_with_site; + }else if(IsEqualGUID(&IID_IObjectSafety, riid)) { + ok(0, "Unexpected IID_IObjectSafety query\n"); + } + + return *ppv ? S_OK : 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_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); + 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 HRESULT WINAPI Test_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "reportSuccess")) { + ok(grfdex == fdexNameCaseInsensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_TEST_REPORTSUCCESS; + return S_OK; + } + + ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Test_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_TEST_REPORTSUCCESS: + CHECK_EXPECT(reportSuccess); + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + break; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Test_GetDispID, + Test_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testObj = { &testObjVtbl }; + +static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "ok")) { + ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex); + *pid = DISPID_GLOBAL_OK; + return S_OK; + } + + ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_GLOBAL_OK: + ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "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(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_VT(pdp->rgvarg+1) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg)); + ok(V_BOOL(pdp->rgvarg+1), "%s\n", wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + break; + + default: + ok(0, "unexpected call\n"); + return E_NOTIMPL; + } + + return S_OK; +} + +static IDispatchExVtbl globalObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Global_GetDispID, + Global_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx globalObj = { &globalObjVtbl }; + +static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) { + *ppv = iface; + return S_OK; + } + + /* TODO: IClassFactoryEx */ + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) +{ + return 2; +} + +static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) +{ + return 1; +} + +static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) +{ + CHECK_EXPECT(CreateInstance); + + ok(!outer, "outer = %p\n", outer); + ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid)); + + if(SUCCEEDED(CreateInstance_hres)) + *ppv = &testObj; + return CreateInstance_hres; +} + +static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) +{ + ok(0, "unexpected call\n"); + return S_OK; +} + +static const IClassFactoryVtbl ClassFactoryVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ClassFactory_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory activex_cf = { &ClassFactoryVtbl }; + +static HRESULT WINAPI InternetHostSecurityManager_QueryInterface(IInternetHostSecurityManager *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI InternetHostSecurityManager_AddRef(IInternetHostSecurityManager *iface) +{ + return 2; +} + +static ULONG WINAPI InternetHostSecurityManager_Release(IInternetHostSecurityManager *iface) +{ + return 1; +} + +static HRESULT WINAPI InternetHostSecurityManager_GetSecurityId(IInternetHostSecurityManager *iface, BYTE *pbSecurityId, + DWORD *pcbSecurityId, DWORD_PTR dwReserved) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI InternetHostSecurityManager_ProcessUrlAction(IInternetHostSecurityManager *iface, DWORD dwAction, + BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved) +{ + CHECK_EXPECT(ProcessUrlAction); + + ok(dwAction == URLACTION_ACTIVEX_RUN, "dwAction = %x\n", dwAction); + ok(pPolicy != NULL, "pPolicy == NULL\n"); + ok(cbPolicy == sizeof(DWORD), "cbPolicy = %d\n", cbPolicy); + ok(pContext != NULL, "pContext == NULL\n"); + ok(cbContext == sizeof(GUID), "cbContext = %d\n", cbContext); + ok(IsEqualGUID(pContext, &CLSID_TestObj), "pContext = %s\n", debugstr_guid((const IID*)pContext)); + ok(!dwFlags, "dwFlags = %x\n", dwFlags); + ok(!dwReserved, "dwReserved = %x\n", dwReserved); + + if(SUCCEEDED(ProcessUrlAction_hres)) + *(DWORD*)pPolicy = ProcessUrlAction_policy; + return ProcessUrlAction_hres; +} + +static HRESULT WINAPI InternetHostSecurityManager_QueryCustomPolicy(IInternetHostSecurityManager *iface, REFGUID guidKey, + BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwReserved) +{ + const struct CONFIRMSAFETY *cs = (const struct CONFIRMSAFETY*)pContext; + DWORD *ret; + + CHECK_EXPECT(QueryCustomPolicy); + + ok(IsEqualGUID(&GUID_CUSTOM_CONFIRMOBJECTSAFETY, guidKey), "guidKey = %s\n", debugstr_guid(guidKey)); + + ok(ppPolicy != NULL, "ppPolicy == NULL\n"); + ok(pcbPolicy != NULL, "pcbPolicy == NULL\n"); + ok(pContext != NULL, "pContext == NULL\n"); + ok(cbContext == sizeof(struct CONFIRMSAFETY), "cbContext = %d\n", cbContext); + ok(!dwReserved, "dwReserved = %x\n", dwReserved); + + /* TODO: CLSID */ + ok(cs->pUnk != NULL, "cs->pUnk == NULL\n"); + ok(!cs->dwFlags, "dwFlags = %x\n", cs->dwFlags); + + if(FAILED(QueryCustomPolicy_hres)) + return QueryCustomPolicy_hres; + + ret = CoTaskMemAlloc(QueryCustomPolicy_psize); + *ppPolicy = (BYTE*)ret; + *pcbPolicy = QueryCustomPolicy_psize; + memset(ret, 0, QueryCustomPolicy_psize); + if(QueryCustomPolicy_psize >= sizeof(DWORD)) + *ret = QueryCustomPolicy_policy; + + return QueryCustomPolicy_hres; +} + +static const IInternetHostSecurityManagerVtbl InternetHostSecurityManagerVtbl = { + InternetHostSecurityManager_QueryInterface, + InternetHostSecurityManager_AddRef, + InternetHostSecurityManager_Release, + InternetHostSecurityManager_GetSecurityId, + InternetHostSecurityManager_ProcessUrlAction, + InternetHostSecurityManager_QueryCustomPolicy +}; + +static IInternetHostSecurityManager InternetHostSecurityManager = { &InternetHostSecurityManagerVtbl }; + +static IServiceProvider ServiceProvider; + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, + REFGUID guidService, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&SID_GetCaller, guidService)) + return E_NOINTERFACE; + + if(IsEqualGUID(&SID_SInternetHostSecurityManager, guidService)) { + if(iface == &ServiceProvider) + CHECK_EXPECT(Host_QS_SecMgr); + else + CHECK_EXPECT(Caller_QS_SecMgr); + ok(IsEqualGUID(&IID_IInternetHostSecurityManager, riid), "unexpected riid %s\n", debugstr_guid(riid)); + if(SUCCEEDED(QS_SecMgr_hres)) + *ppv = &InternetHostSecurityManager; + return QS_SecMgr_hres; + } + + ok(0, "unexpected service %s\n", debugstr_guid(guidService)); + return E_NOINTERFACE; +} + +static IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +static IServiceProvider ServiceProvider = { &ServiceProviderVtbl }; + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) { + *ppv = iface; + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + *ppv = &ServiceProvider; + }else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + *plcid = GetUserDefaultLCID(); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask); + ok(!ppti, "ppti != NULL\n"); + ok(!strcmp_wa(pstrName, "test"), "pstrName = %s\n", wine_dbgstr_w(pstrName)); + + *ppiunkItem = (IUnknown*)&globalObj; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +static void set_safety_options(IUnknown *unk, BOOL use_sec_mgr) +{ + IObjectSafety *safety; + DWORD supported, enabled, options_all, options_set; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IObjectSafety, (void**)&safety); + ok(hres == S_OK, "Could not get IObjectSafety: %08x\n", hres); + if(FAILED(hres)) + return; + + options_all = INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER; + if(use_sec_mgr) + options_set = options_all; + else + options_set = INTERFACE_USES_DISPEX; + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, options_all, options_set); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == options_all, "supported=%x, expected %x\n", supported, options_all); + ok(enabled == options_set, "enabled=%x, expected %x\n", enabled, options_set); + + IObjectSafety_Release(safety); +} + +#define parse_script_a(p,s) _parse_script_a(__LINE__,p,s) +static void _parse_script_a(unsigned line, IActiveScriptParse *parser, const char *script) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(script); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(str); + ok_(__FILE__,line)(hres == S_OK, "ParseScriptText failed: %08x\n", hres); +} + +static HRESULT parse_script_ae(IActiveScriptParse *parser, const char *script) +{ + BSTR str; + HRESULT hres; + + str = a2bstr(script); + hres = IActiveScriptParse_ParseScriptText(parser, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(str); + + return hres; +} + +static IActiveScriptParse *create_script(BOOL use_sec_mgr) +{ + IActiveScriptParse *parser; + IActiveScript *script; + HRESULT hres; + + QS_SecMgr_hres = S_OK; + ProcessUrlAction_hres = S_OK; + ProcessUrlAction_policy = URLPOLICY_ALLOW; + CreateInstance_hres = S_OK; + QueryCustomPolicy_hres = S_OK; + QueryCustomPolicy_psize = sizeof(DWORD); + QueryCustomPolicy_policy = URLPOLICY_ALLOW; + QI_IDispatch_hres = S_OK; + QI_IObjectWithSite_hres = S_OK; + SetSite_hres = S_OK; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&script); + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + if(FAILED(hres)) + return NULL; + + set_safety_options((IUnknown*)script, use_sec_mgr); + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(script, testW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + IActiveScript_Release(script); + + return parser; +} + +static void test_CreateObject(void) +{ + IActiveScriptParse *parser; + HRESULT hres; + + parser = create_script(TRUE); + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "Call CreateObject(\"Wine.Test\").reportSuccess()"); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.TestABC\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + QS_SecMgr_hres = E_NOINTERFACE; + + SET_EXPECT(Host_QS_SecMgr); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + ProcessUrlAction_hres = E_FAIL; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + ProcessUrlAction_policy = URLPOLICY_DISALLOW; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + CreateInstance_hres = E_FAIL; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + QueryCustomPolicy_hres = E_FAIL; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + QueryCustomPolicy_psize = 6; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "Call CreateObject(\"Wine.Test\").reportSuccess()"); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + QueryCustomPolicy_policy = URLPOLICY_DISALLOW; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + + QueryCustomPolicy_psize = 6; + + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + + QueryCustomPolicy_policy = URLPOLICY_ALLOW; + QueryCustomPolicy_psize = 3; + + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + + IActiveScriptParse_Release(parser); + + parser = create_script(FALSE); + + SET_EXPECT(CreateInstance); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "Call CreateObject(\"Wine.Test\").reportSuccess()"); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + + IActiveScriptParse_Release(parser); + + parser = create_script(TRUE); + object_with_site = &ObjectWithSite; + + SET_EXPECT(Host_QS_SecMgr); + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(SetSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "Call CreateObject(\"Wine.Test\").reportSuccess()"); + CHECK_CALLED(Host_QS_SecMgr); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(SetSite); + CHECK_CALLED(reportSuccess); + + SetSite_hres = E_FAIL; + SET_EXPECT(ProcessUrlAction); + SET_EXPECT(CreateInstance); + SET_EXPECT(QueryCustomPolicy); + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(SetSite); + hres = parse_script_ae(parser, "Call CreateObject(\"Wine.Test\")"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + CHECK_CALLED(ProcessUrlAction); + CHECK_CALLED(CreateInstance); + CHECK_CALLED(QueryCustomPolicy); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(SetSite); + + IActiveScriptParse_Release(parser); +} + +static void test_GetObject(void) +{ + IActiveScriptParse *parser; + HRESULT hres; + + /* Never allowed with security manager */ + parser = create_script(TRUE); + hres = parse_script_ae(parser, "Call GetObject(\"clsid:" TESTOBJINST_CLSID "\").reportSuccess()"); + ok(hres == VB_E_CANNOT_CREATE_OBJ, "hres = %08x\n", hres); + IActiveScriptParse_Release(parser); + + parser = create_script(FALSE); + + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(SetSite); + SET_EXPECT(reportSuccess); + hres = parse_script_ae(parser, "Call GetObject(\"clsid:" TESTOBJINST_CLSID "\").reportSuccess()"); + if(hres == 0x8007007e) { /* Workaround for broken win2k */ + win_skip("got unexpected error %08x\n", hres); + CLEAR_CALLED(QI_IObjectWithSite); + CLEAR_CALLED(SetSite); + CLEAR_CALLED(reportSuccess); + IActiveScriptParse_Release(parser); + return; + } + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(SetSite); + CHECK_CALLED(reportSuccess); + + SetSite_hres = E_FAIL; + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(SetSite); + hres = parse_script_ae(parser, "Call GetObject(\"clsid:" TESTOBJINST_CLSID "\").reportSuccess()"); + ok(hres == E_FAIL, "hres = %08x\n", hres); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(SetSite); + + QI_IObjectWithSite_hres = E_NOINTERFACE; + SET_EXPECT(QI_IObjectWithSite); + SET_EXPECT(reportSuccess); + parse_script_a(parser, "Call GetObject(\"clsid:" TESTOBJINST_CLSID "\").reportSuccess()"); + CHECK_CALLED(QI_IObjectWithSite); + CHECK_CALLED(reportSuccess); + + IActiveScriptParse_Release(parser); + + /* Invalid moniker */ + parser = create_script(FALSE); + hres = parse_script_ae(parser, "Call GetObject(\"nonexistent:test\").reportSuccess()"); + ok(hres == MK_E_SYNTAX, "hres = %08x\n", hres); + IActiveScriptParse_Release(parser); +} + +static BOOL init_key(const char *key_name, const char *def_value, BOOL init) +{ + HKEY hkey; + DWORD res; + + if(!init) { + RegDeleteKey(HKEY_CLASSES_ROOT, key_name); + return TRUE; + } + + res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey); + if(res != ERROR_SUCCESS) + return FALSE; + + if(def_value) + res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value)); + + RegCloseKey(hkey); + + return res == ERROR_SUCCESS; +} + +static BOOL init_registry(BOOL init) +{ + return init_key("Wine.Test\\CLSID", TESTOBJ_CLSID, init); +} + +static BOOL register_activex(void) +{ + DWORD regid; + HRESULT hres; + + if(!init_registry(TRUE)) { + init_registry(FALSE); + return FALSE; + } + + hres = CoRegisterClassObject(&CLSID_TestObj, (IUnknown *)&activex_cf, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); + ok(hres == S_OK, "Could not register script engine: %08x\n", hres); + + hres = CoRegisterClassObject(&CLSID_TestObjInst, (IUnknown *)&testObj, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); + ok(hres == S_OK, "Could not register script engine: %08x\n", hres); + + return TRUE; +} + +static BOOL check_vbscript(void) +{ + IActiveScriptParseProcedure2 *vbscript; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScriptParseProcedure2, (void**)&vbscript); + if(SUCCEEDED(hres)) + IActiveScriptParseProcedure2_Release(vbscript); + + return hres == S_OK; +} + + +START_TEST(createobj) +{ + CoInitialize(NULL); + + if(check_vbscript()) { + register_activex(); + + test_CreateObject(); + test_GetObject(); + + init_registry(FALSE); + }else { + win_skip("Broken engine, probably too old\n"); + } + + CoUninitialize(); +} diff --git a/rostests/winetests/vbscript/lang.vbs b/rostests/winetests/vbscript/lang.vbs new file mode 100644 index 00000000000..8cffc7fa9c8 --- /dev/null +++ b/rostests/winetests/vbscript/lang.vbs @@ -0,0 +1,975 @@ +' +' Copyright 2011 Jacek Caban for CodeWeavers +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +' + +Option Explicit + +dim x, y, z + +call ok(true, "true is not true?") +ok true, "true is not true?" +call ok((true), "true is not true?") + +ok not false, "not false but not true?" +ok not not true, "not not true but not true?" + +Call ok(true = true, "true = true is false") +Call ok(false = false, "false = false is false") +Call ok(not (true = false), "true = false is true") +Call ok("x" = "x", """x"" = ""x"" is false") +Call ok(empty = empty, "empty = empty is false") +Call ok(empty = "", "empty = """" is false") +Call ok(0 = 0.0, "0 <> 0.0") +Call ok(16 = &h10&, "16 <> &h10&") +Call ok(010 = 10, "010 <> 10") +Call ok(10. = 10, "10. <> 10") +Call ok(&hffFFffFF& = -1, "&hffFFffFF& <> -1") +Call ok(&hffFFffFF& = -1, "&hffFFffFF& <> -1") +Call ok(--1 = 1, "--1 = " & --1) +Call ok(-empty = 0, "-empty = " & (-empty)) +Call ok(true = -1, "! true = -1") +Call ok(false = 0, "false <> 0") +Call ok(&hff = 255, "&hff <> 255") +Call ok(&Hff = 255, "&Hff <> 255") + +x = "xx" +Call ok(x = "xx", "x = " & x & " expected ""xx""") + +Call ok(true <> false, "true <> false is false") +Call ok(not (true <> true), "true <> true is true") +Call ok(not ("x" <> "x"), """x"" <> ""x"" is true") +Call ok(not (empty <> empty), "empty <> empty is true") +Call ok(x <> "x", "x = ""x""") +Call ok("true" <> true, """true"" = true is true") + +Call ok("" = true = false, """"" = true = false is false") +Call ok(not(false = true = ""), "false = true = """" is true") +Call ok(not (false = false <> false = false), "false = false <> false = false is true") +Call ok(not ("" <> false = false), """"" <> false = false is true") + +Call ok(getVT(false) = "VT_BOOL", "getVT(false) is not VT_BOOL") +Call ok(getVT(true) = "VT_BOOL", "getVT(true) is not VT_BOOL") +Call ok(getVT("") = "VT_BSTR", "getVT("""") is not VT_BSTR") +Call ok(getVT("test") = "VT_BSTR", "getVT(""test"") is not VT_BSTR") +Call ok(getVT(Empty) = "VT_EMPTY", "getVT(Empty) is not VT_EMPTY") +Call ok(getVT(null) = "VT_NULL", "getVT(null) is not VT_NULL") +Call ok(getVT(0) = "VT_I2", "getVT(0) is not VT_I2") +Call ok(getVT(1) = "VT_I2", "getVT(1) is not VT_I2") +Call ok(getVT(0.5) = "VT_R8", "getVT(0.5) is not VT_R8") +Call ok(getVT(0.0) = "VT_R8", "getVT(0.0) is not VT_R8") +Call ok(getVT(2147483647) = "VT_I4", "getVT(2147483647) is not VT_I4") +Call ok(getVT(2147483648) = "VT_R8", "getVT(2147483648) is not VT_R8") +Call ok(getVT(&h10&) = "VT_I2", "getVT(&h10&) is not VT_I2") +Call ok(getVT(&h10000&) = "VT_I4", "getVT(&h10000&) is not VT_I4") +Call ok(getVT(&H10000&) = "VT_I4", "getVT(&H10000&) is not VT_I4") +Call ok(getVT(&hffFFffFF&) = "VT_I2", "getVT(&hffFFffFF&) is not VT_I2") +Call ok(getVT(1 & 100000) = "VT_BSTR", "getVT(1 & 100000) is not VT_BSTR") +Call ok(getVT(-empty) = "VT_I2", "getVT(-empty) = " & getVT(-empty)) +Call ok(getVT(-null) = "VT_NULL", "getVT(-null) = " & getVT(-null)) +Call ok(getVT(y) = "VT_EMPTY*", "getVT(y) = " & getVT(y)) +Call ok(getVT(nothing) = "VT_DISPATCH", "getVT(nothing) = " & getVT(nothing)) +set x = nothing +Call ok(getVT(x) = "VT_DISPATCH*", "getVT(x=nothing) = " & getVT(x)) +x = true +Call ok(getVT(x) = "VT_BOOL*", "getVT(x) = " & getVT(x)) +Call ok(getVT(false or true) = "VT_BOOL", "getVT(false) is not VT_BOOL") +x = "x" +Call ok(getVT(x) = "VT_BSTR*", "getVT(x) is not VT_BSTR*") +x = 0.0 +Call ok(getVT(x) = "VT_R8*", "getVT(x) = " & getVT(x)) + +Call ok(isNullDisp(nothing), "nothing is not nulldisp?") + +x = "xx" +Call ok("ab" & "cd" = "abcd", """ab"" & ""cd"" <> ""abcd""") +Call ok("ab " & null = "ab ", """ab"" & null = " & ("ab " & null)) +Call ok("ab " & empty = "ab ", """ab"" & empty = " & ("ab " & empty)) +Call ok(1 & 100000 = "1100000", "1 & 100000 = " & (1 & 100000)) +Call ok("ab" & x = "abxx", """ab"" & x = " & ("ab"&x)) + +if(isEnglishLang) then + Call ok("" & true = "True", """"" & true = " & true) + Call ok(true & false = "TrueFalse", "true & false = " & (true & false)) +end if + +call ok(true and true, "true and true is not true") +call ok(true and not false, "true and not false is not true") +call ok(not (false and true), "not (false and true) is not true") +call ok(getVT(null and true) = "VT_NULL", "getVT(null and true) = " & getVT(null and true)) + +call ok(false or true, "false or uie is false?") +call ok(not (false or false), "false or false is not false?") +call ok(false and false or true, "false and false or true is false?") +call ok(true or false and false, "true or false and false is false?") +call ok(null or true, "null or true is false") + +call ok(true xor false, "true xor false is false?") +call ok(not (false xor false), "false xor false is true?") +call ok(not (true or false xor true), "true or false xor true is true?") +call ok(not (true xor false or true), "true xor false or true is true?") + +call ok(false eqv false, "false does not equal false?") +call ok(not (false eqv true), "false equals true?") +call ok(getVT(false eqv null) = "VT_NULL", "getVT(false eqv null) = " & getVT(false eqv null)) + +call ok(true imp true, "true does not imp true?") +call ok(false imp false, "false does not imp false?") +call ok(not (true imp false), "true imp false?") +call ok(false imp null, "false imp null is false?") + +Call ok(2 >= 1, "! 2 >= 1") +Call ok(2 >= 2, "! 2 >= 2") +Call ok(not(true >= 2), "true >= 2 ?") +Call ok(2 > 1, "! 2 > 1") +Call ok(false > true, "! false < true") +Call ok(0 > true, "! 0 > true") +Call ok(not (true > 0), "true > 0") +Call ok(not (0 > 1 = 1), "0 > 1 = 1") +Call ok(1 < 2, "! 1 < 2") +Call ok(1 = 1 < 0, "! 1 = 1 < 0") +Call ok(1 <= 2, "! 1 <= 2") +Call ok(2 <= 2, "! 2 <= 2") + +Call ok(isNull(0 = null), "'(0 = null)' is not null") +Call ok(isNull(null = 1), "'(null = 1)' is not null") +Call ok(isNull(0 > null), "'(0 > null)' is not null") +Call ok(isNull(null > 1), "'(null > 1)' is not null") +Call ok(isNull(0 < null), "'(0 < null)' is not null") +Call ok(isNull(null < 1), "'(null < 1)' is not null") +Call ok(isNull(0 <> null), "'(0 <> null)' is not null") +Call ok(isNull(null <> 1), "'(null <> 1)' is not null") +Call ok(isNull(0 >= null), "'(0 >= null)' is not null") +Call ok(isNull(null >= 1), "'(null >= 1)' is not null") +Call ok(isNull(0 <= null), "'(0 <= null)' is not null") +Call ok(isNull(null <= 1), "'(null <= 1)' is not null") + +x = 3 +Call ok(2+2 = 4, "2+2 = " & (2+2)) +Call ok(false + 6 + true = 5, "false + 6 + true <> 5") +Call ok(getVT(2+null) = "VT_NULL", "getVT(2+null) = " & getVT(2+null)) +Call ok(2+empty = 2, "2+empty = " & (2+empty)) +Call ok(x+x = 6, "x+x = " & (x+x)) + +Call ok(5-1 = 4, "5-1 = " & (5-1)) +Call ok(3+5-true = 9, "3+5-true <> 9") +Call ok(getVT(2-null) = "VT_NULL", "getVT(2-null) = " & getVT(2-null)) +Call ok(2-empty = 2, "2-empty = " & (2-empty)) +Call ok(2-x = -1, "2-x = " & (2-x)) + +Call ok(9 Mod 6 = 3, "9 Mod 6 = " & (9 Mod 6)) +Call ok(11.6 Mod 5.5 = False, "11.6 Mod 5.5 = " & (11.6 Mod 5.5 = 0.6)) +Call ok(7 Mod 4+2 = 5, "7 Mod 4+2 <> 5") +Call ok(getVT(2 mod null) = "VT_NULL", "getVT(2 mod null) = " & getVT(2 mod null)) +Call ok(getVT(null mod 2) = "VT_NULL", "getVT(null mod 2) = " & getVT(null mod 2)) +'FIXME: Call ok(empty mod 2 = 0, "empty mod 2 = " & (empty mod 2)) + +Call ok(5 \ 2 = 2, "5 \ 2 = " & (5\2)) +Call ok(4.6 \ 1.5 = 2, "4.6 \ 1.5 = " & (4.6\1.5)) +Call ok(4.6 \ 1.49 = 5, "4.6 \ 1.49 = " & (4.6\1.49)) +Call ok(2+3\4 = 2, "2+3\4 = " & (2+3\4)) + +Call ok(2*3 = 6, "2*3 = " & (2*3)) +Call ok(3/2 = 1.5, "3/2 = " & (3/2)) +Call ok(5\4/2 = 2, "5\4/2 = " & (5\2/1)) +Call ok(12/3\2 = 2, "12/3\2 = " & (12/3\2)) + +Call ok(2^3 = 8, "2^3 = " & (2^3)) +Call ok(2^3^2 = 64, "2^3^2 = " & (2^3^2)) +Call ok(-3^2 = 9, "-3^2 = " & (-3^2)) +Call ok(2*3^2 = 18, "2*3^2 = " & (2*3^2)) + +x =_ + 3 +x _ + = 3 + +x = 3 + +if true then y = true : x = y +ok x, "x is false" + +x = true : if false then x = false +ok x, "x is false, if false called?" + +if not false then x = true +ok x, "x is false, if not false not called?" + +if not false then x = "test" : x = true +ok x, "x is false, if not false not called?" + +if false then x = y : call ok(false, "if false .. : called") + +if false then x = y : call ok(false, "if false .. : called") else x = "else" +Call ok(x = "else", "else not called?") + +if true then x = y else y = x : Call ok(false, "in else?") + +if false then : + +if false then x = y : if true then call ok(false, "embedded if called") + +if false then x=1 else x=2 end if + +if false then + ok false, "if false called" +end if + +x = true +if x then + x = false +end if +Call ok(not x, "x is false, if not evaluated?") + +x = false +If false Then + Call ok(false, "inside if false") +Else + x = true +End If +Call ok(x, "else not called?") + +x = false +If false Then + Call ok(false, "inside if false") +ElseIf not True Then + Call ok(false, "inside elseif not true") +Else + x = true +End If +Call ok(x, "else not called?") + +x = false +If false Then + Call ok(false, "inside if false") + x = 1 + y = 10+x +ElseIf not False Then + x = true +Else + Call ok(false, "inside else not true") +End If +Call ok(x, "elseif not called?") + +x = false +If false Then + Call ok(false, "inside if false") +ElseIf not False Then + x = true +End If +Call ok(x, "elseif not called?") + +x = false +if 1 then x = true +Call ok(x, "if 1 not run?") + +x = false +if &h10000& then x = true +Call ok(x, "if &h10000& not run?") + +x = false +y = false +while not (x and y) + if x then + y = true + end if + x = true +wend +call ok((x and y), "x or y is false after while") + +if false then +' empty body +end if + +if false then + x = false +elseif true then +' empty body +end if + +if false then + x = false +else +' empty body +end if + +while false +wend + +x = false +y = false +do while not (x and y) + if x then + y = true + end if + x = true +loop +call ok((x and y), "x or y is false after while") + +do while false +loop + +do while true + exit do + ok false, "exit do didn't work" +loop + +x = false +y = false +do until x and y + if x then + y = true + end if + x = true +loop +call ok((x and y), "x or y is false after do until") + +do until true +loop + +do until false + exit do + ok false, "exit do didn't work" +loop + +x = false +do + if x then exit do + x = true +loop +call ok(x, "x is false after do..loop?") + +x = false +y = false +do + if x then + y = true + end if + x = true +loop until x and y +call ok((x and y), "x or y is false after while") + +do +loop until true + +do + exit do + ok false, "exit do didn't work" +loop until false + +x = false +y = false +do + if x then + y = true + end if + x = true +loop while not (x and y) +call ok((x and y), "x or y is false after while") + +do +loop while false + +do + exit do + ok false, "exit do didn't work" +loop while true + +y = "for1:" +for x = 5 to 8 + y = y & " " & x +next +Call ok(y = "for1: 5 6 7 8", "y = " & y) + +y = "for2:" +for x = 5 to 8 step 2 + y = y & " " & x +next +Call ok(y = "for2: 5 7", "y = " & y) + +y = "for3:" +x = 2 +for x = x+3 to 8 + y = y & " " & x +next +Call ok(y = "for3: 5 6 7 8", "y = " & y) + +y = "for4:" +for x = 5 to 4 + y = y & " " & x +next +Call ok(y = "for4:", "y = " & y) + +y = "for5:" +for x = 5 to 3 step true + y = y & " " & x +next +Call ok(y = "for5: 5 4 3", "y = " & y) + +y = "for6:" +z = 4 +for x = 5 to z step 3-4 + y = y & " " & x + z = 0 +next +Call ok(y = "for6: 5 4", "y = " & y) + +y = "for7:" +z = 1 +for x = 5 to 8 step z + y = y & " " & x + z = 2 +next +Call ok(y = "for7: 5 6 7 8", "y = " & y) + +y = "for8:" +for x = 5 to 8 + y = y & " " & x + x = x+1 +next +Call ok(y = "for8: 5 7", "y = " & y) + +for x = 1.5 to 1 + Call ok(false, "for..to called when unexpected") +next + +for x = 1 to 100 + exit for + Call ok(false, "exit for not escaped the loop?") +next + +do while true + for x = 1 to 100 + exit do + next +loop + +if null then call ok(false, "if null evaluated") + +while null + call ok(false, "while null evaluated") +wend + +Call collectionObj.reset() +y = 0 +x = 10 +for each x in collectionObj + y = y+1 + Call ok(x = y, "x <> y") +next +Call ok(y = 3, "y = " & y) +Call ok(getVT(x) = "VT_EMPTY*", "getVT(x) = " & getVT(x)) + +Call collectionObj.reset() +y = false +for each x in collectionObj + if x = 2 then exit for + y = 1 +next +Call ok(y = 1, "y = " & y) +Call ok(x = 2, "x = " & x) + +x = false +select case 3 + case 2 + Call ok(false, "unexpected case") + case 2 + Call ok(false, "unexpected case") + case 4 + Call ok(false, "unexpected case") + case "test" + case "another case" + Call ok(false, "unexpected case") + case 0, false, 2+1, 10 + x = true + case ok(false, "unexpected case") + Call ok(false, "unexpected case") + case else + Call ok(false, "unexpected case") +end select +Call ok(x, "wrong case") + +x = false +select case 3 + case 3 + x = true +end select +Call ok(x, "wrong case") + +x = false +select case 2+2 + case 3 + Call ok(false, "unexpected case") + case else + x = true +end select +Call ok(x, "wrong case") + +y = "3" +x = false +select case y + case "3" + x = true + case 3 + Call ok(false, "unexpected case") +end select +Call ok(x, "wrong case") + +select case 0 + case 1 + Call ok(false, "unexpected case") + case "2" + Call ok(false, "unexpected case") +end select + +select case 0 +end select + +if false then +Sub testsub + x = true +End Sub +end if + +x = false +Call testsub +Call ok(x, "x is false, testsub not called?") + +Sub SubSetTrue(v) + Call ok(not v, "v is not true") + v = true +End Sub + +x = false +SubSetTrue x +Call ok(x, "x was not set by SubSetTrue") + +SubSetTrue false +Call ok(not false, "false is no longer false?") + +Sub SubSetTrue2(ByRef v) + Call ok(not v, "v is not true") + v = true +End Sub + +x = false +SubSetTrue2 x +Call ok(x, "x was not set by SubSetTrue") + +Sub TestSubArgVal(ByVal v) + Call ok(not v, "v is not false") + v = true + Call ok(v, "v is not true?") +End Sub + +x = false +Call TestSubArgVal(x) +Call ok(not x, "x is true after TestSubArgVal call?") + +Sub TestSubMultiArgs(a,b,c,d,e) + Call ok(a=1, "a = " & a) + Call ok(b=2, "b = " & b) + Call ok(c=3, "c = " & c) + Call ok(d=4, "d = " & d) + Call ok(e=5, "e = " & e) +End Sub + +Sub TestSubExit(ByRef a) + If a Then + Exit Sub + End If + Call ok(false, "Exit Sub not called?") +End Sub + +Call TestSubExit(true) + +Sub TestSubExit2 + for x = 1 to 100 + Exit Sub + next +End Sub +Call TestSubExit2 + +TestSubMultiArgs 1, 2, 3, 4, 5 +Call TestSubMultiArgs(1, 2, 3, 4, 5) + +Sub TestSubLocalVal + x = false + Call ok(not x, "local x is not false?") + Dim x + Dim a,b, c +End Sub + +x = true +y = true +Call TestSubLocalVal +Call ok(x, "global x is not true?") + +Public Sub TestPublicSub +End Sub +Call TestPublicSub + +Private Sub TestPrivateSub +End Sub +Call TestPrivateSub + +if false then +Function testfunc + x = true +End Function +end if + +x = false +Call TestFunc +Call ok(x, "x is false, testfunc not called?") + +Function FuncSetTrue(v) + Call ok(not v, "v is not true") + v = true +End Function + +x = false +FuncSetTrue x +Call ok(x, "x was not set by FuncSetTrue") + +FuncSetTrue false +Call ok(not false, "false is no longer false?") + +Function FuncSetTrue2(ByRef v) + Call ok(not v, "v is not true") + v = true +End Function + +x = false +FuncSetTrue2 x +Call ok(x, "x was not set by FuncSetTrue") + +Function TestFuncArgVal(ByVal v) + Call ok(not v, "v is not false") + v = true + Call ok(v, "v is not true?") +End Function + +x = false +Call TestFuncArgVal(x) +Call ok(not x, "x is true after TestFuncArgVal call?") + +Function TestFuncMultiArgs(a,b,c,d,e) + Call ok(a=1, "a = " & a) + Call ok(b=2, "b = " & b) + Call ok(c=3, "c = " & c) + Call ok(d=4, "d = " & d) + Call ok(e=5, "e = " & e) +End Function + +TestFuncMultiArgs 1, 2, 3, 4, 5 +Call TestFuncMultiArgs(1, 2, 3, 4, 5) + +Function TestFuncLocalVal + x = false + Call ok(not x, "local x is not false?") + Dim x +End Function + +x = true +y = true +Call TestFuncLocalVal +Call ok(x, "global x is not true?") + +Function TestFuncExit(ByRef a) + If a Then + Exit Function + End If + Call ok(false, "Exit Function not called?") +End Function + +Call TestFuncExit(true) + +Function TestFuncExit2(ByRef a) + For x = 1 to 100 + For y = 1 to 100 + Exit Function + Next + Next + Call ok(false, "Exit Function not called?") +End Function + +Call TestFuncExit2(true) + +Sub SubParseTest +End Sub : x = false +Call SubParseTest + +Function FuncParseTest +End Function : x = false + +Function ReturnTrue + ReturnTrue = false + ReturnTrue = true +End Function + +Call ok(ReturnTrue(), "ReturnTrue returned false?") + +Function SetVal(ByRef x, ByVal v) + x = v + SetVal = x + Exit Function +End Function + +x = false +ok SetVal(x, true), "SetVal returned false?" +Call ok(x, "x is not set to true by SetVal?") + +Public Function TestPublicFunc +End Function +Call TestPublicFunc + +Private Function TestPrivateFunc +End Function +Call TestPrivateFunc + +' Stop has an effect only in debugging mode +Stop + +set x = testObj +Call ok(getVT(x) = "VT_DISPATCH*", "getVT(x=testObj) = " & getVT(x)) + +Dim obj +Set obj = New EmptyClass +Call ok(getVT(obj) = "VT_DISPATCH*", "getVT(obj) = " & getVT(obj)) + +Class EmptyClass +End Class + +Set x = obj +Call ok(getVT(x) = "VT_DISPATCH*", "getVT(x) = " & getVT(x)) + +Class TestClass + Public publicProp + + Private privateProp + + Public Function publicFunction() + privateSub() + publicFunction = 4 + End Function + + Public Property Get gsProp() + gsProp = privateProp + funcCalled = "gsProp get" + exit property + Call ok(false, "exit property not returned?") + End Property + + Public Default Property Get DefValGet + DefValGet = privateProp + funcCalled = "GetDefVal" + End Property + + Public Property Let DefValGet(x) + End Property + + Public publicProp2 + + Public Sub publicSub + End Sub + + Public Property Let gsProp(val) + privateProp = val + funcCalled = "gsProp let" + exit property + Call ok(false, "exit property not returned?") + End Property + + Public Property Set gsProp(val) + funcCalled = "gsProp set" + exit property + Call ok(false, "exit property not returned?") + End Property + + Public Sub setPrivateProp(x) + privateProp = x + End Sub + + Function getPrivateProp + getPrivateProp = privateProp + End Function + + Private Sub privateSub + End Sub + + Public Sub Class_Initialize + publicProp2 = 2 + privateProp = true + End Sub +End Class + +Call testDisp(new testClass) + +Set obj = New TestClass + +Call ok(obj.publicFunction = 4, "obj.publicFunction = " & obj.publicFunction) +Call ok(obj.publicFunction() = 4, "obj.publicFunction() = " & obj.publicFunction()) + +obj.publicSub() +Call obj.publicSub +Call obj.publicFunction() + +Call ok(getVT(obj.publicProp) = "VT_EMPTY", "getVT(obj.publicProp) = " & getVT(obj.publicProp)) +obj.publicProp = 3 +Call ok(obj.publicProp = 3, "obj.publicProp = " & obj.publicProp) +obj.publicProp() = 3 + +Call ok(obj.getPrivateProp() = true, "obj.getPrivateProp() = " & obj.getPrivateProp()) +Call obj.setPrivateProp(6) +Call ok(obj.getPrivateProp = 6, "obj.getPrivateProp = " & obj.getPrivateProp) + +Dim funcCalled +funcCalled = "" +Call ok(obj.gsProp = 6, "obj.gsProp = " & obj.gsProp) +Call ok(funcCalled = "gsProp get", "funcCalled = " & funcCalled) +obj.gsProp = 3 +Call ok(funcCalled = "gsProp let", "funcCalled = " & funcCalled) +Call ok(obj.getPrivateProp = 3, "obj.getPrivateProp = " & obj.getPrivateProp) +Set obj.gsProp = New testclass +Call ok(funcCalled = "gsProp set", "funcCalled = " & funcCalled) + +x = obj +Call ok(x = 3, "(x = obj) = " & x) +Call ok(funcCalled = "GetDefVal", "funcCalled = " & funcCalled) +funcCalled = "" +Call ok(obj = 3, "(x = obj) = " & obj) +Call ok(funcCalled = "GetDefVal", "funcCalled = " & funcCalled) + +Call obj.Class_Initialize +Call ok(obj.getPrivateProp() = true, "obj.getPrivateProp() = " & obj.getPrivateProp()) + +x = (New testclass).publicProp + +Class TermTest + Public Sub Class_Terminate() + funcCalled = "terminate" + End Sub +End Class + +Set obj = New TermTest +funcCalled = "" +Set obj = Nothing +Call ok(funcCalled = "terminate", "funcCalled = " & funcCalled) + +Set obj = New TermTest +funcCalled = "" +Call obj.Class_Terminate +Call ok(funcCalled = "terminate", "funcCalled = " & funcCalled) +funcCalled = "" +Set obj = Nothing +Call ok(funcCalled = "terminate", "funcCalled = " & funcCalled) + +Call (New testclass).publicSub() +Call (New testclass).publicSub + +x = "following ':' is correct syntax" : +x = "following ':' is correct syntax" :: : +:: x = "also correct syntax" +rem another ugly way for comments +x = "rem as simplestatement" : rem rem comment +: + +Set obj = new EmptyClass +Set x = obj +Set y = new EmptyClass + +Call ok(obj is x, "obj is not x") +Call ok(x is obj, "x is not obj") +Call ok(not (obj is y), "obj is not y") +Call ok(not obj is y, "obj is not y") +Call ok(not (x is Nothing), "x is 1") +Call ok(Nothing is Nothing, "Nothing is not Nothing") +Call ok(x is obj and true, "x is obj and true is false") + +Class TestMe + Public Sub Test(MyMe) + Call ok(Me is MyMe, "Me is not MyMe") + End Sub +End Class + +Set obj = New TestMe +Call obj.test(obj) + +Call ok(getVT(test) = "VT_DISPATCH", "getVT(test) = " & getVT(test)) +Call ok(Me is Test, "Me is not Test") + +Const c1 = 1, c2 = 2, c3 = -3 +Call ok(c1 = 1, "c1 = " & c1) +Call ok(getVT(c1) = "VT_I2", "getVT(c1) = " & getVT(c1)) +Call ok(c3 = -3, "c3 = " & c3) +Call ok(getVT(c3) = "VT_I2", "getVT(c3) = " & getVT(c3)) + +Const cb = True, cs = "test", cnull = null +Call ok(cb, "cb = " & cb) +Call ok(getVT(cb) = "VT_BOOL", "getVT(cb) = " & getVT(cb)) +Call ok(cs = "test", "cs = " & cs) +Call ok(getVT(cs) = "VT_BSTR", "getVT(cs) = " & getVT(cs)) +Call ok(isNull(cnull), "cnull = " & cnull) +Call ok(getVT(cnull) = "VT_NULL", "getVT(cnull) = " & getVT(cnull)) + +if false then Const conststr = "str" +Call ok(conststr = "str", "conststr = " & conststr) +Call ok(getVT(conststr) = "VT_BSTR", "getVT(conststr) = " & getVT(conststr)) +Call ok(conststr = "str", "conststr = " & conststr) + +Sub ConstTestSub + Const funcconst = 1 + Call ok(c1 = 1, "c1 = " & c1) + Call ok(funcconst = 1, "funcconst = " & funcconst) +End Sub + +Call ConstTestSub +Dim funcconst + +' Property may be used as an identifier (although it's a keyword) +Sub TestProperty + Dim Property + PROPERTY = true + Call ok(property, "property = " & property) + + for property = 1 to 2 + next +End Sub + +Call TestProperty + +Class Property + Public Sub Property() + End Sub + + Sub Test(byref property) + End Sub +End Class + +Class Property2 + Function Property() + End Function + + + Sub Test(property) + End Sub + + Sub Test2(byval property) + End Sub +End Class + +reportSuccess() diff --git a/rostests/winetests/vbscript/regexp.vbs b/rostests/winetests/vbscript/regexp.vbs new file mode 100644 index 00000000000..72fa108a7e0 --- /dev/null +++ b/rostests/winetests/vbscript/regexp.vbs @@ -0,0 +1,171 @@ +' +' Copyright 2013 Piotr Caban for CodeWeavers +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY; without even the implied warranty of +' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +' + +Option Explicit + +Dim x, matches, match, submatch + +Set x = CreateObject("vbscript.regexp") +Call ok(getVT(x.Pattern) = "VT_BSTR", "getVT(RegExp.Pattern) = " & getVT(x.Pattern)) +Call ok(x.Pattern = "", "RegExp.Pattern = " & x.Pattern) +Call ok(getVT(x.IgnoreCase) = "VT_BOOL", "getVT(RegExp.IgnoreCase) = " & getVT(x.IgnoreCase)) +Call ok(x.IgnoreCase = false, "RegExp.IgnoreCase = " & x.IgnoreCase) +Call ok(getVT(x.Global) = "VT_BOOL", "getVT(RegExp.Global) = " & getVT(x.Global)) +Call ok(x.Global = false, "RegExp.Global = " & x.Global) +Call ok(getVT(x.Multiline) = "VT_BOOL", "getVT(RegExp.Multiline) = " & getVT(x.Multiline)) +Call ok(x.Multiline = false, "RegExp.Multiline = " & x.Multiline) + +x.Pattern = "a+" +matches = x.Test(" aabaaa") +Call ok(matches = true, "RegExp.Test returned: " & matches) +Set matches = x.Execute(" aabaaa") +Call ok(getVT(matches.Count) = "VT_I4", "getVT(matches.Count) = " & getVT(matches.Count)) +Call ok(matches.Count = 1, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "aa", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 1, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Global = true +Set matches = x.Execute(" aabaaa") +Call ok(matches.Count = 2, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "aa", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 1, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) +Set match = matches.Item(1) +Call ok(match.Value = "aaa", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 4, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 3, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +Set matches = x.Execute(" aabaaa") +Call ok(matches.Count = 2, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "aa", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 1, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Pattern = "^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$" +x.Global = false +Set matches = x.Execute("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") +Call ok(matches.Count = 0, "matches.Count = " & matches.Count) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Pattern = "(a|b)+|(c)" +Set matches = x.Execute("aa") +Call ok(matches.Count = 1, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "aa", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 0, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 2, "submatch.Count = " & submatch.Count) +Call ok(getVT(submatch.Item(0)) = "VT_BSTR", "getVT(submatch.Item(0)) = " & getVT(submatch.Item(0))) +Call ok(submatch.Item(0) = "a", "submatch.Item(0) = " & submatch.Item(0)) +Call ok(getVT(submatch.Item(1)) = "VT_EMPTY", "getVT(submatch.Item(1)) = " & getVT(submatch.Item(1))) +Call ok(submatch.Item(1) = "", "submatch.Item(0) = " & submatch.Item(1)) + +matches = x.Test(" a ") +Call ok(matches = true, "RegExp.Test returned: " & matches) +matches = x.Test(" a ") +Call ok(matches = true, "RegExp.Test returned: " & matches) + +x.Pattern = "\[([^\[]+)\]" +x.Global = true +Set matches = x.Execute(" [test] ") +Call ok(matches.Count = 1, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "[test]", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 1, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 6, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 1, "submatch.Count = " & submatch.Count) +Call ok(submatch.Item(0) = "test", "submatch.Item(0) = " & submatch.Item(0)) + +x.Pattern = "Ab" +x.IgnoreCase = true +Set matches = x.Execute("abcaBc") +Call ok(matches.Count = 2, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "ab", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 0, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) +Set match = matches.Item(1) +Call ok(match.Value = "aB", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 3, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Pattern = "a+b" +x.IgnoreCase = false +Set matches = x.Execute("aaabcabc") +Call ok(matches.Count = 2, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "aaab", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 0, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 4, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) +Set match = matches.Item(1) +Call ok(match.Value = "ab", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 5, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 2, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Pattern = "\\" +Set matches = x.Execute("aaa\\cabc") +Call ok(matches.Count = 2, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "\", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 3, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 1, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) +Set match = matches.Item(1) +Call ok(match.Value = "\", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 4, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 1, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 0, "submatch.Count = " & submatch.Count) + +x.Pattern = "(a)(b)cabc" +Set matches = x.Execute("abcabc") +Call ok(matches.Count = 1, "matches.Count = " & matches.Count) +Set match = matches.Item(0) +Call ok(match.Value = "abcabc", "match.Value = " & match.Value) +Call ok(match.FirstIndex = 0, "match.FirstIndex = " & match.FirstIndex) +Call ok(match.Length = 6, "match.Length = " & match.Length) +Set submatch = match.SubMatches +Call ok(submatch.Count = 2, "submatch.Count = " & submatch.Count) +Call ok(submatch.Item(0) = "a", "submatch.Item(0) = " & submatch.Item(0)) +Call ok(submatch.Item(1) = "b", "submatch.Item(0) = " & submatch.Item(1)) + +Call reportSuccess() diff --git a/rostests/winetests/vbscript/rsrc.rc b/rostests/winetests/vbscript/rsrc.rc new file mode 100644 index 00000000000..1fb34407e66 --- /dev/null +++ b/rostests/winetests/vbscript/rsrc.rc @@ -0,0 +1,26 @@ +/* + * Copyright 2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* @makedep: api.vbs */ +api.vbs 40 "api.vbs" + +/* @makedep: lang.vbs */ +lang.vbs 40 "lang.vbs" + +/* @makedep: regexp.vbs */ +regexp.vbs 40 "regexp.vbs" diff --git a/rostests/winetests/vbscript/run.c b/rostests/winetests/vbscript/run.c new file mode 100644 index 00000000000..e471b44612f --- /dev/null +++ b/rostests/winetests/vbscript/run.c @@ -0,0 +1,1985 @@ +/* + * Copyright 2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + +#define COBJMACROS +#define CONST_VTABLE + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_64_ParseProcedureText + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_32_ParseProcedureText + +#endif + +extern const CLSID CLSID_VBScript; +extern const CLSID CLSID_VBScriptRegExp; + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define CLEAR_CALLED(func) \ + expect_ ## func = called_ ## func = FALSE + +DEFINE_EXPECT(global_success_d); +DEFINE_EXPECT(global_success_i); +DEFINE_EXPECT(global_vbvar_d); +DEFINE_EXPECT(global_vbvar_i); +DEFINE_EXPECT(testobj_propget_d); +DEFINE_EXPECT(testobj_propget_i); +DEFINE_EXPECT(testobj_propput_d); +DEFINE_EXPECT(testobj_propput_i); +DEFINE_EXPECT(global_propargput_d); +DEFINE_EXPECT(global_propargput_i); +DEFINE_EXPECT(global_propargput1_d); +DEFINE_EXPECT(global_propargput1_i); +DEFINE_EXPECT(collectionobj_newenum_i); +DEFINE_EXPECT(Next); +DEFINE_EXPECT(GetWindow); +DEFINE_EXPECT(GetUIBehavior); +DEFINE_EXPECT(EnableModeless); + +#define DISPID_GLOBAL_REPORTSUCCESS 1000 +#define DISPID_GLOBAL_TRACE 1001 +#define DISPID_GLOBAL_OK 1002 +#define DISPID_GLOBAL_GETVT 1003 +#define DISPID_GLOBAL_ISENGLANG 1004 +#define DISPID_GLOBAL_VBVAR 1005 +#define DISPID_GLOBAL_TESTOBJ 1006 +#define DISPID_GLOBAL_ISNULLDISP 1007 +#define DISPID_GLOBAL_TESTDISP 1008 +#define DISPID_GLOBAL_REFOBJ 1009 +#define DISPID_GLOBAL_COUNTER 1010 +#define DISPID_GLOBAL_PROPARGPUT 1011 +#define DISPID_GLOBAL_PROPARGPUT1 1012 +#define DISPID_GLOBAL_COLLOBJ 1013 +#define DISPID_GLOBAL_DOUBLEASSTRING 1014 + +#define DISPID_TESTOBJ_PROPGET 2000 +#define DISPID_TESTOBJ_PROPPUT 2001 + +#define DISPID_COLLOBJ_RESET 3000 + +static const WCHAR testW[] = {'t','e','s','t',0}; +static const WCHAR emptyW[] = {0}; + +static BOOL strict_dispid_check, is_english, allow_ui; +static const char *test_name = "(null)"; +static int test_counter; +static SCRIPTUICHANDLING uic_handling = SCRIPTUICHANDLING_NOUIERROR; + +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len-1); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + +static int strcmp_wa(LPCWSTR strw, const char *stra) +{ + CHAR buf[512]; + WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), 0, 0); + 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)) { + static char buf[64]; + sprintf(buf, "%s*", vt2a(V_BYREF(v))); + return buf; + } + + switch(V_VT(v)) { + case VT_EMPTY: + return "VT_EMPTY"; + case VT_NULL: + return "VT_NULL"; + case VT_I2: + return "VT_I2"; + case VT_I4: + return "VT_I4"; + case VT_R8: + return "VT_R8"; + case VT_DATE: + return "VT_DATE"; + case VT_BSTR: + return "VT_BSTR"; + case VT_DISPATCH: + return "VT_DISPATCH"; + case VT_BOOL: + return "VT_BOOL"; + case VT_ARRAY|VT_VARIANT: + return "VT_ARRAY|VT_VARIANT"; + default: + ok(0, "unknown vt %d\n", V_VT(v)); + return NULL; + } +} + +/* Returns true if the user interface is in English. Note that this does not + * presume of the formatting of dates, numbers, etc. + */ +static BOOL is_lang_english(void) +{ + static HMODULE hkernel32 = NULL; + static LANGID (WINAPI *pGetThreadUILanguage)(void) = NULL; + static LANGID (WINAPI *pGetUserDefaultUILanguage)(void) = NULL; + + if (!hkernel32) + { + hkernel32 = GetModuleHandleA("kernel32.dll"); + pGetThreadUILanguage = (void*)GetProcAddress(hkernel32, "GetThreadUILanguage"); + pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage"); + } + if (pGetThreadUILanguage && PRIMARYLANGID(pGetThreadUILanguage()) != LANG_ENGLISH) + return FALSE; + if (pGetUserDefaultUILanguage && PRIMARYLANGID(pGetUserDefaultUILanguage()) != LANG_ENGLISH) + return FALSE; + + return PRIMARYLANGID(GetUserDefaultLangID()) == LANG_ENGLISH; +} + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, + REFIID riid, void **ppv) +{ + ok(0, "unexpected service %s\n", debugstr_guid(guidService)); + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +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 named_args[5] = {DISPID_PROPERTYPUT}; + VARIANT v, args[5]; + DISPPARAMS dp = {args, named_args}; + IDispatchEx *dispex; + EXCEPINFO ei = {0}; + BSTR str; + HRESULT hres; + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + + str = a2bstr("publicProp"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_prop_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp) failed: %08x\n", hres); + + str = a2bstr("PUBLICPROP"); + hres = IDispatchEx_GetDispID(dispex, str, 0, &id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(PUBLICPROP) failed: %08x\n", hres); + ok(public_prop_id == id, "id = %d\n", public_prop_id); + + str = a2bstr("publicPROP2"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_prop2_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp2) failed: %08x\n", hres); + + str = a2bstr("defValGet"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &defvalget_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(defValGet) failed: %08x\n", hres); + ok(defvalget_id == DISPID_VALUE, "id = %d\n", defvalget_id); + + str = a2bstr("privateProp"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &id); + SysFreeString(str); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateProp) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres); + ok(id == -1, "id = %d\n", id); + + str = a2bstr("class_initialize"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp2) failed: %08x\n", hres); + + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_TRUE; + dp.cArgs = dp.cNamedArgs = 1; + V_VT(&v) = VT_BOOL; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYPUT, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_prop_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_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); + 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 = 1; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == DISP_E_MEMBERNOTFOUND, "InvokeEx failed: %08x, expected DISP_E_MEMBERNOTFOUND\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_FALSE; + dp.cArgs = 1; + V_VT(&v) = VT_BOOL; + hres = IDispatchEx_InvokeEx(dispex, public_prop_id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); + ok(hres == DISP_E_PARAMNOTOPTIONAL, "InvokeEx failed: %08x, expected DISP_E_PARAMNOTOPTIONAL\n", hres); + + str = a2bstr("publicFunction"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_func_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicFunction) failed: %08x\n", hres); + ok(public_func_id != -1, "public_func_id = -1\n"); + + str = a2bstr("publicSub"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &public_sub_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicSub) failed: %08x\n", hres); + ok(public_sub_id != -1, "public_func_id = -1\n"); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_func_id, 0, DISPATCH_PROPERTYGET|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_func_id, 0, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL); + ok(hres == DISP_E_MEMBERNOTFOUND, "InvokeEx failed: %08x, expected DISP_E_MEMBERNOTFOUND\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_func_id, 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); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL); + ok(hres == DISP_E_MEMBERNOTFOUND, "InvokeEx failed: %08x, expected DISP_E_MEMBERNOTFOUND\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + V_VT(args) = VT_BOOL; + V_BOOL(args) = VARIANT_TRUE; + dp.cArgs = dp.cNamedArgs = 1; + hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL); + ok(FAILED(hres), "InvokeEx succeeded: %08x\n", hres); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_func_id, 0, DISPATCH_PROPERTYGET|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_func_id, 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); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + dp.cArgs = dp.cNamedArgs = 0; + hres = IDispatchEx_InvokeEx(dispex, public_sub_id, 0, DISPATCH_METHOD, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_EMPTY, "V_VT(v) = %d\n", V_VT(&v)); + + str = a2bstr("privateSub"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive, &id); + SysFreeString(str); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateSub) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres); + ok(id == -1, "id = %d\n", id); + + str = a2bstr("dynprop"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseInsensitive|fdexNameEnsure, &id); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateProp) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres); + ok(id == -1, "id = %d\n", id); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure, &id); + ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(privateProp) failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres); + ok(id == -1, "id = %d\n", id); + SysFreeString(str); + + str = a2bstr("publicProp"); + hres = IDispatchEx_GetDispID(dispex, str, 0x80000000|fdexNameCaseInsensitive, &public_prop_id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp) failed: %08x\n", hres); + + id = 0xdeadbeef; + str = a2bstr("publicProp"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp) failed: %08x\n", hres); + ok(id == public_prop_id, "id = %d, expected %d\n", id, public_prop_id); + + id = 0xdeadbeef; + str = a2bstr("publicprop"); + hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id); + SysFreeString(str); + ok(hres == S_OK, "GetDispID(publicProp) failed: %08x\n", hres); + ok(id == public_prop_id, "id = %d, expected %d\n", id, public_prop_id); + + IDispatchEx_Release(dispex); +} + +#define test_grfdex(a,b) _test_grfdex(__LINE__,a,b) +static void _test_grfdex(unsigned line, DWORD grfdex, DWORD expect) +{ + ok_(__FILE__,line)(grfdex == expect, "grfdex = %x, expected %x\n", grfdex, expect); +} + +static IDispatchEx enumDisp; + +static HRESULT WINAPI EnumVARIANT_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumVARIANT)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(riid, &IID_IDispatch)) { + *ppv = &enumDisp; + return S_OK; + } + + ok(0, "unexpected call %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI EnumVARIANT_AddRef(IEnumVARIANT *iface) +{ + return 2; +} + +static ULONG WINAPI EnumVARIANT_Release(IEnumVARIANT *iface) +{ + return 1; +} + +static unsigned next_cnt; + +static HRESULT WINAPI EnumVARIANT_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) +{ + if(strict_dispid_check) + CHECK_EXPECT2(Next); + + ok(celt == 1, "celt = %d\n", celt); + ok(V_VT(rgVar) == VT_EMPTY, "V_VT(rgVar) = %d\n", V_VT(rgVar)); + ok(!pCeltFetched, "pCeltFetched = %p\n", pCeltFetched); + + if(next_cnt++ < 3) { + V_VT(rgVar) = VT_I2; + V_I2(rgVar) = next_cnt; + return S_OK; + } + + return S_FALSE; +} + +static HRESULT WINAPI EnumVARIANT_Skip(IEnumVARIANT *iface, ULONG celt) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumVARIANT_Reset(IEnumVARIANT *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumVARIANT_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IEnumVARIANTVtbl EnumVARIANTVtbl = { + EnumVARIANT_QueryInterface, + EnumVARIANT_AddRef, + EnumVARIANT_Release, + EnumVARIANT_Next, + EnumVARIANT_Skip, + EnumVARIANT_Reset, + EnumVARIANT_Clone +}; + +static IEnumVARIANT enumObj = { &EnumVARIANTVtbl }; + +static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IDispatch) + || IsEqualGUID(riid, &IID_IDispatchEx)) + *ppv = iface; + else { + trace("QI %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +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_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) +{ + ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); + 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 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) +{ + ok(0, "unexpected call %d\n", id); + return E_NOTIMPL; +} + +static HRESULT WINAPI testObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "propget")) { + CHECK_EXPECT(testobj_propget_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_TESTOBJ_PROPGET; + return S_OK; + } + if(!strcmp_wa(bstrName, "propput")) { + CHECK_EXPECT(testobj_propput_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_TESTOBJ_PROPPUT; + return S_OK; + } + + ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); + return DISP_E_UNKNOWNNAME; +} + +static HRESULT WINAPI testObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_TESTOBJ_PROPGET: + CHECK_EXPECT(testobj_propget_i); + + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_I2; + V_I2(pvarRes) = 10; + return S_OK; + case DISPID_TESTOBJ_PROPPUT: + CHECK_EXPECT(testobj_propput_i); + + ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 1, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg)); + return S_OK; + } + + ok(0, "unexpected call %d\n", id); + return E_FAIL; +} + +static IDispatchExVtbl testObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + testObj_GetDispID, + testObj_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx testObj = { &testObjVtbl }; + +static HRESULT WINAPI enumDisp_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) +{ + return IEnumVARIANT_QueryInterface(&enumObj, riid, ppv); +} + +static IDispatchExVtbl enumDispVtbl = { + enumDisp_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 enumDisp = { &enumDispVtbl }; + +static HRESULT WINAPI collectionObj_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "reset")) { + *pid = DISPID_COLLOBJ_RESET; + return S_OK; + } + + ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName)); + return DISP_E_UNKNOWNNAME; +} + +static HRESULT WINAPI collectionObj_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_NEWENUM: + if(strict_dispid_check) + CHECK_EXPECT(collectionobj_newenum_i); + + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_UNKNOWN; + V_UNKNOWN(pvarRes) = (IUnknown*)&enumObj; + return S_OK; + case DISPID_COLLOBJ_RESET: + next_cnt = 0; + return S_OK; + } + + ok(0, "unexpected call %d\n", id); + return E_NOTIMPL; +} + +static IDispatchExVtbl collectionObjVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + collectionObj_GetDispID, + collectionObj_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx collectionObj = { &collectionObjVtbl }; + +static ULONG refobj_ref; + +static ULONG WINAPI RefObj_AddRef(IDispatchEx *iface) +{ + return ++refobj_ref; +} + +static ULONG WINAPI RefObj_Release(IDispatchEx *iface) +{ + return --refobj_ref; +} + +static IDispatchExVtbl RefObjVtbl = { + DispatchEx_QueryInterface, + RefObj_AddRef, + RefObj_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 RefObj = { &RefObjVtbl }; + +static HRESULT WINAPI Global_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) +{ + if(!strcmp_wa(bstrName, "ok")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_OK; + return S_OK; + } + if(!strcmp_wa(bstrName, "trace")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_TRACE; + return S_OK; + } + if(!strcmp_wa(bstrName, "reportSuccess")) { + CHECK_EXPECT(global_success_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_REPORTSUCCESS; + return S_OK; + } + if(!strcmp_wa(bstrName, "getVT")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_GETVT; + return S_OK; + } + if(!strcmp_wa(bstrName, "isEnglishLang")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_ISENGLANG; + return S_OK; + } + if(!strcmp_wa(bstrName, "testObj")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_TESTOBJ; + return S_OK; + } + if(!strcmp_wa(bstrName, "collectionObj")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_COLLOBJ; + return S_OK; + } + if(!strcmp_wa(bstrName, "vbvar")) { + CHECK_EXPECT(global_vbvar_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_VBVAR; + return S_OK; + } + if(!strcmp_wa(bstrName, "isNullDisp")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_ISNULLDISP; + return S_OK; + } + if(!strcmp_wa(bstrName, "testDisp")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_TESTDISP; + return S_OK; + } + if(!strcmp_wa(bstrName, "RefObj")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_REFOBJ; + return S_OK; + } + if(!strcmp_wa(bstrName, "propargput")) { + CHECK_EXPECT(global_propargput_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_PROPARGPUT; + return S_OK; + } + if(!strcmp_wa(bstrName, "propargput1")) { + CHECK_EXPECT(global_propargput1_d); + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_PROPARGPUT1; + return S_OK; + } + if(!strcmp_wa(bstrName, "counter")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_COUNTER; + return S_OK; + } + if(!strcmp_wa(bstrName, "doubleAsString")) { + test_grfdex(grfdex, fdexNameCaseInsensitive); + *pid = DISPID_GLOBAL_DOUBLEASSTRING; + return S_OK; + } + + if(strict_dispid_check && strcmp_wa(bstrName, "x")) + ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); + return DISP_E_UNKNOWNNAME; +} + +static HRESULT WINAPI Global_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + switch(id) { + case DISPID_GLOBAL_OK: { + VARIANT *b; + + ok(wFlags == INVOKE_FUNC || wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "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); + if(wFlags & INVOKE_PROPERTYGET) + ok(pvarRes != NULL, "pvarRes == NULL\n"); + else + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + + b = pdp->rgvarg+1; + if(V_VT(b) == (VT_BYREF|VT_VARIANT)) + b = V_BYREF(b); + + ok(V_VT(b) == VT_BOOL, "V_VT(b) = %d\n", V_VT(b)); + + ok(V_BOOL(b), "%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + return S_OK; + } + + 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"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 1, "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_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + if(V_VT(pdp->rgvarg) == VT_BSTR) + trace("%s: %s\n", test_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg))); + + return S_OK; + + case DISPID_GLOBAL_REPORTSUCCESS: + CHECK_EXPECT(global_success_i); + + ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + return S_OK; + + case DISPID_GLOBAL_GETVT: + 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(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_BSTR; + V_BSTR(pvarRes) = a2bstr(vt2a(pdp->rgvarg)); + return S_OK; + + case DISPID_GLOBAL_ISENGLANG: + ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = is_english ? VARIANT_TRUE : VARIANT_FALSE; + return S_OK; + + case DISPID_GLOBAL_VBVAR: + CHECK_EXPECT(global_vbvar_i); + + ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 3, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg)); + return S_OK; + + case DISPID_GLOBAL_TESTOBJ: + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)&testObj; + return S_OK; + + case DISPID_GLOBAL_COLLOBJ: + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg != NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)&collectionObj; + return S_OK; + + case DISPID_GLOBAL_REFOBJ: + ok(wFlags == (DISPATCH_PROPERTYGET|DISPATCH_METHOD), "wFlags = %x\n", wFlags); + + ok(pdp != NULL, "pdp == NULL\n"); + ok(!pdp->rgvarg, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + IDispatchEx_AddRef(&RefObj); + V_VT(pvarRes) = VT_DISPATCH; + V_DISPATCH(pvarRes) = (IDispatch*)&RefObj; + return S_OK; + + case DISPID_GLOBAL_ISNULLDISP: { + VARIANT *v; + + ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "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(pvarRes != NULL, "pvarRes == NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + v = pdp->rgvarg; + if(V_VT(v) == (VT_VARIANT|VT_BYREF)) + v = V_VARIANTREF(v); + + ok(V_VT(v) == VT_DISPATCH, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + V_VT(pvarRes) = VT_BOOL; + V_BOOL(pvarRes) = V_DISPATCH(v) ? VARIANT_FALSE : VARIANT_TRUE; + return S_OK; + } + + case DISPID_GLOBAL_TESTDISP: + 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 == 1, "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_DISPATCH, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + test_disp(V_DISPATCH(pdp->rgvarg)); + return S_OK; + + case DISPID_GLOBAL_PROPARGPUT: + CHECK_EXPECT(global_propargput_i); + + ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cArgs == 3, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 0, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg)); + + ok(V_VT(pdp->rgvarg+1) == VT_I2, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg+1)); + ok(V_I2(pdp->rgvarg+1) == 2, "V_I2(psp->rgvargs+1) = %d\n", V_I2(pdp->rgvarg+1)); + + ok(V_VT(pdp->rgvarg+2) == VT_I2, "V_VT(psp->rgvargs+2) = %d\n", V_VT(pdp->rgvarg+2)); + ok(V_I2(pdp->rgvarg+2) == 1, "V_I2(psp->rgvargs+2) = %d\n", V_I2(pdp->rgvarg+2)); + return S_OK; + + case DISPID_GLOBAL_PROPARGPUT1: + CHECK_EXPECT(global_propargput1_i); + + ok(wFlags == DISPATCH_PROPERTYPUT, "wFlags = %x\n", wFlags); + ok(pdp != NULL, "pdp == NULL\n"); + ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(pdp->rgdispidNamedArgs != NULL, "rgdispidNamedArgs == NULL\n"); + ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs); + ok(pdp->cNamedArgs == 1, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pdp->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT, "pdp->rgdispidNamedArgs[0] = %d\n", pdp->rgdispidNamedArgs[0]); + ok(!pvarRes, "pvarRes != NULL\n"); + ok(pei != NULL, "pei == NULL\n"); + + ok(V_VT(pdp->rgvarg) == VT_I2, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg)); + ok(V_I2(pdp->rgvarg) == 0, "V_I2(psp->rgvargs) = %d\n", V_I2(pdp->rgvarg)); + + ok(V_VT(pdp->rgvarg+1) == VT_I2, "V_VT(psp->rgvargs+1) = %d\n", V_VT(pdp->rgvarg+1)); + ok(V_I2(pdp->rgvarg+1) == 1, "V_I2(psp->rgvargs+1) = %d\n", V_I2(pdp->rgvarg+1)); + + return S_OK; + + case DISPID_GLOBAL_COUNTER: + ok(pdp != NULL, "pdp == NULL\n"); + todo_wine ok(pdp->rgvarg != NULL, "rgvarg == NULL\n"); + ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n"); + ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs); + ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes)); + ok(pei != NULL, "pei == NULL\n"); + + V_VT(pvarRes) = VT_I2; + V_I2(pvarRes) = test_counter++; + return S_OK; + + case DISPID_GLOBAL_DOUBLEASSTRING: + ok(wFlags == (INVOKE_FUNC|INVOKE_PROPERTYGET), "wFlags = %x\n", wFlags); + ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs); + ok(V_VT(pdp->rgvarg) == VT_R8, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); + ok(pvarRes != NULL, "pvarRes == NULL\n"); + + V_VT(pvarRes) = VT_BSTR; + return VarBstrFromR8(V_R8(pdp->rgvarg), 0, 0, &V_BSTR(pvarRes)); + } + + ok(0, "unexpected call %d\n", id); + return DISP_E_MEMBERNOTFOUND; +} + +static IDispatchExVtbl GlobalVtbl = { + DispatchEx_QueryInterface, + DispatchEx_AddRef, + DispatchEx_Release, + DispatchEx_GetTypeInfoCount, + DispatchEx_GetTypeInfo, + DispatchEx_GetIDsOfNames, + DispatchEx_Invoke, + Global_GetDispID, + Global_InvokeEx, + DispatchEx_DeleteMemberByName, + DispatchEx_DeleteMemberByDispID, + DispatchEx_GetMemberProperties, + DispatchEx_GetMemberName, + DispatchEx_GetNextDispID, + DispatchEx_GetNameSpaceParent +}; + +static IDispatchEx Global = { &GlobalVtbl }; + +static HRESULT WINAPI ActiveScriptSiteWindow_QueryInterface(IActiveScriptSiteWindow *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ActiveScriptSiteWindow_AddRef(IActiveScriptSiteWindow *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSiteWindow_Release(IActiveScriptSiteWindow *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSiteWindow_GetWindow(IActiveScriptSiteWindow *iface, HWND *phwnd) +{ + if(!allow_ui) + CHECK_EXPECT(GetWindow); + *phwnd = NULL; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSiteWindow_EnableModeless(IActiveScriptSiteWindow *iface, BOOL fEnable) +{ + if(allow_ui) + return S_OK; + + CHECK_EXPECT(EnableModeless); + ok(!fEnable, "fEnable = %x\n", fEnable); + return E_FAIL; +} + +static const IActiveScriptSiteWindowVtbl ActiveScriptSiteWindowVtbl = { + ActiveScriptSiteWindow_QueryInterface, + ActiveScriptSiteWindow_AddRef, + ActiveScriptSiteWindow_Release, + ActiveScriptSiteWindow_GetWindow, + ActiveScriptSiteWindow_EnableModeless +}; + +static IActiveScriptSiteWindow ActiveScriptSiteWindow = { &ActiveScriptSiteWindowVtbl }; + +static HRESULT WINAPI ActiveScriptSiteUIControl_QueryInterface(IActiveScriptSiteUIControl *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ActiveScriptSiteUIControl_AddRef(IActiveScriptSiteUIControl *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSiteUIControl_Release(IActiveScriptSiteUIControl *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSiteUIControl_GetUIBehavior(IActiveScriptSiteUIControl *iface, SCRIPTUICITEM UicItem, + SCRIPTUICHANDLING *pUicHandling) +{ + if(!allow_ui) { + CHECK_EXPECT(GetUIBehavior); + ok(UicItem == SCRIPTUICITEM_MSGBOX, "UidItem = %d\n", UicItem); + } + *pUicHandling = uic_handling; + return S_OK; +} + +static const IActiveScriptSiteUIControlVtbl ActiveScriptSiteUIControlVtbl = { + ActiveScriptSiteUIControl_QueryInterface, + ActiveScriptSiteUIControl_AddRef, + ActiveScriptSiteUIControl_Release, + ActiveScriptSiteUIControl_GetUIBehavior +}; + +static IActiveScriptSiteUIControl ActiveScriptSiteUIControl = { &ActiveScriptSiteUIControlVtbl }; + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) + *ppv = iface; + else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) + *ppv = iface; + else if(IsEqualGUID(&IID_IActiveScriptSiteWindow, riid)) + *ppv = &ActiveScriptSiteWindow; + else if(IsEqualGUID(&IID_IActiveScriptSiteUIControl, riid)) + *ppv = &ActiveScriptSiteUIControl; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + *plcid = GetUserDefaultLCID(); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(dwReturnMask == SCRIPTINFO_IUNKNOWN, "unexpected dwReturnMask %x\n", dwReturnMask); + ok(!ppti, "ppti != NULL\n"); + + if(strcmp_wa(pstrName, "test")) + ok(0, "unexpected pstrName %s\n", wine_dbgstr_w(pstrName)); + + *ppiunkItem = (IUnknown*)&Global; + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + return E_NOTIMPL; +} + +#undef ACTSCPSITE_THIS + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +static IActiveScript *create_script(void) +{ + IActiveScript *script; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&script); + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + + return script; +} + +static IActiveScript *create_and_init_script(DWORD flags) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + HRESULT hres; + + engine = create_script(); + if(!engine) + return NULL; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + IActiveScriptParse_Release(parser); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(engine, testW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + return engine; +} + +static void close_script(IActiveScript *script) +{ + ULONG ref; + HRESULT hres; + + hres = IActiveScript_Close(script); + ok(hres == S_OK, "Close failed: %08x\n", hres); + + ref = IActiveScript_Release(script); + ok(!ref, "ref=%u\n", ref); +} + +static HRESULT parse_script(DWORD flags, BSTR script_str, const WCHAR *delim) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + IDispatch *script_disp; + LONG ref; + HRESULT hres; + + engine = create_and_init_script(flags); + if(!engine) + return S_OK; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + if (FAILED(hres)) + { + IActiveScript_Release(engine); + return hres; + } + + hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); + ok(script_disp != NULL, "script_disp == NULL\n"); + ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n"); + + test_counter = 0; + + hres = IActiveScriptParse_ParseScriptText(parser, script_str, NULL, NULL, delim, 0, 0, 0, NULL, NULL); + + IActiveScript_Close(engine); + + IDispatch_Release(script_disp); + IActiveScript_Release(engine); + + ref = IActiveScriptParse_Release(parser); + ok(!ref, "ref=%d\n", ref); + return hres; +} + +static void parse_script_af(DWORD flags, const char *src) +{ + BSTR tmp; + HRESULT hres; + + tmp = a2bstr(src); + hres = parse_script(flags, tmp, NULL); + SysFreeString(tmp); + ok(hres == S_OK, "parse_script failed: %08x\n", hres); +} + +static HRESULT parse_script_ar(const char *src) +{ + BSTR tmp; + HRESULT hres; + + tmp = a2bstr(src); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, tmp, NULL); + SysFreeString(tmp); + return hres; +} + +static void parse_script_a(const char *src) +{ + parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src); +} + +#define parse_htmlscript_a(a) _parse_htmlscript_a(__LINE__,a) +static void _parse_htmlscript_a(unsigned line, const char *src) +{ + BSTR tmp; + HRESULT hres; + + static const WCHAR script_delimW[] = {'<','/','S','C','R','I','P','T','>',0}; + + tmp = a2bstr(src); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, tmp, script_delimW); + SysFreeString(tmp); + ok_(__FILE__,line)(hres == S_OK, "parse_script failed: %08x\n", hres); +} + +static IDispatchEx *parse_procedure(IActiveScriptParseProcedure2 *parse_proc, const char *src) +{ + IDispatchEx *dispex; + IDispatch *disp; + BSTR str; + HRESULT hres; + + static const WCHAR delimiterW[] = {'\"',0}; + + str = a2bstr(src); + hres = IActiveScriptParseProcedure2_ParseProcedureText(parse_proc, str, NULL, emptyW, NULL, NULL, delimiterW, 0, 0, + SCRIPTPROC_HOSTMANAGESSOURCE|SCRIPTPROC_IMPLICIT_THIS|SCRIPTPROC_IMPLICIT_PARENTS, &disp); + SysFreeString(str); + ok(hres == S_OK, "ParseProcedureText failed: %08x\n", hres); + ok(disp != NULL, "disp = NULL\n"); + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + IDispatch_Release(disp); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + + return dispex; +} + + +static void test_procedures(void) +{ + IActiveScriptParseProcedure2 *parse_proc; + DISPPARAMS dp = {NULL}; + IActiveScript *script; + IDispatchEx *proc; + EXCEPINFO ei = {0}; + VARIANT v; + HRESULT hres; + + script = create_and_init_script(0); + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); + ok(hres == S_OK, "Could not get IActiveScriptParseProcedure2 iface: %08x\n", hres); + + proc = parse_procedure(parse_proc, "dim x\nif true then x=false"); + + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(proc, DISPID_VALUE, 0, DISPATCH_METHOD, &dp, &v, &ei, &caller_sp); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + + IDispatchEx_Release(proc); + + IActiveScriptParseProcedure2_Release(parse_proc); + + close_script(script); +} + +static void test_gc(void) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + BSTR src; + HRESULT hres; + + strict_dispid_check = FALSE; + + engine = create_script(); + if(!engine) + return; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(engine, testW, + SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + src = a2bstr( + "class C\n" + " Public ref\n" + " Public Sub Class_Terminate\n" + " Call reportSuccess()\n" + " End Sub\n" + "End Class\n" + "Dim x\n" + "set x = new C\n" + "set x.ref = x\n" + "set x = nothing\n"); + + hres = IActiveScriptParse_ParseScriptText(parser, src, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + SysFreeString(src); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + IActiveScript_Close(engine); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + IActiveScript_Release(engine); + IActiveScriptParse_Release(parser); +} + +static void test_msgbox(void) +{ + HRESULT hres; + + uic_handling = SCRIPTUICHANDLING_NOUIDEFAULT; + + SET_EXPECT(GetUIBehavior); + SET_EXPECT(GetWindow); + SET_EXPECT(EnableModeless); + hres = parse_script_ar("MsgBox \"testing...\""); + CLEAR_CALLED(GetUIBehavior); + CLEAR_CALLED(GetWindow); + CLEAR_CALLED(EnableModeless); + if(FAILED(hres)) { + win_skip("Skipping MsgBox tests, broken (probably too old) vbscript\n"); + return; + } + + SET_EXPECT(GetUIBehavior); + parse_script_a("dim r\n r=MsgBox(\"testing...\")\n Call ok(r=0, \"r=\"&r)"); + CHECK_CALLED(GetUIBehavior); + + SET_EXPECT(GetUIBehavior); + parse_script_a("MsgBox 10"); + CHECK_CALLED(GetUIBehavior); + + uic_handling = SCRIPTUICHANDLING_ALLOW; + + SET_EXPECT(GetUIBehavior); + SET_EXPECT(GetWindow); + SET_EXPECT(EnableModeless); + hres = parse_script_ar("MsgBox \"testing...\""); + ok(FAILED(hres), "script not failed\n"); + CHECK_CALLED(GetUIBehavior); + CHECK_CALLED(GetWindow); + CHECK_CALLED(EnableModeless); + + uic_handling = SCRIPTUICHANDLING_NOUIERROR; + + SET_EXPECT(GetUIBehavior); + hres = parse_script_ar("MsgBox \"testing...\""); + ok(FAILED(hres), "script not failed\n"); + CHECK_CALLED(GetUIBehavior); +} + +static HRESULT test_global_vars_ref(BOOL use_close) +{ + IActiveScriptParse *parser; + IActiveScript *engine; + BSTR script_str; + LONG ref; + HRESULT hres; + + engine = create_script(); + if(!engine) + return S_OK; + + hres = IActiveScript_QueryInterface(engine, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + if (FAILED(hres)) + { + IActiveScript_Release(engine); + return hres; + } + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(engine, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + + hres = IActiveScript_AddNamedItem(engine, testW, SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS); + ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres); + + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + + refobj_ref = 0; + + script_str = a2bstr("Dim x\nset x = RefObj\n"); + hres = IActiveScriptParse_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(script_str); + + ok(refobj_ref, "refobj_ref = 0\n"); + + if(use_close) { + hres = IActiveScript_Close(engine); + ok(hres == S_OK, "Close failed: %08x\n", hres); + }else { + hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres); + } + + ok(!refobj_ref, "refobj_ref = %d\n", refobj_ref); + + IActiveScript_Release(engine); + + ref = IActiveScriptParse_Release(parser); + ok(!ref, "ref=%d\n", ref); + return hres; +} + +static BSTR get_script_from_file(const char *filename) +{ + DWORD size, len; + HANDLE file, map; + const char *file_map; + BSTR ret; + + file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if(file == INVALID_HANDLE_VALUE) { + trace("Could not open file: %u\n", GetLastError()); + return NULL; + } + + size = GetFileSize(file, NULL); + + map = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(file); + if(map == INVALID_HANDLE_VALUE) { + trace("Could not create file mapping: %u\n", GetLastError()); + return NULL; + } + + file_map = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0); + CloseHandle(map); + if(!file_map) { + trace("MapViewOfFile failed: %u\n", GetLastError()); + return NULL; + } + + len = MultiByteToWideChar(CP_ACP, 0, file_map, size, NULL, 0); + ret = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_ACP, 0, file_map, size, ret, len); + + UnmapViewOfFile(file_map); + + return ret; +} + +static void run_from_file(const char *filename) +{ + BSTR script_str; + HRESULT hres; + + script_str = get_script_from_file(filename); + if(!script_str) + return; + + strict_dispid_check = FALSE; + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str, NULL); + SysFreeString(script_str); + ok(hres == S_OK, "parse_script failed: %08x\n", hres); +} + +static void run_from_res(const char *name) +{ + const char *data; + DWORD size, len; + BSTR str; + HRSRC src; + HRESULT hres; + + strict_dispid_check = FALSE; + test_name = name; + + src = FindResourceA(NULL, name, (LPCSTR)40); + ok(src != NULL, "Could not find resource %s\n", name); + + size = SizeofResource(NULL, src); + data = LoadResource(NULL, src); + + len = MultiByteToWideChar(CP_ACP, 0, data, size, NULL, 0); + str = SysAllocStringLen(NULL, len); + MultiByteToWideChar(CP_ACP, 0, data, size, str, len); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + hres = parse_script(SCRIPTITEM_GLOBALMEMBERS, str, NULL); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + ok(hres == S_OK, "parse_script failed: %08x\n", hres); + SysFreeString(str); +} + +static void run_tests(void) +{ + HRESULT hres; + + strict_dispid_check = TRUE; + + parse_script_a(""); + parse_script_a("' empty ;"); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + parse_script_a("reportSuccess"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + parse_script_a("reportSuccess()"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + parse_script_a("Call reportSuccess"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_success_d); + SET_EXPECT(global_success_i); + parse_script_a("test.reportSuccess()"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + SET_EXPECT(global_vbvar_d); + SET_EXPECT(global_vbvar_i); + parse_script_a("Option Explicit\nvbvar = 3"); + CHECK_CALLED(global_vbvar_d); + CHECK_CALLED(global_vbvar_i); + + SET_EXPECT(global_vbvar_d); + SET_EXPECT(global_vbvar_i); + parse_script_a("Option Explicit\nvbvar() = 3"); + CHECK_CALLED(global_vbvar_d); + CHECK_CALLED(global_vbvar_i); + + SET_EXPECT(testobj_propget_d); + SET_EXPECT(testobj_propget_i); + parse_script_a("dim x\nx = testObj.propget"); + CHECK_CALLED(testobj_propget_d); + CHECK_CALLED(testobj_propget_i); + + SET_EXPECT(testobj_propput_d); + SET_EXPECT(testobj_propput_i); + parse_script_a("testObj.propput = 1"); + CHECK_CALLED(testobj_propput_d); + CHECK_CALLED(testobj_propput_i); + + SET_EXPECT(global_propargput_d); + SET_EXPECT(global_propargput_i); + parse_script_a("propargput(counter(), counter()) = counter()"); + CHECK_CALLED(global_propargput_d); + CHECK_CALLED(global_propargput_i); + + SET_EXPECT(global_propargput_d); + SET_EXPECT(global_propargput_i); + parse_script_a("test.propargput(counter(), counter()) = counter()"); + CHECK_CALLED(global_propargput_d); + CHECK_CALLED(global_propargput_i); + + SET_EXPECT(global_propargput1_d); + SET_EXPECT(global_propargput1_i); + parse_script_a("propargput1 (counter()) = counter()"); + CHECK_CALLED(global_propargput1_d); + CHECK_CALLED(global_propargput1_i); + + SET_EXPECT(global_propargput1_d); + SET_EXPECT(global_propargput1_i); + parse_script_a("test.propargput1(counter()) = counter()"); + CHECK_CALLED(global_propargput1_d); + CHECK_CALLED(global_propargput1_i); + + parse_htmlscript_a(""); + parse_htmlscript_a("\n"); + parse_htmlscript_a("\n\n"); + + hres = parse_script_ar(" <>\nCall reportSuccess()\n-->\n"); + CHECK_CALLED(global_success_d); + CHECK_CALLED(global_success_i); + + next_cnt = 0; + SET_EXPECT(collectionobj_newenum_i); + SET_EXPECT(Next); + parse_script_a("for each x in collectionObj\nnext"); + CHECK_CALLED(collectionobj_newenum_i); + CHECK_CALLED(Next); + ok(next_cnt == 4, "next_cnt = %d\n", next_cnt); + + parse_script_a("x = 1\n Call ok(x = 1, \"x = \" & x)"); + + parse_script_a("x = _ \n3"); + + test_global_vars_ref(TRUE); + test_global_vars_ref(FALSE); + + strict_dispid_check = FALSE; + + parse_script_a("Sub testsub\n" + "x = 1\n" + "Call ok(x = 1, \"x = \" & x)\n" + "End Sub\n" + "Call testsub()"); + + parse_script_a("Call ok(getVT(x) = \"VT_EMPTY*\", \"getVT(x) = \" & getVT(x))\n"); + parse_script_a("Call ok(x = \"\", \"x = \" & x)\n"); + parse_script_a("x = y\n" + "Call ok(getVT(x) = \"VT_EMPTY*\", \"getVT(x) = \" & getVT(x))\n" + "Call ok(getVT(y) = \"VT_EMPTY*\", \"getVT(y) = \" & getVT(y))"); + hres = parse_script_ar("x = y(\"a\")"); + ok(FAILED(hres), "script didn't fail\n"); + + run_from_res("lang.vbs"); + run_from_res("api.vbs"); + run_from_res("regexp.vbs"); + + test_procedures(); + test_gc(); + test_msgbox(); +} + +static BOOL check_vbscript(void) +{ + IRegExp2 *regexp; + IUnknown *unk; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScriptRegExp, NULL, + CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IUnknown, (void**)&unk); + if(hres == REGDB_E_CLASSNOTREG) + return FALSE; + ok(hres == S_OK, "CoCreateInstance(CLSID_VBScriptRegExp) failed: %x\n", hres); + + hres = IUnknown_QueryInterface(unk, &IID_IRegExp2, (void**)®exp); + if(SUCCEEDED(hres)) + IRegExp2_Release(regexp); + IUnknown_Release(unk); + + return hres == S_OK; +} + +START_TEST(run) +{ + int argc; + char **argv; + + is_english = is_lang_english(); + if(!is_english) + skip("Skipping some tests in non-English locale\n"); + + argc = winetest_get_mainargs(&argv); + + CoInitialize(NULL); + + if(!check_vbscript()) { + win_skip("Broken engine, probably too old\n"); + }else if(argc > 2) { + allow_ui = TRUE; + uic_handling = SCRIPTUICHANDLING_ALLOW; + run_from_file(argv[2]); + }else { + run_tests(); + } + + CoUninitialize(); +} diff --git a/rostests/winetests/vbscript/testlist.c b/rostests/winetests/vbscript/testlist.c new file mode 100644 index 00000000000..92b820ae091 --- /dev/null +++ b/rostests/winetests/vbscript/testlist.c @@ -0,0 +1,16 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define STANDALONE +#include + +extern void func_createobj(void); +extern void func_run(void); +extern void func_vbscript(void); + +const struct test winetest_testlist[] = +{ + { "createobj", func_createobj }, + { "run", func_run }, + { "vbscript", func_vbscript }, + { 0, 0 } +}; diff --git a/rostests/winetests/vbscript/vbscript.c b/rostests/winetests/vbscript/vbscript.c new file mode 100644 index 00000000000..1996e2bf0a1 --- /dev/null +++ b/rostests/winetests/vbscript/vbscript.c @@ -0,0 +1,968 @@ +/* + * Copyright 2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + +#define COBJMACROS +#define CONST_VTABLE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef _WIN64 + +#define IActiveScriptParse_QueryInterface IActiveScriptParse64_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse64_Release +#define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release \ + IActiveScriptParseProcedure2_64_Release + +#else + +#define IActiveScriptParse_QueryInterface IActiveScriptParse32_QueryInterface +#define IActiveScriptParse_Release IActiveScriptParse32_Release +#define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew +#define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release \ + IActiveScriptParseProcedure2_32_Release + +#endif + +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(GetLCID); +DEFINE_EXPECT(OnStateChange_UNINITIALIZED); +DEFINE_EXPECT(OnStateChange_STARTED); +DEFINE_EXPECT(OnStateChange_CONNECTED); +DEFINE_EXPECT(OnStateChange_DISCONNECTED); +DEFINE_EXPECT(OnStateChange_CLOSED); +DEFINE_EXPECT(OnStateChange_INITIALIZED); +DEFINE_EXPECT(OnEnterScript); +DEFINE_EXPECT(OnLeaveScript); + +DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4,0xb0, 0x00,0xaa,0x00,0x4a,0x55,0xe8); +DEFINE_GUID(CLSID_VBScriptRegExp, 0x3f4daca4, 0x160d, 0x11d2, 0xa8,0xe9, 0x00,0x10,0x4b,0x36,0x5c,0x9f); + +static BSTR a2bstr(const char *str) +{ + BSTR ret; + int len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len-1); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + + return ret; +} + +#define test_state(s,ss) _test_state(__LINE__,s,ss) +static void _test_state(unsigned line, IActiveScript *script, SCRIPTSTATE exstate) +{ + SCRIPTSTATE state = -1; + HRESULT hres; + + hres = IActiveScript_GetScriptState(script, &state); + ok_(__FILE__,line) (hres == S_OK, "GetScriptState failed: %08x\n", hres); + ok_(__FILE__,line) (state == exstate, "state=%d, expected %d\n", state, exstate); +} + +static HRESULT WINAPI ActiveScriptSite_QueryInterface(IActiveScriptSite *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) + *ppv = iface; + else if(IsEqualGUID(&IID_IActiveScriptSite, riid)) + *ppv = iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI ActiveScriptSite_AddRef(IActiveScriptSite *iface) +{ + return 2; +} + +static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) +{ + return 1; +} + +static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) +{ + CHECK_EXPECT(GetLCID); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR pstrName, + DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *pbstrVersion) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptTerminate(IActiveScriptSite *iface, + const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnStateChange(IActiveScriptSite *iface, SCRIPTSTATE ssScriptState) +{ + switch(ssScriptState) { + case SCRIPTSTATE_UNINITIALIZED: + CHECK_EXPECT(OnStateChange_UNINITIALIZED); + return S_OK; + case SCRIPTSTATE_STARTED: + CHECK_EXPECT(OnStateChange_STARTED); + return S_OK; + case SCRIPTSTATE_CONNECTED: + CHECK_EXPECT(OnStateChange_CONNECTED); + return S_OK; + case SCRIPTSTATE_DISCONNECTED: + CHECK_EXPECT(OnStateChange_DISCONNECTED); + return S_OK; + case SCRIPTSTATE_CLOSED: + CHECK_EXPECT(OnStateChange_CLOSED); + return S_OK; + case SCRIPTSTATE_INITIALIZED: + CHECK_EXPECT(OnStateChange_INITIALIZED); + return S_OK; + default: + ok(0, "unexpected call %d\n", ssScriptState); + } + + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnScriptError(IActiveScriptSite *iface, IActiveScriptError *pscripterror) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ActiveScriptSite_OnEnterScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnEnterScript); + return S_OK; +} + +static HRESULT WINAPI ActiveScriptSite_OnLeaveScript(IActiveScriptSite *iface) +{ + CHECK_EXPECT(OnLeaveScript); + return S_OK; +} + +static const IActiveScriptSiteVtbl ActiveScriptSiteVtbl = { + ActiveScriptSite_QueryInterface, + ActiveScriptSite_AddRef, + ActiveScriptSite_Release, + ActiveScriptSite_GetLCID, + ActiveScriptSite_GetItemInfo, + ActiveScriptSite_GetDocVersionString, + ActiveScriptSite_OnScriptTerminate, + ActiveScriptSite_OnStateChange, + ActiveScriptSite_OnScriptError, + ActiveScriptSite_OnEnterScript, + ActiveScriptSite_OnLeaveScript +}; + +static IActiveScriptSite ActiveScriptSite = { &ActiveScriptSiteVtbl }; + +static void test_safety(IActiveScript *script) +{ + IObjectSafety *safety; + DWORD supported, enabled; + HRESULT hres; + + hres = IActiveScript_QueryInterface(script, &IID_IObjectSafety, (void**)&safety); + ok(hres == S_OK, "Could not get IObjectSafety: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_NULL, &supported, NULL); + ok(hres == E_POINTER, "GetInterfaceSafetyOptions failed: %08x, expected E_POINTER\n", hres); + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_NULL, NULL, &enabled); + ok(hres == E_POINTER, "GetInterfaceSafetyOptions failed: %08x, expected E_POINTER\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_NULL, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScript, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER + |INTERFACESAFE_FOR_UNTRUSTED_CALLER, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER); + ok(hres == E_FAIL, "SetInterfaceSafetyOptions failed: %08x, expected E_FAIL\n", hres); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, INTERFACESAFE_FOR_UNTRUSTED_DATA, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == (INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + hres = IObjectSafety_SetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, + INTERFACE_USES_DISPEX, 0); + ok(hres == S_OK, "SetInterfaceSafetyOptions failed: %08x\n", hres); + + supported = enabled = 0xdeadbeef; + hres = IObjectSafety_GetInterfaceSafetyOptions(safety, &IID_IActiveScriptParse, &supported, &enabled); + ok(hres == S_OK, "GetInterfaceSafetyOptions failed: %08x\n", hres); + ok(supported == (INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_DISPEX|INTERFACE_USES_SECURITY_MANAGER), + "supported=%x\n", supported); + ok(enabled == INTERFACE_USES_DISPEX, "enabled=%x\n", enabled); + + IObjectSafety_Release(safety); +} + +static IDispatchEx *get_script_dispatch(IActiveScript *script) +{ + IDispatchEx *dispex; + IDispatch *disp; + HRESULT hres; + + disp = (void*)0xdeadbeef; + hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres); + if(FAILED(hres)) + return NULL; + + hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); + IDispatch_Release(disp); + ok(hres == S_OK, "Could not get IDispatchEx iface: %08x\n", hres); + return dispex; +} + +static void parse_script(IActiveScriptParse *parse, const char *src) +{ + BSTR str; + HRESULT hres; + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + str = a2bstr(src); + hres = IActiveScriptParse_ParseScriptText(parse, str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + SysFreeString(str); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); +} + +#define get_disp_id(a,b,c,d) _get_disp_id(__LINE__,a,b,c,d) +static void _get_disp_id(unsigned line, IDispatchEx *dispex, const char *name, HRESULT exhres, DISPID *id) +{ + DISPID id2; + BSTR str; + HRESULT hres; + + str = a2bstr(name); + hres = IDispatchEx_GetDispID(dispex, str, 0, id); + ok_(__FILE__,line)(hres == exhres, "GetDispID(%s) returned %08x, expected %08x\n", name, hres, exhres); + + hres = IDispatchEx_GetIDsOfNames(dispex, &IID_NULL, &str, 1, 0, &id2); + SysFreeString(str); + ok_(__FILE__,line)(hres == exhres, "GetIDsOfNames(%s) returned %08x, expected %08x\n", name, hres, exhres); + ok_(__FILE__,line)(*id == id2, "GetIDsOfNames(%s) id != id2\n", name); +} + +static void test_no_script_dispatch(IActiveScript *script) +{ + IDispatch *disp; + HRESULT hres; + + disp = (void*)0xdeadbeef; + hres = IActiveScript_GetScriptDispatch(script, NULL, &disp); + ok(hres == E_UNEXPECTED, "hres = %08x, expected E_UNEXPECTED\n", hres); + ok(!disp, "disp != NULL\n"); +} + +static IActiveScript *create_vbscript(void) +{ + IActiveScript *ret; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScript, (void**)&ret); + ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); + + return ret; +} + +static void test_scriptdisp(void) +{ + IActiveScriptParse *parser; + IDispatchEx *script_disp; + IActiveScript *vbscript; + DISPID id, id2; + DISPPARAMS dp; + EXCEPINFO ei; + VARIANT v; + ULONG ref; + HRESULT hres; + + vbscript = create_vbscript(); + + hres = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hres); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + test_safety(vbscript); + + SET_EXPECT(GetLCID); + hres = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(vbscript, SCRIPTSTATE_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + hres = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + script_disp = get_script_dispatch(vbscript); + + id = 100; + get_disp_id(script_disp, "LCase", DISP_E_UNKNOWNNAME, &id); + ok(id == -1, "id = %d, expected -1\n", id); + + get_disp_id(script_disp, "globalVariable", DISP_E_UNKNOWNNAME, &id); + parse_script(parser, "dim globalVariable\nglobalVariable = 3"); + get_disp_id(script_disp, "globalVariable", S_OK, &id); + + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(script_disp, id, 0, DISPATCH_PROPERTYGET|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) == 3, "V_I2(v) = %d\n", V_I2(&v)); + + get_disp_id(script_disp, "globalVariable2", DISP_E_UNKNOWNNAME, &id); + parse_script(parser, "globalVariable2 = 4"); + get_disp_id(script_disp, "globalVariable2", S_OK, &id); + + get_disp_id(script_disp, "globalFunction", DISP_E_UNKNOWNNAME, &id); + parse_script(parser, "function globalFunction()\nglobalFunction=5\nend function"); + get_disp_id(script_disp, "globalFunction", S_OK, &id); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(script_disp, id, 0, DISPATCH_PROPERTYGET|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) == 5, "V_I2(v) = %d\n", V_I2(&v)); + + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_Invoke(script_disp, 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_I2, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I2(&v) == 5, "V_I2(v) = %d\n", V_I2(&v)); + + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + get_disp_id(script_disp, "globalSub", DISP_E_UNKNOWNNAME, &id); + parse_script(parser, "sub globalSub()\nend sub"); + get_disp_id(script_disp, "globalSub", S_OK, &id); + get_disp_id(script_disp, "globalSub", S_OK, &id2); + ok(id == id2, "id != id2\n"); + + get_disp_id(script_disp, "constVariable", DISP_E_UNKNOWNNAME, &id); + parse_script(parser, "const constVariable = 6"); + get_disp_id(script_disp, "ConstVariable", S_OK, &id); + get_disp_id(script_disp, "Constvariable", S_OK, &id2); + ok(id == id2, "id != id2\n"); + + IDispatchEx_Release(script_disp); + + IActiveScriptParse_Release(parser); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + hres = IActiveScript_Close(vbscript); + ok(hres == S_OK, "Close failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); + + ref = IActiveScript_Release(vbscript); + ok(!ref, "ref = %d\n", ref); +} + +static void test_vbscript(void) +{ + IActiveScriptParseProcedure2 *parse_proc; + IActiveScriptParse *parser; + IActiveScript *vbscript; + ULONG ref; + HRESULT hres; + + vbscript = create_vbscript(); + + hres = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hres); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + test_safety(vbscript); + + SET_EXPECT(GetLCID); + hres = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(vbscript, SCRIPTSTATE_INITIALIZED); + + hres = IActiveScriptParse_InitNew(parser); + ok(hres == E_UNEXPECTED, "InitNew failed: %08x, expected E_UNEXPECTED\n", hres); + + SET_EXPECT(OnStateChange_CONNECTED); + hres = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + hres = IActiveScript_Close(vbscript); + ok(hres == S_OK, "Close failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); + + test_state(vbscript, SCRIPTSTATE_CLOSED); + test_no_script_dispatch(vbscript); + + IActiveScriptParse_Release(parser); + + hres = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParseProcedure, (void**)&parse_proc); + ok(hres == E_NOINTERFACE, "Got IActiveScriptParseProcedure interface, expected E_NOTIMPL\n"); + + hres = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); + ok(hres == S_OK, "Could not get IActiveScriptParseProcedure2 interface\n"); + IActiveScriptParseProcedure2_Release(parse_proc); + + ref = IActiveScript_Release(vbscript); + ok(!ref, "ref = %d\n", ref); +} + +static void test_vbscript_uninitializing(void) +{ + IActiveScriptParse *parse; + IActiveScript *script; + IDispatchEx *dispex; + ULONG ref; + HRESULT hres; + + static const WCHAR script_textW[] = + {'F','u','n','c','t','i','o','n',' ','f','\n','E','n','d',' ','F','u','n','c','t','i','o','n','\n',0}; + + script = create_vbscript(); + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScriptParse_InitNew(parse); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(script, SCRIPTSTATE_INITIALIZED); + + hres = IActiveScriptParse_ParseScriptText(parse, script_textW, NULL, NULL, NULL, 0, 1, 0x42, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == E_UNEXPECTED, "SetScriptSite failed: %08x, expected E_UNEXPECTED\n", hres); + + SET_EXPECT(OnStateChange_UNINITIALIZED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); + + test_state(script, SCRIPTSTATE_CONNECTED); + + dispex = get_script_dispatch(script); + ok(dispex != NULL, "dispex == NULL\n"); + if(dispex) + IDispatchEx_Release(dispex); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_UNINITIALIZED); + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_UNINITIALIZED); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + hres = IActiveScript_Close(script); + ok(hres == S_OK, "Close failed: %08x\n", hres); + + test_state(script, SCRIPTSTATE_CLOSED); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == E_UNEXPECTED, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x, expected E_UNEXPECTED\n", hres); + + test_state(script, SCRIPTSTATE_CLOSED); + + SET_EXPECT(GetLCID); + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(script, SCRIPTSTATE_INITIALIZED); + + SET_EXPECT(OnStateChange_CLOSED); + hres = IActiveScript_Close(script); + ok(hres == S_OK, "Close failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CLOSED); + + test_state(script, SCRIPTSTATE_CLOSED); + + IActiveScriptParse_Release(parse); + + ref = IActiveScript_Release(script); + ok(!ref, "ref = %d\n", ref); +} + +static void test_vbscript_release(void) +{ + IActiveScriptParse *parser; + IActiveScript *vbscript; + ULONG ref; + HRESULT hres; + + vbscript = create_vbscript(); + + hres = IActiveScript_QueryInterface(vbscript, &IID_IActiveScriptParse, (void**)&parser); + ok(hres == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hres); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + test_safety(vbscript); + + SET_EXPECT(GetLCID); + hres = IActiveScript_SetScriptSite(vbscript, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + + test_state(vbscript, SCRIPTSTATE_UNINITIALIZED); + + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScriptParse_InitNew(parser); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_INITIALIZED); + + test_state(vbscript, SCRIPTSTATE_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + hres = IActiveScript_SetScriptState(vbscript, SCRIPTSTATE_CONNECTED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CONNECTED); + + test_state(vbscript, SCRIPTSTATE_CONNECTED); + + IActiveScriptParse_Release(parser); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + ref = IActiveScript_Release(vbscript); + ok(!ref, "ref = %d\n", ref); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); +} + +static void test_vbscript_simplecreate(void) +{ + IActiveScript *script; + ULONG ref; + HRESULT hres; + + script = create_vbscript(); + + hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED); + ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08x\n", hres); + + ref = IActiveScript_Release(script); + ok(!ref, "ref = %d\n", ref); +} + +static void test_vbscript_initializing(void) +{ + IActiveScriptParse *parse; + IActiveScript *script; + ULONG ref; + HRESULT hres; + + script = create_vbscript(); + + hres = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parse); + ok(hres == S_OK, "Could not get IActiveScriptParse: %08x\n", hres); + + test_state(script, SCRIPTSTATE_UNINITIALIZED); + + SET_EXPECT(GetLCID); + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres); + CHECK_CALLED(GetLCID); + + SET_EXPECT(OnStateChange_INITIALIZED); + hres = IActiveScriptParse_InitNew(parse); + ok(hres == S_OK, "InitNew failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_INITIALIZED); + + hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hres == E_UNEXPECTED, "SetScriptSite failed: %08x, expected E_UNEXPECTED\n", hres); + + SET_EXPECT(OnStateChange_CLOSED); + hres = IActiveScript_Close(script); + ok(hres == S_OK, "Close failed: %08x\n", hres); + CHECK_CALLED(OnStateChange_CLOSED); + + test_state(script, SCRIPTSTATE_CLOSED); + + IActiveScriptParse_Release(parse); + + ref = IActiveScript_Release(script); + ok(!ref, "ref = %d\n", ref); +} + +static void test_RegExp(void) +{ + IRegExp2 *regexp; + IMatchCollection2 *mc; + IMatch2 *match; + ISubMatches *sm; + IEnumVARIANT *ev; + IUnknown *unk; + IDispatch *disp; + HRESULT hres; + BSTR bstr; + LONG count; + VARIANT v; + ULONG fetched; + + hres = CoCreateInstance(&CLSID_VBScriptRegExp, NULL, + CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IUnknown, (void**)&unk); + if(hres == REGDB_E_CLASSNOTREG) { + win_skip("VBScriptRegExp is not registered\n"); + return; + } + ok(hres == S_OK, "CoCreateInstance(CLSID_VBScriptRegExp) failed: %x\n", hres); + + hres = IUnknown_QueryInterface(unk, &IID_IRegExp2, (void**)®exp); + if(hres == E_NOINTERFACE) { + win_skip("IRegExp2 interface is not available\n"); + return; + } + ok(hres == S_OK, "QueryInterface(IID_IRegExp2) failed: %x\n", hres); + IUnknown_Release(unk); + + hres = IRegExp2_QueryInterface(regexp, &IID_IRegExp, (void**)&unk); + ok(hres == S_OK, "QueryInterface(IID_IRegExp) returned %x\n", hres); + IUnknown_Release(unk); + + hres = IRegExp2_QueryInterface(regexp, &IID_IDispatchEx, (void**)&unk); + ok(hres == E_NOINTERFACE, "QueryInterface(IID_IDispatchEx) returned %x\n", hres); + + hres = IRegExp2_get_Pattern(regexp, &bstr); + ok(bstr == NULL, "bstr != NULL\n"); + ok(hres == S_OK, "get_Pattern returned %x, expected S_OK\n", hres); + + hres = IRegExp2_get_Pattern(regexp, NULL); + ok(hres == E_POINTER, "get_Pattern returned %x, expected E_POINTER\n", hres); + + hres = IRegExp2_get_IgnoreCase(regexp, NULL); + ok(hres == E_POINTER, "get_IgnoreCase returned %x, expected E_POINTER\n", hres); + + hres = IRegExp2_get_Global(regexp, NULL); + ok(hres == E_POINTER, "get_Global returned %x, expected E_POINTER\n", hres); + + hres = IRegExp2_Execute(regexp, NULL, &disp); + ok(hres == S_OK, "Execute returned %x, expected S_OK\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IMatchCollection2, (void**)&mc); + ok(hres == S_OK, "QueryInterface(IID_IMatchCollection2) returned %x\n", hres); + IDispatch_Release(disp); + + hres = IMatchCollection2_get_Count(mc, NULL); + ok(hres == E_POINTER, "get_Count returned %x, expected E_POINTER\n", hres); + + hres = IMatchCollection2_get_Count(mc, &count); + ok(hres == S_OK, "get_Count returned %x, expected S_OK\n", hres); + ok(count == 1, "count = %d\n", count); + + hres = IMatchCollection2_get_Item(mc, 1, &disp); + ok(hres == E_INVALIDARG, "get_Item returned %x, expected E_INVALIDARG\n", hres); + + hres = IMatchCollection2_get_Item(mc, 1, NULL); + ok(hres == E_POINTER, "get_Item returned %x, expected E_POINTER\n", hres); + + hres = IMatchCollection2_get_Item(mc, 0, &disp); + ok(hres == S_OK, "get_Item returned %x, expected S_OK\n", hres); + hres = IDispatch_QueryInterface(disp, &IID_IMatch2, (void**)&match); + ok(hres == S_OK, "QueryInterface(IID_IMatch2) returned %x\n", hres); + IDispatch_Release(disp); + + hres = IMatch2_get_Value(match, NULL); + ok(hres == E_POINTER, "get_Value returned %x, expected E_POINTER\n", hres); + + hres = IMatch2_get_FirstIndex(match, NULL); + ok(hres == E_POINTER, "get_FirstIndex returned %x, expected E_POINTER\n", hres); + + hres = IMatch2_get_Length(match, NULL); + ok(hres == E_POINTER, "get_Length returned %x, expected E_POINTER\n", hres); + + hres = IMatch2_get_SubMatches(match, NULL); + ok(hres == E_POINTER, "get_SubMatches returned %x, expected E_POINTER\n", hres); + + hres = IMatch2_get_SubMatches(match, &disp); + ok(hres == S_OK, "get_SubMatches returned %x, expected S_OK\n", hres); + IMatch2_Release(match); + hres = IDispatch_QueryInterface(disp, &IID_ISubMatches, (void**)&sm); + ok(hres == S_OK, "QueryInterface(IID_ISubMatches) returned %x\n", hres); + IDispatch_Release(disp); + + hres = ISubMatches_get_Item(sm, 0, &v); + ok(hres == E_INVALIDARG, "get_Item returned %x, expected E_INVALIDARG\n", hres); + + hres = ISubMatches_get_Item(sm, 0, NULL); + ok(hres == E_POINTER, "get_Item returned %x, expected E_POINTER\n", hres); + + hres = ISubMatches_get_Count(sm, NULL); + ok(hres == E_POINTER, "get_Count returned %x, expected E_POINTER\n", hres); + ISubMatches_Release(sm); + + hres = IMatchCollection2_get__NewEnum(mc, &unk); + ok(hres == S_OK, "get__NewEnum returned %x, expected S_OK\n", hres); + hres = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&ev); + ok(hres == S_OK, "QueryInterface(IID_IEnumVARIANT) returned %x\n", hres); + IUnknown_Release(unk); + IMatchCollection2_Release(mc); + + hres = IEnumVARIANT_Skip(ev, 2); + ok(hres == S_OK, "Skip returned %x\n", hres); + + hres = IEnumVARIANT_Next(ev, 1, &v, &fetched); + ok(hres == S_FALSE, "Next returned %x, expected S_FALSE\n", hres); + ok(fetched == 0, "fetched = %d\n", fetched); + + hres = IEnumVARIANT_Skip(ev, -1); + ok(hres == S_OK, "Skip returned %x\n", hres); + + hres = IEnumVARIANT_Next(ev, 1, &v, &fetched); + ok(hres == S_OK, "Next returned %x\n", hres); + ok(fetched == 1, "fetched = %d\n", fetched); + VariantClear(&v); + IEnumVARIANT_Release(ev); + + IRegExp2_Release(regexp); +} + +static BOOL check_vbscript(void) +{ + IActiveScriptParseProcedure2 *vbscript; + HRESULT hres; + + hres = CoCreateInstance(&CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, + &IID_IActiveScriptParseProcedure2, (void**)&vbscript); + if(SUCCEEDED(hres)) + IActiveScriptParseProcedure2_Release(vbscript); + + return hres == S_OK; +} + +START_TEST(vbscript) +{ + CoInitialize(NULL); + + if(check_vbscript()) { + test_vbscript(); + test_vbscript_uninitializing(); + test_vbscript_release(); + test_vbscript_simplecreate(); + test_vbscript_initializing(); + test_scriptdisp(); + test_RegExp(); + }else { + win_skip("VBScript engine not available or too old\n"); + } + + CoUninitialize(); +} diff --git a/rostests/winetests/vbscript/vbscript_defs.h b/rostests/winetests/vbscript/vbscript_defs.h new file mode 100644 index 00000000000..3af86c374f8 --- /dev/null +++ b/rostests/winetests/vbscript/vbscript_defs.h @@ -0,0 +1,33 @@ +/* + * Copyright 2011 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define DISPID_SUBMATCHES_COUNT 1 + +#define DISPID_MATCHCOLLECTION_COUNT 1 + +#define DISPID_MATCH_FIRSTINDEX 10001 +#define DISPID_MATCH_LENGTH 10002 +#define DISPID_MATCH_SUBMATCHES 10003 + +#define DISPID_REGEXP_PATTERN 10001 +#define DISPID_REGEXP_IGNORECASE 10002 +#define DISPID_REGEXP_GLOBAL 10003 +#define DISPID_REGEXP_EXECUTE 10004 +#define DISPID_REGEXP_TEST 10005 +#define DISPID_REGEXP_REPLACE 10006 +#define DISPID_REGEXP_MULTILINE 10007 diff --git a/rostests/winetests/vbscript/vbsregexp55.idl b/rostests/winetests/vbscript/vbsregexp55.idl new file mode 100644 index 00000000000..b6934e02711 --- /dev/null +++ b/rostests/winetests/vbscript/vbsregexp55.idl @@ -0,0 +1,270 @@ +/* + * Copyright 2013 Piotr Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +import "oaidl.idl"; + +#include "vbscript_defs.h" + +[ + helpstring("Microsoft VBScript Regular Expressions 5.5"), + uuid(3f4daca7-160d-11d2-a8e9-00104b365c9f), + version(5.5) +] +library VBScript_RegExp_55 +{ + importlib("stdole2.tlb"); + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4daca0-160d-11d2-a8e9-00104b365c9f), + ] + interface IRegExp : IDispatch + { + [id(DISPID_REGEXP_PATTERN), propget] + HRESULT Pattern([out, retval] BSTR *pPattern); + + [id(DISPID_REGEXP_PATTERN), propput] + HRESULT Pattern([in] BSTR pPattern); + + [id(DISPID_REGEXP_IGNORECASE), propget] + HRESULT IgnoreCase([out, retval] VARIANT_BOOL *pIgnoreCase); + + [id(DISPID_REGEXP_IGNORECASE), propput] + HRESULT IgnoreCase([in] VARIANT_BOOL pIgnoreCase); + + [id(DISPID_REGEXP_GLOBAL), propget] + HRESULT Global([out, retval] VARIANT_BOOL *pGlobal); + + [id(DISPID_REGEXP_GLOBAL), propput] + HRESULT Global([in] VARIANT_BOOL pGlobal); + + [id(DISPID_REGEXP_EXECUTE)] + HRESULT Execute( + [in] BSTR sourceString, + [out, retval] IDispatch **ppMatches); + + [id(DISPID_REGEXP_TEST)] + HRESULT Test( + [in] BSTR sourceString, + [out, retval] VARIANT_BOOL *pMatch); + + [id(DISPID_REGEXP_REPLACE)] + HRESULT Replace( + [in] BSTR sourceString, + [in] BSTR replaceString, + [out, retval] BSTR *pDestString); + } + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4dacb0-160d-11d2-a8e9-00104b365c9f) + ] + interface IRegExp2 : IDispatch + { + [id(DISPID_REGEXP_PATTERN), propget] + HRESULT Pattern([out, retval] BSTR *pPattern); + + [id(DISPID_REGEXP_PATTERN), propput] + HRESULT Pattern([in] BSTR pPattern); + + [id(DISPID_REGEXP_IGNORECASE), propget] + HRESULT IgnoreCase([out, retval] VARIANT_BOOL *pIgnoreCase); + + [id(DISPID_REGEXP_IGNORECASE), propput] + HRESULT IgnoreCase([in] VARIANT_BOOL pIgnoreCase); + + [id(DISPID_REGEXP_GLOBAL), propget] + HRESULT Global([out, retval] VARIANT_BOOL *pGlobal); + + [id(DISPID_REGEXP_GLOBAL), propput] + HRESULT Global([in] VARIANT_BOOL pGlobal); + + [id(DISPID_REGEXP_MULTILINE), propget] + HRESULT Multiline([out, retval] VARIANT_BOOL *pMultiline); + + [id(DISPID_REGEXP_MULTILINE), propput] + HRESULT Multiline([in] VARIANT_BOOL pMultiline); + + [id(DISPID_REGEXP_EXECUTE)] + HRESULT Execute( + [in] BSTR sourceString, + [out, retval] IDispatch **ppMatches); + + [id(DISPID_REGEXP_TEST)] + HRESULT Test( + [in] BSTR sourceString, + [out, retval] VARIANT_BOOL *pMatch); + + [id(DISPID_REGEXP_REPLACE)] + HRESULT Replace( + [in] BSTR sourceString, + [in] VARIANT replaceVar, + [out, retval] BSTR *pDestString); + } + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4daca1-160d-11d2-a8e9-00104b365c9f) + ] + interface IMatch : IDispatch + { + [id(DISPID_VALUE), propget] + HRESULT Value([out, retval] BSTR *pValue); + + [id(DISPID_MATCH_FIRSTINDEX), propget] + HRESULT FirstIndex([out, retval] LONG *pFirstIndex); + + [id(DISPID_MATCH_LENGTH), propget] + HRESULT Length([out, retval] LONG *pLength); + } + + [ + odl, + uuid(3f4dacb1-160d-11d2-a8e9-00104b365c9f), + hidden, + dual, + nonextensible, + oleautomation + ] + interface IMatch2 : IDispatch + { + [id(DISPID_VALUE), propget] + HRESULT Value([out, retval] BSTR *pValue); + + [id(DISPID_MATCH_FIRSTINDEX), propget] + HRESULT FirstIndex([out, retval] LONG *pFirstIndex); + + [id(DISPID_MATCH_LENGTH), propget] + HRESULT Length([out, retval] LONG *pLength); + + [id(DISPID_MATCH_SUBMATCHES), propget] + HRESULT SubMatches([out, retval] IDispatch **ppSubMatches); + } + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4daca2-160d-11d2-a8e9-00104b365c9f) + ] + interface IMatchCollection : IDispatch + { + [id(DISPID_VALUE), propget] + HRESULT Item( + [in] LONG index, + [out, retval] IDispatch **ppMatch); + + [id(DISPID_MATCHCOLLECTION_COUNT), propget] + HRESULT Count([out, retval] LONG *pCount); + + [id(DISPID_NEWENUM), propget] + HRESULT _NewEnum([out, retval] IUnknown **ppEnum); + } + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4dacb2-160d-11d2-a8e9-00104b365c9f) + ] + interface IMatchCollection2 : IDispatch + { + [id(DISPID_VALUE), propget] + HRESULT Item( + [in] LONG index, + [out, retval] IDispatch **ppMatch); + + [id(DISPID_MATCHCOLLECTION_COUNT), propget] + HRESULT Count([out, retval] LONG *pCount); + + [id(DISPID_NEWENUM), propget] + HRESULT _NewEnum([out, retval] IUnknown **ppEnum); + } + + [ + dual, + hidden, + nonextensible, + odl, + oleautomation, + uuid(3f4dacb3-160d-11d2-a8e9-00104b365c9f) + ] + interface ISubMatches : IDispatch + { + [id(DISPID_VALUE), propget] + HRESULT Item( + [in] LONG index, + [out, retval] VARIANT *pSubMatch); + + [id(DISPID_SUBMATCHES_COUNT), propget] + HRESULT Count([out, retval] LONG *pCount); + + [id(DISPID_NEWENUM), propget] + HRESULT _NewEnum([out, retval] IUnknown **ppEnum); + } + + [ + uuid(3f4daca4-160d-11d2-a8e9-00104b365c9f) + ] + coclass RegExp + { + [default] interface IRegExp2; + } + + [ + noncreatable, + uuid(3f4daca5-160d-11d2-a8e9-00104b365c9f) + ] + coclass Match + { + [default] interface IMatch2; + } + + [ + noncreatable, + uuid(3f4daca6-160d-11d2-a8e9-00104b365c9f) + ] + coclass MatchCollection + { + [default] interface IMatchCollection2; + } + + [ + noncreatable, + uuid(3f4dacc0-160d-11d2-a8e9-00104b365c9f) + ] + coclass SubMatches { + [default] interface ISubMatches; + } +}