From 8993e15cfa5b77ac2487239354ffe63bbc5e562d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 11 Apr 2022 17:21:47 +0200 Subject: [PATCH] kernelbase: Support UTF-7/8 codepages in get_codepage_table(). Signed-off-by: Alexandre Julliard --- dlls/kernel32/tests/locale.c | 34 ++++++++++++++++-- dlls/kernelbase/locale.c | 86 +++++++++++++------------------------------- 2 files changed, 57 insertions(+), 63 deletions(-) diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 9b95fcae640..8dc5814162a 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -4251,6 +4251,7 @@ static void test_GetCPInfo(void) { BOOL ret; CPINFO cpinfo; + CPINFOEXW cpiw; SetLastError(0xdeadbeef); ret = GetCPInfo(CP_SYMBOL, &cpinfo); @@ -4275,6 +4276,18 @@ static void test_GetCPInfo(void) for (i = 0; i < sizeof(cpinfo.LeadByte); i++) ok(!cpinfo.LeadByte[i], "expected NUL byte in index %u\n", i); ok(cpinfo.MaxCharSize == 5, "expected 5, got 0x%x\n", cpinfo.MaxCharSize); + + memset( &cpiw, 0xcc, sizeof(cpiw) ); + ret = GetCPInfoExW( CP_UTF7, 0, &cpiw ); + ok( ret, "GetCPInfoExW failed err %lu\n", GetLastError() ); + ok( cpiw.DefaultChar[0] == 0x3f, "wrong DefaultChar[0] %02x\n", cpiw.DefaultChar[0] ); + ok( cpiw.DefaultChar[1] == 0, "wrong DefaultChar[1] %02x\n", cpiw.DefaultChar[1] ); + for (i = 0; i < 12; i++) ok( cpiw.LeadByte[i] == 0, "wrong LeadByte[%u] %02x\n", i, cpiw.LeadByte[i] ); + ok( cpiw.MaxCharSize == 5, "wrong MaxCharSize %02x\n", cpiw.MaxCharSize ); + ok( cpiw.CodePage == CP_UTF7, "wrong CodePage %02x\n", cpiw.CodePage ); + ok( cpiw.UnicodeDefaultChar == 0xfffd, "wrong UnicodeDefaultChar %02x\n", cpiw.UnicodeDefaultChar ); + ok( !wcscmp( cpiw.CodePageName, L"65000 (UTF-7)" ), + "wrong CodePageName %s\n", debugstr_w(cpiw.CodePageName) ); } memset(cpinfo.LeadByte, '-', ARRAY_SIZE(cpinfo.LeadByte)); @@ -4293,10 +4306,27 @@ static void test_GetCPInfo(void) ok(cpinfo.DefaultChar[1] == 0, "expected 0, got 0x%x\n", cpinfo.DefaultChar[1]); for (i = 0; i < sizeof(cpinfo.LeadByte); i++) ok(!cpinfo.LeadByte[i], "expected NUL byte in index %u\n", i); - ok(cpinfo.MaxCharSize == 4 || broken(cpinfo.MaxCharSize == 3) /* win9x */, - "expected 4, got %u\n", cpinfo.MaxCharSize); + ok(cpinfo.MaxCharSize == 4, "expected 4, got %u\n", cpinfo.MaxCharSize); + + memset( &cpiw, 0xcc, sizeof(cpiw) ); + ret = GetCPInfoExW( CP_UTF8, 0, &cpiw ); + ok( ret, "GetCPInfoExW failed err %lu\n", GetLastError() ); + ok( cpiw.DefaultChar[0] == 0x3f, "wrong DefaultChar[0] %02x\n", cpiw.DefaultChar[0] ); + ok( cpiw.DefaultChar[1] == 0, "wrong DefaultChar[1] %02x\n", cpiw.DefaultChar[1] ); + for (i = 0; i < 12; i++) ok( cpiw.LeadByte[i] == 0, "wrong LeadByte[%u] %02x\n", i, cpiw.LeadByte[i] ); + ok( cpiw.MaxCharSize == 4, "wrong MaxCharSize %02x\n", cpiw.MaxCharSize ); + ok( cpiw.CodePage == CP_UTF8, "wrong CodePage %02x\n", cpiw.CodePage ); + ok( cpiw.UnicodeDefaultChar == 0xfffd, "wrong UnicodeDefaultChar %02x\n", cpiw.UnicodeDefaultChar ); + ok( !wcscmp( cpiw.CodePageName, L"65001 (UTF-8)" ), + "wrong CodePageName %s\n", debugstr_w(cpiw.CodePageName) ); } + + SetLastError( 0xdeadbeef ); + ret = GetCPInfoExW( 0xbeef, 0, &cpiw ); + ok( !ret, "GetCPInfoExW succeeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() ); + if (pNtGetNlsSectionPtr) { CPTABLEINFO table; diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 67052af7e4f..c0cd0307447 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -164,8 +164,8 @@ static const struct { UINT cp; const WCHAR *name; } codepage_names[] = { 28604, L"ISO 8859-14 Latin 8 (Celtic)" }, { 28605, L"ISO 8859-15 Latin 9 (Euro)" }, { 28606, L"ISO 8859-16 Latin 10 (Balkan)" }, - { 65000, L"Unicode (UTF-7)" }, - { 65001, L"Unicode (UTF-8)" } + { 65000, L"65000 (UTF-7)" }, + { 65001, L"65001 (UTF-8)" } }; /* Unicode expanded ligatures */ @@ -1964,24 +1964,28 @@ static WCHAR compose_chars( WCHAR ch1, WCHAR ch2 ) static UINT get_locale_codepage( const NLS_LOCALE_DATA *locale, ULONG flags ) { UINT ret = locale->idefaultansicodepage; - if ((flags & LOCALE_USE_CP_ACP) || ret == CP_UTF8) ret = system_locale->idefaultansicodepage; + if ((flags & LOCALE_USE_CP_ACP) || ret == CP_UTF8) ret = nls_info.AnsiTableInfo.CodePage; return ret; } static UINT get_lcid_codepage( LCID lcid, ULONG flags ) { - UINT ret = GetACP(); + UINT ret = nls_info.AnsiTableInfo.CodePage; - if (!(flags & LOCALE_USE_CP_ACP) && lcid != GetSystemDefaultLCID()) - GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, - (WCHAR *)&ret, sizeof(ret)/sizeof(WCHAR) ); + if (!(flags & LOCALE_USE_CP_ACP) && lcid != system_lcid) + { + const NLS_LOCALE_DATA *locale = NlsValidateLocale( &lcid, 0 ); + if (locale) ret = locale->idefaultansicodepage; + } return ret; } static const CPTABLEINFO *get_codepage_table( UINT codepage ) { + static const CPTABLEINFO utf7_cpinfo = { CP_UTF7, 5, '?', 0xfffd, '?', '?' }; + static const CPTABLEINFO utf8_cpinfo = { CP_UTF8, 4, '?', 0xfffd, '?', '?' }; unsigned int i; USHORT *ptr; SIZE_T size; @@ -1996,15 +2000,13 @@ static const CPTABLEINFO *get_codepage_table( UINT codepage ) codepage = mac_cp; break; case CP_THREAD_ACP: - if (NtCurrentTeb()->CurrentLocale == GetUserDefaultLCID()) return &nls_info.AnsiTableInfo; codepage = get_lcid_codepage( NtCurrentTeb()->CurrentLocale, 0 ); - if (!codepage) return &nls_info.AnsiTableInfo; - break; - default: - if (codepage == nls_info.AnsiTableInfo.CodePage) return &nls_info.AnsiTableInfo; - if (codepage == nls_info.OemTableInfo.CodePage) return &nls_info.OemTableInfo; break; } + if (codepage == nls_info.AnsiTableInfo.CodePage) return &nls_info.AnsiTableInfo; + if (codepage == nls_info.OemTableInfo.CodePage) return &nls_info.OemTableInfo; + if (codepage == CP_UTF8) return &utf8_cpinfo; + if (codepage == CP_UTF7) return &utf7_cpinfo; RtlEnterCriticalSection( &locale_section ); @@ -4838,27 +4840,14 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetCPInfo( UINT codepage, CPINFO *cpinfo ) { const CPTABLEINFO *table; - if (!cpinfo) + if (!cpinfo || !(table = get_codepage_table( codepage ))) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - switch (codepage) - { - case CP_UTF7: - case CP_UTF8: - cpinfo->DefaultChar[0] = 0x3f; - cpinfo->DefaultChar[1] = 0; - memset( cpinfo->LeadByte, 0, sizeof(cpinfo->LeadByte) ); - cpinfo->MaxCharSize = (codepage == CP_UTF7) ? 5 : 4; - break; - default: - if (!(table = get_codepage_table( codepage ))) return FALSE; - cpinfo->MaxCharSize = table->MaximumCharacterSize; - memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) ); - memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) ); - break; - } + cpinfo->MaxCharSize = table->MaximumCharacterSize; + memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) ); + memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) ); return TRUE; } @@ -4871,38 +4860,16 @@ BOOL WINAPI GetCPInfoExW( UINT codepage, DWORD flags, CPINFOEXW *cpinfo ) const CPTABLEINFO *table; int min, max, pos; - if (!cpinfo) + if (!cpinfo || !(table = get_codepage_table( codepage ))) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - switch (codepage) - { - case CP_UTF7: - cpinfo->DefaultChar[0] = 0x3f; - cpinfo->DefaultChar[1] = 0; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0; - cpinfo->MaxCharSize = 5; - cpinfo->CodePage = CP_UTF7; - cpinfo->UnicodeDefaultChar = 0x3f; - break; - case CP_UTF8: - cpinfo->DefaultChar[0] = 0x3f; - cpinfo->DefaultChar[1] = 0; - cpinfo->LeadByte[0] = cpinfo->LeadByte[1] = 0; - cpinfo->MaxCharSize = 4; - cpinfo->CodePage = CP_UTF8; - cpinfo->UnicodeDefaultChar = 0x3f; - break; - default: - if (!(table = get_codepage_table( codepage ))) return FALSE; - cpinfo->MaxCharSize = table->MaximumCharacterSize; - memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) ); - memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) ); - cpinfo->CodePage = table->CodePage; - cpinfo->UnicodeDefaultChar = table->UniDefaultChar; - break; - } + cpinfo->MaxCharSize = table->MaximumCharacterSize; + memcpy( cpinfo->DefaultChar, &table->DefaultChar, sizeof(cpinfo->DefaultChar) ); + memcpy( cpinfo->LeadByte, table->LeadByte, sizeof(cpinfo->LeadByte) ); + cpinfo->CodePage = table->CodePage; + cpinfo->UnicodeDefaultChar = table->UniDefaultChar; min = 0; max = ARRAY_SIZE(codepage_names) - 1; @@ -5775,9 +5742,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsValidCodePage( UINT codepage ) case CP_MACCP: case CP_THREAD_ACP: return FALSE; - case CP_UTF7: - case CP_UTF8: - return TRUE; default: return get_codepage_table( codepage ) != NULL; } -- 2.11.4.GIT