From: Francis De Brabandere <francisdb@gmail.com> Also fix InStrB registration to accept 2 args minimum, matching Windows. --- dlls/vbscript/global.c | 81 +++++++++++++++++++++++++++++++++++-- dlls/vbscript/tests/api.vbs | 6 +++ 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 14b58b017ef..54a24115744 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -1974,10 +1974,83 @@ static HRESULT Global_InStr(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, return return_int(res, ++ret ? ret+start : 0); } -static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_InStrB(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + BSTR str1, str2, conv_str1 = NULL, conv_str2 = NULL; + int start = 0, byte_len1, byte_len2; + const char *p, *end; + HRESULT hres; + int ret = -1; + + TRACE("(%u args)\n", args_cnt); + + assert(2 <= args_cnt && args_cnt <= 4); + + if(args_cnt == 2) { + if(V_VT(args) == VT_BSTR) { + str1 = V_BSTR(args); + }else { + hres = to_string(This->ctx->lcid, args, &conv_str1); + if(FAILED(hres)) + return hres; + str1 = conv_str1; + } + if(V_VT(args+1) == VT_BSTR) { + str2 = V_BSTR(args+1); + }else { + hres = to_string(This->ctx->lcid, args+1, &conv_str2); + if(FAILED(hres)) { + SysFreeString(conv_str1); + return hres; + } + str2 = conv_str2; + } + }else { + hres = to_int(args, &start); + if(FAILED(hres)) + return hres; + if(start <= 0) { + return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); + } + start--; + if(V_VT(args+1) == VT_BSTR) { + str1 = V_BSTR(args+1); + }else { + hres = to_string(This->ctx->lcid, args+1, &conv_str1); + if(FAILED(hres)) + return hres; + str1 = conv_str1; + } + if(V_VT(args+2) == VT_BSTR) { + str2 = V_BSTR(args+2); + }else { + hres = to_string(This->ctx->lcid, args+2, &conv_str2); + if(FAILED(hres)) { + SysFreeString(conv_str1); + return hres; + } + str2 = conv_str2; + } + } + + byte_len1 = SysStringByteLen(str1); + byte_len2 = SysStringByteLen(str2); + + if(byte_len2 == 0) { + ret = start; + }else if(start < byte_len1) { + end = (const char*)str1 + byte_len1 - byte_len2 + 1; + for(p = (const char*)str1 + start; p < end; p++) { + if(!memcmp(p, str2, byte_len2)) { + ret = p - (const char*)str1; + break; + } + } + } + + SysFreeString(conv_str1); + SysFreeString(conv_str2); + return return_int(res, ret >= 0 ? ret + 1 : 0); } static HRESULT Global_AscB(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) @@ -4438,7 +4511,7 @@ static const builtin_prop_t global_props[] = { {L"Hour", Global_Hour, 0, 1}, {L"InputBox", Global_InputBox, 0, 1, 7}, {L"InStr", Global_InStr, 0, 2, 4}, - {L"InStrB", Global_InStrB, 0, 3, 4}, + {L"InStrB", Global_InStrB, 0, 2, 4}, {L"InStrRev", Global_InStrRev, 0, 2, 4}, {L"Int", Global_Int, 0, 1}, {L"IsArray", Global_IsArray, 0, 1}, diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index f3878e7836c..306be2c49ff 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -2993,4 +2993,10 @@ end sub call testByteSubstrErrors() +' InStrB tests +Call ok(InStrB("ABC", "B") = 3, "InStrB(""ABC"", ""B"") = " & InStrB("ABC", "B")) +Call ok(InStrB("ABC", "D") = 0, "InStrB(""ABC"", ""D"") = " & InStrB("ABC", "D")) +Call ok(InStrB("ABC", "A") = 1, "InStrB(""ABC"", ""A"") = " & InStrB("ABC", "A")) +Call ok(InStrB("ABCABC", "B") = 3, "InStrB(""ABCABC"", ""B"") = " & InStrB("ABCABC", "B")) + Call reportSuccess() -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10510