[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 4/4] XenAgent: Add options to time sync code
Adds registry overrided to control how and when XenAgent will update the system time. "TimeSyncMode" is a bit-field with the following options: 0b0000 = do not update system time 0b0001 = update after resume from suspend 0b0010 = update periodically 0b0100 = update when xeniface device detected (including on service start) Default is 0b0001 (after resume). "TimeSyncInterval" is the number of minutes between attempts to update system time. This only applies if "TimeSyncMode" contains 0b0010 Default is 30 minutes. Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx> --- src/xenagent/service.cpp | 6 +- src/xenagent/xenifacedevice.cpp | 144 +++++++++++++++++++++++++++++--- src/xenagent/xenifacedevice.h | 15 +++- 3 files changed, 149 insertions(+), 16 deletions(-) diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp index ec32ecc..3e30bb0 100644 --- a/src/xenagent/service.cpp +++ b/src/xenagent/service.cpp @@ -198,7 +198,7 @@ void CXenAgent::OnPowerEvent(DWORD evt, LPVOID data) bool CXenAgent::ServiceMainLoop() { - DWORD timeout = 30 * 60 * 1000; + DWORD timeout = 1 * 60 * 1000; HANDLE events[] = { m_svc_stop, m_xeniface.m_evt_shutdown, m_xeniface.m_evt_suspend, @@ -221,7 +221,7 @@ bool CXenAgent::ServiceMainLoop() case WAIT_OBJECT_0+2: ResetEvent(m_xeniface.m_evt_suspend); - m_xeniface.CheckXenTime(); + m_xeniface.CheckXenTime(XENIFACE_TIMESYNC_RESUME); m_xeniface.CheckSuspend(); return true; // continue loop @@ -239,7 +239,7 @@ bool CXenAgent::ServiceMainLoop() return true; // continue loop case WAIT_TIMEOUT: - m_xeniface.CheckXenTime(); + m_xeniface.CheckXenTime(XENIFACE_TIMESYNC_PERIODIC); __fallthrough; case WAIT_IO_COMPLETION: m_xeniface.CheckSuspend(); diff --git a/src/xenagent/xenifacedevice.cpp b/src/xenagent/xenifacedevice.cpp index 223d6e9..ffada25 100644 --- a/src/xenagent/xenifacedevice.cpp +++ b/src/xenagent/xenifacedevice.cpp @@ -43,6 +43,13 @@ #define DEFAULT_SHUTDOWN_RETRIES 5 #define DEFAULT_SHUTDOWN_RETRY_TIME 60 +#define XENAGENT_TIMESYNC_INTERVAL_DEFAULT 30 + +#define XENAGENT_SERVICE_KEY "SYSTEM\\CurrentControlSet\\Services\\xenagent" +#define XENAGENT_TIMESYNC_MODE "TimeSyncMode" +#define XENAGENT_TIMESYNC_INTERVAL "TimeSyncInterval" +#define XENAGENT_TIMESYNC_LAST "LastSyncFiletime" + CXenIfaceDevice::CXenIfaceDevice(const wchar_t* path) : CDevice(path) {} @@ -222,7 +229,7 @@ CXenIfaceDeviceList::CXenIfaceDeviceList(CXenAgent* agent) : CDeviceList(GUID_IN AdvertiseFeatures(device, true); - SetXenTime(device); + SetXenTime(device, XENIFACE_TIMESYNC_ADDED); } /*virtual*/ void CXenIfaceDeviceList::OnDeviceRemoved(CDevice* dev) @@ -352,7 +359,7 @@ void CXenIfaceDeviceList::CheckShutdownRetry() RequestSystemShutdown(); } -void CXenIfaceDeviceList::CheckXenTime() +void CXenIfaceDeviceList::CheckXenTime(DWORD reason) { CCritSec crit(&m_crit); CXenIfaceDevice* device = (CXenIfaceDevice*)GetFirstDevice(); @@ -360,7 +367,7 @@ void CXenIfaceDeviceList::CheckXenTime() if (device == NULL) return; - SetXenTime(device); + SetXenTime(device, reason); } void CXenIfaceDeviceList::CheckSuspend() @@ -543,28 +550,30 @@ void CXenIfaceDeviceList::AcquireShutdownPrivilege() CloseHandle(token); } -void CXenIfaceDeviceList::SetXenTime(CXenIfaceDevice* device) +void CXenIfaceDeviceList::SetXenTime(CXenIfaceDevice* device, DWORD reason) { - bool local; + XENIFACE_SHARED_TIME now; - FILETIME now = { 0 }; - if (!device->SharedInfoGetTime(&now, &local)) + if (!device->SharedInfoGetTime(&now.time, &now.local)) + return; + + if (!CheckXenTimeEnabled(reason, &now)) return; SYSTEMTIME cur = { 0 }; - if (local) + if (now.local) GetLocalTime(&cur); else GetSystemTime(&cur); SYSTEMTIME sys = { 0 }; - if (!FileTimeToSystemTime(&now, &sys)) + if (!FileTimeToSystemTime(&now.time, &sys)) return; if (memcmp(&cur, &sys, sizeof(SYSTEMTIME)) == 0) return; - CXenAgent::Log("RTC is in %s\n", local ? "local time" : "UTC"); + CXenAgent::Log("RTC is in %s\n", now.local ? "local time" : "UTC"); CXenAgent::Log("Time Now = %d/%d/%d %d:%02d:%02d.%d\n", cur.wYear, cur.wMonth, cur.wDay, cur.wHour, cur.wMinute, cur.wSecond, cur.wMilliseconds); @@ -572,8 +581,121 @@ void CXenIfaceDeviceList::SetXenTime(CXenIfaceDevice* device) sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds); - if (local) + if (now.local) SetLocalTime(&sys); else SetSystemTime(&sys); } + +static FORCEINLINE LONG64 +TimeDiff(FILETIME* old, FILETIME* now) +{ + ULONG64 ftOld; + ULONG64 ftNow; + LONG64 ftDiff; + + ftOld = ((ULONG64)old->dwHighDateTime) << 32 | + (ULONG64)old->dwLowDateTime; + + ftNow = ((ULONG64)now->dwHighDateTime) << 32 | + (ULONG64)now->dwLowDateTime; + + ftDiff = (LONG64)(ftNow - ftOld); + //From 100NS to whole minutes. + ftDiff /= (10 * 1000 * 1000 * 60); + return ftDiff; +} + +bool CXenIfaceDeviceList::CheckXenTimeEnabled(DWORD reason, PXENIFACE_SHARED_TIME now) +{ + HKEY key; + LONG lResult; + DWORD type; + DWORD size; + DWORD mode; + bool enabled; + + enabled = (reason == XENIFACE_TIMESYNC_RESUME); + + lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + XENAGENT_SERVICE_KEY, + 0, + KEY_READ, + &key); + if (lResult != ERROR_SUCCESS) + goto fail1; + + size = sizeof(DWORD); + lResult = RegQueryValueEx(key, + XENAGENT_TIMESYNC_MODE, + NULL, + &type, + (LPBYTE)&mode, + &size); + if (lResult != ERROR_SUCCESS) + goto fail2; + + if (type != REG_DWORD || + size != sizeof(DWORD)) + goto fail3; + + // mode is bit-flags, test for reason's bit + enabled = (mode & reason) != 0; + + if (reason == XENIFACE_TIMESYNC_PERIODIC && enabled) { + DWORD interval; + XENIFACE_SHARED_TIME last; + + // check interval has expired + size = sizeof(DWORD); + lResult = RegQueryValueEx(key, + XENAGENT_TIMESYNC_INTERVAL, + NULL, + &type, + (LPBYTE)&interval, + &size); + if (lResult != ERROR_SUCCESS || + type != REG_DWORD || + size != sizeof(DWORD)) + interval = XENAGENT_TIMESYNC_INTERVAL_DEFAULT; + + size = sizeof(XENIFACE_SHARED_TIME); + lResult = RegQueryValueEx(key, + XENAGENT_TIMESYNC_LAST, + NULL, + &type, + (LPBYTE)&last, + &size); + if (lResult == ERROR_SUCCESS || + type == REG_BINARY || + size == sizeof(XENIFACE_SHARED_TIME)) { + // check if time is within interval -> dont update time + if ((last.local == now->local) && + (TimeDiff(&last.time, &now->time) < interval)) { + enabled = false; + } + } + } + + if (enabled) { + lResult = RegSetValueEx(key, + XENAGENT_TIMESYNC_LAST, + 0, + REG_BINARY, + (LPBYTE)&now, + sizeof(XENIFACE_SHARED_TIME)); + if (lResult != ERROR_SUCCESS) + CXenAgent::Log("SetLastUpdateTime failed %08x\n", lResult); + } + + RegCloseKey(key); + + return enabled; + +fail3: +fail2: + RegCloseKey(key); + +fail1: + return enabled; +} \ No newline at end of file diff --git a/src/xenagent/xenifacedevice.h b/src/xenagent/xenifacedevice.h index 5a1aecf..4878db0 100644 --- a/src/xenagent/xenifacedevice.h +++ b/src/xenagent/xenifacedevice.h @@ -37,6 +37,16 @@ #include <string> #include "devicelist.h" +#define XENIFACE_TIMESYNC_NONE 0 +#define XENIFACE_TIMESYNC_RESUME 1 +#define XENIFACE_TIMESYNC_PERIODIC 2 +#define XENIFACE_TIMESYNC_ADDED 4 + +typedef struct _XENIFACE_SHARED_TIME { + FILETIME time; + bool local; +} XENIFACE_SHARED_TIME, *PXENIFACE_SHARED_TIME; + class CXenIfaceDevice : public CDevice { public: @@ -86,7 +96,7 @@ public: void Log(const char* message); bool CheckShutdown(); void CheckShutdownRetry(); - void CheckXenTime(); + void CheckXenTime(DWORD reason); void CheckSuspend(); bool CheckSlateMode(std::string& mode); void LogIfRebootPending(); @@ -99,7 +109,8 @@ private: void AdvertiseFeatures(CXenIfaceDevice* device, bool add); void RequestSystemShutdown(); void AcquireShutdownPrivilege(); - void SetXenTime(CXenIfaceDevice* device); + void SetXenTime(CXenIfaceDevice* device, DWORD reason); + bool CheckXenTimeEnabled(DWORD reason, PXENIFACE_SHARED_TIME now); private: CXenAgent* m_agent; -- 2.41.0.windows.3
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |