diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 43e339ba393..e4ce77ebe05 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -324,6 +324,7 @@ @ stdcall EnumSystemLanguageGroupsA(ptr long ptr) @ stdcall EnumSystemLanguageGroupsW(ptr long ptr) @ stdcall EnumSystemLocalesA(ptr long) +@ stdcall EnumSystemLocalesEx(ptr long long ptr) @ stdcall EnumSystemLocalesW(ptr long) @ stdcall EnumTimeFormatsA(ptr long long) @ stdcall EnumTimeFormatsW(ptr long long) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 168bb198c3b..927d05850cc 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -2222,6 +2222,55 @@ BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags ) } +struct enum_locale_ex_data +{ + LOCALE_ENUMPROCEX proc; + DWORD flags; + LPARAM lparam; +}; + +static BOOL CALLBACK enum_locale_ex_proc( HMODULE module, LPCWSTR type, + LPCWSTR name, WORD lang, LONG_PTR lparam ) +{ + struct enum_locale_ex_data *data = (struct enum_locale_ex_data *)lparam; + WCHAR buffer[256]; + DWORD neutral; + unsigned int flags; + + GetLocaleInfoW( MAKELCID( lang, SORT_DEFAULT ), LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, + buffer, sizeof(buffer) / sizeof(WCHAR) ); + if (!GetLocaleInfoW( MAKELCID( lang, SORT_DEFAULT ), + LOCALE_INEUTRAL | LOCALE_NOUSEROVERRIDE | LOCALE_RETURN_NUMBER, + (LPWSTR)&neutral, sizeof(neutral) / sizeof(WCHAR) )) + neutral = 0; + flags = LOCALE_WINDOWS; + flags |= neutral ? LOCALE_NEUTRALDATA : LOCALE_SPECIFICDATA; + if (data->flags && ~(data->flags & flags)) return TRUE; + return data->proc( buffer, flags, data->lparam ); +} + +/****************************************************************************** + * EnumSystemLocalesEx (KERNEL32.@) + */ +BOOL WINAPI EnumSystemLocalesEx( LOCALE_ENUMPROCEX proc, DWORD flags, LPARAM lparam, LPVOID reserved ) +{ + struct enum_locale_ex_data data; + + if (reserved) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + data.proc = proc; + data.flags = flags; + data.lparam = lparam; + EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING, + (LPCWSTR)MAKEINTRESOURCE((LOCALE_SNAME >> 4) + 1), + enum_locale_ex_proc, (LONG_PTR)&data ); + return TRUE; +} + + /*********************************************************************** * VerLanguageNameA (KERNEL32.@) * diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 9d6f7e4fe92..34b5f0065cd 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -67,23 +67,13 @@ static inline int isdigitW( WCHAR wc ) static HMODULE hKernel32; static WORD enumCount; -typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC, - DWORD, LONG_PTR); -static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA; -typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC, - LGRPID, DWORD, LONG_PTR); -static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA; -typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC, - DWORD, LONG_PTR); -static EnumUILanguagesAFn pEnumUILanguagesA; - -typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT); -static FoldStringAFn pFoldStringA; -typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT); -static FoldStringWFn pFoldStringW; - -typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD); -static IsValidLanguageGroupFn pIsValidLanguageGroup; +static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR); +static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR); +static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR); +static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID); +static INT (WINAPI *pFoldStringA)(DWORD, LPCSTR, INT, LPSTR, INT); +static INT (WINAPI *pFoldStringW)(DWORD, LPCWSTR, INT, LPWSTR, INT); +static BOOL (WINAPI *pIsValidLanguageGroup)(LGRPID, DWORD); static void InitFunctionPointers(void) { @@ -94,6 +84,7 @@ static void InitFunctionPointers(void) pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW"); pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup"); pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA"); + pEnumSystemLocalesEx = (void*)GetProcAddress(hKernel32, "EnumSystemLocalesEx"); } #define eq(received, expected, label, type) \ @@ -2346,6 +2337,29 @@ static void test_EnumSystemLanguageGroupsA(void) pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0); } +static BOOL CALLBACK enum_func( LPWSTR name, DWORD flags, LPARAM lparam ) +{ + trace( "%s %x\n", wine_dbgstr_w(name), flags ); + return TRUE; +} + +static void test_EnumSystemLocalesEx(void) +{ + BOOL ret; + + if (!pEnumSystemLocalesEx) + { + win_skip( "EnumSystemLocalesEx not available\n" ); + return; + } + SetLastError( 0xdeadbeef ); + ret = pEnumSystemLocalesEx( enum_func, LOCALE_ALL, 0, (void *)1 ); + ok( !ret, "should have failed\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pEnumSystemLocalesEx( enum_func, 0, 0, NULL ); + ok( ret, "failed err %u\n", GetLastError() ); +} static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum, LONG_PTR lParam) @@ -2801,6 +2815,7 @@ START_TEST(locale) test_FoldStringW(); test_ConvertDefaultLocale(); test_EnumSystemLanguageGroupsA(); + test_EnumSystemLocalesEx(); test_EnumLanguageGroupLocalesA(); test_SetLocaleInfoA(); test_EnumUILanguageA(); diff --git a/include/winnls.h b/include/winnls.h index b75e24a4b0a..279c9443315 100644 --- a/include/winnls.h +++ b/include/winnls.h @@ -150,6 +150,14 @@ extern "C" { #define LCID_SUPPORTED 0x2 #define LCID_ALTERNATE_SORTS 0x4 +#define LOCALE_ALL 0x00 +#define LOCALE_WINDOWS 0x01 +#define LOCALE_SUPPLEMENTAL 0x02 +#define LOCALE_ALTERNATE_SORTS 0x04 +#define LOCALE_REPLACEMENT 0x08 +#define LOCALE_NEUTRALDATA 0x10 +#define LOCALE_SPECIFICDATA 0x20 + /* Locale flags */ #define LOCALE_NOUSEROVERRIDE 0x80000000 #define LOCALE_USE_CP_ACP 0x40000000 @@ -279,6 +287,16 @@ extern "C" { #define LOCALE_SPARENT 0x006D #define LOCALE_SCONSOLEFALLBACKNAME 0x006E #define LOCALE_SLANGDISPLAYNAME 0x006F +#define LOCALE_IREADINGLAYOUT 0x0070 +#define LOCALE_INEUTRAL 0x0071 +#define LOCALE_INEGATIVEPERCENT 0x0074 +#define LOCALE_IPOSITIVEPERCENT 0x0075 +#define LOCALE_SPERCENT 0x0076 +#define LOCALE_SPERMILLE 0x0077 +#define LOCALE_SMONTHDAY 0x0078 +#define LOCALE_SSHORTTIME 0x0079 +#define LOCALE_SOPENTYPELANGUAGETAG 0X007A +#define LOCALE_SSORTLOCALE 0x007B #define LOCALE_IDEFAULTEBCDICCODEPAGE 0x1012 #define LOCALE_IPAPERSIZE 0x100A @@ -624,6 +642,7 @@ typedef BOOL (CALLBACK *LANGUAGEGROUP_ENUMPROCA)(LGRPID,LPSTR,LPSTR,DWORD,LON typedef BOOL (CALLBACK *LANGUAGEGROUP_ENUMPROCW)(LGRPID,LPWSTR,LPWSTR,DWORD,LONG_PTR); typedef BOOL (CALLBACK *LOCALE_ENUMPROCA)(LPSTR); typedef BOOL (CALLBACK *LOCALE_ENUMPROCW)(LPWSTR); +typedef BOOL (CALLBACK *LOCALE_ENUMPROCEX)(LPWSTR, DWORD, LPARAM); typedef BOOL (CALLBACK *TIMEFMT_ENUMPROCA)(LPSTR); typedef BOOL (CALLBACK *TIMEFMT_ENUMPROCW)(LPWSTR); typedef BOOL (CALLBACK *UILANGUAGE_ENUMPROCA)(LPSTR,LONG_PTR);