[TIMEDATE.CPL][SYSSETUP][TZLIB] Introduce a small static library "tzlib": "TimeZone Utilities Library", and use it in timedate.cpl and syssetup.dll.

This small win32 library provides time-zone utility wrappers around
Win32 functions, that are used by different ReactOS modules such as
timedate.cpl, syssetup.dll, and a possible future 'tzutil' tool.

The code has been extracted from the common code found in both
timedate.cpl and syssetup.dll.
This commit is contained in:
Hermès Bélusca-Maïto 2020-04-19 17:48:25 +02:00
parent 87f6c82d85
commit 7c3e96a26a
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
9 changed files with 605 additions and 539 deletions

View file

@ -1,4 +1,6 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/tzlib)
spec2def(timedate.cpl timedate.spec)
list(APPEND SOURCE
@ -19,6 +21,7 @@ add_library(timedate MODULE
${CMAKE_CURRENT_BINARY_DIR}/timedate.def)
set_module_type(timedate cpl UNICODE)
target_link_libraries(timedate tzlib)
add_importlibs(timedate w32time advapi32 user32 gdi32 comctl32 ws2_32 iphlpapi msvcrt kernel32 ntdll)
add_pch(timedate timedate.h SOURCE)
add_cd_file(TARGET timedate DESTINATION reactos/system32 FOR all)

View file

@ -10,25 +10,16 @@
*/
#include "timedate.h"
// See also sdk/include/reactos/libs/syssetup/syssetup.h
typedef struct _TZ_INFO
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} TZ_INFO, *PTZ_INFO;
#include <tzlib.h>
typedef struct _TIMEZONE_ENTRY
{
struct _TIMEZONE_ENTRY *Prev;
struct _TIMEZONE_ENTRY *Next;
WCHAR Description[128]; /* 'Display' */
WCHAR StandardName[33]; /* 'Std' */
WCHAR DaylightName[33]; /* 'Dlt' */
TZ_INFO TimezoneInfo; /* 'TZI' */
WCHAR Description[128]; /* 'Display' */
WCHAR StandardName[33]; /* 'Std' */
WCHAR DaylightName[33]; /* 'Dlt' */
REG_TZI_FORMAT TimezoneInfo; /* 'TZI' */
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
@ -64,160 +55,92 @@ GetLargerTimeZoneEntry(
return NULL;
}
static
LONG
QueryTimezoneData(
HKEY hZoneKey,
PTIMEZONE_ENTRY Entry)
static LONG
RetrieveTimeZone(
IN HKEY hZoneKey,
IN PVOID Context)
{
DWORD dwValueSize;
LONG lError;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
ULONG DescriptionSize;
ULONG StandardNameSize;
ULONG DaylightNameSize;
dwValueSize = sizeof(Entry->Description);
lError = RegQueryValueExW(hZoneKey,
L"Display",
NULL,
NULL,
(LPBYTE)&Entry->Description,
&dwValueSize);
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
DescriptionSize = sizeof(Entry->Description);
StandardNameSize = sizeof(Entry->StandardName);
DaylightNameSize = sizeof(Entry->DaylightName);
lError = QueryTimeZoneData(hZoneKey,
NULL,
&Entry->TimezoneInfo,
Entry->Description,
&DescriptionSize,
Entry->StandardName,
&StandardNameSize,
Entry->DaylightName,
&DaylightNameSize);
if (lError != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, Entry);
return lError;
}
dwValueSize = sizeof(Entry->StandardName);
lError = RegQueryValueExW(hZoneKey,
L"Std",
NULL,
NULL,
(LPBYTE)&Entry->StandardName,
&dwValueSize);
if (lError != ERROR_SUCCESS)
return lError;
if (TimeZoneListHead == NULL &&
TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
TimeZoneListHead = Entry;
TimeZoneListTail = Entry;
}
else
{
Current = GetLargerTimeZoneEntry(Entry->TimezoneInfo.Bias, Entry->Description);
if (Current != NULL)
{
if (Current == TimeZoneListHead)
{
/* Prepend to head */
Entry->Prev = NULL;
Entry->Next = TimeZoneListHead;
TimeZoneListHead->Prev = Entry;
TimeZoneListHead = Entry;
}
else
{
/* Insert before current */
Entry->Prev = Current->Prev;
Entry->Next = Current;
Current->Prev->Next = Entry;
Current->Prev = Entry;
}
}
else
{
/* Append to tail */
Entry->Prev = TimeZoneListTail;
Entry->Next = NULL;
TimeZoneListTail->Next = Entry;
TimeZoneListTail = Entry;
}
}
dwValueSize = sizeof(Entry->DaylightName);
lError = RegQueryValueExW(hZoneKey,
L"Dlt",
NULL,
NULL,
(LPBYTE)&Entry->DaylightName,
&dwValueSize);
if (lError != ERROR_SUCCESS)
return lError;
dwValueSize = sizeof(Entry->TimezoneInfo);
lError = RegQueryValueExW(hZoneKey,
L"TZI",
NULL,
NULL,
(LPBYTE)&Entry->TimezoneInfo,
&dwValueSize);
return lError;
return ERROR_SUCCESS;
}
static VOID
CreateTimeZoneList(VOID)
{
WCHAR szKeyName[256];
DWORD dwIndex;
DWORD dwNameSize;
LONG lError;
HKEY hZonesKey;
HKEY hZoneKey;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_ENUMERATE_SUB_KEYS,
&hZonesKey))
return;
for (dwIndex = 0; ; dwIndex++)
{
dwNameSize = sizeof(szKeyName);
lError = RegEnumKeyExW(hZonesKey,
dwIndex,
szKeyName,
&dwNameSize,
NULL,
NULL,
NULL,
NULL);
if (lError == ERROR_NO_MORE_ITEMS)
break;
if (RegOpenKeyEx (hZonesKey,
szKeyName,
0,
KEY_QUERY_VALUE,
&hZoneKey))
break;
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
RegCloseKey(hZoneKey);
break;
}
lError = QueryTimezoneData(hZoneKey,
Entry);
RegCloseKey(hZoneKey);
if (lError != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, Entry);
break;
}
if (TimeZoneListHead == NULL &&
TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
TimeZoneListHead = Entry;
TimeZoneListTail = Entry;
}
else
{
Current = GetLargerTimeZoneEntry(Entry->TimezoneInfo.Bias, Entry->Description);
if (Current != NULL)
{
if (Current == TimeZoneListHead)
{
/* Prepend to head */
Entry->Prev = NULL;
Entry->Next = TimeZoneListHead;
TimeZoneListHead->Prev = Entry;
TimeZoneListHead = Entry;
}
else
{
/* Insert before current */
Entry->Prev = Current->Prev;
Entry->Next = Current;
Current->Prev->Next = Entry;
Current->Prev = Entry;
}
}
else
{
/* Append to tail */
Entry->Prev = TimeZoneListTail;
Entry->Next = NULL;
TimeZoneListTail->Next = Entry;
TimeZoneListTail = Entry;
}
}
}
RegCloseKey(hZonesKey);
EnumerateTimeZoneList(RetrieveTimeZone, NULL);
}
static VOID
DestroyTimeZoneList(VOID)
{
@ -299,9 +222,9 @@ SetLocalTimeZone(HWND hwnd)
}
wcscpy(TimeZoneInformation.StandardName,
Entry->StandardName);
Entry->StandardName);
wcscpy(TimeZoneInformation.DaylightName,
Entry->DaylightName);
Entry->DaylightName);
TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
@ -319,71 +242,6 @@ SetLocalTimeZone(HWND hwnd)
}
static VOID
GetAutoDaylightInfo(HWND hwnd)
{
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
0,
KEY_QUERY_VALUE,
&hKey))
return;
/* If the call fails (non zero), the reg value isn't available,
* which means it shouldn't be disabled, so we should check the button.
*/
if (RegQueryValueExW(hKey,
L"DisableAutoDaylightTimeSet",
NULL,
NULL,
NULL,
NULL))
{
SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
}
else
{
SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
}
RegCloseKey(hKey);
}
static VOID
SetAutoDaylightInfo(HWND hwnd)
{
HKEY hKey;
DWORD dwValue = 1;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
0,
KEY_SET_VALUE,
&hKey))
return;
if (SendMessageW(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
{
RegSetValueExW(hKey,
L"DisableAutoDaylightTimeSet",
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(dwValue));
}
else
{
RegDeleteValueW(hKey,
L"DisableAutoDaylightTimeSet");
}
RegCloseKey(hKey);
}
/* Property page dialog callback */
INT_PTR CALLBACK
TimeZonePageProc(HWND hwndDlg,
@ -396,9 +254,13 @@ TimeZonePageProc(HWND hwndDlg,
switch (uMsg)
{
case WM_INITDIALOG:
{
CreateTimeZoneList();
ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST));
GetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK,
(WPARAM)(GetAutoDaylight() ? BST_CHECKED : BST_UNCHECKED), 0);
hBitmap = LoadImageW(hApplet, MAKEINTRESOURCEW(IDC_WORLD), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (hBitmap != NULL)
{
@ -408,6 +270,7 @@ TimeZonePageProc(HWND hwndDlg,
cySource = bitmap.bmHeight;
}
break;
}
case WM_DRAWITEM:
{
@ -452,7 +315,8 @@ TimeZonePageProc(HWND hwndDlg,
{
case PSN_APPLY:
{
SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
SetAutoDaylight(SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT,
BM_GETCHECK, 0, 0) != BST_UNCHECKED);
SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST));
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
return TRUE;

View file

@ -1,4 +1,6 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/tzlib)
spec2def(syssetup.dll syssetup.spec)
list(APPEND SOURCE
@ -20,6 +22,6 @@ add_library(syssetup MODULE
add_pch(syssetup precomp.h SOURCE)
set_module_type(syssetup win32dll UNICODE)
target_link_libraries(syssetup uuid wine ${PSEH_LIB})
target_link_libraries(syssetup uuid wine tzlib ${PSEH_LIB})
add_importlibs(syssetup advapi32 gdi32 user32 samlib userenv comctl32 setupapi rpcrt4 ole32 shell32 shlwapi msvcrt kernel32 ntdll)
add_cd_file(TARGET syssetup DESTINATION reactos/system32 FOR all)

View file

@ -19,6 +19,8 @@
#include <wincon.h>
#include <shlobj.h>
#include <tzlib.h>
#define NDEBUG
#include <debug.h>
@ -45,6 +47,17 @@ typedef struct _REGISTRATIONDATA
PVOID DefaultContext;
} REGISTRATIONDATA, *PREGISTRATIONDATA;
typedef struct _TIMEZONE_ENTRY
{
struct _TIMEZONE_ENTRY *Prev;
struct _TIMEZONE_ENTRY *Next;
WCHAR Description[128]; /* 'Display' */
WCHAR StandardName[32]; /* 'Std' */
WCHAR DaylightName[32]; /* 'Dlt' */
REG_TZI_FORMAT TimezoneInfo; /* 'TZI' */
ULONG Index;
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
/* FUNCTIONS ****************************************************************/
@ -1237,166 +1250,93 @@ GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index)
return NULL;
}
static LONG
RetrieveTimeZone(
IN HKEY hZoneKey,
IN PVOID Context)
{
LONG lError;
PSETUPDATA SetupData = (PSETUPDATA)Context;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
ULONG DescriptionSize;
ULONG StandardNameSize;
ULONG DaylightNameSize;
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
DescriptionSize = sizeof(Entry->Description);
StandardNameSize = sizeof(Entry->StandardName);
DaylightNameSize = sizeof(Entry->DaylightName);
lError = QueryTimeZoneData(hZoneKey,
&Entry->Index,
&Entry->TimezoneInfo,
Entry->Description,
&DescriptionSize,
Entry->StandardName,
&StandardNameSize,
Entry->DaylightName,
&DaylightNameSize);
if (lError != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, Entry);
return lError;
}
if (SetupData->TimeZoneListHead == NULL &&
SetupData->TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
SetupData->TimeZoneListHead = Entry;
SetupData->TimeZoneListTail = Entry;
}
else
{
Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
if (Current != NULL)
{
if (Current == SetupData->TimeZoneListHead)
{
/* Prepend to head */
Entry->Prev = NULL;
Entry->Next = SetupData->TimeZoneListHead;
SetupData->TimeZoneListHead->Prev = Entry;
SetupData->TimeZoneListHead = Entry;
}
else
{
/* Insert before current */
Entry->Prev = Current->Prev;
Entry->Next = Current;
Current->Prev->Next = Entry;
Current->Prev = Entry;
}
}
else
{
/* Append to tail */
Entry->Prev = SetupData->TimeZoneListTail;
Entry->Next = NULL;
SetupData->TimeZoneListTail->Next = Entry;
SetupData->TimeZoneListTail = Entry;
}
}
return ERROR_SUCCESS;
}
static VOID
CreateTimeZoneList(PSETUPDATA SetupData)
{
WCHAR szKeyName[256];
DWORD dwIndex;
DWORD dwNameSize;
DWORD dwValueSize;
LONG lError;
HKEY hZonesKey;
HKEY hZoneKey;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_ALL_ACCESS,
&hZonesKey))
return;
dwIndex = 0;
while (TRUE)
{
dwNameSize = 256 * sizeof(WCHAR);
lError = RegEnumKeyExW(hZonesKey,
dwIndex,
szKeyName,
&dwNameSize,
NULL,
NULL,
NULL,
NULL);
if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
break;
if (RegOpenKeyExW(hZonesKey,
szKeyName,
0,
KEY_ALL_ACCESS,
&hZoneKey))
break;
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 64 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Display",
NULL,
NULL,
(LPBYTE)&Entry->Description,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 32 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Std",
NULL,
NULL,
(LPBYTE)&Entry->StandardName,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = 32 * sizeof(WCHAR);
if (RegQueryValueExW(hZoneKey,
L"Dlt",
NULL,
NULL,
(LPBYTE)&Entry->DaylightName,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = sizeof(DWORD);
if (RegQueryValueExW(hZoneKey,
L"Index",
NULL,
NULL,
(LPBYTE)&Entry->Index,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
dwValueSize = sizeof(TZ_INFO);
if (RegQueryValueExW(hZoneKey,
L"TZI",
NULL,
NULL,
(LPBYTE)&Entry->TimezoneInfo,
&dwValueSize))
{
RegCloseKey(hZoneKey);
break;
}
RegCloseKey(hZoneKey);
if (SetupData->TimeZoneListHead == NULL &&
SetupData->TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
SetupData->TimeZoneListHead = Entry;
SetupData->TimeZoneListTail = Entry;
}
else
{
Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
if (Current != NULL)
{
if (Current == SetupData->TimeZoneListHead)
{
/* Prepend to head */
Entry->Prev = NULL;
Entry->Next = SetupData->TimeZoneListHead;
SetupData->TimeZoneListHead->Prev = Entry;
SetupData->TimeZoneListHead = Entry;
}
else
{
/* Insert before current */
Entry->Prev = Current->Prev;
Entry->Next = Current;
Current->Prev->Next = Entry;
Current->Prev = Entry;
}
}
else
{
/* Append to tail */
Entry->Prev = SetupData->TimeZoneListTail;
Entry->Next = NULL;
SetupData->TimeZoneListTail->Next = Entry;
SetupData->TimeZoneListTail = Entry;
}
}
dwIndex++;
}
RegCloseKey(hZonesKey);
EnumerateTimeZoneList(RetrieveTimeZone, SetupData);
}
static VOID
DestroyTimeZoneList(PSETUPDATA SetupData)
{
@ -1418,117 +1358,6 @@ DestroyTimeZoneList(PSETUPDATA SetupData)
SetupData->TimeZoneListTail = NULL;
}
static BOOL
GetTimeZoneListIndex(LPDWORD lpIndex)
{
WCHAR szLanguageIdString[9];
HKEY hKey;
DWORD dwValueSize;
DWORD Length;
LPWSTR Buffer;
LPWSTR Ptr;
LPWSTR End;
BOOL bFound = FALSE;
unsigned long iLanguageID;
if (*lpIndex == -1)
{
*lpIndex = 85; /* fallback to GMT time zone */
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
0,
KEY_ALL_ACCESS,
&hKey))
return FALSE;
dwValueSize = 9 * sizeof(WCHAR);
if (RegQueryValueExW(hKey,
L"Default",
NULL,
NULL,
(LPBYTE)szLanguageIdString,
&dwValueSize))
{
RegCloseKey(hKey);
return FALSE;
}
iLanguageID = wcstoul(szLanguageIdString, NULL, 16);
RegCloseKey(hKey);
}
else
{
iLanguageID = *lpIndex;
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_ALL_ACCESS,
&hKey))
return FALSE;
dwValueSize = 0;
if (RegQueryValueExW(hKey,
L"IndexMapping",
NULL,
NULL,
NULL,
&dwValueSize))
{
RegCloseKey(hKey);
return FALSE;
}
Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
if (Buffer == NULL)
{
RegCloseKey(hKey);
return FALSE;
}
if (RegQueryValueExW(hKey,
L"IndexMapping",
NULL,
NULL,
(LPBYTE)Buffer,
&dwValueSize))
{
HeapFree(GetProcessHeap(), 0, Buffer);
RegCloseKey(hKey);
return FALSE;
}
RegCloseKey(hKey);
Ptr = Buffer;
while (*Ptr != 0)
{
Length = wcslen(Ptr);
if (wcstoul(Ptr, NULL, 16) == iLanguageID)
bFound = TRUE;
Ptr = Ptr + Length + 1;
if (*Ptr == 0)
break;
if (bFound)
{
*lpIndex = wcstoul(Ptr, &End, 10);
HeapFree(GetProcessHeap(), 0, Buffer);
return TRUE;
}
Length = wcslen(Ptr);
Ptr = Ptr + Length + 1;
}
HeapFree(GetProcessHeap(), 0, Buffer);
return FALSE;
}
static VOID
ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData, DWORD dwEntryIndex)
@ -1634,32 +1463,6 @@ GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData)
}
static VOID
SetAutoDaylightInfo(HWND hwnd)
{
HKEY hKey;
DWORD dwValue = 1;
if (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
{
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
0,
KEY_SET_VALUE,
&hKey))
return;
RegSetValueExW(hKey,
L"DisableAutoDaylightTimeSet",
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(DWORD));
RegCloseKey(hKey);
}
}
static BOOL
SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData)
{
@ -1696,7 +1499,8 @@ WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData)
SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
SetupData);
SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
SetAutoDaylight(SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT,
BM_GETCHECK, 0, 0) != BST_UNCHECKED);
if (!SetSystemLocalTime(hwndDlg, SetupData))
{
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
@ -1730,6 +1534,7 @@ DateTimePageDlgProc(HWND hwndDlg,
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
@ -1754,6 +1559,7 @@ DateTimePageDlgProc(HWND hwndDlg,
SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
}
break;
}
case WM_TIMER:
UpdateLocalSystemTime(hwndDlg);

View file

@ -23,27 +23,6 @@
#ifndef __SYSSETUP_H_INCLUDED__
#define __SYSSETUP_H_INCLUDED__
// See also dll/cpl/timedate/timezone.c
typedef struct _TZ_INFO
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} TZ_INFO, *PTZ_INFO;
typedef struct _TIMEZONE_ENTRY
{
struct _TIMEZONE_ENTRY *Prev;
struct _TIMEZONE_ENTRY *Next;
WCHAR Description[64]; /* 'Display' */
WCHAR StandardName[32]; /* 'Std' */
WCHAR DaylightName[32]; /* 'Dlt' */
TZ_INFO TimezoneInfo; /* 'TZI' */
ULONG Index;
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
typedef enum _PRODUCT_OPTION
{
PRODUCT_OPTION_SERVER,
@ -67,8 +46,8 @@ typedef struct _SETUPDATA
BOOL DisableGeckoInst;
SYSTEMTIME SystemTime;
PTIMEZONE_ENTRY TimeZoneListHead;
PTIMEZONE_ENTRY TimeZoneListTail;
struct _TIMEZONE_ENTRY* TimeZoneListHead;
struct _TIMEZONE_ENTRY* TimeZoneListTail;
DWORD TimeZoneIndex;
DWORD DisableAutoDaylightTimeSet;
LCID LocaleID;

View file

@ -46,6 +46,7 @@ add_subdirectory(skiplist)
add_subdirectory(strmiids)
add_subdirectory(smlib)
add_subdirectory(tdilib)
add_subdirectory(tzlib)
add_subdirectory(udmihelp)
add_subdirectory(uuid)
add_subdirectory(wdmguid)

View file

@ -0,0 +1,3 @@
add_library(tzlib tzlib.c)
add_dependencies(tzlib xdk)

352
sdk/lib/tzlib/tzlib.c Normal file
View file

@ -0,0 +1,352 @@
/*
* PROJECT: ReactOS TimeZone Utilities Library
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
* PURPOSE: Provides time-zone utility wrappers around Win32 functions,
* that are used by different ReactOS modules such as
* timedate.cpl, syssetup.dll.
* COPYRIGHT: Copyright 2004-2005 Eric Kohl
* Copyright 2016 Carlo Bramini
* Copyright 2020 Hermes Belusca-Maito
*/
#include <stdlib.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include "tzlib.h"
BOOL
GetTimeZoneListIndex(
IN OUT PULONG pIndex)
{
LONG lError;
HKEY hKey;
DWORD dwType;
DWORD dwValueSize;
DWORD Length;
LPWSTR Buffer;
LPWSTR Ptr, End;
BOOL bFound = FALSE;
unsigned long iLanguageID;
WCHAR szLanguageIdString[9];
if (*pIndex == -1)
{
*pIndex = 85; /* fallback to GMT time zone */
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
0,
KEY_QUERY_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
{
return FALSE;
}
dwValueSize = sizeof(szLanguageIdString);
lError = RegQueryValueExW(hKey,
L"Default",
NULL,
NULL,
(LPBYTE)szLanguageIdString,
&dwValueSize);
if (lError != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return FALSE;
}
iLanguageID = wcstoul(szLanguageIdString, NULL, 16);
RegCloseKey(hKey);
}
else
{
iLanguageID = *pIndex;
}
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_QUERY_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
{
return FALSE;
}
dwValueSize = 0;
lError = RegQueryValueExW(hKey,
L"IndexMapping",
NULL,
&dwType,
NULL,
&dwValueSize);
if ((lError != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ))
{
RegCloseKey(hKey);
return FALSE;
}
Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
if (Buffer == NULL)
{
RegCloseKey(hKey);
return FALSE;
}
lError = RegQueryValueExW(hKey,
L"IndexMapping",
NULL,
&dwType,
(LPBYTE)Buffer,
&dwValueSize);
RegCloseKey(hKey);
if ((lError != ERROR_SUCCESS) || (dwType != REG_MULTI_SZ))
{
HeapFree(GetProcessHeap(), 0, Buffer);
return FALSE;
}
Ptr = Buffer;
while (*Ptr != 0)
{
Length = wcslen(Ptr);
if (wcstoul(Ptr, NULL, 16) == iLanguageID)
bFound = TRUE;
Ptr = Ptr + Length + 1;
if (*Ptr == 0)
break;
if (bFound)
{
*pIndex = wcstoul(Ptr, &End, 10);
HeapFree(GetProcessHeap(), 0, Buffer);
return TRUE;
}
Length = wcslen(Ptr);
Ptr = Ptr + Length + 1;
}
HeapFree(GetProcessHeap(), 0, Buffer);
return FALSE;
}
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)
{
LONG lError;
DWORD dwValueSize;
if (Description && DescriptionSize && *DescriptionSize > 0)
{
lError = RegQueryValueExW(hZoneKey,
L"Display",
NULL,
NULL,
(LPBYTE)Description,
DescriptionSize);
if (lError != ERROR_SUCCESS)
return lError;
}
if (StandardName && StandardNameSize && *StandardNameSize > 0)
{
lError = RegQueryValueExW(hZoneKey,
L"Std",
NULL,
NULL,
(LPBYTE)StandardName,
StandardNameSize);
if (lError != ERROR_SUCCESS)
return lError;
}
if (DaylightName && DaylightNameSize && *DaylightNameSize > 0)
{
lError = RegQueryValueExW(hZoneKey,
L"Dlt",
NULL,
NULL,
(LPBYTE)DaylightName,
DaylightNameSize);
if (lError != ERROR_SUCCESS)
return lError;
}
if (Index)
{
dwValueSize = sizeof(*Index);
lError = RegQueryValueExW(hZoneKey,
L"Index",
NULL,
NULL,
(LPBYTE)Index,
&dwValueSize);
if (lError != ERROR_SUCCESS)
return lError;
}
dwValueSize = sizeof(*TimeZoneInfo);
lError = RegQueryValueExW(hZoneKey,
L"TZI",
NULL,
NULL,
(LPBYTE)TimeZoneInfo,
&dwValueSize);
return lError;
}
//
// NOTE: Very similar to the EnumDynamicTimeZoneInformation() function
// introduced in Windows 8.
//
VOID
EnumerateTimeZoneList(
IN PENUM_TIMEZONE_CALLBACK Callback,
IN PVOID Context OPTIONAL)
{
LONG lError;
HKEY hZonesKey;
HKEY hZoneKey;
DWORD dwIndex;
DWORD dwNameSize;
WCHAR szKeyName[256];
/* Open the registry key containing the list of time zones */
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
0,
KEY_ENUMERATE_SUB_KEYS,
&hZonesKey);
if (lError != ERROR_SUCCESS)
return;
/* Enumerate it */
for (dwIndex = 0; ; dwIndex++)
{
dwNameSize = sizeof(szKeyName);
lError = RegEnumKeyExW(hZonesKey,
dwIndex,
szKeyName,
&dwNameSize,
NULL,
NULL,
NULL,
NULL);
// if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA)
if (lError == ERROR_NO_MORE_ITEMS)
break;
/* Open the time zone sub-key */
if (RegOpenKeyExW(hZonesKey,
szKeyName,
0,
KEY_QUERY_VALUE,
&hZoneKey))
{
/* We failed, continue with another sub-key */
continue;
}
/* Call the user-provided callback */
lError = Callback(hZoneKey, Context);
// lError = QueryTimeZoneData(hZoneKey, Context);
RegCloseKey(hZoneKey);
}
RegCloseKey(hZonesKey);
}
// Returns TRUE if AutoDaylight is ON.
// Returns FALSE if AutoDaylight is OFF.
BOOL
GetAutoDaylight(VOID)
{
LONG lError;
HKEY hKey;
DWORD dwType;
DWORD dwDisabled;
DWORD dwValueSize;
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
0,
KEY_QUERY_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
return FALSE;
// NOTE: On Vista+: REG_DWORD "DynamicDaylightTimeDisabled"
dwValueSize = sizeof(dwDisabled);
lError = RegQueryValueExW(hKey,
L"DisableAutoDaylightTimeSet",
NULL,
&dwType,
(LPBYTE)&dwDisabled,
&dwValueSize);
RegCloseKey(hKey);
if ((lError != ERROR_SUCCESS) || (dwType != REG_DWORD) || (dwValueSize != sizeof(dwDisabled)))
{
/*
* The call failed (non zero) because the registry value isn't available,
* which means auto-daylight shouldn't be disabled.
*/
dwDisabled = FALSE;
}
return !dwDisabled;
}
VOID
SetAutoDaylight(
IN BOOL EnableAutoDaylightTime)
{
LONG lError;
HKEY hKey;
DWORD dwDisabled = TRUE;
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
0,
KEY_SET_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
return;
if (!EnableAutoDaylightTime)
{
/* Auto-Daylight disabled: set the value to TRUE */
// NOTE: On Vista+: REG_DWORD "DynamicDaylightTimeDisabled"
RegSetValueExW(hKey,
L"DisableAutoDaylightTimeSet",
0,
REG_DWORD,
(LPBYTE)&dwDisabled,
sizeof(dwDisabled));
}
else
{
/* Auto-Daylight enabled: just delete the value */
RegDeleteValueW(hKey, L"DisableAutoDaylightTimeSet");
}
RegCloseKey(hKey);
}

56
sdk/lib/tzlib/tzlib.h Normal file
View file

@ -0,0 +1,56 @@
/*
* PROJECT: ReactOS TimeZone Utilities Library
* LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
* PURPOSE: Provides time-zone utility wrappers around Win32 functions,
* that are used by different ReactOS modules such as
* timedate.cpl, syssetup.dll.
* COPYRIGHT: Copyright 2004-2005 Eric Kohl
* Copyright 2016 Carlo Bramini
* Copyright 2020 Hermes Belusca-Maito
*/
#pragma once
typedef struct _REG_TZI_FORMAT
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT, *PREG_TZI_FORMAT;
typedef LONG
(*PENUM_TIMEZONE_CALLBACK)(
IN HKEY hZoneKey,
IN PVOID Context OPTIONAL);
BOOL
GetTimeZoneListIndex(
IN OUT PULONG pIndex);
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);
VOID
EnumerateTimeZoneList(
IN PENUM_TIMEZONE_CALLBACK Callback,
IN PVOID Context OPTIONAL);
// Returns TRUE if AutoDaylight is ON.
// Returns FALSE if AutoDaylight is OFF.
BOOL
GetAutoDaylight(VOID);
VOID
SetAutoDaylight(
IN BOOL EnableAutoDaylightTime);