2006-06-23 08:13:50 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Timedate Control Panel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2011-11-29 14:55:58 +00:00
|
|
|
* FILE: dll/cpl/timedate/timezone.c
|
2006-06-23 08:13:50 +00:00
|
|
|
* PURPOSE: Time Zone property page
|
|
|
|
* COPYRIGHT: Copyright 2004-2005 Eric Kohl
|
|
|
|
* Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
|
|
|
|
* Copyright 2006 Christoph v. Wittich <Christoph@ActiveVB.de>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2013-01-24 23:00:42 +00:00
|
|
|
#include "timedate.h"
|
2020-04-19 15:48:25 +00:00
|
|
|
#include <tzlib.h>
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
typedef struct _TIMEZONE_ENTRY
|
|
|
|
{
|
|
|
|
struct _TIMEZONE_ENTRY *Prev;
|
|
|
|
struct _TIMEZONE_ENTRY *Next;
|
2020-04-19 15:48:25 +00:00
|
|
|
WCHAR Description[128]; /* 'Display' */
|
|
|
|
WCHAR StandardName[33]; /* 'Std' */
|
|
|
|
WCHAR DaylightName[33]; /* 'Dlt' */
|
|
|
|
REG_TZI_FORMAT TimezoneInfo; /* 'TZI' */
|
2006-06-23 08:13:50 +00:00
|
|
|
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
|
|
|
|
|
|
|
|
|
|
|
|
static HBITMAP hBitmap = NULL;
|
|
|
|
static int cxSource, cySource;
|
|
|
|
|
|
|
|
PTIMEZONE_ENTRY TimeZoneListHead = NULL;
|
|
|
|
PTIMEZONE_ENTRY TimeZoneListTail = NULL;
|
|
|
|
|
2016-05-28 00:12:02 +00:00
|
|
|
static
|
|
|
|
PTIMEZONE_ENTRY
|
|
|
|
GetLargerTimeZoneEntry(
|
|
|
|
LONG Bias,
|
|
|
|
LPWSTR lpDescription)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
PTIMEZONE_ENTRY Entry;
|
|
|
|
|
|
|
|
Entry = TimeZoneListHead;
|
|
|
|
while (Entry != NULL)
|
|
|
|
{
|
2017-09-23 18:54:58 +00:00
|
|
|
if (Entry->TimezoneInfo.Bias < Bias)
|
2006-06-23 08:13:50 +00:00
|
|
|
return Entry;
|
|
|
|
|
2016-05-28 00:12:02 +00:00
|
|
|
if (Entry->TimezoneInfo.Bias == Bias)
|
|
|
|
{
|
|
|
|
if (_wcsicmp(Entry->Description, lpDescription) > 0)
|
|
|
|
return Entry;
|
|
|
|
}
|
|
|
|
|
2006-06-23 08:13:50 +00:00
|
|
|
Entry = Entry->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
static LONG
|
|
|
|
RetrieveTimeZone(
|
|
|
|
IN HKEY hZoneKey,
|
|
|
|
IN PVOID Context)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
LONG lError;
|
|
|
|
PTIMEZONE_ENTRY Entry;
|
|
|
|
PTIMEZONE_ENTRY Current;
|
2020-04-19 15:48:25 +00:00
|
|
|
ULONG DescriptionSize;
|
|
|
|
ULONG StandardNameSize;
|
|
|
|
ULONG DaylightNameSize;
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
|
|
|
|
if (Entry == NULL)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
2020-04-19 15:48:25 +00:00
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
DescriptionSize = sizeof(Entry->Description);
|
|
|
|
StandardNameSize = sizeof(Entry->StandardName);
|
|
|
|
DaylightNameSize = sizeof(Entry->DaylightName);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
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)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
2020-04-19 15:48:25 +00:00
|
|
|
if (Current == TimeZoneListHead)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
2020-04-19 15:48:25 +00:00
|
|
|
/* Prepend to head */
|
|
|
|
Entry->Prev = NULL;
|
|
|
|
Entry->Next = TimeZoneListHead;
|
|
|
|
TimeZoneListHead->Prev = Entry;
|
|
|
|
TimeZoneListHead = Entry;
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-04-19 15:48:25 +00:00
|
|
|
/* Insert before current */
|
|
|
|
Entry->Prev = Current->Prev;
|
|
|
|
Entry->Next = Current;
|
|
|
|
Current->Prev->Next = Entry;
|
|
|
|
Current->Prev = Entry;
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-19 15:48:25 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Append to tail */
|
|
|
|
Entry->Prev = TimeZoneListTail;
|
|
|
|
Entry->Next = NULL;
|
|
|
|
TimeZoneListTail->Next = Entry;
|
|
|
|
TimeZoneListTail = Entry;
|
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
return ERROR_SUCCESS;
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
|
2020-04-19 15:48:25 +00:00
|
|
|
static VOID
|
|
|
|
CreateTimeZoneList(VOID)
|
|
|
|
{
|
|
|
|
EnumerateTimeZoneList(RetrieveTimeZone, NULL);
|
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
static VOID
|
|
|
|
DestroyTimeZoneList(VOID)
|
|
|
|
{
|
|
|
|
PTIMEZONE_ENTRY Entry;
|
|
|
|
|
|
|
|
while (TimeZoneListHead != NULL)
|
|
|
|
{
|
|
|
|
Entry = TimeZoneListHead;
|
|
|
|
|
|
|
|
TimeZoneListHead = Entry->Next;
|
|
|
|
if (TimeZoneListHead != NULL)
|
|
|
|
{
|
|
|
|
TimeZoneListHead->Prev = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, Entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
TimeZoneListTail = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VOID
|
|
|
|
ShowTimeZoneList(HWND hwnd)
|
|
|
|
{
|
|
|
|
TIME_ZONE_INFORMATION TimeZoneInfo;
|
|
|
|
PTIMEZONE_ENTRY Entry;
|
|
|
|
DWORD dwIndex;
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
GetTimeZoneInformation(&TimeZoneInfo);
|
|
|
|
|
|
|
|
dwIndex = 0;
|
|
|
|
i = 0;
|
|
|
|
Entry = TimeZoneListHead;
|
|
|
|
while (Entry != NULL)
|
|
|
|
{
|
2007-07-31 22:17:07 +00:00
|
|
|
SendMessageW(hwnd,
|
|
|
|
CB_ADDSTRING,
|
|
|
|
0,
|
|
|
|
(LPARAM)Entry->Description);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
2007-07-31 22:17:07 +00:00
|
|
|
if (!wcscmp(Entry->StandardName, TimeZoneInfo.StandardName))
|
2006-06-23 08:13:50 +00:00
|
|
|
dwIndex = i;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
Entry = Entry->Next;
|
|
|
|
}
|
|
|
|
|
2007-07-31 22:17:07 +00:00
|
|
|
SendMessageW(hwnd,
|
|
|
|
CB_SETCURSEL,
|
|
|
|
(WPARAM)dwIndex,
|
|
|
|
0);
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VOID
|
|
|
|
SetLocalTimeZone(HWND hwnd)
|
|
|
|
{
|
|
|
|
TIME_ZONE_INFORMATION TimeZoneInformation;
|
|
|
|
PTIMEZONE_ENTRY Entry;
|
|
|
|
DWORD dwIndex;
|
|
|
|
DWORD i;
|
|
|
|
|
2007-07-31 22:17:07 +00:00
|
|
|
dwIndex = (DWORD)SendMessageW(hwnd,
|
|
|
|
CB_GETCURSEL,
|
|
|
|
0,
|
|
|
|
0);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
i = 0;
|
|
|
|
Entry = TimeZoneListHead;
|
|
|
|
while (i < dwIndex)
|
|
|
|
{
|
|
|
|
if (Entry == NULL)
|
2006-07-09 16:19:39 +00:00
|
|
|
return;
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
i++;
|
|
|
|
Entry = Entry->Next;
|
|
|
|
}
|
|
|
|
|
2007-07-31 22:17:07 +00:00
|
|
|
wcscpy(TimeZoneInformation.StandardName,
|
2020-04-19 15:48:25 +00:00
|
|
|
Entry->StandardName);
|
2007-07-31 22:17:07 +00:00
|
|
|
wcscpy(TimeZoneInformation.DaylightName,
|
2020-04-19 15:48:25 +00:00
|
|
|
Entry->DaylightName);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
|
|
|
|
TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
|
|
|
|
TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias;
|
|
|
|
|
|
|
|
memcpy(&TimeZoneInformation.StandardDate,
|
|
|
|
&Entry->TimezoneInfo.StandardDate,
|
|
|
|
sizeof(SYSTEMTIME));
|
|
|
|
memcpy(&TimeZoneInformation.DaylightDate,
|
|
|
|
&Entry->TimezoneInfo.DaylightDate,
|
|
|
|
sizeof(SYSTEMTIME));
|
|
|
|
|
|
|
|
/* Set time zone information */
|
|
|
|
SetTimeZoneInformation(&TimeZoneInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Property page dialog callback */
|
|
|
|
INT_PTR CALLBACK
|
|
|
|
TimeZonePageProc(HWND hwndDlg,
|
2007-06-07 16:18:38 +00:00
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2006-06-23 08:13:50 +00:00
|
|
|
{
|
|
|
|
BITMAP bitmap;
|
|
|
|
|
|
|
|
switch (uMsg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
2020-04-19 15:48:25 +00:00
|
|
|
{
|
2006-06-23 08:13:50 +00:00
|
|
|
CreateTimeZoneList();
|
|
|
|
ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST));
|
2020-04-19 15:48:25 +00:00
|
|
|
|
|
|
|
SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK,
|
|
|
|
(WPARAM)(GetAutoDaylight() ? BST_CHECKED : BST_UNCHECKED), 0);
|
|
|
|
|
2007-07-31 22:17:07 +00:00
|
|
|
hBitmap = LoadImageW(hApplet, MAKEINTRESOURCEW(IDC_WORLD), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
2006-06-23 08:13:50 +00:00
|
|
|
if (hBitmap != NULL)
|
|
|
|
{
|
2016-05-28 15:23:00 +00:00
|
|
|
GetObjectW(hBitmap, sizeof(bitmap), &bitmap);
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
cxSource = bitmap.bmWidth;
|
|
|
|
cySource = bitmap.bmHeight;
|
|
|
|
}
|
2007-06-07 16:18:38 +00:00
|
|
|
break;
|
2020-04-19 15:48:25 +00:00
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
case WM_DRAWITEM:
|
|
|
|
{
|
|
|
|
LPDRAWITEMSTRUCT lpDrawItem;
|
|
|
|
lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
if(lpDrawItem->CtlID == IDC_WORLD_BACKGROUND)
|
|
|
|
{
|
2006-09-01 21:53:31 +00:00
|
|
|
HDC hdcMem;
|
|
|
|
hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
|
|
|
|
if (hdcMem != NULL)
|
|
|
|
{
|
|
|
|
SelectObject(hdcMem, hBitmap);
|
|
|
|
StretchBlt(lpDrawItem->hDC, lpDrawItem->rcItem.left, lpDrawItem->rcItem.top,
|
|
|
|
lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
|
|
|
|
lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
|
|
|
|
hdcMem, 0, 0, cxSource, cySource, SRCCOPY);
|
|
|
|
DeleteDC(hdcMem);
|
|
|
|
}
|
2006-06-23 08:13:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
if ((LOWORD(wParam) == IDC_TIMEZONELIST && HIWORD(wParam) == CBN_SELCHANGE) ||
|
|
|
|
(LOWORD(wParam) == IDC_AUTODAYLIGHT && HIWORD(wParam) == BN_CLICKED))
|
|
|
|
{
|
|
|
|
/* Enable the 'Apply' button */
|
|
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
|
|
}
|
2007-06-07 16:18:38 +00:00
|
|
|
break;
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
DestroyTimeZoneList();
|
|
|
|
DeleteObject(hBitmap);
|
2007-06-07 16:18:38 +00:00
|
|
|
break;
|
2006-06-23 08:13:50 +00:00
|
|
|
|
|
|
|
case WM_NOTIFY:
|
|
|
|
{
|
|
|
|
LPNMHDR lpnm = (LPNMHDR)lParam;
|
|
|
|
|
|
|
|
switch (lpnm->code)
|
|
|
|
{
|
|
|
|
case PSN_APPLY:
|
|
|
|
{
|
2020-04-19 15:48:25 +00:00
|
|
|
SetAutoDaylight(SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT,
|
|
|
|
BM_GETCHECK, 0, 0) != BST_UNCHECKED);
|
2006-06-23 08:13:50 +00:00
|
|
|
SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST));
|
2018-02-27 21:48:32 +00:00
|
|
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
|
2006-06-23 08:13:50 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|