ReactOS  0.4.14-dev-77-gd9e7c48
japanese.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS system libraries
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Japanese era support
5  * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 #include <k32.h>
8 
9 #define NDEBUG
10 #include <debug.h>
11 #include "japanese.h"
12 
13 #define JAPANESE_ERA_MAX 16
14 
15 /* #define DONT_USE_REGISTRY */
16 
20 #ifdef DONT_USE_REGISTRY
21 =
22 {
23  {1868, 1, 1, {0x660E, 0x6CBB}, {0x660E, 0}, L"Meiji", L"M"},
24  {1912, 7, 30, {0x5927, 0x6B63}, {0x5927, 0}, L"Taisho", L"T"},
25  {1926, 12, 25, {0x662D, 0x548C}, {0x662D, 0}, L"Showa", L"S"},
26  {1989, 1, 8, {0x5E73, 0x6210}, {0x5E73, 0}, L"Heisei", L"H"},
27  {2019, 5, 1, {0x4EE4, 0x548C}, {0x4EE4, 0}, L"Reiwa", L"R"},
28 }
29 #endif
30 ;
31 
32 HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName);
33 
35  LPWSTR szValueName, ULONG valueNameSize,
36  LPWSTR szValueData, ULONG valueDataSize);
37 
39 {
42 }
43 
44 static INT JapaneseEra_Compare(const void *e1, const void *e2)
45 {
46  PCJAPANESE_ERA pEra1 = (PCJAPANESE_ERA)e1;
47  PCJAPANESE_ERA pEra2 = (PCJAPANESE_ERA)e2;
48  if (pEra1->wYear < pEra2->wYear)
49  return -1;
50  if (pEra1->wYear > pEra2->wYear)
51  return 1;
52  if (pEra1->wMonth < pEra2->wMonth)
53  return -1;
54  if (pEra1->wMonth > pEra2->wMonth)
55  return 1;
56  if (pEra1->wDay < pEra2->wDay)
57  return -1;
58  if (pEra1->wDay > pEra2->wDay)
59  return 1;
60  return 0;
61 }
62 
64 {
65 #ifdef DONT_USE_REGISTRY
66  return TRUE;
67 #else
69  DWORD dwIndex;
70  WCHAR szName[32], szValue[32];
71  static BOOL s_bFirstIsGannen = TRUE;
72 
74  return s_bFirstIsGannen;
75 
76  KeyHandle = NLS_RegOpenKey(NULL, L"\\Registry\\Machine\\System\\"
77  L"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese");
78  if (!KeyHandle)
79  return TRUE;
80 
81  s_bFirstIsGannen = TRUE;
82  for (dwIndex = 0; dwIndex < 16; ++dwIndex)
83  {
84  if (!NLS_RegEnumValue(KeyHandle, dwIndex, szName, sizeof(szName),
85  szValue, sizeof(szValue)))
86  {
87  break;
88  }
89 
90  if (lstrcmpiW(szName, L"InitialEraYear") == 0)
91  {
92  s_bFirstIsGannen = (szValue[0] == 0x5143);
93  break;
94  }
95  }
96 
98 
100 
101  return s_bFirstIsGannen;
102 #endif
103 }
104 
105 /*
106  * SEE ALSO:
107  * https://en.wikipedia.org/wiki/Japanese_era_name
108  * https://docs.microsoft.com/en-us/windows/desktop/Intl/era-handling-for-the-japanese-calendar
109  */
111 {
112 #ifndef DONT_USE_REGISTRY
114  DWORD dwIndex;
115  WCHAR szName[128], szValue[128];
116  JAPANESE_ERA *pEntry;
117  LPWSTR pch1, pch2, pch3, pch4;
118 #endif
119 
120  ASSERT(pdwCount != NULL);
121 
122  /* return cache if any */
123  if (s_JapaneseEraCount != 0)
124  {
125  *pdwCount = s_JapaneseEraCount;
126  return s_JapaneseEraTable;
127  }
128 
129 #ifdef DONT_USE_REGISTRY
131 #else
132  /* init */
133  *pdwCount = 0;
135 
136  /* open registry key */
137  KeyHandle = NLS_RegOpenKey(NULL, L"\\Registry\\Machine\\System\\"
138  L"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese\\Eras");
139  if (!KeyHandle)
140  return NULL;
141 
142  /* for all values */
143  for (dwIndex = 0; dwIndex < JAPANESE_ERA_MAX; ++dwIndex)
144  {
145  pEntry = &s_JapaneseEraTable[dwIndex];
146 
147  /* get name and data */
148  if (!NLS_RegEnumValue(KeyHandle, dwIndex, szName, sizeof(szName),
149  szValue, sizeof(szValue)))
150  {
151  break;
152  }
153 
154  /* split fields */
155  pch1 = szName;
156  pch2 = wcschr(pch1, L' ');
157  if (pch2 == NULL)
158  {
159  break;
160  }
161  *pch2++ = UNICODE_NULL;
162 
163  pch3 = wcschr(pch2, L' ');
164  if (pch3 == NULL)
165  {
166  break;
167  }
168  *pch3++ = UNICODE_NULL;
169 
170  pEntry->wYear = _wtoi(pch1);
171  pEntry->wMonth = _wtoi(pch2);
172  pEntry->wDay = _wtoi(pch3);
173  if (pEntry->wYear == 0 || pEntry->wMonth == 0 || pEntry->wDay == 0)
174  {
175  break;
176  }
177 
178  /* split fields */
179  pch1 = szValue;
180  pch2 = wcschr(pch1, L'_');
181  if (pch2 == NULL)
182  {
183  break;
184  }
185  *pch2++ = UNICODE_NULL;
186 
187  pch3 = wcschr(pch2, L'_');
188  if (pch3 == NULL)
189  {
190  break;
191  }
192  *pch3++ = UNICODE_NULL;
193 
194  pch4 = wcschr(pch3, L'_');
195  if (pch4 == NULL)
196  {
197  break;
198  }
199  *pch4++ = UNICODE_NULL;
200 
201  /* store */
202  RtlStringCbCopyW(pEntry->szEraName, sizeof(pEntry->szEraName), pch1);
203  RtlStringCbCopyW(pEntry->szEraAbbrev, sizeof(pEntry->szEraAbbrev), pch2);
204  RtlStringCbCopyW(pEntry->szEnglishEraName, sizeof(pEntry->szEnglishEraName), pch3);
205  RtlStringCbCopyW(pEntry->szEnglishEraAbbrev, sizeof(pEntry->szEnglishEraAbbrev), pch4);
206  }
207 
208  /* close key */
210 
211  /* sort */
214 
215  /* make cache */
216  s_JapaneseEraCount = dwIndex;
217 #endif
218 
219  *pdwCount = s_JapaneseEraCount;
220 
221  return s_JapaneseEraTable;
222 }
223 
225 {
226  ASSERT(pEra != NULL);
227  ASSERT(pst != NULL);
228 
229  ZeroMemory(pst, sizeof(*pst));
230  pst->wYear = pEra->wYear;
231  pst->wMonth = pEra->wMonth;
232  pst->wDay = pEra->wDay;
233  return TRUE;
234 }
235 
237 {
238  DWORD dwIndex, dwCount = 0;
239  PCJAPANESE_ERA pTable, pEntry, pPrevEntry = NULL;
240  SYSTEMTIME st1, st2;
241  FILETIME ft1, ft2;
242  LONG nCompare;
243 
244  /* pst --> ft1 */
245  if (pst == NULL)
246  {
247  GetLocalTime(&st1);
248  pst = &st1;
249  }
250  SystemTimeToFileTime(pst, &ft1);
251 
252  /* load era table */
253  pTable = JapaneseEra_Load(&dwCount);
254  if (pTable == NULL || dwCount == 0 || dwCount > JAPANESE_ERA_MAX)
255  {
256  return NULL;
257  }
258 
259  /* for all eras */
260  for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
261  {
262  pEntry = &pTable[dwIndex];
263 
264  /* pEntry --> st2 --> ft2 */
265  JapaneseEra_ToSystemTime(pEntry, &st2);
266  SystemTimeToFileTime(&st2, &ft2);
267 
268  /* ft1 <=> ft2 */
269  nCompare = CompareFileTime(&ft1, &ft2);
270  if (nCompare == 0)
271  return pEntry;
272  if (nCompare < 0)
273  return pPrevEntry;
274  pPrevEntry = pEntry;
275  }
276 
277  return pPrevEntry;
278 }
NTSTRSAFEAPI RtlStringCbCopyW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:174
static INT JapaneseEra_Compare(const void *e1, const void *e2)
Definition: japanese.c:44
#define TRUE
Definition: types.h:120
void JapaneseEra_ClearCache(void)
Definition: japanese.c:38
BOOL JapaneseEra_IsFirstYearGannen(void)
Definition: japanese.c:63
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
WORD wMonth
Definition: winbase.h:871
static DWORD s_JapaneseEraCount
Definition: japanese.c:18
_Check_return_ _CRTIMP int __cdecl _wtoi(_In_z_ const wchar_t *_Str)
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ZeroMemory
Definition: winbase.h:1635
static BOOL JapaneseEra_ToSystemTime(PCJAPANESE_ERA pEra, LPSYSTEMTIME pst)
Definition: japanese.c:224
int32_t INT
Definition: typedefs.h:56
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
#define JAPANESE_ERA_MAX
Definition: japanese.c:13
WORD wYear
Definition: winbase.h:870
HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex, LPWSTR szValueName, ULONG valueNameSize, LPWSTR szValueData, ULONG valueDataSize)
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
smooth NULL
Definition: ftsmooth.c:416
WORD wMonth
Definition: japanese.h:12
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:276
LONG WINAPI CompareFileTime(IN CONST FILETIME *lpFileTime1, IN CONST FILETIME *lpFileTime2)
Definition: time.c:106
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR szEraName[16]
Definition: japanese.h:14
WORD wDay
Definition: japanese.h:13
PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL)
Definition: japanese.c:236
unsigned long DWORD
Definition: ntddk_ex.h:95
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR L[]
Definition: oid.c:1250
WORD wDay
Definition: winbase.h:873
ULONG ulIndex
Definition: symbols.c:92
BOOL WINAPI SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime, OUT LPFILETIME lpFileTime)
Definition: time.c:148
const JAPANESE_ERA * PCJAPANESE_ERA
Definition: japanese.h:19
static PCJAPANESE_ERA JapaneseEra_Load(DWORD *pdwCount)
Definition: japanese.c:110
unsigned int UINT
Definition: ndis.h:50
static const WCHAR szName[]
Definition: msipriv.h:1194
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
WCHAR szEraAbbrev[5]
Definition: japanese.h:15
static const EHCI_PERIOD pTable[]
Definition: usbehci.c:29
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static BOOL s_bIsGannenCached
Definition: japanese.c:17
WCHAR szEnglishEraAbbrev[5]
Definition: japanese.h:17
WORD wYear
Definition: japanese.h:11
static JAPANESE_ERA s_JapaneseEraTable[JAPANESE_ERA_MAX]
Definition: japanese.c:30
WCHAR szEnglishEraName[24]
Definition: japanese.h:16
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68