[MMIXER] Fix additional data size initialization for different audio formats (#6753)
[reactos.git] / dll / cpl / timedate / timezone.c
1 /*
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>
9 *
10 */
11
12 #include "timedate.h"
13
14 // See also sdk/include/reactos/libs/syssetup/syssetup.h
15 typedef struct _TZ_INFO
16 {
17 LONG Bias;
18 LONG StandardBias;
19 LONG DaylightBias;
20 SYSTEMTIME StandardDate;
21 SYSTEMTIME DaylightDate;
22 } TZ_INFO, *PTZ_INFO;
23
24 typedef struct _TIMEZONE_ENTRY
25 {
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;
33
34
35 static HBITMAP hBitmap = NULL;
36 static int cxSource, cySource;
37
38 PTIMEZONE_ENTRY TimeZoneListHead = NULL;
39 PTIMEZONE_ENTRY TimeZoneListTail = NULL;
40
41 static
42 PTIMEZONE_ENTRY
43 GetLargerTimeZoneEntry(
44 LONG Bias,
45 LPWSTR lpDescription)
46 {
47 PTIMEZONE_ENTRY Entry;
48
49 Entry = TimeZoneListHead;
50 while (Entry != NULL)
51 {
52 if (Entry->TimezoneInfo.Bias < Bias)
53 return Entry;
54
55 if (Entry->TimezoneInfo.Bias == Bias)
56 {
57 if (_wcsicmp(Entry->Description, lpDescription) > 0)
58 return Entry;
59 }
60
61 Entry = Entry->Next;
62 }
63
64 return NULL;
65 }
66
67
68 static
69 LONG
70 QueryTimezoneData(
71 HKEY hZoneKey,
72 PTIMEZONE_ENTRY Entry)
73 {
74 DWORD dwValueSize;
75 LONG lError;
76
77 dwValueSize = sizeof(Entry->Description);
78 lError = RegQueryValueExW(hZoneKey,
79 L"Display",
80 NULL,
81 NULL,
82 (LPBYTE)&Entry->Description,
83 &dwValueSize);
84 if (lError != ERROR_SUCCESS)
85 return lError;
86
87 dwValueSize = sizeof(Entry->StandardName);
88 lError = RegQueryValueExW(hZoneKey,
89 L"Std",
90 NULL,
91 NULL,
92 (LPBYTE)&Entry->StandardName,
93 &dwValueSize);
94 if (lError != ERROR_SUCCESS)
95 return lError;
96
97 dwValueSize = sizeof(Entry->DaylightName);
98 lError = RegQueryValueExW(hZoneKey,
99 L"Dlt",
100 NULL,
101 NULL,
102 (LPBYTE)&Entry->DaylightName,
103 &dwValueSize);
104 if (lError != ERROR_SUCCESS)
105 return lError;
106
107 dwValueSize = sizeof(Entry->TimezoneInfo);
108 lError = RegQueryValueExW(hZoneKey,
109 L"TZI",
110 NULL,
111 NULL,
112 (LPBYTE)&Entry->TimezoneInfo,
113 &dwValueSize);
114 return lError;
115 }
116
117
118 static VOID
119 CreateTimeZoneList(VOID)
120 {
121 WCHAR szKeyName[256];
122 DWORD dwIndex;
123 DWORD dwNameSize;
124 LONG lError;
125 HKEY hZonesKey;
126 HKEY hZoneKey;
127 PTIMEZONE_ENTRY Entry;
128 PTIMEZONE_ENTRY Current;
129
130 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
131 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
132 0,
133 KEY_ENUMERATE_SUB_KEYS,
134 &hZonesKey))
135 return;
136
137 for (dwIndex = 0; ; dwIndex++)
138 {
139 dwNameSize = sizeof(szKeyName);
140 lError = RegEnumKeyExW(hZonesKey,
141 dwIndex,
142 szKeyName,
143 &dwNameSize,
144 NULL,
145 NULL,
146 NULL,
147 NULL);
148 if (lError == ERROR_NO_MORE_ITEMS)
149 break;
150
151 if (RegOpenKeyEx (hZonesKey,
152 szKeyName,
153 0,
154 KEY_QUERY_VALUE,
155 &hZoneKey))
156 break;
157
158 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
159 if (Entry == NULL)
160 {
161 RegCloseKey(hZoneKey);
162 break;
163 }
164
165 lError = QueryTimezoneData(hZoneKey,
166 Entry);
167
168 RegCloseKey(hZoneKey);
169
170 if (lError != ERROR_SUCCESS)
171 {
172 HeapFree(GetProcessHeap(), 0, Entry);
173 break;
174 }
175
176 if (TimeZoneListHead == NULL &&
177 TimeZoneListTail == NULL)
178 {
179 Entry->Prev = NULL;
180 Entry->Next = NULL;
181 TimeZoneListHead = Entry;
182 TimeZoneListTail = Entry;
183 }
184 else
185 {
186 Current = GetLargerTimeZoneEntry(Entry->TimezoneInfo.Bias, Entry->Description);
187 if (Current != NULL)
188 {
189 if (Current == TimeZoneListHead)
190 {
191 /* Prepend to head */
192 Entry->Prev = NULL;
193 Entry->Next = TimeZoneListHead;
194 TimeZoneListHead->Prev = Entry;
195 TimeZoneListHead = Entry;
196 }
197 else
198 {
199 /* Insert before current */
200 Entry->Prev = Current->Prev;
201 Entry->Next = Current;
202 Current->Prev->Next = Entry;
203 Current->Prev = Entry;
204 }
205 }
206 else
207 {
208 /* Append to tail */
209 Entry->Prev = TimeZoneListTail;
210 Entry->Next = NULL;
211 TimeZoneListTail->Next = Entry;
212 TimeZoneListTail = Entry;
213 }
214 }
215 }
216
217 RegCloseKey(hZonesKey);
218 }
219
220
221 static VOID
222 DestroyTimeZoneList(VOID)
223 {
224 PTIMEZONE_ENTRY Entry;
225
226 while (TimeZoneListHead != NULL)
227 {
228 Entry = TimeZoneListHead;
229
230 TimeZoneListHead = Entry->Next;
231 if (TimeZoneListHead != NULL)
232 {
233 TimeZoneListHead->Prev = NULL;
234 }
235
236 HeapFree(GetProcessHeap(), 0, Entry);
237 }
238
239 TimeZoneListTail = NULL;
240 }
241
242
243 static VOID
244 ShowTimeZoneList(HWND hwnd)
245 {
246 TIME_ZONE_INFORMATION TimeZoneInfo;
247 PTIMEZONE_ENTRY Entry;
248 DWORD dwIndex;
249 DWORD i;
250
251 GetTimeZoneInformation(&TimeZoneInfo);
252
253 dwIndex = 0;
254 i = 0;
255 Entry = TimeZoneListHead;
256 while (Entry != NULL)
257 {
258 SendMessageW(hwnd,
259 CB_ADDSTRING,
260 0,
261 (LPARAM)Entry->Description);
262
263 if (!wcscmp(Entry->StandardName, TimeZoneInfo.StandardName))
264 dwIndex = i;
265
266 i++;
267 Entry = Entry->Next;
268 }
269
270 SendMessageW(hwnd,
271 CB_SETCURSEL,
272 (WPARAM)dwIndex,
273 0);
274 }
275
276
277 static VOID
278 SetLocalTimeZone(HWND hwnd)
279 {
280 TIME_ZONE_INFORMATION TimeZoneInformation;
281 PTIMEZONE_ENTRY Entry;
282 DWORD dwIndex;
283 DWORD i;
284
285 dwIndex = (DWORD)SendMessageW(hwnd,
286 CB_GETCURSEL,
287 0,
288 0);
289
290 i = 0;
291 Entry = TimeZoneListHead;
292 while (i < dwIndex)
293 {
294 if (Entry == NULL)
295 return;
296
297 i++;
298 Entry = Entry->Next;
299 }
300
301 wcscpy(TimeZoneInformation.StandardName,
302 Entry->StandardName);
303 wcscpy(TimeZoneInformation.DaylightName,
304 Entry->DaylightName);
305
306 TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
307 TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
308 TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias;
309
310 memcpy(&TimeZoneInformation.StandardDate,
311 &Entry->TimezoneInfo.StandardDate,
312 sizeof(SYSTEMTIME));
313 memcpy(&TimeZoneInformation.DaylightDate,
314 &Entry->TimezoneInfo.DaylightDate,
315 sizeof(SYSTEMTIME));
316
317 /* Set time zone information */
318 SetTimeZoneInformation(&TimeZoneInformation);
319 }
320
321
322 static VOID
323 GetAutoDaylightInfo(HWND hwnd)
324 {
325 HKEY hKey;
326
327 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
328 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
329 0,
330 KEY_QUERY_VALUE,
331 &hKey))
332 return;
333
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.
336 */
337 if (RegQueryValueExW(hKey,
338 L"DisableAutoDaylightTimeSet",
339 NULL,
340 NULL,
341 NULL,
342 NULL))
343 {
344 SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
345 }
346 else
347 {
348 SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
349 }
350
351 RegCloseKey(hKey);
352 }
353
354
355 static VOID
356 SetAutoDaylightInfo(HWND hwnd)
357 {
358 HKEY hKey;
359 DWORD dwValue = 1;
360
361 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
362 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
363 0,
364 KEY_SET_VALUE,
365 &hKey))
366 return;
367
368 if (SendMessageW(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
369 {
370 RegSetValueExW(hKey,
371 L"DisableAutoDaylightTimeSet",
372 0,
373 REG_DWORD,
374 (LPBYTE)&dwValue,
375 sizeof(dwValue));
376 }
377 else
378 {
379 RegDeleteValueW(hKey,
380 L"DisableAutoDaylightTimeSet");
381 }
382
383 RegCloseKey(hKey);
384 }
385
386
387 /* Property page dialog callback */
388 INT_PTR CALLBACK
389 TimeZonePageProc(HWND hwndDlg,
390 UINT uMsg,
391 WPARAM wParam,
392 LPARAM lParam)
393 {
394 BITMAP bitmap;
395
396 switch (uMsg)
397 {
398 case WM_INITDIALOG:
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);
403 if (hBitmap != NULL)
404 {
405 GetObjectW(hBitmap, sizeof(bitmap), &bitmap);
406
407 cxSource = bitmap.bmWidth;
408 cySource = bitmap.bmHeight;
409 }
410 break;
411
412 case WM_DRAWITEM:
413 {
414 LPDRAWITEMSTRUCT lpDrawItem;
415 lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
416 if(lpDrawItem->CtlID == IDC_WORLD_BACKGROUND)
417 {
418 HDC hdcMem;
419 hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
420 if (hdcMem != NULL)
421 {
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);
427 DeleteDC(hdcMem);
428 }
429 }
430 }
431 break;
432
433 case WM_COMMAND:
434 if ((LOWORD(wParam) == IDC_TIMEZONELIST && HIWORD(wParam) == CBN_SELCHANGE) ||
435 (LOWORD(wParam) == IDC_AUTODAYLIGHT && HIWORD(wParam) == BN_CLICKED))
436 {
437 /* Enable the 'Apply' button */
438 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
439 }
440 break;
441
442 case WM_DESTROY:
443 DestroyTimeZoneList();
444 DeleteObject(hBitmap);
445 break;
446
447 case WM_NOTIFY:
448 {
449 LPNMHDR lpnm = (LPNMHDR)lParam;
450
451 switch (lpnm->code)
452 {
453 case PSN_APPLY:
454 {
455 SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT));
456 SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST));
457 SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
458 return TRUE;
459 }
460
461 default:
462 break;
463 }
464 }
465 break;
466 }
467
468 return FALSE;
469 }