From bf37d6655a27cc3ea5af5412c9717596c9d1c30f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 19 Jun 2015 18:18:13 +0000 Subject: timezone api migrated to mir_core git-svn-id: http://svn.miranda-ng.org/main/trunk@14266 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_core/src/mir_core.def | 16 ++ src/mir_core/src/mir_core64.def | 16 ++ src/mir_core/src/miranda.cpp | 14 +- src/mir_core/src/stdafx.h | 2 + src/mir_core/src/timezones.cpp | 587 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 625 insertions(+), 10 deletions(-) create mode 100644 src/mir_core/src/timezones.cpp (limited to 'src/mir_core') diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def index f693d41233..70ee0c1c1d 100644 --- a/src/mir_core/src/mir_core.def +++ b/src/mir_core/src/mir_core.def @@ -953,3 +953,19 @@ Utils_AssertInsideScreen @1110 Utils_RestoreWindowPosition @1111 Utils_SaveWindowPosition @1112 mir_getLP @1113 +TimeZone_CreateByContact @1114 +TimeZone_CreateByName @1115 +TimeZone_GetDescription @1116 +TimeZone_GetInfo @1117 +TimeZone_GetName @1118 +TimeZone_GetTimeZoneTime @1119 +TimeZone_PrepareList @1120 +TimeZone_PrintDateTime @1121 +TimeZone_PrintTimeStamp @1122 +TimeZone_SelectListItem @1123 +TimeZone_StoreByContact @1124 +TimeZone_StoreListResult @1125 +TimeZone_ToLocal @1126 +TimeZone_ToString @1127 +TimeZone_ToStringW @1128 +TimeZone_UtcToLocal @1129 diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def index eadbef2572..cc345a6ca8 100644 --- a/src/mir_core/src/mir_core64.def +++ b/src/mir_core/src/mir_core64.def @@ -953,3 +953,19 @@ Utils_AssertInsideScreen @1110 Utils_RestoreWindowPosition @1111 Utils_SaveWindowPosition @1112 mir_getLP @1113 +TimeZone_CreateByContact @1114 +TimeZone_CreateByName @1115 +TimeZone_GetDescription @1116 +TimeZone_GetInfo @1117 +TimeZone_GetName @1118 +TimeZone_GetTimeZoneTime @1119 +TimeZone_PrepareList @1120 +TimeZone_PrintDateTime @1121 +TimeZone_PrintTimeStamp @1122 +TimeZone_SelectListItem @1123 +TimeZone_StoreByContact @1124 +TimeZone_StoreListResult @1125 +TimeZone_ToLocal @1126 +TimeZone_ToString @1127 +TimeZone_ToStringW @1128 +TimeZone_UtcToLocal @1129 diff --git a/src/mir_core/src/miranda.cpp b/src/mir_core/src/miranda.cpp index 53091dc2c9..fa99d1d8db 100644 --- a/src/mir_core/src/miranda.cpp +++ b/src/mir_core/src/miranda.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. HWND hAPCWindow = NULL; int InitPathUtils(void); -void (*RecalculateTime)(void); +void RecalculateTime(void); void CheckLogs(); void InitLogs(); @@ -36,6 +36,7 @@ void UninitLogs(); void InitWinver(); void InitMetaContacts(); +void InitTimeZones(); int hLangpack = 0; HINSTANCE hInst = 0; @@ -57,7 +58,7 @@ static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP if (msg == WM_TIMER) CheckLogs(); - if (msg == WM_TIMECHANGE && RecalculateTime) + if (msg == WM_TIMECHANGE) RecalculateTime(); return DefWindowProc(hwnd, msg, wParam, lParam); @@ -73,7 +74,6 @@ static void LoadCoreModule(void) hAPCWindow = CreateWindowEx(0, _T("ComboLBox"), NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); DestroyWindow(hAPCWindow); - hAPCWindow = NULL; hAPCWindow = CreateWindowEx(0, _T("STATIC"), NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); @@ -81,16 +81,10 @@ static void LoadCoreModule(void) hStackMutex = CreateMutex(NULL, FALSE, NULL); hThreadQueueEmpty = CreateEvent(NULL, TRUE, TRUE, NULL); - #ifdef _WIN64 - HMODULE mirInst = GetModuleHandleA("miranda64.exe"); - #else - HMODULE mirInst = GetModuleHandleA("miranda32.exe"); - #endif - RecalculateTime = (void (*)()) GetProcAddress(mirInst, "RecalculateTime"); - InitWinver(); InitPathUtils(); InitLogs(); + InitTimeZones(); InitialiseModularEngine(); InitMetaContacts(); } diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h index 359230ab17..eb5f1ac352 100644 --- a/src/mir_core/src/stdafx.h +++ b/src/mir_core/src/stdafx.h @@ -57,6 +57,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include +#include #include "miranda.h" diff --git a/src/mir_core/src/timezones.cpp b/src/mir_core/src/timezones.cpp new file mode 100644 index 0000000000..b9510f2a71 --- /dev/null +++ b/src/mir_core/src/timezones.cpp @@ -0,0 +1,587 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +implements services to handle location - based timezones, instead of +simple UTC offsets. +*/ + +#include "stdafx.h" + +typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi); +static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation; + +struct REG_TZI_FORMAT +{ + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +}; + +#define MIM_TZ_DISPLAYLEN 128 + +struct MIM_TIMEZONE +{ + unsigned hash; + int offset; + + TCHAR tszName[MIM_TZ_NAMELEN]; // windows name for the time zone + wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs) + // every hour should be sufficient. + TIME_ZONE_INFORMATION tzi; + + static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2) + { return p2->tzi.Bias - p1->tzi.Bias; + } +}; + +struct TZ_INT_INFO +{ + DWORD timestamp; // last time updated + MIM_TIMEZONE myTZ; // set to my own timezone +}; + +static TZ_INT_INFO myInfo; + +static OBJLIST g_timezones(55, NumericKeySortT); +static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); + +// KB167296 +void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) +{ + unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = ll >> 32; +} + +mir_time FileTimeToUnixTime(LPFILETIME pft) +{ + unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime; + ll -= 116444736000000000i64; + return (mir_time)(ll / 10000000); +} + +void FormatTime(const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, size_t cbDest) +{ + if (szDest == NULL || cbDest == 0) return; + + CMString tszTemp; + + for (const TCHAR* pFormat = szFormat; *pFormat; ++pFormat) { + DWORD fmt = 0; + bool date = false, iso = false; + switch (*pFormat) { + case 't': + fmt = TIME_NOSECONDS; + date = false; + break; + + case 's': + fmt = 0; + date = false; + break; + + case 'm': + fmt = TIME_NOMINUTESORSECONDS; + date = false; + break; + + case 'd': + fmt = DATE_SHORTDATE; + date = true; + break; + + case 'D': + fmt = DATE_LONGDATE; + date = true; + break; + + case 'I': + iso = true; + break; + + default: + tszTemp.AppendChar(*pFormat); + continue; + } + + TCHAR dateTimeStr[64]; + if (iso) + tszTemp.AppendFormat(_T("%d-%02d-%02dT%02d:%02d:%02dZ"), st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond); + else if (date) { + GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + else { + GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + } + + _tcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE); +} + +#define fnSystemTimeToTzSpecificLocalTime SystemTimeToTzSpecificLocalTime + +MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st) +{ + if (st == NULL) return 1; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == UTC_TIME_HANDLE) + GetSystemTime(st); + else if (tz && tz != &myInfo.myTZ) { + SYSTEMTIME sto; + GetSystemTime(&sto); + return !fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st); + } + else + GetLocalTime(st); + + return 0; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL) + return myInfo.myTZ.tszName; + else if (tz == UTC_TIME_HANDLE) + return _T("UTC"); + + return tz->tszName; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname) +{ + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + + if (!mir_tstrcmp(tz->tszName, TZname)) + return tz->szDisplay; + } + return _T(""); +} + +static void CalcTsOffset(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + GetSystemTime(&st); + + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + mir_time ts1 = FileTimeToUnixTime(&ft); + + if (!fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl)) + return; + + SystemTimeToFileTime(&stl, &ft); + mir_time ts2 = FileTimeToUnixTime(&ft); + + tz->offset = ts2 - ts1; +} + +static bool IsSameTime(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + + if (tz == &myInfo.myTZ) + return true; + + TimeZone_GetTimeZoneTime(tz, &stl); + TimeZone_GetTimeZoneTime(NULL, &st); + + return st.wHour == stl.wHour && st.wMinute == stl.wMinute; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags) +{ + if (tszName == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (mir_tstrcmp(myInfo.myTZ.tszName, tszName) == 0) + return (dwFlags & TZF_DIFONLY) ? NULL : &myInfo.myTZ; + + MIM_TIMEZONE tzsearch; + tzsearch.hash = mir_hashstrT(tszName); + + MIM_TIMEZONE *tz = g_timezones.find(&tzsearch); + if (tz == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (dwFlags & TZF_DIFONLY) + return IsSameTime(tz) ? NULL : tz; + + return tz; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags) +{ + if (hContact == NULL && szModule == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (szModule == NULL) szModule = "UserInfo"; + + DBVARIANT dbv; + if (!db_get_ts(hContact, szModule, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.ptszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + + signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1); + if (timezone == -1) { + char *szProto = GetContactProto(hContact); + if (!db_get_ts(hContact, szProto, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.ptszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1); + } + + if (timezone != -1) { + MIM_TIMEZONE tzsearch; + tzsearch.tzi.Bias = timezone * 30; + if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) { + if (dwFlags & TZF_DIFONLY) return NULL; + return &myInfo.myTZ; + } + + int i = g_timezonesBias.getIndex(&tzsearch); + while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i; + + int delta = LONG_MAX; + for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) { + int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth); + if (delta1 <= delta) { + delta = delta1; + i = j; + } + } + + if (i >= 0) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? NULL : tz; + } + } + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; +} + +MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ) +{ + if (szModule == NULL) szModule = "UserInfo"; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz) { + db_set_ts(hContact, szModule, "TzName", tz->tszName); + db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30)); + } + else { + db_unset(hContact, szModule, "TzName"); + db_unset(hContact, szModule, "Timezone"); + } +} + +MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) + return 1; + + SYSTEMTIME st; + if (TimeZone_GetTimeZoneTime(tz, &st)) + return 1; + + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) + return 1; + + if (tz == NULL) + tz = &myInfo.myTZ; + + FILETIME ft; + if (tz == UTC_TIME_HANDLE) + UnixTimeToFileTime(ts, &ft); + else { + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + UnixTimeToFileTime(ts + tz->offset, &ft); + } + + SYSTEMTIME st; + FileTimeToSystemTime(&ft, &st); + + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + return tz ? &tz->tzi : &myInfo.myTZ.tzi; +} + +MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL) + tz = &myInfo.myTZ; + + if (tz == UTC_TIME_HANDLE) + return ts; + + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + return ts + tz->offset; +} + +/////////////////////////////////////////////////////////////////////////////// + +struct ListMessages +{ + UINT addStr, getSel, setSel, getData, setData; +}; + +static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA }; +static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA }; + +static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags) +{ + if (hWnd == NULL) + return NULL; + + if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) { + TCHAR tszClassName[128]; + GetClassName(hWnd, tszClassName, SIZEOF(tszClassName)); + if (!mir_tstrcmpi(tszClassName, _T("COMBOBOX"))) + dwFlags |= TZF_PLF_CB; + else if (!mir_tstrcmpi(tszClassName, _T("LISTBOX"))) + dwFlags |= TZF_PLF_LB; + } + if (dwFlags & TZF_PLF_CB) + return &cbMessages; + else if (dwFlags & TZF_PLF_LB) + return &lbMessages; + else + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == NULL) + return -1; + + if (szModule == NULL) szModule = "UserInfo"; + + int iSelection = 0; + ptrT tszName(db_get_tsa(hContact, szModule, "TzName")); + if (tszName != NULL) { + unsigned hash = mir_hashstrT(tszName); + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + if (hash == g_timezonesBias[i]->hash) { + iSelection = i + 1; + break; + } + } + } + else { + signed char cBias = db_get_b(hContact, szModule, "Timezone", -100); + if (cBias != -100) { + int iBias = cBias * 30; + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + if (iBias == g_timezonesBias[i]->tzi.Bias) { + iSelection = i + 1; + break; + } + } + } + } + + SendMessage(hWnd, lstMsg->setSel, iSelection, 0); + return iSelection; +} + +MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == NULL) + return 0; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateT("")); + + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)tz->szDisplay); + SendMessage(hWnd, lstMsg->setData, i + 1, (LPARAM)tz); + } + + return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags); +} + +MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + if (szModule == NULL) szModule = "UserInfo"; + + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg) { + LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0); + if (offset > 0) { + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0); + if ((INT_PTR)tz != CB_ERR && tz != NULL) + TimeZone_StoreByContact(hContact, szModule, tz); + } + else TimeZone_StoreByContact(hContact, szModule, NULL); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal) +{ + return TimeZone_UtcToLocal(NULL, (mir_time)timeVal); +} + +MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest) +{ + TCHAR *szTemp = (TCHAR*)alloca(cchDest*sizeof(TCHAR)); + TimeZone_PrintTimeStamp(NULL, timeVal, _A2T(szFormat), szTemp, cchDest, 0); + WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, NULL, NULL); + return szDest; +} + +MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest) +{ + TimeZone_PrintTimeStamp(NULL, timeVal, wszFormat, wszDest, cchDest, 0); + return wszDest; +} + +/////////////////////////////////////////////////////////////////////////////// + +void GetLocalizedString(HKEY hSubKey, const TCHAR *szName, wchar_t *szBuf, DWORD cbLen) +{ + DWORD dwLength = cbLen * sizeof(wchar_t); + RegQueryValueEx(hSubKey, szName, NULL, NULL, (unsigned char *)szBuf, &dwLength); + szBuf[min(dwLength / sizeof(TCHAR), cbLen - 1)] = 0; +} + +void RecalculateTime(void) +{ + GetTimeZoneInformation(&myInfo.myTZ.tzi); + myInfo.timestamp = time(NULL); + myInfo.myTZ.offset = INT_MIN; + + bool found = false; + DYNAMIC_TIME_ZONE_INFORMATION dtzi; + + if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) { + TCHAR *myTzKey = mir_u2t(dtzi.TimeZoneKeyName); + _tcsncpy_s(myInfo.myTZ.tszName, myTzKey, _TRUNCATE); + mir_free(myTzKey); + found = true; + } + + for (int i = 0; i < g_timezones.getCount(); i++) { + MIM_TIMEZONE &tz = g_timezones[i]; + if (tz.offset != INT_MIN) + tz.offset = INT_MIN; + + if (!found) { + if (!mir_wstrcmp(tz.tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz.tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) { + _tcsncpy_s(myInfo.myTZ.tszName, tz.tszName, _TRUNCATE); + found = true; + } + } + } +} + +void InitTimeZones(void) +{ + REG_TZI_FORMAT tzi; + HKEY hKey; + + const TCHAR *tszKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"); + + /* + * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with + * the registry key name, so finding our own time zone later will be MUCH easier for + * localized systems or systems with a MUI pack installed + */ + if (IsWinVerVistaPlus()) + pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetDynamicTimeZoneInformation"); + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) { + DWORD dwIndex = 0; + HKEY hSubKey; + TCHAR tszName[MIM_TZ_NAMELEN]; + + DWORD dwSize = SIZEOF(tszName); + while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, NULL, NULL, 0, NULL)) { + if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) { + dwSize = sizeof(tszName); + + DWORD dwLength = sizeof(tzi); + if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, _T("TZI"), NULL, NULL, (unsigned char *)&tzi, &dwLength)) + continue; + + MIM_TIMEZONE *tz = new MIM_TIMEZONE; + + tz->tzi.Bias = tzi.Bias; + tz->tzi.StandardDate = tzi.StandardDate; + tz->tzi.StandardBias = tzi.StandardBias; + tz->tzi.DaylightDate = tzi.DaylightDate; + tz->tzi.DaylightBias = tzi.DaylightBias; + + mir_tstrcpy(tz->tszName, tszName); + tz->hash = mir_hashstrT(tszName); + tz->offset = INT_MIN; + + GetLocalizedString(hSubKey, _T("Display"), tz->szDisplay, SIZEOF(tz->szDisplay)); + GetLocalizedString(hSubKey, _T("Std"), tz->tzi.StandardName, SIZEOF(tz->tzi.StandardName)); + GetLocalizedString(hSubKey, _T("Dlt"), tz->tzi.DaylightName, SIZEOF(tz->tzi.DaylightName)); + + g_timezones.insert(tz); + g_timezonesBias.insert(tz); + + RegCloseKey(hSubKey); + } + dwSize = SIZEOF(tszName); + } + RegCloseKey(hKey); + } + + RecalculateTime(); +} -- cgit v1.2.3