From: Francis De Brabandere <francisdb@gmail.com> Date parsing in the Day/Month/Year/Hour/Minute/Second/Weekday/DateAdd built-ins went through VariantChangeType(..., 0, VT_DATE), so string inputs were always parsed with the user default locale regardless of SetLocale. Thread the script LCID through to_system_time() so date coercions honor the script-level locale, and use it in FormatDateTime in place of the inline VariantCopyInd + VariantChangeTypeEx pair. --- dlls/vbscript/global.c | 30 ++++++++++++------------------ dlls/vbscript/tests/lang.vbs | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 378be6d24e1..543dd76f39c 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -467,17 +467,17 @@ static HRESULT to_string(LCID lcid, VARIANT *v, BSTR *ret) return S_OK; } -static HRESULT to_system_time(VARIANT *v, SYSTEMTIME *st) +static HRESULT to_system_time(LCID lcid, VARIANT *v, SYSTEMTIME *st) { VARIANT date; HRESULT hres; V_VT(&date) = VT_EMPTY; - hres = VariantChangeType(&date, v, 0, VT_DATE); + hres = VariantChangeTypeEx(&date, v, lcid, 0, VT_DATE); if(FAILED(hres)) return hres; - return VariantTimeToSystemTime(V_DATE(&date), st); + return VariantTimeToSystemTime(V_DATE(&date), st) ? S_OK : E_INVALIDARG; } static HRESULT set_object_site(script_ctx_t *ctx, IUnknown *obj) @@ -2122,7 +2122,7 @@ static HRESULT Global_Day(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VA TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wDay); } @@ -2133,7 +2133,7 @@ static HRESULT Global_Month(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wMonth); } @@ -2178,7 +2178,7 @@ static HRESULT Global_Weekday(BuiltinDisp *This, VARIANT *args, unsigned args_cn if (V_VT(args) == VT_NULL) return return_null(res); - if (FAILED(hres = to_system_time(args, &st))) return hres; + if (FAILED(hres = to_system_time(This->ctx->lcid, args, &st))) return hres; return return_short(res, 1 + (7 - first_day + st.wDayOfWeek) % 7); } @@ -2190,7 +2190,7 @@ static HRESULT Global_Year(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, V TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wYear); } @@ -2201,7 +2201,7 @@ static HRESULT Global_Hour(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, V TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wHour); } @@ -2212,7 +2212,7 @@ static HRESULT Global_Minute(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wMinute); } @@ -2223,7 +2223,7 @@ static HRESULT Global_Second(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, TRACE("(%s)\n", debugstr_variant(arg)); - hres = to_system_time(arg, &st); + hres = to_system_time(This->ctx->lcid, arg, &st); return FAILED(hres) ? hres : return_short(res, st.wSecond); } @@ -2497,7 +2497,7 @@ static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *args, unsigned args_cn if (SUCCEEDED(hres)) hres = to_int(args + 1, &count); if (SUCCEEDED(hres)) - hres = to_system_time(args + 2, &ud.st); + hres = to_system_time(This->ctx->lcid, args + 2, &ud.st); if (SUCCEEDED(hres)) { if (!vbs_wcsicmp(interval, L"yyyy")) @@ -3697,7 +3697,6 @@ static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *args, unsigned int format = 0; LCID lcid = This->ctx->lcid; WCHAR buff[256]; - VARIANT v; SYSTEMTIME st; HRESULT hres; BSTR str; @@ -3724,13 +3723,8 @@ static HRESULT Global_FormatDateTime(BuiltinDisp *This, VARIANT *args, unsigned return return_bstr(res, str); } - V_VT(&v) = VT_EMPTY; - hres = VariantCopyInd(&v, args); + hres = to_system_time(lcid, args, &st); if(FAILED(hres)) return hres; - hres = VariantChangeTypeEx(&v, &v, lcid, 0, VT_DATE); - if(FAILED(hres)) return hres; - if(!VariantTimeToSystemTime(V_DATE(&v), &st)) - return E_INVALIDARG; switch(format) { case 1: /* vbLongDate */ diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 09cebe25bff..d66e52e8e3a 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -3849,6 +3849,23 @@ Call ok(CStr(1.5) = "1,5", "CStr(1.5) de-DE: " & CStr(1.5)) Call SetLocale(1033) Call ok(CStr(1.5) = "1.5", "CStr(1.5) en-US: " & CStr(1.5)) +' Day/Month/Year parse date strings using the script LCID. +Call SetLocale(1031) +Call ok(Day("15.03.2026") = 15, "Day(""15.03.2026"") de-DE: " & Day("15.03.2026")) +Call ok(Month("15.03.2026") = 3, "Month(""15.03.2026"") de-DE: " & Month("15.03.2026")) +Call ok(Year("15.03.2026") = 2026, "Year(""15.03.2026"") de-DE: " & Year("15.03.2026")) + +' The German-format string is rejected under en-US. +Call SetLocale(1033) +Dim dateErr +On Error Resume Next +Err.Clear +Call Day("15.03.2026") +dateErr = Err.Number +Err.Clear +On Error Goto 0 +Call ok(dateErr <> 0, "Day(""15.03.2026"") en-US should error: err=" & dateErr) + ' Restore original locale. Call SetLocale(origLcid) Call ok(GetLocale() = origLcid, "restore: GetLocale = " & GetLocale()) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10504