https://git.reactos.org/?p=reactos.git;a=commitdiff;h=15537c3bbe30a80641bc5f42c7375dafe6643572

commit 15537c3bbe30a80641bc5f42c7375dafe6643572
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Sun Apr 7 20:20:23 2019 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Sun Apr 7 20:20:23 2019 +0900

    [KERNEL32] Support Japanese calendar (#1482)
    
    Implement the Japanese calendar in kernel32. Locale info and date 
formatting. CORE-15920
---
 dll/win32/kernel32/CMakeLists.txt           |   1 +
 dll/win32/kernel32/winnls/string/japanese.c | 229 ++++++++++++++++++++++++++++
 dll/win32/kernel32/winnls/string/japanese.h |  21 +++
 dll/win32/kernel32/winnls/string/lang.c     |  14 ++
 dll/win32/kernel32/winnls/string/lcformat.c | 200 ++++++++++++++++++++++++
 5 files changed, 465 insertions(+)

diff --git a/dll/win32/kernel32/CMakeLists.txt 
b/dll/win32/kernel32/CMakeLists.txt
index 22409a7605..f2a4e0f029 100644
--- a/dll/win32/kernel32/CMakeLists.txt
+++ b/dll/win32/kernel32/CMakeLists.txt
@@ -76,6 +76,7 @@ list(APPEND SOURCE
     winnls/string/digitmap.c
     winnls/string/fold.c
     winnls/string/format_msg.c
+    winnls/string/japanese.c
     winnls/string/lang.c
     winnls/string/lcformat.c
     winnls/string/lstring.c
diff --git a/dll/win32/kernel32/winnls/string/japanese.c 
b/dll/win32/kernel32/winnls/string/japanese.c
new file mode 100644
index 0000000000..c3719f51f2
--- /dev/null
+++ b/dll/win32/kernel32/winnls/string/japanese.c
@@ -0,0 +1,229 @@
+/*
+ * PROJECT:     ReactOS system libraries
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Japanese era support
+ * COPYRIGHT:   Copyright 2019 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
+ */
+#include <k32.h>
+
+#define NDEBUG
+#include <debug.h>
+#include "japanese.h"
+
+#define JAPANESE_ERA_MAX 16
+
+/* #define DONT_USE_REGISTRY */
+
+static DWORD        s_JapaneseEraCount = 0;
+static JAPANESE_ERA s_JapaneseEraTable[JAPANESE_ERA_MAX]
+#ifdef DONT_USE_REGISTRY
+=
+{
+    {1868, 1, 1, {0x660E, 0x6CBB}, {0x660E, 0}, L"Meiji", L"M"},
+    {1912, 7, 30, {0x5927, 0x6B63}, {0x5927, 0}, L"Taisho", L"T"},
+    {1926, 12, 25, {0x662D, 0x548C}, {0x662D, 0}, L"Showa", L"S"},
+    {1989, 1, 8, {0x5E73, 0x6210}, {0x5E73, 0}, L"Heisei", L"H"},
+    {2019, 5, 1, {0x4EE4, 0x548C}, {0x4EE4, 0}, L"Reiwa", L"R"},
+}
+#endif
+;
+
+HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName);
+
+BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
+                      LPWSTR szValueName, ULONG valueNameSize,
+                      LPWSTR szValueData, ULONG valueDataSize);
+
+static INT JapaneseEra_Compare(const void *e1, const void *e2)
+{
+    PCJAPANESE_ERA pEra1 = (PCJAPANESE_ERA)e1;
+    PCJAPANESE_ERA pEra2 = (PCJAPANESE_ERA)e2;
+    if (pEra1->wYear < pEra2->wYear)
+        return -1;
+    if (pEra1->wYear > pEra2->wYear)
+        return 1;
+    if (pEra1->wMonth < pEra2->wMonth)
+        return -1;
+    if (pEra1->wMonth > pEra2->wMonth)
+        return 1;
+    if (pEra1->wDay < pEra2->wDay)
+        return -1;
+    if (pEra1->wDay > pEra2->wDay)
+        return 1;
+    return 0;
+}
+
+/* 
+ * SEE ALSO:
+ * https://en.wikipedia.org/wiki/Japanese_era_name
+ * 
https://docs.microsoft.com/en-us/windows/desktop/Intl/era-handling-for-the-japanese-calendar
+ */
+static PCJAPANESE_ERA JapaneseEra_Load(DWORD *pdwCount)
+{
+#ifndef DONT_USE_REGISTRY
+    HANDLE KeyHandle = NULL;
+    DWORD dwIndex;
+    WCHAR szName[128], szValue[128];
+    JAPANESE_ERA *pEntry;
+    LPWSTR pch1, pch2, pch3, pch4;
+#endif
+
+    ASSERT(pdwCount != NULL);
+
+    /* return cache if any */
+    if (s_JapaneseEraCount != 0)
+    {
+        *pdwCount = s_JapaneseEraCount;
+        return s_JapaneseEraTable;
+    }
+
+#ifdef DONT_USE_REGISTRY
+    s_JapaneseEraCount = ARRAYSIZE(s_JapaneseEraTable);
+#else
+    /* init */
+    *pdwCount = 0;
+    RtlZeroMemory(&s_JapaneseEraTable, sizeof(s_JapaneseEraTable));
+
+    /* open registry key */
+    KeyHandle = NLS_RegOpenKey(NULL, L"\\Registry\\Machine\\System\\"
+        L"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese\\Eras");
+    if (!KeyHandle)
+        return NULL;
+
+    /* for all values */
+    for (dwIndex = 0; dwIndex < JAPANESE_ERA_MAX; ++dwIndex)
+    {
+        pEntry = &s_JapaneseEraTable[dwIndex];
+
+        /* get name and data */
+        if (!NLS_RegEnumValue(KeyHandle, dwIndex, szName, sizeof(szName),
+                              szValue, sizeof(szValue)))
+        {
+            break;
+        }
+
+        /* split fields */
+        pch1 = szName;
+        pch2 = wcschr(pch1, L' ');
+        if (pch2 == NULL)
+        {
+            break;
+        }
+        *pch2++ = UNICODE_NULL;
+
+        pch3 = wcschr(pch2, L' ');
+        if (pch3 == NULL)
+        {
+            break;
+        }
+        *pch3++ = UNICODE_NULL;
+
+        pEntry->wYear = _wtoi(pch1);
+        pEntry->wMonth = _wtoi(pch2);
+        pEntry->wDay = _wtoi(pch3);
+        if (pEntry->wYear == 0 || pEntry->wMonth == 0 || pEntry->wDay == 0)
+        {
+            break;
+        }
+
+        /* split fields */
+        pch1 = szValue;
+        pch2 = wcschr(pch1, L'_');
+        if (pch2 == NULL)
+        {
+            break;
+        }
+        *pch2++ = UNICODE_NULL;
+
+        pch3 = wcschr(pch2, L'_');
+        if (pch3 == NULL)
+        {
+            break;
+        }
+        *pch3++ = UNICODE_NULL;
+
+        pch4 = wcschr(pch3, L'_');
+        if (pch4 == NULL)
+        {
+            break;
+        }
+        *pch4++ = UNICODE_NULL;
+
+        /* store */
+        RtlStringCbCopyW(pEntry->szEraName, sizeof(pEntry->szEraName), pch1);
+        RtlStringCbCopyW(pEntry->szEraAbbrev, sizeof(pEntry->szEraAbbrev), 
pch2);
+        RtlStringCbCopyW(pEntry->szEnglishEraName, 
sizeof(pEntry->szEnglishEraName), pch3);
+        RtlStringCbCopyW(pEntry->szEnglishEraAbbrev, 
sizeof(pEntry->szEnglishEraAbbrev), pch4);
+    }
+
+    /* close key */
+    NtClose(KeyHandle);
+
+    /* sort */
+    qsort(s_JapaneseEraTable, s_JapaneseEraCount, sizeof(JAPANESE_ERA),
+          JapaneseEra_Compare);
+
+    /* make cache */
+    s_JapaneseEraCount = dwIndex;
+#endif
+
+    *pdwCount = s_JapaneseEraCount;
+
+    return s_JapaneseEraTable;
+}
+
+static BOOL JapaneseEra_ToSystemTime(PCJAPANESE_ERA pEra, LPSYSTEMTIME pst)
+{
+    ASSERT(pEra != NULL);
+    ASSERT(pst != NULL);
+
+    ZeroMemory(pst, sizeof(*pst));
+    pst->wYear = pEra->wYear;
+    pst->wMonth = pEra->wMonth;
+    pst->wDay = pEra->wDay;
+    return TRUE;
+}
+
+PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL)
+{
+    DWORD dwIndex, dwCount = 0;
+    PCJAPANESE_ERA pTable, pEntry, pPrevEntry = NULL;
+    SYSTEMTIME st1, st2;
+    FILETIME ft1, ft2;
+    LONG nCompare;
+
+    /* pst --> ft1 */
+    if (pst == NULL)
+    {
+        GetLocalTime(&st1);
+        pst = &st1;
+    }
+    SystemTimeToFileTime(pst, &ft1);
+
+    /* load era table */
+    pTable = JapaneseEra_Load(&dwCount);
+    if (pTable == NULL || dwCount == 0 || dwCount > JAPANESE_ERA_MAX)
+    {
+        return NULL;
+    }
+
+    /* for all eras */
+    for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
+    {
+        pEntry = &pTable[dwIndex];
+
+        /* pEntry --> st2 --> ft2 */
+        JapaneseEra_ToSystemTime(pEntry, &st2);
+        SystemTimeToFileTime(&st2, &ft2);
+
+        /* ft1 <=> ft2 */
+        nCompare = CompareFileTime(&ft1, &ft2);
+        if (nCompare == 0)
+            return pEntry;
+        if (nCompare < 0)
+            return pPrevEntry;
+        pPrevEntry = pEntry;
+    }
+
+    return pPrevEntry;
+}
diff --git a/dll/win32/kernel32/winnls/string/japanese.h 
b/dll/win32/kernel32/winnls/string/japanese.h
new file mode 100644
index 0000000000..747ee136ed
--- /dev/null
+++ b/dll/win32/kernel32/winnls/string/japanese.h
@@ -0,0 +1,21 @@
+/*
+ * PROJECT:     ReactOS system libraries
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Japanese era support
+ * COPYRIGHT:   Copyright 2019 Katayama Hirofumi MZ 
(katayama.hirofumi...@gmail.com)
+ */
+#define JAPANESE_MAX_TWODIGITYEAR 99
+
+typedef struct JAPANESE_ERA
+{
+    WORD wYear;
+    WORD wMonth;
+    WORD wDay;
+    WCHAR szEraName[16];
+    WCHAR szEraAbbrev[5];
+    WCHAR szEnglishEraName[24];
+    WCHAR szEnglishEraAbbrev[5];
+} JAPANESE_ERA, *PJAPANESE_ERA;
+typedef const JAPANESE_ERA *PCJAPANESE_ERA;
+
+PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL);
diff --git a/dll/win32/kernel32/winnls/string/lang.c 
b/dll/win32/kernel32/winnls/string/lang.c
index 42c57d1aef..7d13980511 100644
--- a/dll/win32/kernel32/winnls/string/lang.c
+++ b/dll/win32/kernel32/winnls/string/lang.c
@@ -2366,14 +2366,22 @@ INT WINAPI CompareStringA(LCID lcid, DWORD flags,
     return ret;
 }
 
+#ifdef __REACTOS__
+HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
+#else
 static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
+#endif
 {
     UNICODE_STRING keyName;
     OBJECT_ATTRIBUTES attr;
     HANDLE hkey;
 
     RtlInitUnicodeString( &keyName, szKeyName );
+#ifdef __REACTOS__
+    InitializeObjectAttributes(&attr, &keyName, OBJ_CASE_INSENSITIVE, 
hRootKey, NULL);
+#else
     InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
+#endif
 
     if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
         hkey = 0;
@@ -2381,9 +2389,15 @@ static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR 
szKeyName)
     return hkey;
 }
 
+#ifdef __REACTOS__
+BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
+                      LPWSTR szValueName, ULONG valueNameSize,
+                      LPWSTR szValueData, ULONG valueDataSize)
+#else
 static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
                              LPWSTR szValueName, ULONG valueNameSize,
                              LPWSTR szValueData, ULONG valueDataSize)
+#endif
 {
     BYTE buffer[80];
     KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
diff --git a/dll/win32/kernel32/winnls/string/lcformat.c 
b/dll/win32/kernel32/winnls/string/lcformat.c
index a4088cb9b2..8d85351190 100644
--- a/dll/win32/kernel32/winnls/string/lcformat.c
+++ b/dll/win32/kernel32/winnls/string/lcformat.c
@@ -25,6 +25,7 @@
 #ifdef __REACTOS__
 
 #include <k32.h>
+#include "japanese.h"   /* Japanese eras */
 
 #define NDEBUG
 #include <debug.h>
@@ -34,6 +35,12 @@ DEBUG_CHANNEL(nls);
 #define CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG
 #define CALINFO_MAX_YEAR 2029
 
+#define IS_LCID_JAPANESE(lcid) PRIMARYLANGID(LANGIDFROMLCID(lcid)) == 
LANG_JAPANESE
+
+#ifndef CAL_SABBREVERASTRING
+    #define CAL_SABBREVERASTRING 0x00000039
+#endif
+
 #else /* __REACTOS__ */
 
 #include "config.h"
@@ -372,7 +379,11 @@ BOOL NLS_IsUnicodeOnlyLcid(LCID lcid)
 #define IsTimeFmtChar(p)   (p == 'H'||p == 'h'||p == 'm'||p == 's'||p == 't')
 
 /* Only the following flags can be given if a date/time format is specified */
+#ifdef __REACTOS__
+#define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY | DATE_USE_ALT_CALENDAR)
+#else
 #define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY)
+#endif
 #define TIME_FORMAT_FLAGS (TIME_TIMEVARSONLY|TIME_FORCE24HOURFORMAT| \
                            TIME_NOMINUTESORSECONDS|TIME_NOSECONDS| \
                            TIME_NOTIMEMARKER)
@@ -604,6 +615,24 @@ static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags,
         break;
 
       case 'y':
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(lcid) && (dwFlags & DATE_USE_ALT_CALENDAR))
+        {
+            PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
+            if (pEra)
+            {
+                if (count >= 2)
+                {
+                    count = 2;
+                }
+                dwVal = lpTime->wYear - pEra->wYear + 1;
+                szAdd = buff;
+                break;
+            }
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return 0;
+        }
+#endif
         if (count >= 4)
         {
           count = 4;
@@ -618,6 +647,32 @@ static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags,
         break;
 
       case 'g':
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(lcid))
+        {
+            if (dwFlags & DATE_USE_ALT_CALENDAR)
+            {
+                PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
+                if (pEra)
+                {
+                    RtlStringCbCopyW(buff, sizeof(buff), pEra->szEraName);
+                    szAdd = buff;
+                    break;
+                }
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return 0;
+            }
+            else
+            {
+                /* Seireki */
+                buff[0] = 0x897F;
+                buff[1] = 0x66A6;
+                buff[2] = 0;
+                szAdd = buff;
+                break;
+            }
+        }
+#endif
         if (count == 2)
         {
           /* FIXME: Our GetCalendarInfo() does not yet support CAL_SERASTRING.
@@ -2367,6 +2422,26 @@ int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, 
CALTYPE CalType,
 {
     int ret, cchDataW = cchData;
     LPWSTR lpCalDataW = NULL;
+#ifdef __REACTOS__
+    DWORD cp = CP_ACP;
+    if (!(CalType & CAL_USE_CP_ACP))
+    {
+        DWORD dwFlags = ((CalType & CAL_NOUSEROVERRIDE) ? 
LOCALE_NOUSEROVERRIDE : 0);
+        const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags);
+        if (!node)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return 0;
+        }
+        cp = node->dwCodePage;
+    }
+    if ((CalType & 0xFFFF) == CAL_SABBREVERASTRING)
+    {
+        /* NOTE: CAL_SABBREVERASTRING is not supported in GetCalendarInfoA */
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+#endif
 
     if (NLS_IsUnicodeOnlyLcid(lcid))
     {
@@ -2381,7 +2456,11 @@ int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, 
CALTYPE CalType,
 
     ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchDataW, 
lpValue);
     if(ret && lpCalDataW && lpCalData)
+#ifdef __REACTOS__
+        ret = WideCharToMultiByte(cp, 0, lpCalDataW, -1, lpCalData, cchData, 
NULL, NULL);
+#else
         ret = WideCharToMultiByte(CP_ACP, 0, lpCalDataW, -1, lpCalData, 
cchData, NULL, NULL);
+#endif
     else if (CalType & CAL_RETURN_NUMBER)
         ret *= sizeof(WCHAR);
     HeapFree(GetProcessHeap(), 0, lpCalDataW);
@@ -2495,18 +2574,101 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID 
Calendar, CALTYPE CalType,
 
     switch (calinfo) {
        case CAL_ICALINTVALUE:
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(Locale))
+        {
+            if (CalType & CAL_RETURN_NUMBER)
+            {
+                *lpValue = CAL_JAPAN;
+                return sizeof(DWORD) / sizeof(WCHAR);
+            }
+            else
+            {
+                static const WCHAR fmtW[] = {'%','u',0};
+                WCHAR buffer[10];
+                int ret = snprintfW( buffer, 10, fmtW, CAL_JAPAN ) + 1;
+                if (!lpCalData) return ret;
+                if (ret <= cchData)
+                {
+                    strcpyW( lpCalData, buffer );
+                    return ret;
+                }
+                SetLastError( ERROR_INSUFFICIENT_BUFFER );
+                return 0;
+            }
+        }
+#endif
             if (CalType & CAL_RETURN_NUMBER)
                 return GetLocaleInfoW(Locale, LOCALE_RETURN_NUMBER | 
LOCALE_ICALENDARTYPE,
                         (LPWSTR)lpValue, 2);
             return GetLocaleInfoW(Locale, LOCALE_ICALENDARTYPE, lpCalData, 
cchData);
        case CAL_SCALNAME:
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
+        {
+            // Wareki
+            lpCalData[0] = 0x548C;
+            lpCalData[1] = 0x66A6;
+            lpCalData[2] = 0;
+            return 3;
+        }
+#endif
             FIXME("Unimplemented caltype %d\n", calinfo);
             if (lpCalData) *lpCalData = 0;
            return 1;
        case CAL_IYEAROFFSETRANGE:
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
+        {
+            PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
+            if (pEra)
+            {
+                if (CalType & CAL_RETURN_NUMBER)
+                {
+                    *lpValue = pEra->wYear;
+                    return sizeof(DWORD) / sizeof(WCHAR);
+                }
+                else
+                {
+                    static const WCHAR fmtW[] = {'%','u',0};
+                    WCHAR buffer[10];
+                    int ret = snprintfW( buffer, 10, fmtW, pEra->wYear ) + 1;
+                    if (!lpCalData) return ret;
+                    if (ret <= cchData)
+                    {
+                        strcpyW( lpCalData, buffer );
+                        return ret;
+                    }
+                    SetLastError( ERROR_INSUFFICIENT_BUFFER );
+                    return 0;
+                }
+            }
+            else
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return 0;
+            }
+        }
+#endif
             FIXME("Unimplemented caltype %d\n", calinfo);
            return 0;
        case CAL_SERASTRING:
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
+        {
+            PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
+            if (pEra)
+            {
+                RtlStringCchCopyW(lpCalData, cchData, pEra->szEraName);
+                return strlenW(lpCalData) + 1;
+            }
+            else
+            {
+                SetLastError(ERROR_INVALID_PARAMETER);
+                return 0;
+            }
+        }
+#endif
             FIXME("Unimplemented caltype %d\n", calinfo);
            return 0;
        case CAL_SSHORTDATE:
@@ -2554,6 +2716,30 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, 
CALTYPE CalType,
        case CAL_SYEARMONTH:
             return GetLocaleInfoW(Locale, caltype_lctype_map[calinfo] | 
localeflags, lpCalData, cchData);
        case CAL_ITWODIGITYEARMAX:
+#ifdef __REACTOS__
+        if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
+        {
+            if (CalType & CAL_RETURN_NUMBER)
+            {
+                *lpValue = JAPANESE_MAX_TWODIGITYEAR;
+                return sizeof(DWORD) / sizeof(WCHAR);
+            }
+            else
+            {
+                static const WCHAR fmtW[] = {'%','u',0};
+                WCHAR buffer[10];
+                int ret = snprintfW( buffer, 10, fmtW, 
JAPANESE_MAX_TWODIGITYEAR ) + 1;
+                if (!lpCalData) return ret;
+                if (ret <= cchData)
+                {
+                    strcpyW( lpCalData, buffer );
+                    return ret;
+                }
+                SetLastError( ERROR_INSUFFICIENT_BUFFER );
+                return 0;
+            }
+        }
+#endif
             if (CalType & CAL_RETURN_NUMBER)
             {
                 *lpValue = CALINFO_MAX_YEAR;
@@ -2574,6 +2760,20 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, 
CALTYPE CalType,
                 return 0;
             }
            break;
+#ifdef __REACTOS__
+    case CAL_SABBREVERASTRING:
+        if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
+        {
+            PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
+            if (pEra)
+            {
+                RtlStringCchCopyW(lpCalData, cchData, pEra->szEraAbbrev);
+                return strlenW(lpCalData) + 1;
+            }
+        }
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+#endif
        default:
             FIXME("Unknown caltype %d\n", calinfo);
             SetLastError(ERROR_INVALID_FLAGS);

Reply via email to