From: Francis De Brabandere <francisdb@gmail.com> --- dlls/vbscript/global.c | 51 ++++++++++++++++++++++++++++++++++--- dlls/vbscript/tests/api.vbs | 51 +++++++++++++++++++++++++++++++++++++ dlls/vbscript/tests/run.c | 21 ++++++++++++++- dlls/vbscript/vbscript.c | 1 + dlls/vbscript/vbscript.h | 3 ++- 5 files changed, 121 insertions(+), 6 deletions(-) diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index f1afcfade89..bda190624ce 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2229,8 +2229,51 @@ static HRESULT Global_Second(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, static HRESULT Global_SetLocale(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + LCID old_lcid = This->ctx->lcid; + LCID new_lcid; + HRESULT hres; + + TRACE("%s\n", args_cnt ? debugstr_variant(args) : "()"); + + if(!args_cnt) { + This->ctx->lcid = This->ctx->host_lcid; + return return_int(res, old_lcid); + } + + switch(V_VT(args)) { + case VT_NULL: + return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); + case VT_EMPTY: + This->ctx->lcid = This->ctx->host_lcid; + return return_int(res, old_lcid); + case VT_BSTR: { + int i; + /* Try numeric conversion first (e.g. "1033") */ + hres = to_int(args, &i); + if(SUCCEEDED(hres)) { + new_lcid = i; + }else { + /* Try as locale name (e.g. "en-us") */ + new_lcid = LocaleNameToLCID(V_BSTR(args), 0); + } + break; + } + default: { + int i; + hres = to_int(args, &i); + if(FAILED(hres)) + return hres; + new_lcid = i; + break; + } + } + + This->ctx->lcid = new_lcid; + return_int(res, old_lcid); + if(!IsValidLocale(new_lcid, LCID_INSTALLED)) + return MAKE_VBSERROR(VBSE_LOCALE_SETTING_NOT_SUPPORTED); + + return S_OK; } static HRESULT Global_DateValue(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) @@ -3386,8 +3429,8 @@ static HRESULT Global_FormatPercent(BuiltinDisp *This, VARIANT *args, unsigned a static HRESULT Global_GetLocale(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + TRACE("() = %#lx\n", This->ctx->lcid); + return return_int(res, This->ctx->lcid); } static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index 2a4f69f0f59..91b4bd10bb6 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -2794,4 +2794,55 @@ end sub call testFilterError() +' GetLocale/SetLocale tests +Dim origLocale +origLocale = GetLocale() +Call ok(getVT(GetLocale()) = "VT_I4", "getVT(GetLocale()) = " & getVT(GetLocale())) + +Dim prevLocale +prevLocale = SetLocale(1033) +Call ok(getVT(prevLocale) = "VT_I4*", "getVT(SetLocale result) = " & getVT(prevLocale)) +Call ok(prevLocale = origLocale, "SetLocale(1033) returned " & prevLocale & " expected " & origLocale) +Call ok(GetLocale() = 1033, "GetLocale() after SetLocale(1033) = " & GetLocale()) + +prevLocale = SetLocale(1031) +Call ok(prevLocale = 1033, "SetLocale(1031) returned " & prevLocale & " expected 1033") +Call ok(GetLocale() = 1031, "GetLocale() after SetLocale(1031) = " & GetLocale()) + +' SetLocale with string locale name +prevLocale = SetLocale("en-us") +Call ok(prevLocale = 1031, "SetLocale(""en-us"") returned " & prevLocale & " expected 1031") +Call ok(GetLocale() = 1033, "GetLocale() after SetLocale(""en-us"") = " & GetLocale()) + +' SetLocale with numeric string +prevLocale = SetLocale("1031") +Call ok(prevLocale = 1033, "SetLocale(""1031"") returned " & prevLocale & " expected 1033") +Call ok(GetLocale() = 1031, "GetLocale() after SetLocale(""1031"") = " & GetLocale()) + +' SetLocale() with no args resets to system default +SetLocale(1033) +prevLocale = SetLocale() +Call ok(prevLocale = 1033, "SetLocale() returned " & prevLocale & " expected 1033") + +sub testSetLocaleError() + on error resume next + + ' SetLocale(Null) should raise error 94 + call Err.clear() + call SetLocale(Null) + Call ok(Err.number = 94, "SetLocale(Null) Err.number = " & Err.number) + + ' SetLocale with invalid numeric LCID should raise error 447 + call Err.clear() + dim prev + prev = SetLocale(99999) + Call ok(Err.number = 447, "SetLocale(99999) Err.number = " & Err.number) +end sub + +call testSetLocaleError() + +' Restore original locale +SetLocale(origLocale) +Call ok(GetLocale() = origLocale, "GetLocale() after restore = " & GetLocale() & " expected " & origLocale) + Call reportSuccess() diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index f4b4829f902..668368bc5f3 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -1962,9 +1962,12 @@ static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface) return 1; } +/* 0 = use the user default; otherwise return this LCID to the engine. */ +static LCID site_lcid_override; + static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *plcid) { - *plcid = GetUserDefaultLCID(); + *plcid = site_lcid_override ? site_lcid_override : GetUserDefaultLCID(); return S_OK; } @@ -3842,12 +3845,28 @@ static void run_from_res(const char *name) test_name = ""; } +static void test_setlocale_reset_uses_host_lcid(void) +{ + /* The engine takes the LCID returned by IActiveScriptSite::GetLCID as the + * baseline; SetLocale with no argument must restore it regardless of the + * user default. */ + site_lcid_override = 1036; /* fr-FR */ + parse_script_w(L"Call ok(GetLocale() = 1036, \"initial GetLocale = \" & GetLocale())\n" + L"SetLocale 1041\n" + L"Call ok(GetLocale() = 1041, \"after SetLocale 1041: \" & GetLocale())\n" + L"SetLocale\n" + L"Call ok(GetLocale() = 1036, \"after SetLocale reset: \" & GetLocale())\n"); + site_lcid_override = 0; +} + static void run_tests(void) { HRESULT hres; strict_dispid_check = TRUE; + test_setlocale_reset_uses_host_lcid(); + parse_script_w(L""); parse_script_w(L"' empty ;"); diff --git a/dlls/vbscript/vbscript.c b/dlls/vbscript/vbscript.c index c274e3a2f7f..ff28b3b17ef 100644 --- a/dlls/vbscript/vbscript.c +++ b/dlls/vbscript/vbscript.c @@ -735,6 +735,7 @@ static HRESULT WINAPI VBScript_SetScriptSite(IActiveScript *iface, IActiveScript IActiveScriptSite_GetLCID(This->ctx->site, &lcid); This->ctx->lcid = IsValidLocale(lcid, 0) ? lcid : GetUserDefaultLCID(); + This->ctx->host_lcid = This->ctx->lcid; GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&This->ctx->codepage, sizeof(This->ctx->codepage)/sizeof(WCHAR)); if (!This->ctx->codepage) diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h index e9eae6b5819..b9f238c3e3e 100644 --- a/dlls/vbscript/vbscript.h +++ b/dlls/vbscript/vbscript.h @@ -203,7 +203,8 @@ struct vbcaller { struct _script_ctx_t { IActiveScriptSite *site; - LCID lcid; + LCID lcid; /* current, mutable via SetLocale */ + LCID host_lcid; /* embedder-supplied baseline (IActiveScriptSite::GetLCID) */ UINT codepage; IInternetHostSecurityManager *secmgr; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10504