File indexing completed on 2024-04-28 16:54:29
0001 /* 0002 SPDX-FileCopyrightText: 2009 Till Adam <adam@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ktimezoned_win.moc" 0008 #include "ktimezonedbase.moc" 0009 0010 #include <climits> 0011 #include <cstdlib> 0012 0013 #include <QDBusConnection> 0014 #include <QDBusMessage> 0015 #include <QDebug> 0016 #include <QStringList> 0017 #include <QTextStream> 0018 #include <QThread> 0019 0020 #include <kcodecs.h> 0021 #include <kconfiggroup.h> 0022 #include <kdebug.h> 0023 #include <kglobal.h> 0024 #include <klocale.h> 0025 0026 #include <kpluginfactory.h> 0027 0028 #ifdef Q_OS_WIN 0029 #include <Windows.h> 0030 #endif 0031 0032 K_PLUGIN_CLASS_WITH_JSON(KTimeZoned, "ktimezoned.json") 0033 0034 // Config file entry names 0035 const char LOCAL_ZONE[] = "LocalZone"; // name of local time zone 0036 static const TCHAR currentTimeZoneKey[] = TEXT("System\\CurrentControlSet\\Control\\TimeZoneInformation"); 0037 0038 class RegistryWatcherThread : public QThread 0039 { 0040 public: 0041 RegistryWatcherThread(KTimeZoned *parent) 0042 : QThread(parent) 0043 , q(parent) 0044 { 0045 } 0046 0047 ~RegistryWatcherThread() 0048 { 0049 RegCloseKey(key); 0050 } 0051 0052 void run() 0053 { 0054 // FIXME: the timezonechange needs to be handled differently 0055 #ifndef _WIN32 0056 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, currentTimeZoneKey, 0, KEY_READ, &key) == ERROR_SUCCESS) { 0057 while (true) { 0058 RegNotifyChangeKeyValue(key, true, REG_NOTIFY_CHANGE_LAST_SET, NULL, false /*async, we want it to block*/); 0059 q->updateLocalZone(); 0060 } 0061 } 0062 #endif 0063 } 0064 0065 private: 0066 KTimeZoned *q; 0067 HKEY key; 0068 }; 0069 0070 KTimeZoned::KTimeZoned(QObject *parent, const QList<QVariant> &l) 0071 : KTimeZonedBase(parent, l) 0072 , mRegistryWatcherThread(0) 0073 { 0074 init(false); 0075 } 0076 0077 KTimeZoned::~KTimeZoned() 0078 { 0079 if (mRegistryWatcherThread) { 0080 mRegistryWatcherThread->quit(); 0081 mRegistryWatcherThread->wait(100); 0082 } 0083 delete mRegistryWatcherThread; 0084 } 0085 0086 void KTimeZoned::init(bool restart) 0087 { 0088 if (restart) { 0089 qDebug() << "KTimeZoned::init(restart)"; 0090 delete mRegistryWatcherThread; 0091 mRegistryWatcherThread = 0; 0092 } 0093 0094 KConfig config(QLatin1String("ktimezonedrc")); 0095 if (restart) 0096 config.reparseConfiguration(); 0097 KConfigGroup group(&config, "TimeZones"); 0098 mConfigLocalZone = group.readEntry(LOCAL_ZONE); 0099 0100 updateLocalZone(); 0101 if (!mRegistryWatcherThread) { 0102 mRegistryWatcherThread = new RegistryWatcherThread(this); 0103 mRegistryWatcherThread->start(); 0104 } 0105 } 0106 0107 // Check if the local zone has been updated, and if so, write the new 0108 // zone to the config file and notify interested parties. 0109 void KTimeZoned::updateLocalZone() 0110 { 0111 // On Windows, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones 0112 // holds the time zone database. The TZI binary value is the TIME_ZONE_INFORMATION structure. 0113 0114 TIME_ZONE_INFORMATION tzinfo; 0115 DWORD res = GetTimeZoneInformation(&tzinfo); 0116 if (res == TIME_ZONE_ID_INVALID) 0117 return; // hm 0118 mLocalZone = QString::fromUtf16(reinterpret_cast<ushort *>(tzinfo.StandardName)); 0119 0120 if (mConfigLocalZone != mLocalZone) { 0121 qDebug() << "Local timezone is now: " << mLocalZone; 0122 KConfig config(QLatin1String("ktimezonedrc")); 0123 KConfigGroup group(&config, "TimeZones"); 0124 mConfigLocalZone = mLocalZone; 0125 group.writeEntry(LOCAL_ZONE, mConfigLocalZone); 0126 group.sync(); 0127 0128 QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "timeZoneChanged"); 0129 QDBusConnection::sessionBus().send(message); 0130 } 0131 }