Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentimezone.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Timedate Control Panel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: dll/cpl/timedate/timezone.c 00005 * PURPOSE: Time Zone property page 00006 * COPYRIGHT: Copyright 2004-2005 Eric Kohl 00007 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com> 00008 * Copyright 2006 Christoph v. Wittich <Christoph@ActiveVB.de> 00009 * 00010 */ 00011 00012 #include <timedate.h> 00013 00014 typedef struct _TZ_INFO 00015 { 00016 LONG Bias; 00017 LONG StandardBias; 00018 LONG DaylightBias; 00019 SYSTEMTIME StandardDate; 00020 SYSTEMTIME DaylightDate; 00021 } TZ_INFO, *PTZ_INFO; 00022 00023 typedef struct _TIMEZONE_ENTRY 00024 { 00025 struct _TIMEZONE_ENTRY *Prev; 00026 struct _TIMEZONE_ENTRY *Next; 00027 WCHAR Description[64]; /* 'Display' */ 00028 WCHAR StandardName[33]; /* 'Std' */ 00029 WCHAR DaylightName[33]; /* 'Dlt' */ 00030 TZ_INFO TimezoneInfo; /* 'TZI' */ 00031 ULONG Index; /* 'Index ' */ 00032 } TIMEZONE_ENTRY, *PTIMEZONE_ENTRY; 00033 00034 00035 static HBITMAP hBitmap = NULL; 00036 static int cxSource, cySource; 00037 00038 PTIMEZONE_ENTRY TimeZoneListHead = NULL; 00039 PTIMEZONE_ENTRY TimeZoneListTail = NULL; 00040 00041 static PTIMEZONE_ENTRY 00042 GetLargerTimeZoneEntry(DWORD Index) 00043 { 00044 PTIMEZONE_ENTRY Entry; 00045 00046 Entry = TimeZoneListHead; 00047 while (Entry != NULL) 00048 { 00049 if (Entry->Index >= Index) 00050 return Entry; 00051 00052 Entry = Entry->Next; 00053 } 00054 00055 return NULL; 00056 } 00057 00058 00059 static VOID 00060 CreateTimeZoneList(VOID) 00061 { 00062 WCHAR szKeyName[256]; 00063 DWORD dwIndex; 00064 DWORD dwNameSize; 00065 DWORD dwValueSize; 00066 LONG lError; 00067 HKEY hZonesKey; 00068 HKEY hZoneKey; 00069 00070 PTIMEZONE_ENTRY Entry; 00071 PTIMEZONE_ENTRY Current; 00072 00073 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 00074 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", 00075 0, 00076 KEY_ENUMERATE_SUB_KEYS, 00077 &hZonesKey)) 00078 return; 00079 00080 dwIndex = 0; 00081 while (TRUE) 00082 { 00083 dwNameSize = 256 * sizeof(WCHAR); 00084 lError = RegEnumKeyExW(hZonesKey, 00085 dwIndex, 00086 szKeyName, 00087 &dwNameSize, 00088 NULL, 00089 NULL, 00090 NULL, 00091 NULL); 00092 if (lError == ERROR_NO_MORE_ITEMS) 00093 break; 00094 00095 if (RegOpenKeyEx (hZonesKey, 00096 szKeyName, 00097 0, 00098 KEY_QUERY_VALUE, 00099 &hZoneKey)) 00100 break; 00101 00102 Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY)); 00103 if (Entry == NULL) 00104 { 00105 RegCloseKey(hZoneKey); 00106 break; 00107 } 00108 00109 dwValueSize = 64 * sizeof(WCHAR); 00110 lError = RegQueryValueExW(hZoneKey, 00111 L"Display", 00112 NULL, 00113 NULL, 00114 (LPBYTE)&Entry->Description, 00115 &dwValueSize); 00116 if (lError != ERROR_SUCCESS) 00117 { 00118 RegCloseKey(hZoneKey); 00119 dwIndex++; 00120 HeapFree(GetProcessHeap(), 0, Entry); 00121 continue; 00122 } 00123 00124 dwValueSize = 33 * sizeof(WCHAR); 00125 if (RegQueryValueExW(hZoneKey, 00126 L"Std", 00127 NULL, 00128 NULL, 00129 (LPBYTE)&Entry->StandardName, 00130 &dwValueSize)) 00131 { 00132 RegCloseKey(hZoneKey); 00133 break; 00134 } 00135 00136 dwValueSize = 33 * sizeof(WCHAR); 00137 if (RegQueryValueExW(hZoneKey, 00138 L"Dlt", 00139 NULL, 00140 NULL, 00141 (LPBYTE)&Entry->DaylightName, 00142 &dwValueSize)) 00143 { 00144 RegCloseKey(hZoneKey); 00145 break; 00146 } 00147 00148 dwValueSize = sizeof(DWORD); 00149 if (RegQueryValueExW(hZoneKey, 00150 L"Index", 00151 NULL, 00152 NULL, 00153 (LPBYTE)&Entry->Index, 00154 &dwValueSize)) 00155 { 00156 RegCloseKey(hZoneKey); 00157 break; 00158 } 00159 00160 dwValueSize = sizeof(TZ_INFO); 00161 if (RegQueryValueExW(hZoneKey, 00162 L"TZI", 00163 NULL, 00164 NULL, 00165 (LPBYTE)&Entry->TimezoneInfo, 00166 &dwValueSize)) 00167 { 00168 RegCloseKey(hZoneKey); 00169 break; 00170 } 00171 00172 RegCloseKey(hZoneKey); 00173 00174 if (TimeZoneListHead == NULL && 00175 TimeZoneListTail == NULL) 00176 { 00177 Entry->Prev = NULL; 00178 Entry->Next = NULL; 00179 TimeZoneListHead = Entry; 00180 TimeZoneListTail = Entry; 00181 } 00182 else 00183 { 00184 Current = GetLargerTimeZoneEntry(Entry->Index); 00185 if (Current != NULL) 00186 { 00187 if (Current == TimeZoneListHead) 00188 { 00189 /* Prepend to head */ 00190 Entry->Prev = NULL; 00191 Entry->Next = TimeZoneListHead; 00192 TimeZoneListHead->Prev = Entry; 00193 TimeZoneListHead = Entry; 00194 } 00195 else 00196 { 00197 /* Insert before current */ 00198 Entry->Prev = Current->Prev; 00199 Entry->Next = Current; 00200 Current->Prev->Next = Entry; 00201 Current->Prev = Entry; 00202 } 00203 } 00204 else 00205 { 00206 /* Append to tail */ 00207 Entry->Prev = TimeZoneListTail; 00208 Entry->Next = NULL; 00209 TimeZoneListTail->Next = Entry; 00210 TimeZoneListTail = Entry; 00211 } 00212 } 00213 00214 dwIndex++; 00215 } 00216 00217 RegCloseKey(hZonesKey); 00218 } 00219 00220 00221 static VOID 00222 DestroyTimeZoneList(VOID) 00223 { 00224 PTIMEZONE_ENTRY Entry; 00225 00226 while (TimeZoneListHead != NULL) 00227 { 00228 Entry = TimeZoneListHead; 00229 00230 TimeZoneListHead = Entry->Next; 00231 if (TimeZoneListHead != NULL) 00232 { 00233 TimeZoneListHead->Prev = NULL; 00234 } 00235 00236 HeapFree(GetProcessHeap(), 0, Entry); 00237 } 00238 00239 TimeZoneListTail = NULL; 00240 } 00241 00242 00243 static VOID 00244 ShowTimeZoneList(HWND hwnd) 00245 { 00246 TIME_ZONE_INFORMATION TimeZoneInfo; 00247 PTIMEZONE_ENTRY Entry; 00248 DWORD dwIndex; 00249 DWORD i; 00250 00251 GetTimeZoneInformation(&TimeZoneInfo); 00252 00253 dwIndex = 0; 00254 i = 0; 00255 Entry = TimeZoneListHead; 00256 while (Entry != NULL) 00257 { 00258 SendMessageW(hwnd, 00259 CB_ADDSTRING, 00260 0, 00261 (LPARAM)Entry->Description); 00262 00263 if (!wcscmp(Entry->StandardName, TimeZoneInfo.StandardName)) 00264 dwIndex = i; 00265 00266 i++; 00267 Entry = Entry->Next; 00268 } 00269 00270 SendMessageW(hwnd, 00271 CB_SETCURSEL, 00272 (WPARAM)dwIndex, 00273 0); 00274 } 00275 00276 00277 static VOID 00278 SetLocalTimeZone(HWND hwnd) 00279 { 00280 TIME_ZONE_INFORMATION TimeZoneInformation; 00281 PTIMEZONE_ENTRY Entry; 00282 DWORD dwIndex; 00283 DWORD i; 00284 00285 dwIndex = (DWORD)SendMessageW(hwnd, 00286 CB_GETCURSEL, 00287 0, 00288 0); 00289 00290 i = 0; 00291 Entry = TimeZoneListHead; 00292 while (i < dwIndex) 00293 { 00294 if (Entry == NULL) 00295 return; 00296 00297 i++; 00298 Entry = Entry->Next; 00299 } 00300 00301 wcscpy(TimeZoneInformation.StandardName, 00302 Entry->StandardName); 00303 wcscpy(TimeZoneInformation.DaylightName, 00304 Entry->DaylightName); 00305 00306 TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias; 00307 TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias; 00308 TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias; 00309 00310 memcpy(&TimeZoneInformation.StandardDate, 00311 &Entry->TimezoneInfo.StandardDate, 00312 sizeof(SYSTEMTIME)); 00313 memcpy(&TimeZoneInformation.DaylightDate, 00314 &Entry->TimezoneInfo.DaylightDate, 00315 sizeof(SYSTEMTIME)); 00316 00317 /* Set time zone information */ 00318 SetTimeZoneInformation(&TimeZoneInformation); 00319 } 00320 00321 00322 static VOID 00323 GetAutoDaylightInfo(HWND hwnd) 00324 { 00325 HKEY hKey; 00326 00327 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 00328 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", 00329 0, 00330 KEY_QUERY_VALUE, 00331 &hKey)) 00332 return; 00333 00334 /* If the call fails (non zero), the reg value isn't available, 00335 * which means it shouldn't be disabled, so we should check the button. 00336 */ 00337 if (RegQueryValueExW(hKey, 00338 L"DisableAutoDaylightTimeSet", 00339 NULL, 00340 NULL, 00341 NULL, 00342 NULL)) 00343 { 00344 SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 00345 } 00346 else 00347 { 00348 SendMessageW(hwnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); 00349 } 00350 00351 RegCloseKey(hKey); 00352 } 00353 00354 00355 static VOID 00356 SetAutoDaylightInfo(HWND hwnd) 00357 { 00358 HKEY hKey; 00359 DWORD dwValue = 1; 00360 00361 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 00362 L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", 00363 0, 00364 KEY_SET_VALUE, 00365 &hKey)) 00366 return; 00367 00368 if (SendMessageW(hwnd, BM_GETCHECK, 0, 0) == BST_UNCHECKED) 00369 { 00370 RegSetValueExW(hKey, 00371 L"DisableAutoDaylightTimeSet", 00372 0, 00373 REG_DWORD, 00374 (LPBYTE)&dwValue, 00375 sizeof(DWORD)); 00376 } 00377 else 00378 { 00379 RegDeleteValueW(hKey, 00380 L"DisableAutoDaylightTimeSet"); 00381 } 00382 00383 RegCloseKey(hKey); 00384 } 00385 00386 00387 /* Property page dialog callback */ 00388 INT_PTR CALLBACK 00389 TimeZonePageProc(HWND hwndDlg, 00390 UINT uMsg, 00391 WPARAM wParam, 00392 LPARAM lParam) 00393 { 00394 BITMAP bitmap; 00395 00396 switch (uMsg) 00397 { 00398 case WM_INITDIALOG: 00399 CreateTimeZoneList(); 00400 ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST)); 00401 GetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT)); 00402 hBitmap = LoadImageW(hApplet, MAKEINTRESOURCEW(IDC_WORLD), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 00403 if (hBitmap != NULL) 00404 { 00405 GetObjectW(hBitmap, sizeof(BITMAP), &bitmap); 00406 00407 cxSource = bitmap.bmWidth; 00408 cySource = bitmap.bmHeight; 00409 } 00410 break; 00411 00412 case WM_DRAWITEM: 00413 { 00414 LPDRAWITEMSTRUCT lpDrawItem; 00415 lpDrawItem = (LPDRAWITEMSTRUCT) lParam; 00416 if(lpDrawItem->CtlID == IDC_WORLD_BACKGROUND) 00417 { 00418 HDC hdcMem; 00419 hdcMem = CreateCompatibleDC(lpDrawItem->hDC); 00420 if (hdcMem != NULL) 00421 { 00422 SelectObject(hdcMem, hBitmap); 00423 StretchBlt(lpDrawItem->hDC, lpDrawItem->rcItem.left, lpDrawItem->rcItem.top, 00424 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left, 00425 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, 00426 hdcMem, 0, 0, cxSource, cySource, SRCCOPY); 00427 DeleteDC(hdcMem); 00428 } 00429 } 00430 } 00431 break; 00432 00433 case WM_COMMAND: 00434 if ((LOWORD(wParam) == IDC_TIMEZONELIST && HIWORD(wParam) == CBN_SELCHANGE) || 00435 (LOWORD(wParam) == IDC_AUTODAYLIGHT && HIWORD(wParam) == BN_CLICKED)) 00436 { 00437 /* Enable the 'Apply' button */ 00438 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 00439 } 00440 break; 00441 00442 case WM_DESTROY: 00443 DestroyTimeZoneList(); 00444 DeleteObject(hBitmap); 00445 break; 00446 00447 case WM_NOTIFY: 00448 { 00449 LPNMHDR lpnm = (LPNMHDR)lParam; 00450 00451 switch (lpnm->code) 00452 { 00453 case PSN_APPLY: 00454 { 00455 SetAutoDaylightInfo(GetDlgItem(hwndDlg, IDC_AUTODAYLIGHT)); 00456 SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST)); 00457 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR); 00458 return TRUE; 00459 } 00460 00461 default: 00462 break; 00463 } 00464 } 00465 break; 00466 } 00467 00468 return FALSE; 00469 } Generated on Sat May 26 2012 04:19:48 for ReactOS by
1.7.6.1
|