[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 13/20] Add SetXenTime functionality



Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/liteagent/LiteAgent.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++--
 src/liteagent/LiteAgent.h   |   3 ++
 2 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/src/liteagent/LiteAgent.cpp b/src/liteagent/LiteAgent.cpp
index 480447d..b61967f 100644
--- a/src/liteagent/LiteAgent.cpp
+++ b/src/liteagent/LiteAgent.cpp
@@ -36,6 +36,12 @@
 #include "LiteAgent.h"
 #include "xeniface_ioctls.h"
 
+#define XENTOOLS_INSTALL_REG_KEY   "SOFTWARE\\Citrix\\XenTools"
+
+#ifdef _WIN64
+#define XENTOOLS_INSTALL_REG_KEY64 "SOFTWARE\\Wow6432Node\\Citrix\\XenTools"
+#endif
+
 int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE ignore, LPSTR lpCmdLine, 
int nCmdShow)
 {
     if (strlen(lpCmdLine) != 0) {
@@ -205,7 +211,6 @@ CLiteAgent::~CLiteAgent()
 {
     CLiteAgent::Log("OnDeviceRemoved(%ws)\n", dev->Path());
     if ((CXenIfaceItf*)dev == m_dev) {
-        m_dev = NULL;
         // active device removed
         CLiteAgent::Log("Active Device Removed\n");
 
@@ -220,6 +225,9 @@ CLiteAgent::~CLiteAgent()
         // unregister watch
         m_dev->StoreRemoveWatch(m_ctxt_shutdown);
         m_ctxt_shutdown = NULL;
+
+        // remove internal reference
+        m_dev = NULL;
     }
 }
 
@@ -246,6 +254,7 @@ bool CLiteAgent::ServiceMainLoop()
     DWORD   wait = WaitForMultipleObjects(3, evts, FALSE, INFINITE);
     switch (wait) {
     case WAIT_OBJECT_0:
+        CLiteAgent::Log("Stop event set\n");
         return false; // service stop event
 
     case WAIT_OBJECT_0+1:
@@ -272,7 +281,6 @@ void CLiteAgent::OnShutdown()
     std::string type;
     m_dev->StoreRead("control/shutdown", type);
 
-
     CLiteAgent::Log("OnShutdown(%s)\n", type.c_str());
 }
 
@@ -293,17 +301,119 @@ void CLiteAgent::OnSuspend()
 void CLiteAgent::SetXenTime()
 {
     CLiteAgent::Log("SetXenTime()\n");
+
+    FILETIME now = { 0 };
+    if (!m_dev->SharedInfoGetTime(&now))
+        return;
+
+    bool IsUtc = HostTimeIsUtc();
+    if (IsUtc)
+        AdjustXenTimeToUtc(&now);
+
+    SYSTEMTIME sys = { 0 };
+    if (!FileTimeToSystemTime(&now, &sys))
+        return;
+
+    SYSTEMTIME cur = { 0 };
+    GetLocalTime(&cur);
+    CLiteAgent::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);
+    CLiteAgent::Log("New Time = %d/%d/%d %d:%02d:%02d.%d\n",
+                    sys.wYear, sys.wMonth, sys.wDay,
+                    sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
+    if (IsUtc)
+        SetSystemTime(&sys);
+    else
+        SetLocalTime(&sys);
 }
 
 void CLiteAgent::KickXapi()
 {
     char value[32];
-    _snprintf_s(value, sizeof(value), 31, "%I64d", m_update);
+    _snprintf_s(value, sizeof(value), 31, "%I64d", (__int64)m_update);
     m_dev->StoreWrite("data/update_cnt", value);
     m_dev->StoreWrite("data/updated", "1");
     ++m_update;
 }
 
+bool CLiteAgent::HostTimeIsUtc()
+{
+#ifdef _WIN64
+    if (RegMatchStr(XENTOOLS_INSTALL_REG_KEY64, "HostTime", "UTC"))
+        return true;
+#endif
+    if (RegMatchStr(XENTOOLS_INSTALL_REG_KEY, "HostTime", "UTC"))
+        return true;
+
+    return false;
+}
+
+void CLiteAgent::AdjustXenTimeToUtc(FILETIME* now)
+{
+    std::string vm;
+    if (!m_dev->StoreRead("vm", vm))
+        return;
+
+    std::string offs;
+    if (!m_dev->StoreRead(vm + "/rtc/timeoffset", offs)) {
+        if (!m_dev->StoreRead("platform/timeoffset", offs))
+            return;
+    }
+
+    long offset = (long)atoi(offs.c_str());
+
+    LARGE_INTEGER loffs;
+    loffs.QuadPart = (LONGLONG)offset * 1000000;
+
+    ULARGE_INTEGER lnow;
+    lnow.LowPart  = now->dwLowDateTime;
+    lnow.HighPart = now->dwHighDateTime;
+
+    lnow.QuadPart -= loffs.QuadPart;
+
+    now->dwLowDateTime  = lnow.LowPart;
+    now->dwHighDateTime = lnow.HighPart;
+}
+
+bool CLiteAgent::RegMatchStr(const char* path, const char* name, const char* 
value)
+{
+    HKEY        key;
+    LRESULT     lr;
+    bool        match = false;
+
+    lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &key);
+    if (lr != ERROR_SUCCESS)
+        return false;
+
+    long        size = 32;
+    DWORD       length;
+    char*       buffer = NULL;
+    do {
+        length = size;
+        if (buffer)
+            delete [] buffer;
+
+        buffer = new char[size];
+        if (buffer == NULL)
+            goto done;
+
+        lr = RegQueryValueEx(key, name, NULL, NULL, (LPBYTE)buffer, &length);
+        size *= 2;
+    } while (lr == ERROR_MORE_DATA);
+    if (lr != ERROR_SUCCESS)
+        goto done;
+    if (_strnicoll(value, buffer, length))
+        goto done;
+    match = true;
+
+done:
+    if (buffer)
+        delete [] buffer;
+    RegCloseKey(key);
+    return match;
+}
+
 void CLiteAgent::SetServiceStatus(DWORD state, DWORD exit /*= 0*/, DWORD hint 
/*= 0*/)
 {
     m_status.dwCurrentState = state;
diff --git a/src/liteagent/LiteAgent.h b/src/liteagent/LiteAgent.h
index 8ab062a..97c6514 100644
--- a/src/liteagent/LiteAgent.h
+++ b/src/liteagent/LiteAgent.h
@@ -72,6 +72,9 @@ private: // service events
     void OnSuspend();
     void SetXenTime();
     void KickXapi();
+    bool HostTimeIsUtc();
+    void AdjustXenTimeToUtc(FILETIME* now);
+    bool RegMatchStr(const char* path, const char* name, const char* value);
 
 private: // service support
     void SetServiceStatus(DWORD state, DWORD exit = 0, DWORD hint = 0);
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.