diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index b4ff7a79582..a26d65edf79 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -248,7 +248,7 @@ @ stub ConsoleSubst @ stdcall -import ContinueDebugEvent(long long long) # @ stub ConvertCalDateTimeToSystemTime -@ stdcall ConvertDefaultLocale (long) +@ stdcall -import ConvertDefaultLocale (long) @ stdcall -import ConvertFiberToThread() # @ stub ConvertNLSDayOfWeekToWin32DayOfWeek # @ stub ConvertSystemTimeToCalDateTime @@ -537,7 +537,7 @@ @ stub FreeVirtualBuffer @ stdcall -import GenerateConsoleCtrlEvent(long long) @ stdcall -i386 -private Get16DLLAddress(long str) krnl386.exe16.Get16DLLAddress -@ stdcall GetACP() +@ stdcall -import GetACP() @ stdcall GetActiveProcessorCount(long) @ stdcall GetActiveProcessorGroupCount() # @ stub GetApplicationRecoveryCallback @@ -703,9 +703,9 @@ @ stdcall -import GetLastError() @ stub GetLinguistLangSize @ stdcall -import GetLocalTime(ptr) -@ stdcall GetLocaleInfoA(long long ptr long) +@ stdcall -import GetLocaleInfoA(long long ptr long) @ stdcall GetLocaleInfoW(long long ptr long) -@ stdcall GetLocaleInfoEx(wstr long ptr long) +@ stdcall -import GetLocaleInfoEx(wstr long ptr long) @ stdcall GetLogicalDriveStringsA(long ptr) @ stdcall GetLogicalDriveStringsW(long ptr) @ stdcall GetLogicalDrives() @@ -758,7 +758,7 @@ @ stdcall GetNumberOfConsoleFonts() @ stdcall -import GetNumberOfConsoleInputEvents(long ptr) @ stdcall GetNumberOfConsoleMouseButtons(ptr) -@ stdcall GetOEMCP() +@ stdcall -import GetOEMCP() @ stdcall -import GetOverlappedResult(long ptr ptr long) @ stdcall GetUserPreferredUILanguages(long ptr ptr ptr) @ stdcall GetPackageFullName(long ptr ptr) @@ -991,8 +991,8 @@ # @ stub IsValidCalDateTime @ stdcall IsValidCodePage(long) @ stdcall -import IsValidLanguageGroup(long long) -@ stdcall IsValidLocale(long long) -@ stdcall IsValidLocaleName(wstr) +@ stdcall -import IsValidLocale(long long) +@ stdcall -import IsValidLocaleName(wstr) # @ stub IsValidUILanguage @ stdcall -import IsWow64Process(ptr ptr) @ stdcall K32EmptyWorkingSet(long) @@ -1061,7 +1061,7 @@ @ stdcall LocalShrink(long long) @ stdcall LocalSize(long) @ stdcall -import LocalUnlock(long) -@ stdcall LocaleNameToLCID(wstr long) +@ stdcall -import LocaleNameToLCID(wstr long) # @ stub LocateXStateFeature @ stdcall -import LockFile(long long long long long) @ stdcall -import LockFileEx(long long long long long ptr) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 1d8371fe0ff..a5ec6593b0a 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -443,20 +443,6 @@ BOOL WINAPI GetUserPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buffe return get_dummy_preferred_ui_language( flags, count, buffer, size ); } -/*********************************************************************** - * LocaleNameToLCID (KERNEL32.@) - */ -LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags ) -{ - LCID lcid; - - if (!name) return GetUserDefaultLCID(); - if (!set_ntstatus( RtlLocaleNameToLcid( name, &lcid, 2 ))) return 0; - if (!(flags & LOCALE_ALLOW_NEUTRAL_NAMES)) lcid = ConvertDefaultLocale( lcid ); - return lcid; -} - - /****************************************************************************** * get_locale_registry_value * @@ -589,83 +575,6 @@ static INT get_registry_locale_info( struct registry_value *registry_value, LPWS } -/****************************************************************************** - * GetLocaleInfoA (KERNEL32.@) - * - * Get information about an aspect of a locale. - * - * PARAMS - * lcid [I] LCID of the locale - * lctype [I] LCTYPE_ flags from "winnls.h" - * buffer [O] Destination for the information - * len [I] Length of buffer in characters - * - * RETURNS - * Success: The size of the data requested. If buffer is non-NULL, it is filled - * with the information. - * Failure: 0. Use GetLastError() to determine the cause. - * - * NOTES - * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT - * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE, - * which is a bit string. - */ -INT WINAPI GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len ) -{ - WCHAR *bufferW; - INT lenW, ret; - - TRACE( "(lcid=0x%x,lctype=0x%x,%p,%d)\n", lcid, lctype, buffer, len ); - - if (len < 0 || (len && !buffer)) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - if (((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_SSHORTTIME) || - (lctype & LOCALE_RETURN_GENITIVE_NAMES)) - { - SetLastError( ERROR_INVALID_FLAGS ); - return 0; - } - - if (!len) buffer = NULL; - - if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0; - - if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return 0; - } - if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW ))) - { - if ((lctype & LOCALE_RETURN_NUMBER) || - ((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_FONTSIGNATURE)) - { - /* it's not an ASCII string, just bytes */ - ret *= sizeof(WCHAR); - if (buffer) - { - if (ret <= len) memcpy( buffer, bufferW, ret ); - else - { - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - ret = 0; - } - } - } - else - { - UINT codepage = CP_ACP; - if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid ); - ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL ); - } - } - HeapFree( GetProcessHeap(), 0, bufferW ); - return ret; -} - static int get_value_base_by_lctype( LCTYPE lctype ) { return lctype == LOCALE_ILANGUAGE || lctype == LOCALE_IDEFAULTLANGUAGE ? 16 : 10; @@ -811,39 +720,6 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len ) return ret; } -/****************************************************************************** - * GetLocaleInfoEx (KERNEL32.@) - */ -INT WINAPI GetLocaleInfoEx(LPCWSTR locale, LCTYPE info, LPWSTR buffer, INT len) -{ - LCID lcid = LocaleNameToLCID(locale, 0); - - TRACE("%s, lcid=0x%x, 0x%x\n", debugstr_w(locale), lcid, info); - - if (!lcid) return 0; - - /* special handling for neutral locale names */ - if (locale && strlenW(locale) == 2) - { - switch (info & ~LOCALE_LOCALEINFOFLAGSMASK) - { - case LOCALE_SNAME: - if (len && len < 3) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return 0; - } - if (len) strcpyW(buffer, locale); - return 3; - case LOCALE_SPARENT: - if (len) buffer[0] = 0; - return 1; - } - } - - return GetLocaleInfoW(lcid, info, buffer, len); -} - /****************************************************************************** * SetLocaleInfoA [KERNEL32.@] * @@ -986,24 +862,6 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data ) } -/****************************************************************************** - * GetACP (KERNEL32.@) - * - * Get the current Ansi code page Id for the system. - * - * PARAMS - * None. - * - * RETURNS - * The current Ansi code page identifier for the system. - */ -UINT WINAPI GetACP(void) -{ - assert( ansi_cptable ); - return ansi_cptable->info.codepage; -} - - /****************************************************************************** * SetCPGlobal (KERNEL32.@) * @@ -1025,24 +883,6 @@ UINT WINAPI SetCPGlobal( UINT acp ) } -/*********************************************************************** - * GetOEMCP (KERNEL32.@) - * - * Get the current OEM code page Id for the system. - * - * PARAMS - * None. - * - * RETURNS - * The current OEM code page identifier for the system. - */ -UINT WINAPI GetOEMCP(void) -{ - assert( oem_cptable ); - return oem_cptable->info.codepage; -} - - /*********************************************************************** * IsValidCodePage (KERNEL32.@) * @@ -1722,97 +1562,6 @@ INT WINAPI WideCharToMultiByte( UINT page, DWORD flags, LPCWSTR src, INT srclen, } -/****************************************************************************** - * ConvertDefaultLocale (KERNEL32.@) - * - * Convert a default locale identifier into a real identifier. - * - * PARAMS - * lcid [I] LCID identifier of the locale to convert - * - * RETURNS - * lcid unchanged, if not a default locale or its sublanguage is - * not SUBLANG_NEUTRAL. - * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT. - * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL. - * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT. - */ -LCID WINAPI ConvertDefaultLocale( LCID lcid ) -{ - switch (lcid) - { - case LOCALE_INVARIANT: - return lcid; /* keep as-is */ - case LOCALE_SYSTEM_DEFAULT: - return GetSystemDefaultLCID(); - case LOCALE_USER_DEFAULT: - case LOCALE_NEUTRAL: - return GetUserDefaultLCID(); - case MAKELANGID( LANG_CHINESE, SUBLANG_NEUTRAL ): - case MAKELANGID( LANG_CHINESE, 0x1e ): - return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); - case MAKELANGID( LANG_CHINESE, 0x1f ): - return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_HONGKONG ); - case MAKELANGID( LANG_SPANISH, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_SPANISH, SUBLANG_SPANISH_MODERN ); - case MAKELANGID( LANG_IRISH, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_IRISH, SUBLANG_IRISH_IRELAND ); - case MAKELANGID( LANG_BENGALI, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_BENGALI, SUBLANG_BENGALI_BANGLADESH ); - case MAKELANGID( LANG_SINDHI, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_SINDHI, SUBLANG_SINDHI_AFGHANISTAN ); - case MAKELANGID( LANG_INUKTITUT, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA_LATIN ); - case MAKELANGID( LANG_TAMAZIGHT, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_ALGERIA_LATIN ); - case MAKELANGID( LANG_FULAH, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_FULAH, SUBLANG_FULAH_SENEGAL ); - case MAKELANGID( LANG_TIGRINYA, SUBLANG_NEUTRAL ): - return MAKELANGID( LANG_TIGRINYA, SUBLANG_TIGRINYA_ERITREA ); - default: - /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */ - if (SUBLANGID(lcid) == SUBLANG_NEUTRAL && SORTIDFROMLCID(lcid) == SORT_DEFAULT) - lcid = MAKELANGID( PRIMARYLANGID(lcid), SUBLANG_DEFAULT ); - break; - } - return lcid; -} - - -/****************************************************************************** - * IsValidLocale (KERNEL32.@) - * - * Determine if a locale is valid. - * - * PARAMS - * lcid [I] LCID of the locale to check - * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system - * - * RETURNS - * TRUE, if lcid is valid, - * FALSE, otherwise. - * - * NOTES - * Wine does not currently make the distinction between supported and installed. All - * languages supported are installed by default. - */ -BOOL WINAPI IsValidLocale( LCID lcid, DWORD flags ) -{ - /* check if language is registered in the kernel32 resources */ - return FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, - (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0; -} - -/****************************************************************************** - * IsValidLocaleName (KERNEL32.@) - */ -BOOL WINAPI IsValidLocaleName( LPCWSTR locale ) -{ - LCID lcid; - - return !RtlLocaleNameToLcid( locale, &lcid, 2 ); -} - /****************************************************************************** * GetStringTypeW (KERNEL32.@) * diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 639f4e10b22..7d20d3b1124 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -159,7 +159,7 @@ @ stdcall CompareStringW(long long wstr long wstr long) kernel32.CompareStringW @ stdcall ConnectNamedPipe(long ptr) @ stdcall ContinueDebugEvent(long long long) -@ stdcall ConvertDefaultLocale(long) kernel32.ConvertDefaultLocale +@ stdcall ConvertDefaultLocale(long) @ stdcall ConvertFiberToThread() @ stdcall ConvertThreadToFiber(ptr) @ stdcall ConvertThreadToFiberEx(ptr long) @@ -402,7 +402,7 @@ @ stdcall FreeUserPhysicalPages(long ptr ptr) @ stdcall GenerateConsoleCtrlEvent(long long) # @ stub GenerateGPNotificationInternal -@ stdcall GetACP() kernel32.GetACP +@ stdcall GetACP() @ stdcall GetAcceptLanguagesA(ptr ptr) @ stdcall GetAcceptLanguagesW(ptr ptr) @ stdcall GetAce(ptr long ptr) @@ -541,8 +541,8 @@ @ stdcall GetLastError() kernelbase_GetLastError @ stdcall GetLengthSid(ptr) @ stdcall GetLocalTime(ptr) -@ stdcall GetLocaleInfoA(long long ptr long) kernel32.GetLocaleInfoA -@ stdcall GetLocaleInfoEx(wstr long ptr long) kernel32.GetLocaleInfoEx +@ stdcall GetLocaleInfoA(long long ptr long) +@ stdcall GetLocaleInfoEx(wstr long ptr long) @ stub GetLocaleInfoHelper @ stdcall GetLocaleInfoW(long long ptr long) kernel32.GetLocaleInfoW @ stdcall GetLogicalDriveStringsW(long ptr) kernel32.GetLogicalDriveStringsW @@ -580,7 +580,7 @@ @ stdcall GetNumberFormatEx(wstr long wstr ptr ptr long) kernel32.GetNumberFormatEx @ stdcall GetNumberFormatW(long long wstr ptr ptr long) kernel32.GetNumberFormatW @ stdcall GetNumberOfConsoleInputEvents(long ptr) -@ stdcall GetOEMCP() kernel32.GetOEMCP +@ stdcall GetOEMCP() # @ stub GetOsManufacturingMode # @ stub GetOsSafeBootMode @ stdcall GetOverlappedResult(long ptr ptr long) @@ -876,8 +876,8 @@ @ stdcall IsValidAcl(ptr) @ stdcall IsValidCodePage(long) kernel32.IsValidCodePage @ stdcall IsValidLanguageGroup(long long) -@ stdcall IsValidLocale(long long) kernel32.IsValidLocale -@ stdcall IsValidLocaleName(wstr) kernel32.IsValidLocaleName +@ stdcall IsValidLocale(long long) +@ stdcall IsValidLocaleName(wstr) # @ stub IsValidNLSVersion @ stub IsValidRelativeSecurityDescriptor @ stdcall IsValidSecurityDescriptor(ptr) @@ -938,7 +938,7 @@ @ stdcall LocalLock(long) @ stdcall LocalReAlloc(long long long) @ stdcall LocalUnlock(long) -@ stdcall LocaleNameToLCID(wstr long) kernel32.LocaleNameToLCID +@ stdcall LocaleNameToLCID(wstr long) # @ stub LocateXStateFeature @ stdcall LockFile(long long long long long) @ stdcall LockFileEx(long long long long long ptr) diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 6a83ee965ad..512c3aeeb10 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -4,9 +4,9 @@ * Copyright 1995 Martin von Loewis * Copyright 1998 David Lee Lambert * Copyright 2000 Julio César Gázquez - * Copyright 2002 Alexandre Julliard for CodeWeavers * Copyright 2003 Jon Griffiths * Copyright 2005 Dmitry Timoshkov + * Copyright 2002, 2019 Alexandre Julliard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -161,6 +161,17 @@ void init_locale(void) } +static UINT get_lcid_codepage( LCID lcid, ULONG flags ) +{ + UINT ret = CP_ACP; + + if (!(flags & LOCALE_USE_CP_ACP) && lcid != GetSystemDefaultLCID()) + GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, + (WCHAR *)&ret, sizeof(ret)/sizeof(WCHAR) ); + return ret; +} + + /* Note: the Internal_ functions are not documented. The number of parameters * should be correct, but their exact meaning may not. */ @@ -517,6 +528,51 @@ INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1, } +/****************************************************************************** + * ConvertDefaultLocale (kernelbase.@) + */ +LCID WINAPI DECLSPEC_HOTPATCH ConvertDefaultLocale( LCID lcid ) +{ + switch (lcid) + { + case LOCALE_INVARIANT: + return lcid; /* keep as-is */ + case LOCALE_SYSTEM_DEFAULT: + return GetSystemDefaultLCID(); + case LOCALE_USER_DEFAULT: + case LOCALE_NEUTRAL: + return GetUserDefaultLCID(); + case MAKELANGID( LANG_CHINESE, SUBLANG_NEUTRAL ): + case MAKELANGID( LANG_CHINESE, 0x1e ): + return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); + case MAKELANGID( LANG_CHINESE, 0x1f ): + return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_HONGKONG ); + case MAKELANGID( LANG_SPANISH, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_SPANISH, SUBLANG_SPANISH_MODERN ); + case MAKELANGID( LANG_IRISH, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_IRISH, SUBLANG_IRISH_IRELAND ); + case MAKELANGID( LANG_BENGALI, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_BENGALI, SUBLANG_BENGALI_BANGLADESH ); + case MAKELANGID( LANG_SINDHI, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_SINDHI, SUBLANG_SINDHI_AFGHANISTAN ); + case MAKELANGID( LANG_INUKTITUT, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_INUKTITUT, SUBLANG_INUKTITUT_CANADA_LATIN ); + case MAKELANGID( LANG_TAMAZIGHT, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_ALGERIA_LATIN ); + case MAKELANGID( LANG_FULAH, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_FULAH, SUBLANG_FULAH_SENEGAL ); + case MAKELANGID( LANG_TIGRINYA, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_TIGRINYA, SUBLANG_TIGRINYA_ERITREA ); + default: + /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */ + if (SUBLANGID(lcid) == SUBLANG_NEUTRAL && SORTIDFROMLCID(lcid) == SORT_DEFAULT) + lcid = MAKELANGID( PRIMARYLANGID(lcid), SUBLANG_DEFAULT ); + break; + } + return lcid; +} + + /****************************************************************************** * EnumCalendarInfoW (kernelbase.@) */ @@ -777,36 +833,11 @@ INT WINAPI DECLSPEC_HOTPATCH FindStringOrdinal( DWORD flag, const WCHAR *src, IN /****************************************************************************** - * IsValidLanguageGroup (kernelbase.@) + * GetACP (kernelbase.@) */ -BOOL WINAPI DECLSPEC_HOTPATCH IsValidLanguageGroup( LGRPID id, DWORD flags ) +UINT WINAPI GetACP(void) { - static const WCHAR format[] = { '%','x',0 }; - WCHAR name[10], value[10]; - DWORD type, value_len = sizeof(value); - BOOL ret = FALSE; - HKEY key; - - if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE; - - swprintf( name, ARRAY_SIZE(name), format, id ); - if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)value, &value_len ) && type == REG_SZ) - ret = (flags & LGRPID_SUPPORTED) || wcstoul( value, NULL, 10 ); - - RegCloseKey( key ); - return ret; -} - - -/*********************************************************************** - * LCIDToLocaleName (kernelbase.@) - */ -INT WINAPI DECLSPEC_HOTPATCH LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags ) -{ - static int once; - if (flags && !once++) FIXME( "unsupported flags %x\n", flags ); - - return GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, name, count ); + return ansi_cp; } @@ -1003,6 +1034,87 @@ INT WINAPI DECLSPEC_HOTPATCH GetCalendarInfoEx( const WCHAR *locale, CALID calen } +/****************************************************************************** + * GetLocaleInfoA (kernelbase.@) + */ +INT WINAPI DECLSPEC_HOTPATCH GetLocaleInfoA( LCID lcid, LCTYPE lctype, char *buffer, INT len ) +{ + WCHAR *bufferW; + INT lenW, ret; + + TRACE( "lcid=0x%x lctype=0x%x %p %d\n", lcid, lctype, buffer, len ); + + if (len < 0 || (len && !buffer)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + if (LOWORD(lctype) == LOCALE_SSHORTTIME || (lctype & LOCALE_RETURN_GENITIVE_NAMES)) + { + SetLastError( ERROR_INVALID_FLAGS ); + return 0; + } + + if (LOWORD(lctype) == LOCALE_FONTSIGNATURE || (lctype & LOCALE_RETURN_NUMBER)) + return GetLocaleInfoW( lcid, lctype, (WCHAR *)buffer, len / sizeof(WCHAR) ) * sizeof(WCHAR); + + if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0; + + if (!(bufferW = RtlAllocateHeap( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return 0; + } + ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW ); + if (ret) ret = WideCharToMultiByte( get_lcid_codepage( lcid, lctype ), 0, + bufferW, ret, buffer, len, NULL, NULL ); + RtlFreeHeap( GetProcessHeap(), 0, bufferW ); + return ret; +} + + +/****************************************************************************** + * GetLocaleInfoEx (kernelbase.@) + */ +INT WINAPI DECLSPEC_HOTPATCH GetLocaleInfoEx( const WCHAR *locale, LCTYPE info, WCHAR *buffer, INT len ) +{ + LCID lcid = LocaleNameToLCID( locale, 0 ); + + TRACE( "%s lcid=0x%x 0x%x\n", debugstr_w(locale), lcid, info ); + + if (!lcid) return 0; + + /* special handling for neutral locale names */ + if (locale && lstrlenW( locale ) == 2) + { + switch (LOWORD( info )) + { + case LOCALE_SNAME: + if (len && len < 3) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; + } + if (len) lstrcpyW( buffer, locale ); + return 3; + case LOCALE_SPARENT: + if (len) buffer[0] = 0; + return 1; + } + } + return GetLocaleInfoW( lcid, info, buffer, len ); +} + + +/****************************************************************************** + * GetOEMCP (kernelbase.@) + */ +UINT WINAPI GetOEMCP(void) +{ + return oem_cp; +} + + /*********************************************************************** * GetSystemDefaultLCID (kernelbase.@) */ @@ -1094,6 +1206,75 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsNormalizedString( NORM_FORM form, const WCHAR *s } +/****************************************************************************** + * IsValidLanguageGroup (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH IsValidLanguageGroup( LGRPID id, DWORD flags ) +{ + WCHAR name[10], value[10]; + DWORD type, value_len = sizeof(value); + BOOL ret = FALSE; + HKEY key; + + if (RegOpenKeyExW( nls_key, L"Language Groups", 0, KEY_READ, &key )) return FALSE; + + swprintf( name, ARRAY_SIZE(name), L"%x", id ); + if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)value, &value_len ) && type == REG_SZ) + ret = (flags & LGRPID_SUPPORTED) || wcstoul( value, NULL, 10 ); + + RegCloseKey( key ); + return ret; +} + + +/****************************************************************************** + * IsValidLocale (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocale( LCID lcid, DWORD flags ) +{ + /* check if language is registered in the kernel32 resources */ + return FindResourceExW( kernel32_handle, (LPWSTR)RT_STRING, + ULongToPtr( (LOCALE_ILANGUAGE >> 4) + 1 ), LANGIDFROMLCID(lcid)) != 0; +} + + +/****************************************************************************** + * IsValidLocaleName (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH IsValidLocaleName( const WCHAR *locale ) +{ + LCID lcid; + + return !RtlLocaleNameToLcid( locale, &lcid, 2 ); +} + + +/*********************************************************************** + * LCIDToLocaleName (kernelbase.@) + */ +INT WINAPI DECLSPEC_HOTPATCH LCIDToLocaleName( LCID lcid, WCHAR *name, INT count, DWORD flags ) +{ + static int once; + if (flags && !once++) FIXME( "unsupported flags %x\n", flags ); + + return GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, name, count ); +} + + +/*********************************************************************** + * LocaleNameToLCID (kernelbase.@) + */ +LCID WINAPI DECLSPEC_HOTPATCH LocaleNameToLCID( const WCHAR *name, DWORD flags ) +{ + LCID lcid; + + if (!name) return GetUserDefaultLCID(); + if (!set_ntstatus( RtlLocaleNameToLcid( name, &lcid, 2 ))) return 0; + if (!(flags & LOCALE_ALLOW_NEUTRAL_NAMES)) lcid = ConvertDefaultLocale( lcid ); + return lcid; +} + + /****************************************************************************** * NormalizeString (kernelbase.@) */