]> xenbits.xensource.com Git - pvdrivers/win/xeniface.git/commitdiff
[CAR-1423] Port UTC hostime / timezone support to lite agent
authorBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 31 Dec 2013 11:13:15 +0000 (11:13 +0000)
committerBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 31 Dec 2013 11:13:15 +0000 (11:13 +0000)
src/win32stubagent/XSAccessor.cpp
src/win32stubagent/XSAccessor.h
src/win32stubagent/XService.cpp

index da730aef57d9508d033a7138cd7ace4ab42aec8d..cdf1d4ab327020a1c32b8b565a25b6fc33525e6d 100644 (file)
@@ -186,6 +186,21 @@ XenstoreRead(const char* path, char** value)
         return -1;
 }
 
+
+bool XenstoreReadDword(const char *path, DWORD *value) {
+    char* buffer;
+    size_t len;
+    len = XenstoreRead(path, &buffer);
+    if (len <= 0) {
+        return false;
+    }
+    *value = atoi(buffer);
+
+    XsFree(buffer);
+
+    return true;
+}
+
 void *
 XenstoreWatch(const char *path, HANDLE event, HANDLE errorevent)
 {
index 64a6e63b2956b191ae2cef58bb21abaf76316da0..2ed41b0243f60087cfe6830c44afeeed3b216567 100644 (file)
@@ -62,6 +62,7 @@ void XsLog(const char *fmt, ...);
 void XenstoreFree(void *tofree);
 void *XsAlloc(size_t size);
 void XsFree(const void *buf);
+bool XenstoreReadDword(const char * path, DWORD *value);
 
 #if DBG
 
index f15889e7a08a26550a26d6f84d96a5ba14dbd4f4..d49d25b81b5c03b175b2b02ff140907acd879a36 100644 (file)
@@ -137,6 +137,19 @@ static void FreeString(const char *string)
     free((void *)string);
 }
 
+static char* PrintfString(const char *fmt, ...){
+    va_list l;
+    va_start(l, fmt);
+    int numchars = _vscprintf(fmt, l);
+    char *outputstring = (char *)calloc(numchars + 1, sizeof(char));
+
+    if (outputstring == NULL)
+        return NULL;
+
+    _vsnprintf(outputstring, numchars, fmt, l);
+    return outputstring;
+}
+
 static struct watch_event *
 EstablishWatch(const char *path, HANDLE errorevent)
 {
@@ -518,21 +531,139 @@ out:
     return true;
 }
 
-/* We need to resync the clock when we recover from suspend/resume. */
+static bool registryMatchString(HKEY    hKey,
+                                LPCTSTR lpValueName,
+                                LPCTSTR comparestring,
+                                bool    matchcase)
+{
+    bool    result = false;
+    LONG    buffersize = sizeof(TCHAR)*256;
+    TCHAR   *outstring = NULL;
+    DWORD  outstringsize;
+    LONG    status;
+    do {
+        outstringsize = buffersize;
+        outstring = (TCHAR *)realloc(outstring, outstringsize);
+
+        status = RegQueryValueEx(hKey,
+                                 lpValueName,
+                                 NULL,
+                                 NULL,
+                                 (LPBYTE) outstring,
+                                 &outstringsize);
+        buffersize *= 2;
+    } while (status == ERROR_MORE_DATA);
+
+    if (status == ERROR_FILE_NOT_FOUND)
+        goto done;
+
+    if (matchcase) {
+        if (_tcsncmp(comparestring, outstring, outstringsize))
+            goto done;
+    }
+    else {
+        if (_tcsnicoll(comparestring, outstring, outstringsize))
+            goto done;
+    }
+
+    result = true;
+
+done:
+    free(outstring);
+
+    return result;
+}
+
+static bool
+adjustXenTimeToUTC(FILETIME *now)
+{
+    DWORD           timeoffset;
+    char            *vm;
+    char            *rtckey;
+    ULARGE_INTEGER  longoffset;
+    ULARGE_INTEGER  longnow;
+    size_t          vmlen;
+    
+    // XenTime is assumed to be in UTC, so we need to remove any
+    // offsets that are applied to it
+
+    vmlen = XenstoreRead("vm", &vm);
+    if (vmlen <= 0)
+        goto fail_readvm;
+
+    rtckey = PrintfString("%s/rtc/timeoffset", vm);
+    if (rtckey == NULL)
+        goto fail_rtckey;
+
+    if (!XenstoreReadDword(rtckey, &timeoffset)) {
+        if (!XenstoreReadDword("platform/timeoffset", &timeoffset))
+            goto fail_platformtimeoffset;
+    }
+
+    //Convert offset from seconds to nanoseconds
+    longoffset.QuadPart =  timeoffset;
+    longoffset.QuadPart = longoffset.QuadPart * 10000000;
+    
+    // Subtract nanosecond timeoffset from now
+    longnow.LowPart = now->dwLowDateTime;
+    longnow.HighPart = now->dwHighDateTime;
+    longnow.QuadPart -= longoffset.QuadPart;
+    now->dwLowDateTime = longnow.LowPart;
+    now->dwHighDateTime = longnow.HighPart;
+
+    FreeString(rtckey);
+    XsFree(vm);
+
+    return true;
+
+fail_platformtimeoffset:
+    XsLog("%s: Read platform time offset", __FUNCTION__);
+
+    FreeString(rtckey);
+
+fail_rtckey:
+    XsLog("%s: Read RTC Key", __FUNCTION__);
+
+    XsFree(vm);
+
+fail_readvm:
+    XsLog("%s: Read VM Key", __FUNCTION__);
+
+    return false;
+}
+
 static void
-finishSuspend(void)
+setTimeToXenTime(void)
 {
-    FILETIME now = {0};
-    SYSTEMTIME sys_time;
-    SYSTEMTIME current_time;
+    FILETIME    now = {0};
+    SYSTEMTIME  sys_time;
+    SYSTEMTIME  current_time;
+    HKEY        InstallRegKey;
+    bool        utc=false;
+    XsLog("Set time to XenTime");
 
-    DBGPRINT(("Coming back from suspend.\n"));
     GetXenTime(&now);
     if ((now.dwLowDateTime == 0) && (now.dwHighDateTime == 0)) {
         XsLog("Cannot set system time to xentime, unable to contact WMI");
-        return;
+        goto fail_readtime;
     }
-    XsLog("Xen time is %I64x", now);
+
+    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+                     XENTOOLS_INSTALL_REG_KEY,
+                     0,
+                     KEY_ALL_ACCESS,
+                     &InstallRegKey) != ERROR_SUCCESS)
+        goto fail_registrykey;
+
+    if (registryMatchString(InstallRegKey, "HostTime", "UTC", false)) 
+    {
+        XsLog("Try UTC");
+        if (!adjustXenTimeToUTC(&now))
+            goto fail_adjusttime;
+        utc=true;
+    }
+
+
     if (!FileTimeToSystemTime(&now, &sys_time)) {
         PrintError("FileTimeToSystemTime()");
         DBGPRINT(("FileTimeToSystemTime(%x.%x)\n",
@@ -547,9 +678,34 @@ finishSuspend(void)
               current_time.wYear, current_time.wMonth, current_time.wDay,
               current_time.wHour, current_time.wMinute, current_time.wSecond,
               current_time.wMilliseconds);
-        if (!SetLocalTime(&sys_time))
-            PrintError("SetSystemTime()");
+        if (utc) {
+            if (!SetSystemTime(&sys_time))
+                PrintError("SetSystemTime()");
+        }
+        else {
+            if (!SetLocalTime(&sys_time))
+                PrintError("SetLocalTime()");
+        }
     }
+
+    return;
+
+fail_adjusttime:
+    XsLog("%s: Adjust time", __FUNCTION__);
+    RegCloseKey(InstallRegKey);
+
+fail_registrykey:    
+    XsLog("%s: Open Registry Key", __FUNCTION__);
+fail_readtime:
+    XsLog("%s: ReadTime", __FUNCTION__);
+}
+
+/* We need to resync the clock when we recover from suspend/resume. */
+static void
+finishSuspend(void)
+{
+    DBGPRINT(("Coming back from suspend.\n"));
+    setTimeToXenTime();
 }
 
 
@@ -585,6 +741,8 @@ BOOL Run()
     }
     XsLog("Guest agent lite main loop starting");
 
+    setTimeToXenTime();
+
     memset(&features, 0, sizeof(features));
 
     HANDLE wmierrorEvent = CreateEvent(NULL, FALSE, FALSE, NULL);