https://git.reactos.org/?p=reactos.git;a=commitdiff;h=655d24d9eb530bcc12935b...
commit 655d24d9eb530bcc12935bc8fa025025c78a23eb Author: Denis Malikov filedem@gmail.com AuthorDate: Sun Nov 18 21:32:13 2018 +0700 Commit: Mark Jansen mark.jansen@reactos.org CommitDate: Sat Jan 5 19:01:30 2019 +0100
[KERNEL32] make some NLS and Format functions work. Wine-sync with latest version --- base/shell/cmd/config.h | 2 +- dll/win32/kernel32/include/kernel32.h | 2 + dll/win32/kernel32/kernel32.spec | 25 +- dll/win32/kernel32/winnls/string/lang.c | 375 +++++++++++++++++++++++++++- dll/win32/kernel32/winnls/string/lcformat.c | 110 +++++--- dll/win32/kernel32/winnls/string/nls.c | 13 + media/doc/README.WINE | 2 +- sdk/include/psdk/winnls.h | 29 +++ 8 files changed, 504 insertions(+), 54 deletions(-)
diff --git a/base/shell/cmd/config.h b/base/shell/cmd/config.h index e89e1eab63..bdeeaa0e04 100644 --- a/base/shell/cmd/config.h +++ b/base/shell/cmd/config.h @@ -42,7 +42,7 @@ /* Define one of these to select the used locale. */ /* (date and time formats etc.) used in DATE, TIME, */ /* DIR, PROMPT etc. */ -#define LOCALE_WINDOWS /* System locale */ +/* #define LOCALE_WINDOWS */ /* System locale */ /* #define LOCALE_GERMAN */ /* German locale */ /* #define LOCALE_DEFAULT */ /* United States locale */
diff --git a/dll/win32/kernel32/include/kernel32.h b/dll/win32/kernel32/include/kernel32.h index d5839bfc8d..005b5d0527 100644 --- a/dll/win32/kernel32/include/kernel32.h +++ b/dll/win32/kernel32/include/kernel32.h @@ -50,6 +50,8 @@ #define ROUND_UP(n, align) \ ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) + #define __TRY _SEH2_TRY #define __EXCEPT_PAGE_FAULT _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION) #define __ENDTRY _SEH2_END diff --git a/dll/win32/kernel32/kernel32.spec b/dll/win32/kernel32/kernel32.spec index aea5d2f280..f3ee418b65 100644 --- a/dll/win32/kernel32/kernel32.spec +++ b/dll/win32/kernel32/kernel32.spec @@ -225,12 +225,12 @@ @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection @ stdcall EnumCalendarInfoA(ptr long long long) @ stdcall EnumCalendarInfoExA(ptr long long long) -@ stub -version=0x600+ EnumCalendarInfoExEx +@ stdcall -version=0x600+ EnumCalendarInfoExEx(ptr wstr long wstr long long) @ stdcall EnumCalendarInfoExW(ptr long long long) @ stdcall EnumCalendarInfoW(ptr long long long) @ stdcall EnumDateFormatsA(ptr long long) @ stdcall EnumDateFormatsExA(ptr long long) -@ stub -version=0x600+ EnumDateFormatsExEx +@ stdcall -version=0x600+ EnumDateFormatsExEx(ptr wstr long long) @ stdcall EnumDateFormatsExW(ptr long long) @ stdcall EnumDateFormatsW(ptr long long) @ stdcall EnumLanguageGroupLocalesA(ptr long long ptr) @@ -254,10 +254,10 @@ @ stdcall EnumSystemLanguageGroupsA(ptr long ptr) @ stdcall EnumSystemLanguageGroupsW(ptr long ptr) @ stdcall EnumSystemLocalesA(ptr long) -@ stub -version=0x600+ EnumSystemLocalesEx +@ stdcall -version=0x600+ EnumSystemLocalesEx(ptr long long ptr) @ stdcall EnumSystemLocalesW(ptr long) @ stdcall EnumTimeFormatsA(ptr long long) -@ stub -version=0x600+ EnumTimeFormatsEx +@ stdcall -version=0x600+ EnumTimeFormatsEx(ptr wstr long long) @ stdcall EnumTimeFormatsW(ptr long long) @ stdcall EnumUILanguagesA(ptr long long) @ stdcall EnumUILanguagesW(ptr long long) @@ -360,7 +360,7 @@ @ stub -version=0x600+ GetCalendarDaysInMonth @ stub -version=0x600+ GetCalendarDifferenceInDays @ stdcall GetCalendarInfoA(long long long ptr long ptr) -@ stub -version=0x600+ GetCalendarInfoEx +@ stdcall -version=0x600+ GetCalendarInfoEx(wstr, long, wstr, long, wstr, long, ptr) @ stdcall GetCalendarInfoW(long long long ptr long ptr) @ stub -version=0x600+ GetCalendarMonthsInYear @ stub -version=0x600+ GetCalendarSupportedDateRange @@ -436,7 +436,7 @@ @ stdcall -norelay GetCurrentThread() @ stdcall -norelay GetCurrentThreadId() @ stdcall GetDateFormatA(long long ptr str ptr long) -@ stub -version=0x600+ GetDateFormatEx +@ stdcall -version=0x600+ GetDateFormatEx(wstr long ptr wstr wstr long wstr) @ stdcall GetDateFormatW(long long ptr wstr ptr long) @ stdcall GetDefaultCommConfigA(str ptr long) @ stdcall GetDefaultCommConfigW(wstr ptr long) @@ -496,8 +496,9 @@ @ stdcall -version=0x500-0x502 GetLinguistLangSize(ptr) @ stdcall GetLocalTime(ptr) @ stdcall GetLocaleInfoA(long long ptr long) -@ stub -version=0x600+ GetLocaleInfoEx +@ stdcall -version=0x600+ GetLocaleInfoEx(wstr long ptr long) @ stdcall GetLocaleInfoW(long long ptr long) +@ stdcall -version=0x600+ IsValidLocaleName(wstr) @ stdcall GetLogicalDriveStringsA(long ptr) @ stdcall GetLogicalDriveStringsW(long ptr) @ stdcall GetLogicalDrives() @@ -514,7 +515,7 @@ @ stdcall GetModuleHandleExW(long ptr ptr) @ stdcall GetModuleHandleW(wstr) @ stdcall GetNLSVersion(long long ptr) -@ stub -version=0x600+ GetNLSVersionEx +@ stdcall GetNLSVersionEx(long wstr ptr) @ stub -version=0x600+ GetNamedPipeAttribute @ stub -version=0x600+ GetNamedPipeClientComputerNameA @ stub -version=0x600+ GetNamedPipeClientComputerNameW @@ -534,7 +535,7 @@ @ stdcall GetNumaProcessorNode(long ptr) @ stub -version=0x600+ GetNumaProximityNode @ stdcall GetNumberFormatA(long long str ptr ptr long) -@ stub -version=0x600+ GetNumberFormatEx +@ stdcall -version=0x600+ GetNumberFormatEx(wstr long wstr ptr wstr long) @ stdcall GetNumberFormatW(long long wstr ptr ptr long) @ stdcall GetNumberOfConsoleFonts() @ stdcall GetNumberOfConsoleInputEvents(long ptr) @@ -628,14 +629,14 @@ @ stdcall GetTickCount() @ stub -version=0x600+ GetTickCount64 @ stdcall GetTimeFormatA(long long ptr str ptr long) -@ stub -version=0x600+ GetTimeFormatEx +@ stdcall -version=0x600+ GetTimeFormatEx(wstr long ptr wstr wstr long) @ stdcall GetTimeFormatW(long long ptr wstr ptr long) @ stdcall GetTimeZoneInformation(ptr) @ stub -version=0x600+ GetTimeZoneInformationForYear @ stub -version=0x600+ GetUILanguageInfo @ stdcall GetUserDefaultLCID() @ stdcall GetUserDefaultLangID() -@ stub -version=0x600+ GetUserDefaultLocaleName +@ stdcall -version=0x600+ GetUserDefaultLocaleName(wstr long) @ stdcall GetUserDefaultUILanguage() @ stdcall GetUserGeoID(long) @ stub -version=0x600+ GetUserPreferredUILanguages @@ -754,7 +755,7 @@ @ stdcall IsWow64Process(ptr ptr) @ stub -version=0x600+ LCIDToLocaleName @ stdcall LCMapStringA(long long str long ptr long) -@ stub -version=0x600+ LCMapStringEx +@ stdcall -version=0x600+ LCMapStringEx(long long wstr long ptr long ptr ptr long) @ stdcall LCMapStringW(long long wstr long ptr long) @ stdcall LZClose(long) @ stdcall LZCloseFile(long) diff --git a/dll/win32/kernel32/winnls/string/lang.c b/dll/win32/kernel32/winnls/string/lang.c index 5bd9ec47b2..42c57d1aef 100644 --- a/dll/win32/kernel32/winnls/string/lang.c +++ b/dll/win32/kernel32/winnls/string/lang.c @@ -56,7 +56,7 @@ static const WCHAR szLangGroupsKeyName[] = { 'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0 };
-#ifndef __REACTOS__ +#if (WINVER >= 0x0600) /* Charset to codepage map, sorted by name. */ static const struct charset_entry { @@ -262,6 +262,248 @@ static inline UINT get_lcid_codepage( LCID lcid ) return ret; }
+#if (WINVER >= 0x0600) +/*********************************************************************** + * charset_cmp (internal) + */ +static int charset_cmp( const void *name, const void *entry ) +{ + const struct charset_entry *charset = entry; + return strcasecmp( name, charset->charset_name ); +} + +/*********************************************************************** + * find_charset + */ +static UINT find_charset( const WCHAR *name ) +{ + const struct charset_entry *entry; + char charset_name[16]; + size_t i, j; + + /* remove punctuation characters from charset name */ + for (i = j = 0; name[i] && j < sizeof(charset_name)-1; i++) + if (isalnum((unsigned char)name[i])) charset_name[j++] = name[i]; + charset_name[j] = 0; + + entry = bsearch( charset_name, charset_names, ARRAY_SIZE( charset_names ), + sizeof(charset_names[0]), charset_cmp ); + if (entry) return entry->codepage; + return 0; +} + +static LANGID get_default_sublang( LANGID lang ) +{ + switch (lang) + { + case MAKELANGID( LANG_SPANISH, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_SPANISH, SUBLANG_SPANISH_MODERN ); + case MAKELANGID( LANG_CHINESE, SUBLANG_NEUTRAL ): + return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); + case MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE ): + return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ); + case MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ): + case MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_MACAU ): + return MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_HONGKONG ); + } + if (SUBLANGID( lang ) == SUBLANG_NEUTRAL) lang = MAKELANGID( PRIMARYLANGID(lang), SUBLANG_DEFAULT ); + return lang; +} + +/*********************************************************************** + * find_locale_id_callback + */ +static BOOL CALLBACK find_locale_id_callback( HMODULE hModule, LPCWSTR type, + LPCWSTR name, LANGID lang, LPARAM lParam ) +{ + struct locale_name *data = (struct locale_name *)lParam; + WCHAR buffer[128]; + int matches = 0; + LCID lcid = MAKELCID( lang, SORT_DEFAULT ); /* FIXME: handle sort order */ + + if (PRIMARYLANGID(lang) == LANG_NEUTRAL) return TRUE; /* continue search */ + + /* first check exact name */ + if (data->win_name[0] && + GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, buffer, ARRAY_SIZE( buffer ))) + { + if (!strcmpiW( data->win_name, buffer )) + { + matches = 4; /* everything matches */ + goto done; + } + } + + if (!GetLocaleInfoW( lcid, LOCALE_SISO639LANGNAME | LOCALE_NOUSEROVERRIDE, + buffer, ARRAY_SIZE( buffer ))) + return TRUE; + if (strcmpiW( buffer, data->lang )) return TRUE; + matches++; /* language name matched */ + + if (data->script) + { + if (GetLocaleInfoW( lcid, LOCALE_SSCRIPTS | LOCALE_NOUSEROVERRIDE, + buffer, ARRAY_SIZE( buffer ))) + { + const WCHAR *p = buffer; + unsigned int len = strlenW( data->script ); + while (*p) + { + if (!strncmpiW( p, data->script, len ) && (!p[len] || p[len] == ';')) break; + if (!(p = strchrW( p, ';'))) goto done; + p++; + } + if (!*p) goto done; + matches++; /* script matched */ + } + } + + if (data->country) + { + if (GetLocaleInfoW( lcid, LOCALE_SISO3166CTRYNAME|LOCALE_NOUSEROVERRIDE, + buffer, ARRAY_SIZE( buffer ))) + { + if (strcmpiW( buffer, data->country )) goto done; + matches++; /* country name matched */ + } + } + else /* match default language */ + { + LANGID def_lang = data->script ? lang : MAKELANGID( PRIMARYLANGID(lang), LANG_NEUTRAL ); + if (lang == get_default_sublang( def_lang )) matches++; + } + + if (data->codepage) + { + UINT unix_cp; + if (GetLocaleInfoW( lcid, LOCALE_IDEFAULTUNIXCODEPAGE | LOCALE_RETURN_NUMBER, + (LPWSTR)&unix_cp, sizeof(unix_cp)/sizeof(WCHAR) )) + { + if (unix_cp == data->codepage) matches++; + } + } + + /* FIXME: check sort order */ + +done: + if (matches > data->matches) + { + data->lcid = lcid; + data->matches = matches; + } + return (data->matches < 4); /* no need to continue for perfect match */ +} + + +/*********************************************************************** + * parse_locale_name + * + * Parse a locale name into a struct locale_name, handling both Windows and Unix formats. + * Unix format is: lang[_country][.charset][@modifier] + * Windows format is: lang[-script][-country][_modifier] + */ +static void parse_locale_name( const WCHAR *str, struct locale_name *name ) +{ + static const WCHAR sepW[] = {'-','_','.','@',0}; + static const WCHAR winsepW[] = {'-','_',0}; + static const WCHAR posixW[] = {'P','O','S','I','X',0}; + static const WCHAR cW[] = {'C',0}; + static const WCHAR latinW[] = {'l','a','t','i','n',0}; + static const WCHAR latnW[] = {'-','L','a','t','n',0}; + WCHAR *p; + + TRACE("%s\n", debugstr_w(str)); + + name->country = name->charset = name->script = name->modifier = NULL; + name->lcid = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT ); + name->matches = 0; + name->codepage = 0; + name->win_name[0] = 0; + lstrcpynW( name->lang, str, ARRAY_SIZE( name->lang )); + + if (!*name->lang) + { + name->lcid = LOCALE_INVARIANT; + name->matches = 4; + return; + } + + if (!(p = strpbrkW( name->lang, sepW ))) + { + if (!strcmpW( name->lang, posixW ) || !strcmpW( name->lang, cW )) + { + name->matches = 4; /* perfect match for default English lcid */ + return; + } + strcpyW( name->win_name, name->lang ); + } + else if (*p == '-') /* Windows format */ + { + strcpyW( name->win_name, name->lang ); + *p++ = 0; + name->country = p; + if ((p = strpbrkW( p, winsepW )) && *p == '-') + { + *p++ = 0; + name->script = name->country; + name->country = p; + p = strpbrkW( p, winsepW ); + } + if (p) + { + *p++ = 0; + name->modifier = p; + } + /* second value can be script or country, check length to resolve the ambiguity */ + if (!name->script && strlenW( name->country ) == 4) + { + name->script = name->country; + name->country = NULL; + } + } + else /* Unix format */ + { + if (*p == '_') + { + *p++ = 0; + name->country = p; + p = strpbrkW( p, sepW + 2 ); + } + if (p && *p == '.') + { + *p++ = 0; + name->charset = p; + p = strchrW( p, '@' ); + } + if (p) + { + *p++ = 0; + name->modifier = p; + } + + if (name->charset) + name->codepage = find_charset( name->charset ); + + /* rebuild a Windows name if possible */ + + if (name->charset) goto done; /* can't specify charset in Windows format */ + if (name->modifier && strcmpW( name->modifier, latinW )) + goto done; /* only Latn script supported for now */ + strcpyW( name->win_name, name->lang ); + if (name->modifier) strcatW( name->win_name, latnW ); + if (name->country) + { + p = name->win_name + strlenW(name->win_name); + *p++ = '-'; + strcpyW( p, name->country ); + } + } +done: + EnumResourceLanguagesW( kernel32_handle, (LPCWSTR)RT_STRING, (LPCWSTR)LOCALE_ILANGUAGE, + find_locale_id_callback, (LPARAM)name ); +} +#endif + /*********************************************************************** * convert_default_lcid * @@ -585,6 +827,52 @@ LANGID WINAPI GetSystemDefaultUILanguage(void) return lang; }
+#if (WINVER >= 0x0600) +/*********************************************************************** + * LocaleNameToLCID (KERNEL32.@) + */ +LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags ) +{ + struct locale_name locale_name; + static int once; + + if (flags && !once++) + FIXME( "unsupported flags %x\n", flags ); + + if (name == LOCALE_NAME_USER_DEFAULT) + return GetUserDefaultLCID(); + + /* string parsing */ + parse_locale_name( name, &locale_name ); + + TRACE( "found lcid %x for %s, matches %d\n", + locale_name.lcid, debugstr_w(name), locale_name.matches ); + + if (!locale_name.matches) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (locale_name.matches == 1) + WARN( "locale %s not recognized, defaulting to %s\n", + debugstr_w(name), debugstr_w(locale_name.lang) ); + + return locale_name.lcid; +} + + +/*********************************************************************** + * LCIDToLocaleName (KERNEL32.@) + */ +INT WINAPI 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 ); +} +#endif
/****************************************************************************** * get_registry_locale_info @@ -965,6 +1253,41 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len ) return ret; }
+#if (WINVER >= 0x0600) +WINBASEAPI +int +WINAPI +GetLocaleInfoEx( + _In_opt_ LPCWSTR lpLocaleName, + _In_ LCTYPE LCType, + _Out_writes_opt_(cchData) LPWSTR lpLCData, + _In_ int cchData) +{ + TRACE( "GetLocaleInfoEx not implemented (lcid=%s,lctype=0x%x,%s,%d)\n", debugstr_w(lpLocaleName), LCType, debugstr_w(lpLCData), cchData ); + return 0; +} + +BOOL +WINAPI +IsValidLocaleName( + LPCWSTR lpLocaleName +) +{ + TRACE( "IsValidLocaleName not implemented (lpLocaleName=%s)\n", debugstr_w(lpLocaleName)); + return TRUE; +} + +INT +WINAPI +GetUserDefaultLocaleName( + LPWSTR lpLocaleName, + INT cchLocaleName +) +{ + TRACE( "GetUserDefaultLocaleName not implemented (lpLocaleName=%s, cchLocaleName=%d)\n", debugstr_w(lpLocaleName), cchLocaleName); + return 0; +} +#endif
/****************************************************************************** * SetLocaleInfoA [KERNEL32.@] @@ -1284,6 +1607,56 @@ BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum, DWORD dwFlags ) return TRUE; }
+ +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, ARRAY_SIZE( buffer )); + 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/dll/win32/kernel32/winnls/string/lcformat.c b/dll/win32/kernel32/winnls/string/lcformat.c index 7f57373e2d..a4088cb9b2 100644 --- a/dll/win32/kernel32/winnls/string/lcformat.c +++ b/dll/win32/kernel32/winnls/string/lcformat.c @@ -124,7 +124,7 @@ static DWORD NLS_GetLocaleNumber(LCID lcid, DWORD dwFlags) DWORD dwVal = 0;
szBuff[0] = '\0'; - GetLocaleInfoW(lcid, dwFlags, szBuff, sizeof(szBuff) / sizeof(WCHAR)); + GetLocaleInfoW(lcid, dwFlags, szBuff, ARRAY_SIZE(szBuff));
if (szBuff[0] && szBuff[1] == ';' && szBuff[2] != '0') dwVal = (szBuff[0] - '0') * 10 + (szBuff[2] - '0'); @@ -149,7 +149,7 @@ static WCHAR* NLS_GetLocaleString(LCID lcid, DWORD dwFlags) DWORD dwLen;
szBuff[0] = '\0'; - GetLocaleInfoW(lcid, dwFlags, szBuff, sizeof(szBuff) / sizeof(WCHAR)); + GetLocaleInfoW(lcid, dwFlags, szBuff, ARRAY_SIZE(szBuff)); dwLen = strlenW(szBuff) + 1; str = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR)); if (str) @@ -278,7 +278,7 @@ static const NLS_FORMAT_NODE *NLS_GetFormats(LCID lcid, DWORD dwFlags) GET_LOCALE_STRING(new_node->cyfmt.lpCurrencySymbol, LOCALE_SCURRENCY);
/* Date/Time Format info, negative character, etc */ - for (i = 0; i < sizeof(NLS_LocaleIndices)/sizeof(NLS_LocaleIndices[0]); i++) + for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++) { GET_LOCALE_STRING(new_node->lppszStrings[i], NLS_LocaleIndices[i]); } @@ -322,7 +322,7 @@ static const NLS_FORMAT_NODE *NLS_GetFormats(LCID lcid, DWORD dwFlags) /* We raced and lost: The node was already added by another thread. * node points to the currently cached node, so free new_node. */ - for (i = 0; i < sizeof(NLS_LocaleIndices)/sizeof(NLS_LocaleIndices[0]); i++) + for (i = 0; i < ARRAY_SIZE(NLS_LocaleIndices); i++) HeapFree(GetProcessHeap(), 0, new_node->lppszStrings[i]); HeapFree(GetProcessHeap(), 0, new_node->fmt.lpDecimalSep); HeapFree(GetProcessHeap(), 0, new_node->fmt.lpThousandSep); @@ -697,7 +697,7 @@ static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags, { static const WCHAR fmtW[] = {'%','.','*','d',0}; /* We have a numeric value to add */ - snprintfW(buff, sizeof(buff)/sizeof(WCHAR), fmtW, count, dwVal); + snprintfW(buff, ARRAY_SIZE(buff), fmtW, count, dwVal); }
dwLen = szAdd ? strlenW(szAdd) : 0; @@ -793,10 +793,10 @@ static INT NLS_GetDateTimeFormatA(LCID lcid, DWORD dwFlags, }
if (lpFormat) - MultiByteToWideChar(cp, 0, lpFormat, -1, szFormat, sizeof(szFormat)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat, -1, szFormat, ARRAY_SIZE(szFormat));
- if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) - cchOut = sizeof(szOut)/sizeof(WCHAR); + if (cchOut > (int) ARRAY_SIZE(szOut)) + cchOut = ARRAY_SIZE(szOut);
szOut[0] = '\0';
@@ -866,7 +866,7 @@ INT WINAPI GetDateFormatA( LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, lpFormat, lpDateStr, cchOut); }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /****************************************************************************** * GetDateFormatEx [KERNEL32.@] * @@ -906,7 +906,7 @@ INT WINAPI GetDateFormatEx(LPCWSTR localename, DWORD flags, flags | DATE_DATEVARSONLY, date, format, outbuf, bufsize); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
/****************************************************************************** * GetDateFormatW [KERNEL32.@] @@ -974,7 +974,7 @@ INT WINAPI GetTimeFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME* lpTime, lpFormat, lpTimeStr, cchOut); }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /****************************************************************************** * GetTimeFormatEx [KERNEL32.@] * @@ -1006,7 +1006,7 @@ INT WINAPI GetTimeFormatEx(LPCWSTR localename, DWORD flags, flags | TIME_TIMEVARSONLY, time, format, outbuf, bufsize); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
/****************************************************************************** * GetTimeFormatW [KERNEL32.@] @@ -1087,21 +1087,21 @@ INT WINAPI GetNumberFormatA(LCID lcid, DWORD dwFlags, pfmt = &fmt; if (lpFormat->lpDecimalSep) { - MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, sizeof(szDec)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, ARRAY_SIZE(szDec)); fmt.lpDecimalSep = szDec; } if (lpFormat->lpThousandSep) { - MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, sizeof(szGrp)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, ARRAY_SIZE(szGrp)); fmt.lpThousandSep = szGrp; } }
if (lpszValue) - MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, sizeof(szIn)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, ARRAY_SIZE(szIn));
- if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) - cchOut = sizeof(szOut)/sizeof(WCHAR); + if (cchOut > (int) ARRAY_SIZE(szOut)) + cchOut = ARRAY_SIZE(szOut);
szOut[0] = '\0';
@@ -1136,7 +1136,7 @@ INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, LPCWSTR lpszValue, const NUMBERFMTW *lpFormat, LPWSTR lpNumberStr, int cchOut) { - WCHAR szBuff[128], *szOut = szBuff + sizeof(szBuff) / sizeof(WCHAR) - 1; + WCHAR szBuff[128], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1; WCHAR szNegBuff[8]; const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc; DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0; @@ -1164,7 +1164,7 @@ INT WINAPI GetNumberFormatW(LCID lcid, DWORD dwFlags, else { GetLocaleInfoW(lcid, LOCALE_SNEGATIVESIGN|(dwFlags & LOCALE_NOUSEROVERRIDE), - szNegBuff, sizeof(szNegBuff)/sizeof(WCHAR)); + szNegBuff, ARRAY_SIZE(szNegBuff)); lpszNegStart = lpszNeg = szNegBuff; } lpszNeg = lpszNeg + strlenW(lpszNeg) - 1; @@ -1368,7 +1368,7 @@ error: return 0; }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /************************************************************************** * GetNumberFormatEx (KERNEL32.@) */ @@ -1387,7 +1387,7 @@ INT WINAPI GetNumberFormatEx(LPCWSTR name, DWORD flags,
return GetNumberFormatW(lcid, flags, value, format, number, numout); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
/************************************************************************** * GetCurrencyFormatA (KERNEL32.@) @@ -1453,26 +1453,26 @@ INT WINAPI GetCurrencyFormatA(LCID lcid, DWORD dwFlags, pfmt = &fmt; if (lpFormat->lpDecimalSep) { - MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, sizeof(szDec)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat->lpDecimalSep, -1, szDec, ARRAY_SIZE(szDec)); fmt.lpDecimalSep = szDec; } if (lpFormat->lpThousandSep) { - MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, sizeof(szGrp)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat->lpThousandSep, -1, szGrp, ARRAY_SIZE(szGrp)); fmt.lpThousandSep = szGrp; } if (lpFormat->lpCurrencySymbol) { - MultiByteToWideChar(cp, 0, lpFormat->lpCurrencySymbol, -1, szCy, sizeof(szCy)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpFormat->lpCurrencySymbol, -1, szCy, ARRAY_SIZE(szCy)); fmt.lpCurrencySymbol = szCy; } }
if (lpszValue) - MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, sizeof(szIn)/sizeof(WCHAR)); + MultiByteToWideChar(cp, 0, lpszValue, -1, szIn, ARRAY_SIZE(szIn));
- if (cchOut > (int)(sizeof(szOut)/sizeof(WCHAR))) - cchOut = sizeof(szOut)/sizeof(WCHAR); + if (cchOut > (int) ARRAY_SIZE(szOut)) + cchOut = ARRAY_SIZE(szOut);
szOut[0] = '\0';
@@ -1528,7 +1528,7 @@ INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, CF_CY_LEFT|CF_CY_SPACE, /* $ 1.1 */ CF_CY_RIGHT|CF_CY_SPACE, /* 1.1 $ */ }; - WCHAR szBuff[128], *szOut = szBuff + sizeof(szBuff) / sizeof(WCHAR) - 1; + WCHAR szBuff[128], *szOut = szBuff + ARRAY_SIZE(szBuff) - 1; WCHAR szNegBuff[8]; const WCHAR *lpszNeg = NULL, *lpszNegStart, *szSrc, *lpszCy, *lpszCyStart; DWORD dwState = 0, dwDecimals = 0, dwGroupCount = 0, dwCurrentGroupCount = 0, dwFmt; @@ -1559,7 +1559,7 @@ INT WINAPI GetCurrencyFormatW(LCID lcid, DWORD dwFlags, else { GetLocaleInfoW(lcid, LOCALE_SNEGATIVESIGN|(dwFlags & LOCALE_NOUSEROVERRIDE), - szNegBuff, sizeof(szNegBuff)/sizeof(WCHAR)); + szNegBuff, ARRAY_SIZE(szNegBuff)); lpszNegStart = lpszNeg = szNegBuff; } dwFlags &= (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP); @@ -1782,6 +1782,21 @@ error: return 0; }
+#if _WIN32_WINNT >= 0x600 +/*********************************************************************** + * GetCurrencyFormatEx (KERNEL32.@) + */ +int WINAPI GetCurrencyFormatEx(LPCWSTR localename, DWORD flags, LPCWSTR value, + const CURRENCYFMTW *format, LPWSTR str, int len) +{ + TRACE("(%s,0x%08x,%s,%p,%p,%d)\n", debugstr_w(localename), flags, + debugstr_w(value), format, str, len); + + return GetCurrencyFormatW( LocaleNameToLCID(localename, 0), flags, value, format, str, len); +} +#endif + + /* FIXME: Everything below here needs to move somewhere else along with the * other EnumXXX functions, when a method for storing resources for * alternate calendars is determined. @@ -1854,9 +1869,9 @@ static BOOL NLS_EnumDateFormats(const struct enumdateformats_context *ctxt)
lctype |= ctxt->flags & LOCALE_USE_CP_ACP; if (ctxt->unicode) - ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, sizeof(bufW)/sizeof(bufW[0])); + ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW)); else - ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, sizeof(bufA)/sizeof(bufA[0])); + ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
if (ret) { @@ -1949,7 +1964,7 @@ BOOL WINAPI EnumDateFormatsW(DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags) return NLS_EnumDateFormats(&ctxt); }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /************************************************************************** * EnumDateFormatsExEx (KERNEL32.@) */ @@ -1966,7 +1981,7 @@ BOOL WINAPI EnumDateFormatsExEx(DATEFMT_ENUMPROCEXEX proc, const WCHAR *locale,
return NLS_EnumDateFormats(&ctxt); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
struct enumtimeformats_context { enum enum_callback_type type; /* callback kind */ @@ -2009,9 +2024,9 @@ static BOOL NLS_EnumTimeFormats(struct enumtimeformats_context *ctxt)
lctype |= ctxt->flags & LOCALE_USE_CP_ACP; if (ctxt->unicode) - ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, sizeof(bufW)/sizeof(bufW[0])); + ret = GetLocaleInfoW(ctxt->lcid, lctype, bufW, ARRAY_SIZE(bufW)); else - ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, sizeof(bufA)/sizeof(bufA[0])); + ret = GetLocaleInfoA(ctxt->lcid, lctype, bufA, ARRAY_SIZE(bufA));
if (ret) { @@ -2073,7 +2088,7 @@ BOOL WINAPI EnumTimeFormatsW(TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags) return NLS_EnumTimeFormats(&ctxt); }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /************************************************************************** * EnumTimeFormatsEx (KERNEL32.@) */ @@ -2090,7 +2105,7 @@ BOOL WINAPI EnumTimeFormatsEx(TIMEFMT_ENUMPROCEX proc, const WCHAR *locale, DWOR
return NLS_EnumTimeFormats(&ctxt); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
struct enumcalendar_context { enum enum_callback_type type; /* callback kind */ @@ -2321,7 +2336,7 @@ BOOL WINAPI EnumCalendarInfoExW( CALINFO_ENUMPROCEXW calinfoproc,LCID locale, return NLS_EnumCalendarInfo(&ctxt); }
-#ifndef __REACTOS__ +#if _WIN32_WINNT >= 0x600 /****************************************************************************** * EnumCalendarInfoExEx [KERNEL32.@] */ @@ -2341,7 +2356,7 @@ BOOL WINAPI EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX calinfoproc, LPCWSTR loca ctxt.unicode = TRUE; return NLS_EnumCalendarInfo(&ctxt); } -#endif /* !__REACTOS__ */ +#endif /* _WIN32_WINNT >= 0x600 */
/********************************************************************* * GetCalendarInfoA (KERNEL32.@) @@ -2567,6 +2582,23 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType, return 0; }
+#if _WIN32_WINNT >= 0x600 +/********************************************************************* + * GetCalendarInfoEx (KERNEL32.@) + */ +int WINAPI GetCalendarInfoEx(LPCWSTR locale, CALID calendar, LPCWSTR lpReserved, CALTYPE caltype, + LPWSTR data, int len, DWORD *value) +{ + static int once; + + LCID lcid = LocaleNameToLCID(locale, 0); + if (!once++) + FIXME("(%s, %d, %p, 0x%08x, %p, %d, %p): semi-stub\n", debugstr_w(locale), calendar, lpReserved, caltype, + data, len, value); + return GetCalendarInfoW(lcid, calendar, caltype, data, len, value); +} +#endif + /********************************************************************* * SetCalendarInfoA (KERNEL32.@) * diff --git a/dll/win32/kernel32/winnls/string/nls.c b/dll/win32/kernel32/winnls/string/nls.c index 86449e877d..391eca8fae 100644 --- a/dll/win32/kernel32/winnls/string/nls.c +++ b/dll/win32/kernel32/winnls/string/nls.c @@ -2261,4 +2261,17 @@ GetNLSVersion(IN NLS_FUNCTION Function, return TRUE; }
+/* + * @unimplemented + */ +BOOL +WINAPI +GetNLSVersionEx(IN NLS_FUNCTION function, + IN LPCWSTR lpLocaleName, + IN OUT LPNLSVERSIONINFOEX lpVersionInformation) +{ + STUB; + return TRUE; +} + /* EOF */ diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 9b59c155a3..4b31162daa 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -283,7 +283,7 @@ kernel32 - reactos/dll/win32/kernel32/winnls/string/fold.c # Synced to WineStaging-3.3 reactos/dll/win32/kernel32/winnls/string/format_msg.c # Synced to WineStaging-3.3 reactos/dll/win32/kernel32/winnls/string/lang.c # Synced in r52754 - reactos/dll/win32/kernel32/winnls/string/lcformat.c # Synced to WineStaging-3.3 + reactos/dll/win32/kernel32/winnls/string/lcformat.c # Synced to WineStaging-3.21 reactos/dll/win32/kernel32/winnls/string/nls.c # Synced in r52754 reactos/dll/win32/kernel32/winnls/string/sortkey.c # Synced to WineStaging-3.3
diff --git a/sdk/include/psdk/winnls.h b/sdk/include/psdk/winnls.h index eb9f94844a..61baa71dce 100644 --- a/sdk/include/psdk/winnls.h +++ b/sdk/include/psdk/winnls.h @@ -198,6 +198,15 @@ extern "C" { #define LCID_INSTALLED 1 #define LCID_SUPPORTED 2 #define LCID_ALTERNATE_SORTS 4 + +#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 + #define MAP_FOLDCZONE 16 #define MAP_FOLDDIGITS 128 #define MAP_PRECOMPOSED 32 @@ -611,6 +620,13 @@ typedef struct nlsversioninfo { DWORD dwNLSVersion; DWORD dwDefinedVersion; } NLSVERSIONINFO,*LPNLSVERSIONINFO; +typedef struct _nlsversioninfoex { + DWORD dwNLSVersionInfoSize; + DWORD dwNLSVersion; + DWORD dwDefinedVersion; + DWORD dwEffectiveId; + GUID guidCustomVersion; +} NLSVERSIONINFOEX, *LPNLSVERSIONINFOEX; typedef struct _numberfmtA { UINT NumDigits; UINT LeadingZero; @@ -760,6 +776,7 @@ GetCurrencyFormatW(
int WINAPI GetDateFormatA(LCID,DWORD,const SYSTEMTIME*,LPCSTR,LPSTR,int); int WINAPI GetDateFormatW(LCID,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,int); +int WINAPI GetDateFormatEx(LPCWSTR,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,int,LPCWSTR);
int WINAPI @@ -797,6 +814,13 @@ GetLocaleInfoW(
BOOL WINAPI GetNLSVersion(_In_ NLS_FUNCTION, _In_ LCID, _Inout_ LPNLSVERSIONINFO);
+BOOL +WINAPI +GetNLSVersionEx( + _In_ NLS_FUNCTION function, + _In_ LPCWSTR lpLocaleName, + _Inout_ LPNLSVERSIONINFOEX lpVersionInformation); + int WINAPI GetNumberFormatA( @@ -859,6 +883,7 @@ LCID WINAPI GetSystemDefaultLCID(void); LCID WINAPI GetThreadLocale(void); int WINAPI GetTimeFormatA(LCID,DWORD,const SYSTEMTIME*,LPCSTR,LPSTR,int); int WINAPI GetTimeFormatW(LCID,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,int); +int WINAPI GetTimeFormatEx(LPCWSTR,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,int); LANGID WINAPI GetUserDefaultLangID(void); LCID WINAPI GetUserDefaultLCID(void); GEOID WINAPI GetUserGeoID(_In_ GEOCLASS); @@ -978,6 +1003,8 @@ GetLocaleInfoEx( _Out_writes_opt_(cchData) LPWSTR lpLCData, _In_ int cchData);
+BOOL WINAPI IsValidLocaleName(_In_ LPCWSTR lpLocaleName); + BOOL WINAPI GetProcessPreferredUILanguages( @@ -1076,6 +1103,8 @@ GetStringScripts( BOOL WINAPI SetProcessPreferredUILanguages(_In_ DWORD, _In_opt_ PCZZWSTR, _Out_opt_ PULONG); BOOL WINAPI SetThreadPreferredUILanguages(_In_ DWORD, _In_opt_ PCZZWSTR, _Out_opt_ PULONG); BOOL WINAPI VerifyScripts(_In_ DWORD, _In_ LPCWSTR, _In_ int, _In_ LPCWSTR, _In_ int); +INT WINAPI LCMapStringEx(_In_ LPCWSTR, _In_ DWORD, _In_ LPCWSTR, _In_ INT, _Out_opt_ LPWSTR, _In_ INT, _In_ LPNLSVERSIONINFO, _In_ LPVOID, _In_ LPARAM); +LCID WINAPI LocaleNameToLCID(_In_ LPCWSTR, _In_ DWORD);
#endif /* (WINVER >= 0x0600) */