diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 414ede5ed0f..122f5c7b71a 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2398,61 +2398,80 @@ static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_ static HRESULT Global_InStrRev(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - int start, ret = 0; + int start = -1, ret = -1, mode = 0; BSTR str1, str2; + size_t len1, len2; HRESULT hres; TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt); - if(args_cnt > 3) { - FIXME("Unsupported args\n"); - return E_NOTIMPL; - } - assert(2 <= args_cnt && args_cnt <= 4); - if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL)) + if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL) + || (args_cnt == 4 && V_VT(args+3) == VT_NULL)) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); - hres = to_string(args, &str1); - if(FAILED(hres)) - return hres; - - hres = to_string(args+1, &str2); - if(SUCCEEDED(hres)) { - if(args_cnt > 2) { - hres = to_int(args+2, &start); - if(SUCCEEDED(hres) && start <= 0) { - FIXME("Unsupported start %d\n", start); - hres = E_NOTIMPL; - } - }else { - start = SysStringLen(str1); - } - } else { - str2 = NULL; + if(args_cnt == 4) { + hres = to_int(args+3, &mode); + if(FAILED(hres)) + return hres; + if (mode != 0 && mode != 1) + return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); } - if(SUCCEEDED(hres)) { - const WCHAR *ptr; - size_t len; - - len = SysStringLen(str2); - if(start >= len && start <= SysStringLen(str1)) { - for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) { - if(!memcmp(ptr, str2, len*sizeof(WCHAR))) { - ret = ptr-str1+1; - break; - } - } - } + if(args_cnt >= 3) { + hres = to_int(args+2, &start); + if(FAILED(hres)) + return hres; + if(!start || start < -1) + return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); } - SysFreeString(str1); - SysFreeString(str2); - if(FAILED(hres)) - return hres; + if(V_VT(args) != VT_BSTR) { + hres = to_string(args, &str1); + if(FAILED(hres)) + return hres; + } + else + str1 = V_BSTR(args); + if(V_VT(args+1) != VT_BSTR) { + hres = to_string(args+1, &str2); + if(FAILED(hres)) { + if(V_VT(args) != VT_BSTR) + SysFreeString(str1); + return hres; + } + } + else + str2 = V_BSTR(args+1); + + len1 = SysStringLen(str1); + if(!len1) { + ret = 0; + goto end; + } + + if(start == -1) + start = len1; + + len2 = SysStringLen(str2); + if(!len2) { + ret = start; + goto end; + } + + if(start >= len2 && start <= len1) { + ret = FindStringOrdinal(FIND_FROMEND, str1, start, + str2, len2, mode); + } + ret++; + +end: + if(V_VT(args) != VT_BSTR) + SysFreeString(str1); + if(V_VT(args+1) != VT_BSTR) + SysFreeString(str2); return return_int(res, ret); } diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index f829afc1019..6af49c849d3 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -508,18 +508,57 @@ Call ok(x = 3, "InStrRev returned " & x) x = InStrRev(1234, 34) Call ok(x = 3, "InStrRev returned " & x) -Sub testInStrRevError(arg1, arg2, arg3, error_num) +x = InStrRev("abcd", "A", 1, 0) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "A", 1, 1) +Call ok(x = 1, "InStrRev returned " & x) + +x = InStrRev("abcd", "Ab", 1, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "Ab", -1, 1) +Call ok(x = 1, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 3, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 4, 1) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 5, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abc" & Chr(0) & "A" & Chr(0) & "BC", "c", 8, 0) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("abc" & Chr(0) & "ABC", Chr(0) & "a", 6, 1) +Call ok(x = 4, "InStrRev returned " & x) + +x = InStrRev("", "hi", 1, 0) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "", 3, 1) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("", "", 3, 0) +Call ok(x = 0, "InStrRev returned " & x) + +Sub testInStrRevError(arg1, arg2, arg3, arg4, error_num) on error resume next Dim x Call Err.clear() - x = InStrRev(arg1, arg2, arg3) + x = InStrRev(arg1, arg2, arg3, arg4) Call ok(Err.number = error_num, "Err.number = " & Err.number) End Sub -call testInStrRevError("abcd", null, 2, 94) -call testInStrRevError(null, "abcd", 2, 94) -call testInStrRevError("abcd", "abcd", null, 94) +call testInStrRevError("abcd", null, 2, 0, 94) +call testInStrRevError(null, "abcd", 2, 0, 94) +call testInStrRevError("abcd", "abcd", null, 0, 94) +call testInStrRevError("abcd", "abcd", 2, null, 94) +call testInStrRevError("abcd", "abcd", -20, 1, 5) +Call testInStrRevError("abcd", "abcd", 2, 10, 5) Sub TestMid(str, start, len, ex) x = Mid(str, start, len)