https://git.reactos.org/?p=reactos.git;a=commitdiff;h=655d24d9eb530bcc12935…
commit 655d24d9eb530bcc12935bc8fa025025c78a23eb
Author: Denis Malikov <filedem(a)gmail.com>
AuthorDate: Sun Nov 18 21:32:13 2018 +0700
Commit: Mark Jansen <mark.jansen(a)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) */