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
[64]; /* 'Display' */
28 WCHAR StandardName
[33]; /* 'Std' */
29 WCHAR DaylightName
[33]; /* 'Dlt' */
30 TZ_INFO TimezoneInfo
; /* 'TZI' */
31 ULONG Index
; /* 'Index ' */
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
;
41 static PTIMEZONE_ENTRY
42 GetLargerTimeZoneEntry(DWORD Index
)
44 PTIMEZONE_ENTRY Entry
;
46 Entry
= TimeZoneListHead
;
49 if (Entry
->Index
>= Index
)
60 CreateTimeZoneList(VOID
)
70 PTIMEZONE_ENTRY Entry
;
71 PTIMEZONE_ENTRY Current
;
73 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
74 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
76 KEY_ENUMERATE_SUB_KEYS
,
83 dwNameSize
= 256 * sizeof(WCHAR
);
84 lError
= RegEnumKeyExW(hZonesKey
,
92 if (lError
== ERROR_NO_MORE_ITEMS
)
95 if (RegOpenKeyEx (hZonesKey
,
102 Entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(TIMEZONE_ENTRY
));
105 RegCloseKey(hZoneKey
);
109 dwValueSize
= 64 * sizeof(WCHAR
);
110 lError
= RegQueryValueExW(hZoneKey
,
114 (LPBYTE
)&Entry
->Description
,
116 if (lError
!= ERROR_SUCCESS
)
118 RegCloseKey(hZoneKey
);
120 HeapFree(GetProcessHeap(), 0, Entry
);
124 dwValueSize
= 33 * sizeof(WCHAR
);
125 if (RegQueryValueExW(hZoneKey
,
129 (LPBYTE
)&Entry
->StandardName
,
132 RegCloseKey(hZoneKey
);
136 dwValueSize
= 33 * sizeof(WCHAR
);
137 if (RegQueryValueExW(hZoneKey
,
141 (LPBYTE
)&Entry
->DaylightName
,
144 RegCloseKey(hZoneKey
);
148 dwValueSize
= sizeof(DWORD
);
149 if (RegQueryValueExW(hZoneKey
,
153 (LPBYTE
)&Entry
->Index
,
156 RegCloseKey(hZoneKey
);
160 dwValueSize
= sizeof(TZ_INFO
);
161 if (RegQueryValueExW(hZoneKey
,
165 (LPBYTE
)&Entry
->TimezoneInfo
,
168 RegCloseKey(hZoneKey
);
172 RegCloseKey(hZoneKey
);
174 if (TimeZoneListHead
== NULL
&&
175 TimeZoneListTail
== NULL
)
179 TimeZoneListHead
= Entry
;
180 TimeZoneListTail
= Entry
;
184 Current
= GetLargerTimeZoneEntry(Entry
->Index
);
187 if (Current
== TimeZoneListHead
)
189 /* Prepend to head */
191 Entry
->Next
= TimeZoneListHead
;
192 TimeZoneListHead
->Prev
= Entry
;
193 TimeZoneListHead
= Entry
;
197 /* Insert before current */
198 Entry
->Prev
= Current
->Prev
;
199 Entry
->Next
= Current
;
200 Current
->Prev
->Next
= Entry
;
201 Current
->Prev
= Entry
;
207 Entry
->Prev
= TimeZoneListTail
;
209 TimeZoneListTail
->Next
= Entry
;
210 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
, DWL_MSGRESULT
, PSNRET_NOERROR
);