From: Daniel Lehman dlehman25@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 );