From c992cb2fdc11f1cac4bc5cbce26e8e2bb3b57da0 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 26 Jun 2012 16:50:14 +0000 Subject: - microkernel addded; - version bumped to 0.92.2 git-svn-id: http://svn.miranda-ng.org/main/trunk@641 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/mir_core/timezones.cpp | 224 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 plugins/mir_core/timezones.cpp (limited to 'plugins/mir_core/timezones.cpp') diff --git a/plugins/mir_core/timezones.cpp b/plugins/mir_core/timezones.cpp new file mode 100644 index 0000000000..24340cd3d8 --- /dev/null +++ b/plugins/mir_core/timezones.cpp @@ -0,0 +1,224 @@ +/* +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2010 Miranda ICQ/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 "commonheaders.h" + +#include + +typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi); +static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation; + +typedef HRESULT (WINAPI *pfnSHLoadIndirectString_t)(LPCWSTR pszSource, LPWSTR pszOutBuf, UINT cchOutBuf, void **ppvReserved); +static pfnSHLoadIndirectString_t pfnSHLoadIndirectString; + +typedef LANGID (WINAPI *pfnGetUserDefaultUILanguage_t)(void); +static pfnGetUserDefaultUILanguage_t pfnGetUserDefaultUILanguage; + +typedef LANGID (WINAPI *pfnGetSystemDefaultUILanguage_t)(void); +static pfnGetSystemDefaultUILanguage_t pfnGetSystemDefaultUILanguage; + +typedef LPARAM (WINAPI *pfnSendMessageW_t)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); +static pfnSendMessageW_t pfnSendMessageW; + +typedef struct _REG_TZI_FORMAT +{ + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +} REG_TZI_FORMAT; + +#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; } +}; + +typedef struct +{ + DWORD timestamp; // last time updated + MIM_TIMEZONE myTZ; // set to my own timezone +} TZ_INT_INFO; + +static TZ_INT_INFO myInfo; +bool muiInstalled; + +static OBJLIST g_timezones(55, NumericKeySortT); +static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); + +void FormatTime (const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, int cbDest); +void UnixTimeToFileTime(time_t ts, LPFILETIME pft); +time_t FileTimeToUnixTime(LPFILETIME pft); + +#define fnSystemTimeToTzSpecificLocalTime SystemTimeToTzSpecificLocalTime + +void GetLocalizedString(HKEY hSubKey, const TCHAR *szName, wchar_t *szBuf, DWORD cbLen) +{ + szBuf[0] = 0; + if (muiInstalled) + { + TCHAR tszTempBuf[MIM_TZ_NAMELEN], tszName[30]; + mir_sntprintf(tszName, SIZEOF(tszName), _T("MUI_%s"), szName); + DWORD dwLength = cbLen * sizeof(TCHAR); + if (ERROR_SUCCESS == RegQueryValueEx(hSubKey, tszName, NULL, NULL, (unsigned char *)tszTempBuf, &dwLength)) + { + tszTempBuf[min(dwLength / sizeof(TCHAR), cbLen - 1)] = 0; + if (pfnSHLoadIndirectString) + pfnSHLoadIndirectString(StrConvU(tszTempBuf), szBuf, cbLen, NULL); + } + } + if (szBuf[0] == 0) + { + 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); + _tcscpy(myInfo.myTZ.tszName, myTzKey); + 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 ( !wcscmp(tz.tzi.StandardName, myInfo.myTZ.tzi.StandardName) || + !wcscmp(tz.tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) + { + _tcscpy(myInfo.myTZ.tszName, tz.tszName); + found = true; + } + } + } +} + +void InitTimeZones(void) +{ + REG_TZI_FORMAT tzi; + HKEY hKey; + + const TCHAR *tszKey = IsWinVerNT() ? + _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones") : + _T("SOFTWARE\\Microsoft\\Windows\\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 (IsWinVer2000Plus()) + { + pfnSHLoadIndirectString = (pfnSHLoadIndirectString_t)GetProcAddress(GetModuleHandle(_T("shlwapi")), "SHLoadIndirectString"); + pfnGetSystemDefaultUILanguage = (pfnGetSystemDefaultUILanguage_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetSystemDefaultUILanguage"); + pfnGetUserDefaultUILanguage = (pfnGetUserDefaultUILanguage_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetUserDefaultUILanguage"); + muiInstalled = pfnSHLoadIndirectString && pfnGetSystemDefaultUILanguage() != pfnGetUserDefaultUILanguage(); + } + + pfnSendMessageW = (pfnSendMessageW_t)GetProcAddress(GetModuleHandle(_T("user32")), "SendMessageW"); + + 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; + + _tcscpy(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(); +} + +void UninitTimeZones(void) +{ + g_timezonesBias.destroy(); + g_timezones.destroy(); +} -- cgit v1.2.3