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 typedef struct _TZ_INFO
19 SYSTEMTIME StandardDate
;
20 SYSTEMTIME DaylightDate
;
23 typedef struct _TIMEZONE_ENTRY
25 struct _TIMEZONE_ENTRY
*Prev
;
26 struct _TIMEZONE_ENTRY
*Next
;
27 WCHAR Description
[128]; /* 'Display' */
28 WCHAR StandardName
[33]; /* 'Std' */
29 WCHAR DaylightName
[33]; /* 'Dlt' */
30 TZ_INFO TimezoneInfo
; /* 'TZI' */
31 } TIMEZONE_ENTRY
, *PTIMEZONE_ENTRY
;
34 static HBITMAP hBitmap
= NULL
;
35 static int cxSource
, cySource
;
37 PTIMEZONE_ENTRY TimeZoneListHead
= NULL
;
38 PTIMEZONE_ENTRY TimeZoneListTail
= NULL
;
42 GetLargerTimeZoneEntry(
46 PTIMEZONE_ENTRY Entry
;
48 Entry
= TimeZoneListHead
;
51 if (Entry
->TimezoneInfo
.Bias
< Bias
)
54 if (Entry
->TimezoneInfo
.Bias
== Bias
)
56 if (_wcsicmp(Entry
->Description
, lpDescription
) > 0)
71 PTIMEZONE_ENTRY Entry
)
76 dwValueSize
= sizeof(Entry
->Description
);
77 lError
= RegQueryValueExW(hZoneKey
,
81 (LPBYTE
)&Entry
->Description
,
83 if (lError
!= ERROR_SUCCESS
)
86 dwValueSize
= sizeof(Entry
->StandardName
);
87 lError
= RegQueryValueExW(hZoneKey
,
91 (LPBYTE
)&Entry
->StandardName
,
93 if (lError
!= ERROR_SUCCESS
)
96 dwValueSize
= sizeof(Entry
->DaylightName
);
97 lError
= RegQueryValueExW(hZoneKey
,
101 (LPBYTE
)&Entry
->DaylightName
,
103 if (lError
!= ERROR_SUCCESS
)
106 dwValueSize
= sizeof(Entry
->TimezoneInfo
);
107 lError
= RegQueryValueExW(hZoneKey
,
111 (LPBYTE
)&Entry
->TimezoneInfo
,
118 CreateTimeZoneList(VOID
)
120 WCHAR szKeyName
[256];
126 PTIMEZONE_ENTRY Entry
;
127 PTIMEZONE_ENTRY Current
;
129 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
130 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
132 KEY_ENUMERATE_SUB_KEYS
,
136 for (dwIndex
= 0; ; dwIndex
++)
138 dwNameSize
= sizeof(szKeyName
);
139 lError
= RegEnumKeyExW(hZonesKey
,
147 if (lError
== ERROR_NO_MORE_ITEMS
)
150 if (RegOpenKeyEx (hZonesKey
,
157 Entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(TIMEZONE_ENTRY
));
160 RegCloseKey(hZoneKey
);
164 lError
= QueryTimezoneData(hZoneKey
,
167 RegCloseKey(hZoneKey
);
169 if (lError
!= ERROR_SUCCESS
)
171 HeapFree(GetProcessHeap(), 0, Entry
);
175 if (TimeZoneListHead
== NULL
&&
176 TimeZoneListTail
== NULL
)
180 TimeZoneListHead
= Entry
;
181 TimeZoneListTail
= Entry
;
185 Current
= GetLargerTimeZoneEntry(Entry
->TimezoneInfo
.Bias
, Entry
->Description
);
188 if (Current
== TimeZoneListHead
)
190 /* Prepend to head */
192 Entry
->Next
= TimeZoneListHead
;
193 TimeZoneListHead
->Prev
= Entry
;
194 TimeZoneListHead
= Entry
;
198 /* Insert before current */
199 Entry
->Prev
= Current
->Prev
;
200 Entry
->Next
= Current
;
201 Current
->Prev
->Next
= Entry
;
202 Current
->Prev
= Entry
;
208 Entry
->Prev
= TimeZoneListTail
;
210 TimeZoneListTail
->Next
= Entry
;
211 TimeZoneListTail
= Entry
;
216 RegCloseKey(hZonesKey
);
221 DestroyTimeZoneList(VOID
)
223 PTIMEZONE_ENTRY Entry
;
225 while (TimeZoneListHead
!= NULL
)
227 Entry
= TimeZoneListHead
;
229 TimeZoneListHead
= Entry
->Next
;
230 if (TimeZoneListHead
!= NULL
)
232 TimeZoneListHead
->Prev
= NULL
;
235 HeapFree(GetProcessHeap(), 0, Entry
);
238 TimeZoneListTail
= NULL
;
243 ShowTimeZoneList(HWND hwnd
)
245 TIME_ZONE_INFORMATION TimeZoneInfo
;
246 PTIMEZONE_ENTRY Entry
;
250 GetTimeZoneInformation(&TimeZoneInfo
);
254 Entry
= TimeZoneListHead
;
255 while (Entry
!= NULL
)
260 (LPARAM
)Entry
->Description
);
262 if (!wcscmp(Entry
->StandardName
, TimeZoneInfo
.StandardName
))
277 SetLocalTimeZone(HWND hwnd
)
279 TIME_ZONE_INFORMATION TimeZoneInformation
;
280 PTIMEZONE_ENTRY Entry
;
284 dwIndex
= (DWORD
)SendMessageW(hwnd
,
290 Entry
= TimeZoneListHead
;
300 wcscpy(TimeZoneInformation
.StandardName
,
301 Entry
->StandardName
);
302 wcscpy(TimeZoneInformation
.DaylightName
,
303 Entry
->DaylightName
);
305 TimeZoneInformation
.Bias
= Entry
->TimezoneInfo
.Bias
;
306 TimeZoneInformation
.StandardBias
= Entry
->TimezoneInfo
.StandardBias
;
307 TimeZoneInformation
.DaylightBias
= Entry
->TimezoneInfo
.DaylightBias
;
309 memcpy(&TimeZoneInformation
.StandardDate
,
310 &Entry
->TimezoneInfo
.StandardDate
,
312 memcpy(&TimeZoneInformation
.DaylightDate
,
313 &Entry
->TimezoneInfo
.DaylightDate
,
316 /* Set time zone information */
317 SetTimeZoneInformation(&TimeZoneInformation
);
322 GetAutoDaylightInfo(HWND hwnd
)
326 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
327 L
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
333 /* If the call fails (non zero), the reg value isn't available,
334 * which means it shouldn't be disabled, so we should check the button.
336 if (RegQueryValueExW(hKey
,
337 L
"DisableAutoDaylightTimeSet",
343 SendMessageW(hwnd
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, 0);
347 SendMessageW(hwnd
, BM_SETCHECK
, (WPARAM
)BST_UNCHECKED
, 0);
355 SetAutoDaylightInfo(HWND hwnd
)
360 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
361 L
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
367 if (SendMessageW(hwnd
, BM_GETCHECK
, 0, 0) == BST_UNCHECKED
)
370 L
"DisableAutoDaylightTimeSet",
378 RegDeleteValueW(hKey
,
379 L
"DisableAutoDaylightTimeSet");
386 /* Property page dialog callback */
388 TimeZonePageProc(HWND hwndDlg
,
398 CreateTimeZoneList();
399 ShowTimeZoneList(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
));
400 GetAutoDaylightInfo(GetDlgItem(hwndDlg
, IDC_AUTODAYLIGHT
));
401 hBitmap
= LoadImageW(hApplet
, MAKEINTRESOURCEW(IDC_WORLD
), IMAGE_BITMAP
, 0, 0, LR_DEFAULTCOLOR
);
404 GetObjectW(hBitmap
, sizeof(bitmap
), &bitmap
);
406 cxSource
= bitmap
.bmWidth
;
407 cySource
= bitmap
.bmHeight
;
413 LPDRAWITEMSTRUCT lpDrawItem
;
414 lpDrawItem
= (LPDRAWITEMSTRUCT
) lParam
;
415 if(lpDrawItem
->CtlID
== IDC_WORLD_BACKGROUND
)
418 hdcMem
= CreateCompatibleDC(lpDrawItem
->hDC
);
421 SelectObject(hdcMem
, hBitmap
);
422 StretchBlt(lpDrawItem
->hDC
, lpDrawItem
->rcItem
.left
, lpDrawItem
->rcItem
.top
,
423 lpDrawItem
->rcItem
.right
- lpDrawItem
->rcItem
.left
,
424 lpDrawItem
->rcItem
.bottom
- lpDrawItem
->rcItem
.top
,
425 hdcMem
, 0, 0, cxSource
, cySource
, SRCCOPY
);
433 if ((LOWORD(wParam
) == IDC_TIMEZONELIST
&& HIWORD(wParam
) == CBN_SELCHANGE
) ||
434 (LOWORD(wParam
) == IDC_AUTODAYLIGHT
&& HIWORD(wParam
) == BN_CLICKED
))
436 /* Enable the 'Apply' button */
437 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
442 DestroyTimeZoneList();
443 DeleteObject(hBitmap
);
448 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
454 SetAutoDaylightInfo(GetDlgItem(hwndDlg
, IDC_AUTODAYLIGHT
));
455 SetLocalTimeZone(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
));
456 SetWindowLongPtr(hwndDlg
, DWLP_MSGRESULT
, PSNRET_NOERROR
);