ReactOS  0.4.15-dev-489-g75a0787
tzlib.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS TimeZone Utilities Library
3  * LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
4  * PURPOSE: Provides time-zone utility wrappers around Win32 functions,
5  * that are used by different ReactOS modules such as
6  * timedate.cpl, syssetup.dll.
7  * COPYRIGHT: Copyright 2004-2005 Eric Kohl
8  * Copyright 2016 Carlo Bramini
9  * Copyright 2020 Hermes Belusca-Maito
10  */
11 
12 #include <stdlib.h>
13 #include <windef.h>
14 #include <winbase.h>
15 #include <winreg.h>
16 
17 #include "tzlib.h"
18 
19 BOOL
22 {
23  LONG lError;
24  HKEY hKey;
25  DWORD dwType;
26  DWORD dwValueSize;
27  DWORD Length;
28  LPWSTR Buffer;
29  LPWSTR Ptr, End;
30  BOOL bFound = FALSE;
31  unsigned long iLanguageID;
32  WCHAR szLanguageIdString[9];
33 
34  if (*pIndex == -1)
35  {
36  *pIndex = 85; /* fallback to GMT time zone */
37 
39  L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
40  0,
42  &hKey);
43  if (lError != ERROR_SUCCESS)
44  {
45  return FALSE;
46  }
47 
48  dwValueSize = sizeof(szLanguageIdString);
49  lError = RegQueryValueExW(hKey,
50  L"Default",
51  NULL,
52  NULL,
53  (LPBYTE)szLanguageIdString,
54  &dwValueSize);
55  if (lError != ERROR_SUCCESS)
56  {
57  RegCloseKey(hKey);
58  return FALSE;
59  }
60 
61  iLanguageID = wcstoul(szLanguageIdString, NULL, 16);
62  RegCloseKey(hKey);
63  }
64  else
65  {
66  iLanguageID = *pIndex;
67  }
68 
70  L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
71  0,
73  &hKey);
74  if (lError != ERROR_SUCCESS)
75  {
76  return FALSE;
77  }
78 
79  dwValueSize = 0;
80  lError = RegQueryValueExW(hKey,
81  L"IndexMapping",
82  NULL,
83  &dwType,
84  NULL,
85  &dwValueSize);
86  if ((lError != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ))
87  {
88  RegCloseKey(hKey);
89  return FALSE;
90  }
91 
93  if (Buffer == NULL)
94  {
95  RegCloseKey(hKey);
96  return FALSE;
97  }
98 
99  lError = RegQueryValueExW(hKey,
100  L"IndexMapping",
101  NULL,
102  &dwType,
103  (LPBYTE)Buffer,
104  &dwValueSize);
105 
106  RegCloseKey(hKey);
107 
108  if ((lError != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ))
109  {
111  return FALSE;
112  }
113 
114  Ptr = Buffer;
115  while (*Ptr != 0)
116  {
117  Length = wcslen(Ptr);
118  if (wcstoul(Ptr, NULL, 16) == iLanguageID)
119  bFound = TRUE;
120 
121  Ptr = Ptr + Length + 1;
122  if (*Ptr == 0)
123  break;
124 
125  if (bFound)
126  {
127  *pIndex = wcstoul(Ptr, &End, 10);
129  return TRUE;
130  }
131 
132  Length = wcslen(Ptr);
133  Ptr = Ptr + Length + 1;
134  }
135 
137  return FALSE;
138 }
139 
140 LONG
142  IN HKEY hZoneKey,
144  OUT PREG_TZI_FORMAT TimeZoneInfo,
146  IN OUT PULONG DescriptionSize OPTIONAL,
147  OUT PWCHAR StandardName OPTIONAL,
148  IN OUT PULONG StandardNameSize OPTIONAL,
149  OUT PWCHAR DaylightName OPTIONAL,
150  IN OUT PULONG DaylightNameSize OPTIONAL)
151 {
152  LONG lError;
153  DWORD dwValueSize;
154 
155  if (Index)
156  {
157  dwValueSize = sizeof(*Index);
158  lError = RegQueryValueExW(hZoneKey,
159  L"Index",
160  NULL,
161  NULL,
162  (LPBYTE)Index,
163  &dwValueSize);
164  if (lError != ERROR_SUCCESS)
165  *Index = 0;
166  }
167 
168  /* The time zone information structure is mandatory for a valid time zone */
169  dwValueSize = sizeof(*TimeZoneInfo);
170  lError = RegQueryValueExW(hZoneKey,
171  L"TZI",
172  NULL,
173  NULL,
174  (LPBYTE)TimeZoneInfo,
175  &dwValueSize);
176  if (lError != ERROR_SUCCESS)
177  return lError;
178 
179  if (Description && DescriptionSize && *DescriptionSize > 0)
180  {
181  lError = RegQueryValueExW(hZoneKey,
182  L"Display",
183  NULL,
184  NULL,
186  DescriptionSize);
187  if (lError != ERROR_SUCCESS)
188  *Description = 0;
189  }
190 
191  if (StandardName && StandardNameSize && *StandardNameSize > 0)
192  {
193  lError = RegQueryValueExW(hZoneKey,
194  L"Std",
195  NULL,
196  NULL,
197  (LPBYTE)StandardName,
198  StandardNameSize);
199  if (lError != ERROR_SUCCESS)
200  *StandardName = 0;
201  }
202 
203  if (DaylightName && DaylightNameSize && *DaylightNameSize > 0)
204  {
205  lError = RegQueryValueExW(hZoneKey,
206  L"Dlt",
207  NULL,
208  NULL,
209  (LPBYTE)DaylightName,
210  DaylightNameSize);
211  if (lError != ERROR_SUCCESS)
212  *DaylightName = 0;
213  }
214 
215  return ERROR_SUCCESS;
216 }
217 
218 //
219 // NOTE: Very similar to the EnumDynamicTimeZoneInformation() function
220 // introduced in Windows 8.
221 //
222 VOID
226 {
227  LONG lError;
228  HKEY hZonesKey;
229  HKEY hZoneKey;
230  DWORD dwIndex;
231  DWORD dwNameSize;
232  WCHAR szKeyName[256];
233 
234  /* Open the registry key containing the list of time zones */
236  L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
237  0,
239  &hZonesKey);
240  if (lError != ERROR_SUCCESS)
241  return;
242 
243  /* Enumerate it */
244  for (dwIndex = 0; ; dwIndex++)
245  {
246  dwNameSize = sizeof(szKeyName);
247  lError = RegEnumKeyExW(hZonesKey,
248  dwIndex,
249  szKeyName,
250  &dwNameSize,
251  NULL,
252  NULL,
253  NULL,
254  NULL);
255  // if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
256  if (lError == ERROR_NO_MORE_ITEMS)
257  break;
258 
259  /* Open the time zone sub-key */
260  if (RegOpenKeyExW(hZonesKey,
261  szKeyName,
262  0,
264  &hZoneKey))
265  {
266  /* We failed, continue with another sub-key */
267  continue;
268  }
269 
270  /* Call the user-provided callback */
271  lError = Callback(hZoneKey, Context);
272  // lError = QueryTimeZoneData(hZoneKey, Context);
273 
274  RegCloseKey(hZoneKey);
275  }
276 
277  RegCloseKey(hZonesKey);
278 }
279 
280 // Returns TRUE if AutoDaylight is ON.
281 // Returns FALSE if AutoDaylight is OFF.
282 BOOL
284 {
285  LONG lError;
286  HKEY hKey;
287  DWORD dwType;
288  DWORD dwDisabled;
289  DWORD dwValueSize;
290 
292  L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
293  0,
295  &hKey);
296  if (lError != ERROR_SUCCESS)
297  return FALSE;
298 
299  // NOTE: On Vista+: REG_DWORD "DynamicDaylightTimeDisabled"
300  dwValueSize = sizeof(dwDisabled);
301  lError = RegQueryValueExW(hKey,
302  L"DisableAutoDaylightTimeSet",
303  NULL,
304  &dwType,
305  (LPBYTE)&dwDisabled,
306  &dwValueSize);
307 
308  RegCloseKey(hKey);
309 
310  if ((lError != ERROR_SUCCESS) || (dwType != REG_DWORD) || (dwValueSize != sizeof(dwDisabled)))
311  {
312  /*
313  * The call failed (non zero) because the registry value isn't available,
314  * which means auto-daylight shouldn't be disabled.
315  */
316  dwDisabled = FALSE;
317  }
318 
319  return !dwDisabled;
320 }
321 
322 VOID
324  IN BOOL EnableAutoDaylightTime)
325 {
326  LONG lError;
327  HKEY hKey;
328  DWORD dwDisabled = TRUE;
329 
331  L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
332  0,
334  &hKey);
335  if (lError != ERROR_SUCCESS)
336  return;
337 
338  if (!EnableAutoDaylightTime)
339  {
340  /* Auto-Daylight disabled: set the value to TRUE */
341  // NOTE: On Vista+: REG_DWORD "DynamicDaylightTimeDisabled"
342  RegSetValueExW(hKey,
343  L"DisableAutoDaylightTimeSet",
344  0,
345  REG_DWORD,
346  (LPBYTE)&dwDisabled,
347  sizeof(dwDisabled));
348  }
349  else
350  {
351  /* Auto-Daylight enabled: just delete the value */
352  RegDeleteValueW(hKey, L"DisableAutoDaylightTimeSet");
353  }
354 
355  RegCloseKey(hKey);
356 }
#define IN
Definition: typedefs.h:39
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
BOOL GetTimeZoneListIndex(IN OUT PULONG pIndex)
Definition: tzlib.c:20
static const WCHAR Description[]
Definition: oid.c:1266
uint16_t * PWCHAR
Definition: typedefs.h:55
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define REG_MULTI_SZ
Definition: nt_native.h:1501
VOID EnumerateTimeZoneList(IN PENUM_TIMEZONE_CALLBACK Callback, IN PVOID Context OPTIONAL)
Definition: tzlib.c:223
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
VOID SetAutoDaylight(IN BOOL EnableAutoDaylightTime)
Definition: tzlib.c:323
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4895
LONG(* PENUM_TIMEZONE_CALLBACK)(IN HKEY hZoneKey, IN PVOID Context OPTIONAL)
Definition: tzlib.h:24
#define GetProcessHeap()
Definition: compat.h:404
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
static const UCHAR Index[8]
Definition: usbohci.c:18
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const WCHAR L[]
Definition: oid.c:1250
_Out_ PULONG _Out_ PULONG pIndex
Definition: ndis.h:4564
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2355
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
unsigned int * PULONG
Definition: retypes.h:1
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
BOOL GetAutoDaylight(VOID)
Definition: tzlib.c:283
#define OUT
Definition: typedefs.h:40
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2527
WCHAR * LPWSTR
Definition: xmlstorage.h:184
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define REG_DWORD
Definition: sdbapi.c:596
LPFNPSPCALLBACK Callback
Definition: desk.c:112
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:403
LONG QueryTimeZoneData(IN HKEY hZoneKey, OUT PULONG Index OPTIONAL, OUT PREG_TZI_FORMAT TimeZoneInfo, OUT PWCHAR Description OPTIONAL, IN OUT PULONG DescriptionSize OPTIONAL, OUT PWCHAR StandardName OPTIONAL, IN OUT PULONG StandardNameSize OPTIONAL, OUT PWCHAR DaylightName OPTIONAL, IN OUT PULONG DaylightNameSize OPTIONAL)
Definition: tzlib.c:141
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68