2 * PROJECT: ReactOS Timedate Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/timedate/timezone.c
5 * PURPOSE: Time Zone property page
6 * COPYRIGHT: Copyright 2004-2005 Eric Kohl
7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
8 * Copyright 2006 Christoph v. Wittich <Christoph@ActiveVB.de>
14 // See also sdk/include/reactos/libs/syssetup/syssetup.h
15 typedef struct _TZ_INFO
20 SYSTEMTIME StandardDate
;
21 SYSTEMTIME DaylightDate
;
24 typedef struct _TIMEZONE_ENTRY
26 struct _TIMEZONE_ENTRY
*Prev
;
27 struct _TIMEZONE_ENTRY
*Next
;
28 WCHAR Description
[128]; /* 'Display' */
29 WCHAR StandardName
[33]; /* 'Std' */
30 WCHAR DaylightName
[33]; /* 'Dlt' */
31 TZ_INFO TimezoneInfo
; /* 'TZI' */
32 } TIMEZONE_ENTRY
, *PTIMEZONE_ENTRY
;
35 static HBITMAP hBitmap
= NULL
;
36 static int cxSource
, cySource
;
38 PTIMEZONE_ENTRY TimeZoneListHead
= NULL
;
39 PTIMEZONE_ENTRY TimeZoneListTail
= NULL
;
43 GetLargerTimeZoneEntry(
47 PTIMEZONE_ENTRY Entry
;
49 Entry
= TimeZoneListHead
;
52 if (Entry
->TimezoneInfo
.Bias
< Bias
)
55 if (Entry
->TimezoneInfo
.Bias
== Bias
)
57 if (_wcsicmp(Entry
->Description
, lpDescription
) > 0)
72 PTIMEZONE_ENTRY Entry
)
77 dwValueSize
= sizeof(Entry
->Description
);
78 lError
= RegQueryValueExW(hZoneKey
,
82 (LPBYTE
)&Entry
->Description
,
84 if (lError
!= ERROR_SUCCESS
)
87 dwValueSize
= sizeof(Entry
->StandardName
);
88 lError
= RegQueryValueExW(hZoneKey
,
92 (LPBYTE
)&Entry
->StandardName
,
94 if (lError
!= ERROR_SUCCESS
)
97 dwValueSize
= sizeof(Entry
->DaylightName
);
98 lError
= RegQueryValueExW(hZoneKey
,
102 (LPBYTE
)&Entry
->DaylightName
,
104 if (lError
!= ERROR_SUCCESS
)
107 dwValueSize
= sizeof(Entry
->TimezoneInfo
);
108 lError
= RegQueryValueExW(hZoneKey
,
112 (LPBYTE
)&Entry
->TimezoneInfo
,
119 CreateTimeZoneList(VOID
)
121 WCHAR szKeyName
[256];
127 PTIMEZONE_ENTRY Entry
;
128 PTIMEZONE_ENTRY Current
;
130 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
131 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
133 KEY_ENUMERATE_SUB_KEYS
,
137 for (dwIndex
= 0; ; dwIndex
++)
139 dwNameSize
= sizeof(szKeyName
);
140 lError
= RegEnumKeyExW(hZonesKey
,
148 if (lError
== ERROR_NO_MORE_ITEMS
)
151 if (RegOpenKeyEx (hZonesKey
,
158 Entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(TIMEZONE_ENTRY
));
161 RegCloseKey(hZoneKey
);
165 lError
= QueryTimezoneData(hZoneKey
,
168 RegCloseKey(hZoneKey
);
170 if (lError
!= ERROR_SUCCESS
)
172 HeapFree(GetProcessHeap(), 0, Entry
);
176 if (TimeZoneListHead
== NULL
&&
177 TimeZoneListTail
== NULL
)
181 TimeZoneListHead
= Entry
;
182 TimeZoneListTail
= Entry
;
186 Current
= GetLargerTimeZoneEntry(Entry
->TimezoneInfo
.Bias
, Entry
->Description
);
189 if (Current
== TimeZoneListHead
)
191 /* Prepend to head */
193 Entry
->Next
= TimeZoneListHead
;
194 TimeZoneListHead
->Prev
= Entry
;
195 TimeZoneListHead
= Entry
;
199 /* Insert before current */
200 Entry
->Prev
= Current
->Prev
;
201 Entry
->Next
= Current
;
202 Current
->Prev
->Next
= Entry
;
203 Current
->Prev
= Entry
;
209 Entry
->Prev
= TimeZoneListTail
;
211 TimeZoneListTail
->Next
= Entry
;
212 TimeZoneListTail
= Entry
;
217 RegCloseKey(hZonesKey
);
222 DestroyTimeZoneList(VOID
)
224 PTIMEZONE_ENTRY Entry
;
226 while (TimeZoneListHead
!= NULL
)
228 Entry
= TimeZoneListHead
;
230 TimeZoneListHead
= Entry
->Next
;
231 if (TimeZoneListHead
!= NULL
)
233 TimeZoneListHead
->Prev
= NULL
;
236 HeapFree(GetProcessHeap(), 0, Entry
);
239 TimeZoneListTail
= NULL
;
244 ShowTimeZoneList(HWND hwnd
)
246 TIME_ZONE_INFORMATION TimeZoneInfo
;
247 PTIMEZONE_ENTRY Entry
;
251 GetTimeZoneInformation(&TimeZoneInfo
);
255 Entry
= TimeZoneListHead
;
256 while (Entry
!= NULL
)
261 (LPARAM
)Entry
->Description
);
263 if (!wcscmp(Entry
->StandardName
, TimeZoneInfo
.StandardName
))
278 SetLocalTimeZone(HWND hwnd
)
280 TIME_ZONE_INFORMATION TimeZoneInformation
;
281 PTIMEZONE_ENTRY Entry
;
285 dwIndex
= (DWORD
)SendMessageW(hwnd
,
291 Entry
= TimeZoneListHead
;
301 wcscpy(TimeZoneInformation
.StandardName
,
302 Entry
->StandardName
);
303 wcscpy(TimeZoneInformation
.DaylightName
,
304 Entry
->DaylightName
);
306 TimeZoneInformation
.Bias
= Entry
->TimezoneInfo
.Bias
;
307 TimeZoneInformation
.StandardBias
= Entry
->TimezoneInfo
.StandardBias
;
308 TimeZoneInformation
.DaylightBias
= Entry
->TimezoneInfo
.DaylightBias
;
310 memcpy(&TimeZoneInformation
.StandardDate
,
311 &Entry
->TimezoneInfo
.StandardDate
,
313 memcpy(&TimeZoneInformation
.DaylightDate
,
314 &Entry
->TimezoneInfo
.DaylightDate
,
317 /* Set time zone information */
318 SetTimeZoneInformation(&TimeZoneInformation
);
323 GetAutoDaylightInfo(HWND hwnd
)
327 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
328 L
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
334 /* If the call fails (non zero), the reg value isn't available,
335 * which means it shouldn't be disabled, so we should check the button.
337 if (RegQueryValueExW(hKey
,
338 L
"DisableAutoDaylightTimeSet",
344 SendMessageW(hwnd
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, 0);
348 SendMessageW(hwnd
, BM_SETCHECK
, (WPARAM
)BST_UNCHECKED
, 0);
356 SetAutoDaylightInfo(HWND hwnd
)
361 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
362 L
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
368 if (SendMessageW(hwnd
, BM_GETCHECK
, 0, 0) == BST_UNCHECKED
)
371 L
"DisableAutoDaylightTimeSet",
379 RegDeleteValueW(hKey
,
380 L
"DisableAutoDaylightTimeSet");
387 /* Property page dialog callback */
389 TimeZonePageProc(HWND hwndDlg
,
399 CreateTimeZoneList();
400 ShowTimeZoneList(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
));
401 GetAutoDaylightInfo(GetDlgItem(hwndDlg
, IDC_AUTODAYLIGHT
));
402 hBitmap
= LoadImageW(hApplet
, MAKEINTRESOURCEW(IDC_WORLD
), IMAGE_BITMAP
, 0, 0, LR_DEFAULTCOLOR
);
405 GetObjectW(hBitmap
, sizeof(bitmap
), &bitmap
);
407 cxSource
= bitmap
.bmWidth
;
408 cySource
= bitmap
.bmHeight
;
414 LPDRAWITEMSTRUCT lpDrawItem
;
415 lpDrawItem
= (LPDRAWITEMSTRUCT
) lParam
;
416 if(lpDrawItem
->CtlID
== IDC_WORLD_BACKGROUND
)
419 hdcMem
= CreateCompatibleDC(lpDrawItem
->hDC
);
422 SelectObject(hdcMem
, hBitmap
);
423 StretchBlt(lpDrawItem
->hDC
, lpDrawItem
->rcItem
.left
, lpDrawItem
->rcItem
.top
,
424 lpDrawItem
->rcItem
.right
- lpDrawItem
->rcItem
.left
,
425 lpDrawItem
->rcItem
.bottom
- lpDrawItem
->rcItem
.top
,
426 hdcMem
, 0, 0, cxSource
, cySource
, SRCCOPY
);
434 if ((LOWORD(wParam
) == IDC_TIMEZONELIST
&& HIWORD(wParam
) == CBN_SELCHANGE
) ||
435 (LOWORD(wParam
) == IDC_AUTODAYLIGHT
&& HIWORD(wParam
) == BN_CLICKED
))
437 /* Enable the 'Apply' button */
438 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
443 DestroyTimeZoneList();
444 DeleteObject(hBitmap
);
449 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
455 SetAutoDaylightInfo(GetDlgItem(hwndDlg
, IDC_AUTODAYLIGHT
));
456 SetLocalTimeZone(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
));
457 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, PSNRET_NOERROR
);