ReactOS 0.4.15-dev-8413-gc1c91f2
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
19BOOL
22{
23 LONG lError;
24 HKEY hKey;
25 DWORD dwType;
26 DWORD dwValueSize;
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 {
58 return FALSE;
59 }
60
61 iLanguageID = wcstoul(szLanguageIdString, NULL, 16);
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 {
89 return FALSE;
90 }
91
93 if (Buffer == NULL)
94 {
96 return FALSE;
97 }
98
99 lError = RegQueryValueExW(hKey,
100 L"IndexMapping",
101 NULL,
102 &dwType,
103 (LPBYTE)Buffer,
104 &dwValueSize);
105
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
140LONG
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//
222VOID
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.
282BOOL
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
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
322VOID
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"
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
356}
#define RegCloseKey(hKey)
Definition: registry.h:49
Definition: bufpool.h:45
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
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:2504
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:4882
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
static const WCHAR Description[]
Definition: oid.c:1266
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
FxAutoRegKey hKey
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_Out_ PULONG _Out_ PULONG pIndex
Definition: ndis.h:4565
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define REG_DWORD
Definition: sdbapi.c:596
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * LPBYTE
Definition: typedefs.h:53
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
#define OUT
Definition: typedefs.h:40
VOID EnumerateTimeZoneList(IN PENUM_TIMEZONE_CALLBACK Callback, IN PVOID Context OPTIONAL)
Definition: tzlib.c:223
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
VOID SetAutoDaylight(IN BOOL EnableAutoDaylightTime)
Definition: tzlib.c:323
BOOL GetAutoDaylight(VOID)
Definition: tzlib.c:283
BOOL GetTimeZoneListIndex(IN OUT PULONG pIndex)
Definition: tzlib.c:20
LONG(* PENUM_TIMEZONE_CALLBACK)(IN HKEY hZoneKey, IN PVOID Context OPTIONAL)
Definition: tzlib.h:24
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:458
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184