https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7c3e96a26a15de8930cddf670d43bbf50c16bfad

commit 7c3e96a26a15de8930cddf670d43bbf50c16bfad
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Sun Apr 19 17:48:25 2020 +0200
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Wed Apr 22 00:58:32 2020 +0200

    [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.
---
 dll/cpl/timedate/CMakeLists.txt              |   3 +
 dll/cpl/timedate/timezone.c                  | 296 ++++++----------------
 dll/win32/syssetup/CMakeLists.txt            |   4 +-
 dll/win32/syssetup/wizard.c                  | 362 +++++++--------------------
 sdk/include/reactos/libs/syssetup/syssetup.h |  25 +-
 sdk/lib/CMakeLists.txt                       |   1 +
 sdk/lib/tzlib/CMakeLists.txt                 |   3 +
 sdk/lib/tzlib/tzlib.c                        | 352 ++++++++++++++++++++++++++
 sdk/lib/tzlib/tzlib.h                        |  56 +++++
 9 files changed, 584 insertions(+), 518 deletions(-)

diff --git a/dll/cpl/timedate/CMakeLists.txt b/dll/cpl/timedate/CMakeLists.txt
index 20f0d62d59c..fcf2fd2d03b 100644
--- a/dll/cpl/timedate/CMakeLists.txt
+++ b/dll/cpl/timedate/CMakeLists.txt
@@ -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)
diff --git a/dll/cpl/timedate/timezone.c b/dll/cpl/timedate/timezone.c
index 95a4e33220e..9dd79e1d01a 100644
--- a/dll/cpl/timedate/timezone.c
+++ b/dll/cpl/timedate/timezone.c
@@ -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,159 +55,91 @@ GetLargerTimeZoneEntry(
     return NULL;
 }
 
-
-static
-LONG
-QueryTimezoneData(
-    HKEY hZoneKey,
-    PTIMEZONE_ENTRY Entry)
-{
-    DWORD dwValueSize;
-    LONG lError;
-
-    dwValueSize = sizeof(Entry->Description);
-    lError = RegQueryValueExW(hZoneKey,
-                              L"Display",
-                              NULL,
-                              NULL,
-                              (LPBYTE)&Entry->Description,
-                              &dwValueSize);
-    if (lError != ERROR_SUCCESS)
-        return lError;
-
-    dwValueSize = sizeof(Entry->StandardName);
-    lError = RegQueryValueExW(hZoneKey,
-                              L"Std",
-                              NULL,
-                              NULL,
-                              (LPBYTE)&Entry->StandardName,
-                              &dwValueSize);
-    if (lError != ERROR_SUCCESS)
-        return lError;
-
-    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;
-}
-
-
-static VOID
-CreateTimeZoneList(VOID)
+static LONG
+RetrieveTimeZone(
+    IN HKEY hZoneKey,
+    IN PVOID Context)
 {
-    WCHAR szKeyName[256];
-    DWORD dwIndex;
-    DWORD dwNameSize;
     LONG lError;
-    HKEY hZonesKey;
-    HKEY hZoneKey;
     PTIMEZONE_ENTRY Entry;
     PTIMEZONE_ENTRY Current;
+    ULONG DescriptionSize;
+    ULONG StandardNameSize;
+    ULONG DaylightNameSize;
 
-    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                      L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time 
Zones",
-                      0,
-                      KEY_ENUMERATE_SUB_KEYS,
-                      &hZonesKey))
-        return;
-
-    for (dwIndex = 0; ; dwIndex++)
+    Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
sizeof(TIMEZONE_ENTRY));
+    if (Entry == NULL)
     {
-        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);
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
 
-        RegCloseKey(hZoneKey);
+    DescriptionSize  = sizeof(Entry->Description);
+    StandardNameSize = sizeof(Entry->StandardName);
+    DaylightNameSize = sizeof(Entry->DaylightName);
 
-        if (lError != ERROR_SUCCESS)
-        {
-            HeapFree(GetProcessHeap(), 0, Entry);
-            break;
-        }
+    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;
+    }
 
-        if (TimeZoneListHead == NULL &&
-            TimeZoneListTail == NULL)
-        {
-            Entry->Prev = NULL;
-            Entry->Next = NULL;
-            TimeZoneListHead = Entry;
-            TimeZoneListTail = Entry;
-        }
-        else
+    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)
         {
-            Current = GetLargerTimeZoneEntry(Entry->TimezoneInfo.Bias, 
Entry->Description);
-            if (Current != NULL)
+            if (Current == TimeZoneListHead)
             {
-                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;
-                }
+                /* Prepend to head */
+                Entry->Prev = NULL;
+                Entry->Next = TimeZoneListHead;
+                TimeZoneListHead->Prev = Entry;
+                TimeZoneListHead = Entry;
             }
             else
             {
-                /* Append to tail */
-                Entry->Prev = TimeZoneListTail;
-                Entry->Next = NULL;
-                TimeZoneListTail->Next = Entry;
-                TimeZoneListTail = Entry;
+                /* 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);
+    return ERROR_SUCCESS;
 }
 
+static VOID
+CreateTimeZoneList(VOID)
+{
+    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;
diff --git a/dll/win32/syssetup/CMakeLists.txt 
b/dll/win32/syssetup/CMakeLists.txt
index e3b44d1e6b7..703c1d411c6 100644
--- a/dll/win32/syssetup/CMakeLists.txt
+++ b/dll/win32/syssetup/CMakeLists.txt
@@ -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)
diff --git a/dll/win32/syssetup/wizard.c b/dll/win32/syssetup/wizard.c
index 589a6101ab6..386b04bf356 100644
--- a/dll/win32/syssetup/wizard.c
+++ b/dll/win32/syssetup/wizard.c
@@ -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,165 +1250,92 @@ GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD 
Index)
     return NULL;
 }
 
-
-static VOID
-CreateTimeZoneList(PSETUPDATA SetupData)
+static LONG
+RetrieveTimeZone(
+    IN HKEY hZoneKey,
+    IN PVOID Context)
 {
-    WCHAR szKeyName[256];
-    DWORD dwIndex;
-    DWORD dwNameSize;
-    DWORD dwValueSize;
     LONG lError;
-    HKEY hZonesKey;
-    HKEY hZoneKey;
-
+    PSETUPDATA SetupData = (PSETUPDATA)Context;
     PTIMEZONE_ENTRY Entry;
     PTIMEZONE_ENTRY Current;
+    ULONG DescriptionSize;
+    ULONG StandardNameSize;
+    ULONG DaylightNameSize;
 
-    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;
-        }
+    Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
sizeof(TIMEZONE_ENTRY));
+    if (Entry == NULL)
+    {
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
 
-        dwValueSize = sizeof(DWORD);
-        if (RegQueryValueExW(hZoneKey,
-                             L"Index",
-                             NULL,
-                             NULL,
-                             (LPBYTE)&Entry->Index,
-                             &dwValueSize))
-        {
-            RegCloseKey(hZoneKey);
-            break;
-        }
+    DescriptionSize  = sizeof(Entry->Description);
+    StandardNameSize = sizeof(Entry->StandardName);
+    DaylightNameSize = sizeof(Entry->DaylightName);
 
-        dwValueSize = sizeof(TZ_INFO);
-        if (RegQueryValueExW(hZoneKey,
-                             L"TZI",
-                             NULL,
-                             NULL,
-                             (LPBYTE)&Entry->TimezoneInfo,
-                             &dwValueSize))
-        {
-            RegCloseKey(hZoneKey);
-            break;
-        }
-
-        RegCloseKey(hZoneKey);
+    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
+    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)
         {
-            Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
-            if (Current != NULL)
+            if (Current == SetupData->TimeZoneListHead)
             {
-                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;
-                }
+                /* Prepend to head */
+                Entry->Prev = NULL;
+                Entry->Next = SetupData->TimeZoneListHead;
+                SetupData->TimeZoneListHead->Prev = Entry;
+                SetupData->TimeZoneListHead = Entry;
             }
             else
             {
-                /* Append to tail */
-                Entry->Prev = SetupData->TimeZoneListTail;
-                Entry->Next = NULL;
-                SetupData->TimeZoneListTail->Next = Entry;
-                SetupData->TimeZoneListTail = Entry;
+                /* Insert before current */
+                Entry->Prev = Current->Prev;
+                Entry->Next = Current;
+                Current->Prev->Next = Entry;
+                Current->Prev = Entry;
             }
         }
-
-        dwIndex++;
+        else
+        {
+            /* Append to tail */
+            Entry->Prev = SetupData->TimeZoneListTail;
+            Entry->Next = NULL;
+            SetupData->TimeZoneListTail->Next = Entry;
+            SetupData->TimeZoneListTail = Entry;
+        }
     }
 
-    RegCloseKey(hZonesKey);
+    return ERROR_SUCCESS;
 }
 
+static VOID
+CreateTimeZoneList(PSETUPDATA SetupData)
+{
+    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);
diff --git a/sdk/include/reactos/libs/syssetup/syssetup.h 
b/sdk/include/reactos/libs/syssetup/syssetup.h
index d22ad08ac79..adb924e390d 100644
--- a/sdk/include/reactos/libs/syssetup/syssetup.h
+++ b/sdk/include/reactos/libs/syssetup/syssetup.h
@@ -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;
diff --git a/sdk/lib/CMakeLists.txt b/sdk/lib/CMakeLists.txt
index c9f4e396049..60b2844566b 100644
--- a/sdk/lib/CMakeLists.txt
+++ b/sdk/lib/CMakeLists.txt
@@ -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)
diff --git a/sdk/lib/tzlib/CMakeLists.txt b/sdk/lib/tzlib/CMakeLists.txt
new file mode 100644
index 00000000000..a4606afe5df
--- /dev/null
+++ b/sdk/lib/tzlib/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+add_library(tzlib tzlib.c)
+add_dependencies(tzlib xdk)
diff --git a/sdk/lib/tzlib/tzlib.c b/sdk/lib/tzlib/tzlib.c
new file mode 100644
index 00000000000..93c33a3fb3a
--- /dev/null
+++ b/sdk/lib/tzlib/tzlib.c
@@ -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);
+}
diff --git a/sdk/lib/tzlib/tzlib.h b/sdk/lib/tzlib/tzlib.h
new file mode 100644
index 00000000000..9938c5ab473
--- /dev/null
+++ b/sdk/lib/tzlib/tzlib.h
@@ -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);

Reply via email to