ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/* $Id$ */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/** @file
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * IPRT - Time, Windows.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Copyright (C) 2006-2014 Oracle Corporation
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync *
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * available from http://www.virtualbox.org. This file is free software;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * you can redistribute it and/or modify it under the terms of the GNU
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * General Public License (GPL) as published by the Free Software
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync *
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * The contents of this file may alternatively be used under the terms
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * of the Common Development and Distribution License Version 1.0
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * VirtualBox OSE distribution, in which case the provisions of the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * CDDL are applicable instead of those of the GPL.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync *
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * You may elect to license modified versions of this file under the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * terms and conditions of either the GPL or the CDDL or both.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/*******************************************************************************
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync* Header Files *
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync*******************************************************************************/
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#define LOG_GROUP RTLOGGROUP_TIME
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include "internal-r3-nt.h"
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/time.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/asm.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/assert.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/err.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/ldr.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include <iprt/uint128.h>
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#include "internal/time.h"
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/*******************************************************************************
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync* Global Variables *
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync*******************************************************************************/
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/** Whether we've tried to resolve g_pfnRtlGetSystemTimePrecise or not. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncstatic bool g_fInitialized = false;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/** Pointer to RtlGetSystemTimePrecise, added in 6.2 (windows 8). */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncstatic PFNRTLGETSYSTEMTIMEPRECISE g_pfnRtlGetSystemTimePrecise = NULL;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync/**
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Initializes globals.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncstatic void rtTimeNtInitialize(void)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Make sure we don't recurse here when calling into RTLdr.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (ASMAtomicCmpXchgBool(&g_fInitialized, true, false))
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync void *pvFunc = RTLdrGetSystemSymbol("ntdll.dll", "RtlGetSystemTimePrecise");
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (pvFunc)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync ASMAtomicWritePtr((void * volatile *)&g_pfnRtlGetSystemTimePrecise, pvFunc);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync ASMCompilerBarrier();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync }
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncstatic uint64_t rtTimeGetSystemNanoTS(void)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (RT_UNLIKELY(!g_fInitialized))
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync rtTimeNtInitialize();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#if 1
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * If there is precise time, get the precise system time and calculate the
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * interrupt time from it. (Microsoft doesn't expose interrupt time to user
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * application, which is very unfortunate as there are a lot place where
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * monotonic time is applicable but developer is "forced" to use wall clock.)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (g_pfnRtlGetSystemTimePrecise)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync for (;;)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uUpdateLockBefore;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync while ((uUpdateLockBefore = pUserSharedData->TimeUpdateLock) & 1)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync ASMNopPause();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uInterruptTime = *(uint64_t volatile *)&pUserSharedData->InterruptTime;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uBaselineInterruptTimeQpc = pUserSharedData->BaselineInterruptTimeQpc;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uQpcInterruptTimeIncrement = pUserSharedData->QpcInterruptTimeIncrement;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint8_t uQpcInterruptTimeIncrementShift = pUserSharedData->QpcInterruptTimeIncrementShift;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync LARGE_INTEGER QpcValue;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync RtlQueryPerformanceCounter(&QpcValue);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (pUserSharedData->TimeUpdateLock == uUpdateLockBefore)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uQpcValue = QpcValue.QuadPart;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (uQpcValue <= uBaselineInterruptTimeQpc)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return uInterruptTime * 100;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Calc QPC delta since base line. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uQpcValue -= uBaselineInterruptTimeQpc;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uQpcValue--;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Multiply by 10 million. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uQpcValue *= UINT32_C(10000000);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Multiply by QPC interrupt time increment value. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync RTUINT128U Tmp128;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync RTUInt128MulU64ByU64(&Tmp128, uQpcValue, uQpcInterruptTimeIncrement);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Shift the upper 64 bits by the increment shift factor. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uResult = Tmp128.s.Hi >> uQpcInterruptTimeIncrementShift;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Add to base interrupt time value. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uResult += uInterruptTime;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /* Convert from NT unit to nano seconds. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return uResult * 100;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync }
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync ASMNopPause();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync }
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync }
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#endif
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Just read interrupt time.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#if ARCH_BITS >= 64
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->InterruptTime; /* This is what KeQueryInterruptTime does. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uRet *= 100;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return uRet;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#else
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync LARGE_INTEGER NtTime;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync do
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync NtTime.HighPart = pUserSharedData->InterruptTime.High1Time;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync NtTime.LowPart = pUserSharedData->InterruptTime.LowPart;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync } while (pUserSharedData->InterruptTime.High2Time != NtTime.HighPart);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return (uint64_t)NtTime.QuadPart * 100;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#endif
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncRTDECL(uint64_t) RTTimeSystemNanoTS(void)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return rtTimeGetSystemNanoTS();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncRTDECL(uint64_t) RTTimeSystemMilliTS(void)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return rtTimeGetSystemNanoTS() / RT_NS_1MS;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncRTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Get the precise time if possible.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (RT_UNLIKELY(!g_fInitialized))
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync rtTimeNtInitialize();
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync if (g_pfnRtlGetSystemTimePrecise != NULL)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return RTTimeSpecSetNtTime(pTime, g_pfnRtlGetSystemTimePrecise());
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * Just read system time.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#ifdef RT_ARCH_AMD64
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync uint64_t uRet = *(uint64_t volatile *)&pUserSharedData->SystemTime; /* This is what KeQuerySystemTime does. */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return RTTimeSpecSetNtTime(pTime, uRet);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#else
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync LARGE_INTEGER NtTime;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync do
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync NtTime.HighPart = pUserSharedData->SystemTime.High1Time;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync NtTime.LowPart = pUserSharedData->SystemTime.LowPart;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync } while (pUserSharedData->SystemTime.High2Time != NtTime.HighPart);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return RTTimeSpecSetNtTime(pTime, NtTime.QuadPart);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#endif
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncRTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return RTTimeSpecAddNano(RTTimeNow(pTime), RTTimeLocalDeltaNano());
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsyncRTDECL(int64_t) RTTimeLocalDeltaNano(void)
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync{
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync /*
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync * UTC = local + TimeZoneBias; The bias is given in NT units.
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync */
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync KUSER_SHARED_DATA volatile *pUserSharedData = (KUSER_SHARED_DATA volatile *)MM_SHARED_USER_DATA_VA;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync LARGE_INTEGER Delta;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#if ARCH_BITS == 64
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync Delta.QuadPart = *(int64_t volatile *)&pUserSharedData->TimeZoneBias;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#else
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync do
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync {
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync Delta.HighPart = pUserSharedData->TimeZoneBias.High1Time;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync Delta.LowPart = pUserSharedData->TimeZoneBias.LowPart;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync } while (pUserSharedData->TimeZoneBias.High2Time != Delta.HighPart);
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync#endif
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync return Delta.QuadPart * -100;
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync}
ab79888f2d6b4c61dd9ed587aec2bd70dcc17966vboxsync