From: Daniel Lehman <dlehman25(a)gmail.com> --- dlls/kernel32/tests/locale.c | 11 ------- dlls/kernelbase/locale.c | 59 +++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index bd94e10e9a3..53729453940 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -2929,7 +2929,6 @@ static void test_LCMapStringEx(void) } ok(!!handle, "error %ld\n", GetLastError()); - todo_wine ok(handle == ret, "ret %x, handle %#Ix, error %ld\n", ret, handle, GetLastError()); handle_en = handle; @@ -2938,10 +2937,8 @@ static void test_LCMapStringEx(void) ret = pLCMapStringEx(L"tr-TR", LCMAP_SORTHANDLE, NULL, 0, (LPWSTR)&handle, sizeof(handle), NULL, NULL, 0); ok(!!handle, "error %ld\n", GetLastError()); - todo_wine ok(handle == ret, "ret %x, handle %#Ix, error %ld\n", ret, handle, GetLastError()); handle_tr = handle; - todo_wine ok(handle_en != handle_tr, "handle_en %#Ix, handle_tr %#Ix\n", handle_en, handle_tr); SetLastError(0xdeadbeef); @@ -2956,17 +2953,14 @@ static void test_LCMapStringEx(void) ret = pLCMapStringEx(NULL, LCMAP_LOWERCASE|LCMAP_LINGUISTIC_CASING, L"I", -1, buf, ARRAY_SIZE(buf), NULL, NULL, handle_tr); ok(ret == 2, "ret %d, error %ld\n", ret, GetLastError()); - todo_wine ok(!lstrcmpW(buf, L"\x0131"), "string compare mismatch\n"); SetLastError(0xdeadbeef); handle = 0xdeadbeef; ret = pLCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTHANDLE, NULL, 0, (LPWSTR)&handle, sizeof(handle), NULL, NULL, 0); - todo_wine { ok(!!ret, "error %ld\n", GetLastError()); ok(handle == ret, "ret %x, handle %#Ix, error %ld\n", ret, handle, GetLastError()); - } /* bogus parms with SORTHANDLE */ handle = 0xdeadbeef; @@ -2979,7 +2973,6 @@ static void test_LCMapStringEx(void) handle = 0xdeadbeef; ret = pLCMapStringEx(L"en-US", LCMAP_SORTHANDLE, L"I", -1, (LPWSTR)&handle, sizeof(handle), NULL, NULL, 0); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d, error %ld\n", ret, GetLastError()); ok(handle == 0xdeadbeef, "handle %#Ix\n", handle); @@ -2997,21 +2990,17 @@ static void test_LCMapStringEx(void) memset(buf, 0, sizeof(buf)); ret = pLCMapStringEx(L"en-US", LCMAP_LOWERCASE|LCMAP_LINGUISTIC_CASING, L"I", -1, buf, ARRAY_SIZE(buf), NULL, NULL, handle_en); - todo_wine { ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d, error %ld\n", ret, GetLastError()); ok(!buf[0], "buf %x\n", buf[0]); - } SetLastError(0xdeadbeef); memset(buf, 0, sizeof(buf)); ret = pLCMapStringEx(NULL, LCMAP_LOWERCASE|LCMAP_LINGUISTIC_CASING, L"I", -1, buf, ARRAY_SIZE(buf), NULL, NULL, 0xdeadbeef); - todo_wine { ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "ret %d, error %ld\n", ret, GetLastError()); ok(!buf[0], "buf %x\n", buf[0]); - } } struct neutralsublang_name_t { diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 44af29f163d..33452edb7f5 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -654,7 +654,7 @@ static const NLS_LOCALE_DATA *get_locale_by_name( const WCHAR *name, LCID *lcid } -static const struct sortguid *get_language_sort( const WCHAR *name ) +static const struct sortguid *get_language_sort_index( const WCHAR *name, LPARAM *index ) { const NLS_LOCALE_LCNAME_INDEX *entry; const NLS_LOCALE_DATA *locale; @@ -678,7 +678,11 @@ static const struct sortguid *get_language_sort( const WCHAR *name ) SetLastError( ERROR_INVALID_PARAMETER ); return NULL; } - if ((ret = locale_sorts[entry - lcnames_index])) return ret; + if ((ret = locale_sorts[entry - lcnames_index])) + { + *index = ret - &sort.guids[0]; + return ret; + } lcid = entry->id; name = locale_strings + entry->name + 1; @@ -701,10 +705,16 @@ static const struct sortguid *get_language_sort( const WCHAR *name ) RegCloseKey( key ); } if (!ret) ret = &sort.guids[0]; + *index = ret - &sort.guids[0]; locale_sorts[entry - lcnames_index] = ret; return ret; } +static inline const struct sortguid *get_language_sort( const WCHAR *name ) +{ + LPARAM dummy; + return get_language_sort_index( name, &dummy ); +} /****************************************************************************** * NlsValidateLocale (kernelbase.@) @@ -6613,10 +6623,25 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co if (version) FIXME( "unsupported version structure %p\n", version ); if (reserved) FIXME( "unsupported reserved pointer %p\n", reserved ); - if (handle) + + if (flags & LCMAP_SORTHANDLE) { - static int once; - if (!once++) FIXME( "unsupported lparam %Ix\n", handle ); + if (src || srclen || !dst || dstlen < sizeof(LPARAM)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + handle = 0; + if (!(get_language_sort_index( locale, &handle ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + handle = MAKELONG(handle, 1); + *(LPARAM *)dst = handle; + return handle; } if (!src || !srclen || dstlen < 0) @@ -6639,18 +6664,30 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co } if (flags & (LCMAP_LOWERCASE | LCMAP_UPPERCASE | LCMAP_SORTKEY)) { - if (!(sortid = get_language_sort( locale ))) return 0; + if (handle) + { + if (locale) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + handle = LOWORD(handle); + if (handle < 0 || handle >= sort.guid_count) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + sortid = &sort.guids[handle]; + } + else if (!(sortid = get_language_sort( locale ))) return 0; } if (flags & LCMAP_HASH) { FIXME( "LCMAP_HASH %s not supported\n", debugstr_wn( src, srclen )); return 0; } - if (flags & LCMAP_SORTHANDLE) - { - FIXME( "LCMAP_SORTHANDLE not supported\n" ); - return 0; - } if (flags & LCMAP_SORTKEY) return get_sortkey( sortid, flags, src, srclen, (BYTE *)dst, dstlen ); return lcmap_string( sortid, flags, src, srclen, dst, dstlen ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5696