[PATCH] msvcrt: Use RtlQueryTimeZoneInformation when MUI not required.

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Thu Dec 20 16:46:17 CST 2018


TIME_ZoneID copied from dlls/kernel32/time.c

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46266
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---

If we dont care about an invalid TIME_ZONE then we have the possiblity
to use GetDaylightFlag to reduce the amount of code.
MSVCRT__ftime64
....
buf->timezone = tzinfo.Bias +
      ( tzid == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias :
      ( tzid == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ));

 dlls/msvcrt/time.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 1 deletion(-)

diff --git a/dlls/msvcrt/time.c b/dlls/msvcrt/time.c
index 861b2ed..521c6c8 100644
--- a/dlls/msvcrt/time.c
+++ b/dlls/msvcrt/time.c
@@ -760,6 +760,146 @@ double CDECL MSVCRT_difftime(MSVCRT___time32_t time1, MSVCRT___time32_t time2)
 }
 #endif
 
+#define LL2FILETIME( ll, pft )\
+    (pft)->dwLowDateTime = (UINT)(ll); \
+    (pft)->dwHighDateTime = (UINT)((ll) >> 32);
+#define FILETIME2LL( pft, ll) \
+    ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
+
+static int TIME_DayLightCompareDate( const SYSTEMTIME *date,
+    const SYSTEMTIME *compareDate )
+{
+    int limit_day, dayinsecs;
+
+    if (date->wMonth < compareDate->wMonth)
+        return -1; /* We are in a month before the date limit. */
+
+    if (date->wMonth > compareDate->wMonth)
+        return 1; /* We are in a month after the date limit. */
+
+    /* if year is 0 then date is in day-of-week format, otherwise
+     * it's absolute date.
+     */
+    if (compareDate->wYear == 0)
+    {
+        WORD First;
+        /* compareDate->wDay is interpreted as number of the week in the month
+         * 5 means: the last week in the month */
+        int weekofmonth = compareDate->wDay;
+          /* calculate the day of the first DayOfWeek in the month */
+        First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay 
+               ) % 7 + 1;
+        limit_day = First + 7 * (weekofmonth - 1);
+        /* check needed for the 5th weekday of the month */
+        if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)]
+                [date->wMonth - 1])
+            limit_day -= 7;
+    }
+    else
+    {
+       limit_day = compareDate->wDay;
+    }
+
+    /* convert to seconds */
+    limit_day = ((limit_day * 24  + compareDate->wHour) * 60 +
+            compareDate->wMinute ) * 60;
+    dayinsecs = ((date->wDay * 24  + date->wHour) * 60 +
+            date->wMinute ) * 60 + date->wSecond;
+    /* and compare */
+    return dayinsecs < limit_day ? -1 :
+           dayinsecs > limit_day ? 1 :
+           0;   /* date is equal to the date limit. */
+}
+
+static DWORD TIME_CompTimeZoneID ( const TIME_ZONE_INFORMATION *pTZinfo,
+    FILETIME *lpFileTime, BOOL islocal )
+{
+    int ret, year;
+    BOOL beforeStandardDate, afterDaylightDate;
+    DWORD retval = TIME_ZONE_ID_INVALID;
+    LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
+    SYSTEMTIME SysTime;
+    FILETIME ftTemp;
+
+    if (pTZinfo->DaylightDate.wMonth != 0)
+    {
+        /* if year is 0 then date is in day-of-week format, otherwise
+         * it's absolute date.
+         */
+        if (pTZinfo->StandardDate.wMonth == 0 ||
+            (pTZinfo->StandardDate.wYear == 0 &&
+            (pTZinfo->StandardDate.wDay<1 ||
+            pTZinfo->StandardDate.wDay>5 ||
+            pTZinfo->DaylightDate.wDay<1 ||
+            pTZinfo->DaylightDate.wDay>5)))
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return TIME_ZONE_ID_INVALID;
+        }
+
+        if (!islocal) {
+            FILETIME2LL( lpFileTime, llTime );
+            llTime -= pTZinfo->Bias * (LONGLONG)600000000;
+            LL2FILETIME( llTime, &ftTemp)
+            lpFileTime = &ftTemp;
+        }
+
+        FileTimeToSystemTime(lpFileTime, &SysTime);
+        year = SysTime.wYear;
+
+        if (!islocal) {
+            llTime -= pTZinfo->DaylightBias * (LONGLONG)600000000;
+            LL2FILETIME( llTime, &ftTemp)
+            FileTimeToSystemTime(lpFileTime, &SysTime);
+        }
+
+        if(year == SysTime.wYear) {
+            ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
+            if (ret == -2)
+                return TIME_ZONE_ID_INVALID;
+
+            beforeStandardDate = ret < 0;
+        } else
+            beforeStandardDate = SysTime.wYear < year;
+
+        if (!islocal) {
+            llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias )
+                * (LONGLONG)600000000;
+            LL2FILETIME( llTime, &ftTemp)
+            FileTimeToSystemTime(lpFileTime, &SysTime);
+        }
+
+        if(year == SysTime.wYear) {
+            ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
+            if (ret == -2)
+                return TIME_ZONE_ID_INVALID;
+
+            afterDaylightDate = ret >= 0;
+        } else
+            afterDaylightDate = SysTime.wYear > year;
+
+        retval = TIME_ZONE_ID_STANDARD;
+        if( pTZinfo->DaylightDate.wMonth <  pTZinfo->StandardDate.wMonth ) {
+            /* Northern hemisphere */
+            if( beforeStandardDate && afterDaylightDate )
+                retval = TIME_ZONE_ID_DAYLIGHT;
+        } else    /* Down south */
+            if( beforeStandardDate || afterDaylightDate )
+            retval = TIME_ZONE_ID_DAYLIGHT;
+    } else 
+        /* No transition date */
+        retval = TIME_ZONE_ID_UNKNOWN;
+        
+    return retval;
+}
+
+
+static DWORD TIME_ZoneID( const TIME_ZONE_INFORMATION *pTzi )
+{
+    FILETIME ftTime;
+    GetSystemTimeAsFileTime( &ftTime);
+    return TIME_CompTimeZoneID( pTzi, &ftTime, FALSE);
+}
 /*********************************************************************
  *		_ftime64 (MSVCRT.@)
  */
@@ -768,8 +908,10 @@ void CDECL MSVCRT__ftime64(struct MSVCRT___timeb64 *buf)
   TIME_ZONE_INFORMATION tzinfo;
   FILETIME ft;
   ULONGLONG time;
+  DWORD tzid;
 
-  DWORD tzid = GetTimeZoneInformation(&tzinfo);
+  RtlQueryTimeZoneInformation((RTL_TIME_ZONE_INFORMATION *)&tzinfo);
+  tzid = TIME_ZoneID(&tzinfo);
   GetSystemTimeAsFileTime(&ft);
 
   time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
-- 
1.9.1




More information about the wine-devel mailing list