Signed-off-by: Mark Harmstone mark@harmstone.com --- dlls/ntdll/tests/Makefile.in | 1 + dlls/ntdll/tests/mui.c | 451 +++++++++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 dlls/ntdll/tests/mui.c
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index ed15c51339f..e8896fe25cb 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ generated.c \ info.c \ large_int.c \ + mui.c \ om.c \ path.c \ pipe.c \ diff --git a/dlls/ntdll/tests/mui.c b/dlls/ntdll/tests/mui.c new file mode 100644 index 00000000000..488dfc02033 --- /dev/null +++ b/dlls/ntdll/tests/mui.c @@ -0,0 +1,451 @@ +/* + * Unit test suite for MUI functions + * + * Copyright 2021 Mark Harmstone + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "ntdll_test.h" + +static BOOLEAN (NTAPI *pRtlLCIDToCultureName)(LCID, PUNICODE_STRING); +static NTSTATUS (NTAPI *pNtQueryDefaultLocale)(BOOLEAN, PLCID); +static LONG (NTAPI *pRtlCompareUnicodeString)(PCUNICODE_STRING, PCUNICODE_STRING, BOOLEAN); + +static const char *debugstr_us( const UNICODE_STRING *us ) +{ + if (!us) return "<null>"; + return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) ); +} + +static void test_lcid_to_culture_name(void) +{ + struct lang + { + LCID lcid; + const WCHAR *name; + }; + + static const struct lang list[] = + { + { 0x0001, L"ar" }, + { 0x0002, L"bg" }, + { 0x0003, L"ca" }, + { 0x0004, L"zh-Hans" }, + { 0x0005, L"cs" }, + { 0x0006, L"da" }, + { 0x0007, L"de" }, + { 0x0008, L"el" }, + { 0x0009, L"en" }, + { 0x000a, L"es" }, + { 0x000b, L"fi" }, + { 0x000c, L"fr" }, + { 0x000d, L"he" }, + { 0x000e, L"hu" }, + { 0x000f, L"is" }, + { 0x0010, L"it" }, + { 0x0011, L"ja" }, + { 0x0012, L"ko" }, + { 0x0013, L"nl" }, + { 0x0014, L"no" }, + { 0x0015, L"pl" }, + { 0x0016, L"pt" }, + { 0x0017, L"rm" }, + { 0x0018, L"ro" }, + { 0x0019, L"ru" }, + { 0x001a, L"hr" }, + { 0x001b, L"sk" }, + { 0x001c, L"sq" }, + { 0x001d, L"sv" }, + { 0x001e, L"th" }, + { 0x001f, L"tr" }, + { 0x0020, L"ur" }, + { 0x0021, L"id" }, + { 0x0022, L"uk" }, + { 0x0023, L"be" }, + { 0x0024, L"sl" }, + { 0x0025, L"et" }, + { 0x0026, L"lv" }, + { 0x0027, L"lt" }, + { 0x0028, L"tg" }, + { 0x0029, L"fa" }, + { 0x002a, L"vi" }, + { 0x002b, L"hy" }, + { 0x002c, L"az" }, + { 0x002d, L"eu" }, + { 0x002e, L"hsb" }, + { 0x002f, L"mk" }, + { 0x0032, L"tn" }, + { 0x0034, L"xh" }, + { 0x0035, L"zu" }, + { 0x0036, L"af" }, + { 0x0037, L"ka" }, + { 0x0038, L"fo" }, + { 0x0039, L"hi" }, + { 0x003a, L"mt" }, + { 0x003b, L"se" }, + { 0x003c, L"ga" }, + { 0x003e, L"ms" }, + { 0x003f, L"kk" }, + { 0x0040, L"ky" }, + { 0x0041, L"sw" }, + { 0x0042, L"tk" }, + { 0x0043, L"uz" }, + { 0x0044, L"tt" }, + { 0x0045, L"bn" }, + { 0x0046, L"pa" }, + { 0x0047, L"gu" }, + { 0x0048, L"or" }, + { 0x0049, L"ta" }, + { 0x004a, L"te" }, + { 0x004b, L"kn" }, + { 0x004c, L"ml" }, + { 0x004d, L"as" }, + { 0x004e, L"mr" }, + { 0x004f, L"sa" }, + { 0x0050, L"mn" }, + { 0x0051, L"bo" }, + { 0x0052, L"cy" }, + { 0x0053, L"km" }, + { 0x0054, L"lo" }, + { 0x0056, L"gl" }, + { 0x0057, L"kok" }, + { 0x005a, L"syr" }, + { 0x005b, L"si" }, + { 0x005d, L"iu" }, + { 0x005e, L"am" }, + { 0x005f, L"tzm" }, + { 0x0061, L"ne" }, + { 0x0062, L"fy" }, + { 0x0063, L"ps" }, + { 0x0064, L"fil" }, + { 0x0065, L"dv" }, + { 0x0068, L"ha" }, + { 0x006a, L"yo" }, + { 0x006b, L"quz" }, + { 0x006c, L"nso" }, + { 0x006d, L"ba" }, + { 0x006e, L"lb" }, + { 0x006f, L"kl" }, + { 0x0070, L"ig" }, + { 0x0078, L"ii" }, + { 0x007a, L"arn" }, + { 0x007c, L"moh" }, + { 0x007e, L"br" }, + { 0x007f, L"" }, + { 0x0080, L"ug" }, + { 0x0081, L"mi" }, + { 0x0082, L"oc" }, + { 0x0083, L"co" }, + { 0x0084, L"gsw" }, + { 0x0085, L"sah" }, + { 0x0087, L"rw" }, + { 0x0088, L"wo" }, + { 0x008c, L"prs" }, + { 0x0401, L"ar-SA" }, + { 0x0402, L"bg-BG" }, + { 0x0403, L"ca-ES" }, + { 0x0404, L"zh-TW" }, + { 0x0405, L"cs-CZ" }, + { 0x0406, L"da-DK" }, + { 0x0407, L"de-DE" }, + { 0x0408, L"el-GR" }, + { 0x0409, L"en-US" }, + { 0x040a, L"es-ES_tradnl" }, + { 0x040b, L"fi-FI" }, + { 0x040c, L"fr-FR" }, + { 0x040d, L"he-IL" }, + { 0x040e, L"hu-HU" }, + { 0x040f, L"is-IS" }, + { 0x0410, L"it-IT" }, + { 0x0411, L"ja-JP" }, + { 0x0412, L"ko-KR" }, + { 0x0413, L"nl-NL" }, + { 0x0414, L"nb-NO" }, + { 0x0415, L"pl-PL" }, + { 0x0416, L"pt-BR" }, + { 0x0417, L"rm-CH" }, + { 0x0418, L"ro-RO" }, + { 0x0419, L"ru-RU" }, + { 0x041a, L"hr-HR" }, + { 0x041b, L"sk-SK" }, + { 0x041c, L"sq-AL" }, + { 0x041d, L"sv-SE" }, + { 0x041e, L"th-TH" }, + { 0x041f, L"tr-TR" }, + { 0x0420, L"ur-PK" }, + { 0x0421, L"id-ID" }, + { 0x0422, L"uk-UA" }, + { 0x0423, L"be-BY" }, + { 0x0424, L"sl-SI" }, + { 0x0425, L"et-EE" }, + { 0x0426, L"lv-LV" }, + { 0x0427, L"lt-LT" }, + { 0x0429, L"fa-IR" }, + { 0x042a, L"vi-VN" }, + { 0x042b, L"hy-AM" }, + { 0x042c, L"az-Latn-AZ" }, + { 0x042d, L"eu-ES" }, + { 0x042f, L"mk-MK" }, + { 0x0436, L"af-ZA" }, + { 0x0437, L"ka-GE" }, + { 0x0438, L"fo-FO" }, + { 0x0439, L"hi-IN" }, + { 0x043e, L"ms-MY" }, + { 0x043f, L"kk-KZ" }, + { 0x0440, L"ky-KG" }, + { 0x0441, L"sw-KE" }, + { 0x0443, L"uz-Latn-UZ" }, + { 0x0444, L"tt-RU" }, + { 0x0445, L"bn-IN" }, + { 0x0446, L"pa-IN" }, + { 0x0447, L"gu-IN" }, + { 0x0449, L"ta-IN" }, + { 0x044a, L"te-IN" }, + { 0x044b, L"kn-IN" }, + { 0x044e, L"mr-IN" }, + { 0x044f, L"sa-IN" }, + { 0x0450, L"mn-MN" }, + { 0x0452, L"cy-GB" }, + { 0x0456, L"gl-ES" }, + { 0x0457, L"kok-IN" }, + { 0x045a, L"syr-SY" }, + { 0x045b, L"si-LK" }, + { 0x0461, L"ne-NP" }, + { 0x0465, L"dv-MV" }, + { 0x047e, L"br-FR" }, + { 0x0801, L"ar-IQ" }, + { 0x0804, L"zh-CN" }, + { 0x0807, L"de-CH" }, + { 0x0809, L"en-GB" }, + { 0x080a, L"es-MX" }, + { 0x080c, L"fr-BE" }, + { 0x0810, L"it-CH" }, + { 0x0813, L"nl-BE" }, + { 0x0814, L"nn-NO" }, + { 0x0816, L"pt-PT" }, + { 0x081a, L"sr-Latn-CS" }, + { 0x081d, L"sv-FI" }, + { 0x082c, L"az-Cyrl-AZ" }, + { 0x083c, L"ga-IE" }, + { 0x083e, L"ms-BN" }, + { 0x0843, L"uz-Cyrl-UZ" }, + { 0x0c01, L"ar-EG" }, + { 0x0c04, L"zh-HK" }, + { 0x0c07, L"de-AT" }, + { 0x0c09, L"en-AU" }, + { 0x0c0a, L"es-ES" }, + { 0x0c0c, L"fr-CA" }, + { 0x1001, L"ar-LY" }, + { 0x1004, L"zh-SG" }, + { 0x1007, L"de-LU" }, + { 0x1009, L"en-CA" }, + { 0x100a, L"es-GT" }, + { 0x100c, L"fr-CH" }, + { 0x1401, L"ar-DZ" }, + { 0x1404, L"zh-MO" }, + { 0x1407, L"de-LI" }, + { 0x1409, L"en-NZ" }, + { 0x140a, L"es-CR" }, + { 0x140c, L"fr-LU" }, + { 0x1801, L"ar-MA" }, + { 0x1809, L"en-IE" }, + { 0x180a, L"es-PA" }, + { 0x180c, L"fr-MC" }, + { 0x1c01, L"ar-TN" }, + { 0x1c09, L"en-ZA" }, + { 0x1c0a, L"es-DO" }, + { 0x2001, L"ar-OM" }, + { 0x2009, L"en-JM" }, + { 0x200a, L"es-VE" }, + { 0x2401, L"ar-YE" }, + { 0x2409, L"en-029" }, + { 0x240a, L"es-CO" }, + { 0x2801, L"ar-SY" }, + { 0x2809, L"en-BZ" }, + { 0x280a, L"es-PE" }, + { 0x2c01, L"ar-JO" }, + { 0x2c09, L"en-TT" }, + { 0x2c0a, L"es-AR" }, + { 0x3001, L"ar-LB" }, + { 0x3009, L"en-ZW" }, + { 0x300a, L"es-EC" }, + { 0x3401, L"ar-KW" }, + { 0x3409, L"en-PH" }, + { 0x340a, L"es-CL" }, + { 0x3801, L"ar-AE" }, + { 0x380a, L"es-UY" }, + { 0x3c01, L"ar-BH" }, + { 0x3c0a, L"es-PY" }, + { 0x4001, L"ar-QA" }, + { 0x400a, L"es-BO" }, + { 0x440a, L"es-SV" }, + { 0x480a, L"es-HN" }, + { 0x4c0a, L"es-NI" }, + { 0x500a, L"es-PR" }, + { 0, NULL } + }; + + /* Languages introduced after Vista */ + static const struct lang opt_list[] = + { + { 0x0058, L"mni" }, + { 0x0059, L"sd" }, + { 0x0491, L"gd-GB" }, + { 0x241a, L"sr-Latn-RS" }, + { 0, NULL } + }; + + unsigned int i; + WCHAR buf[255]; + UNICODE_STRING us; + NTSTATUS nts; + LCID user_lcid, system_lcid; + + if (!pRtlLCIDToCultureName) + { + win_skip("RtlLCIDToCultureName not supported\n"); + return; + } + + us.Buffer = buf; + us.Length = us.MaximumLength = sizeof(buf); + + i = 0; + while (list[i].name) + { + BOOLEAN ret; + + ret = pRtlLCIDToCultureName(list[i].lcid, &us); + + ok(ret, "RtlLCIDTOCultureName failed for LCID %04x\n", list[i].lcid); + + if (ret) + { + ok(us.Length == wcslen(list[i].name) * sizeof(WCHAR) + && !memcmp(us.Buffer, list[i].name, us.Length), + "RtlLCIDTOCultureName returned wrong value for LCID %04x (%s, expected %s)\n", + list[i].lcid, debugstr_us(&us), debugstr_w(list[i].name)); + } + + i++; + } + + i = 0; + while (opt_list[i].name) + { + BOOLEAN ret; + + ret = pRtlLCIDToCultureName(opt_list[i].lcid, &us); + + if (!ret) + { + win_skip("RtlLCIDTOCultureName does not recognize LCID %04x\n", + opt_list[i].lcid); + } + else + { + ok(us.Length == wcslen(opt_list[i].name) * sizeof(WCHAR) + && !memcmp(us.Buffer, opt_list[i].name, us.Length), + "RtlLCIDTOCultureName returned wrong value for LCID %04x (%s, expected %s)\n", + opt_list[i].lcid, debugstr_us(&us), debugstr_w(opt_list[i].name)); + } + + i++; + } + + if (!pNtQueryDefaultLocale) + { + win_skip("NtQueryDefaultLocale not supported\n"); + return; + } + + nts = pNtQueryDefaultLocale(TRUE, &user_lcid); + + ok(NT_SUCCESS(nts), "NtQueryDefaultLocale(TRUE) returned %08x, expected STATUS_SUCCESS\n", + nts); + + if (NT_SUCCESS(nts)) + { + WCHAR buf2[255]; + UNICODE_STRING us2; + BOOLEAN ret; + + us2.Buffer = buf2; + us2.Length = us2.MaximumLength = sizeof(buf2); + + ret = pRtlLCIDToCultureName(user_lcid, &us2); + + ok(ret, "RtlLCIDTOCultureName failed for LCID %04x\n", list[i].lcid); + + if (ret) + { + ret = pRtlLCIDToCultureName(LOCALE_USER_DEFAULT, &us); + + ok(ret, "RtlLCIDTOCultureName failed for LOCALE_USER_DEFAULT\n"); + + if (ret) + { + ok(!pRtlCompareUnicodeString(&us, &us2, FALSE), + "RtlLCIDTOCultureName returned incorrect value for LOCALE_USER_DEFAULT (%s, expected %s)\n", + debugstr_us(&us), debugstr_us(&us2)); + } + } + } + + nts = pNtQueryDefaultLocale(FALSE, &system_lcid); + + ok(NT_SUCCESS(nts), "NtQueryDefaultLocale(FALSE) returned %08x, expected STATUS_SUCCESS\n", + nts); + + if (NT_SUCCESS(nts)) + { + WCHAR buf2[255]; + UNICODE_STRING us2; + BOOLEAN ret; + + us2.Buffer = buf2; + us2.Length = us2.MaximumLength = sizeof(buf2); + + ret = pRtlLCIDToCultureName(system_lcid, &us2); + + ok(ret, "RtlLCIDTOCultureName failed for LCID %04x\n", list[i].lcid); + + if (ret) + { + ret = pRtlLCIDToCultureName(LOCALE_SYSTEM_DEFAULT, &us); + + ok(ret, "RtlLCIDTOCultureName failed for LOCALE_SYSTEM_DEFAULT\n"); + + if (ret) + { + ok(!pRtlCompareUnicodeString(&us, &us2, FALSE), + "RtlLCIDTOCultureName returned incorrect value for LOCALE_SYSTEM_DEFAULT (%s, expected %s)\n", + debugstr_us(&us), debugstr_us(&us2)); + } + } + } +} + +START_TEST(mui) +{ + HMODULE hntdll = GetModuleHandleA( "ntdll.dll" ); + + pRtlCompareUnicodeString = (void*)GetProcAddress( hntdll, "RtlCompareUnicodeString" ); + pRtlLCIDToCultureName = (void*)GetProcAddress( hntdll, "RtlLCIDToCultureName" ); + pNtQueryDefaultLocale = (void*)GetProcAddress( hntdll, "NtQueryDefaultLocale" ); + + test_lcid_to_culture_name(); +}