xref: /reactos/sdk/lib/ucrt/time/ftime.cpp (revision 4de43491)
1 //
2 // ftime.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // The ftime() family of functions, which return the system date and time in a
7 // time structure.
8 //
9 #include <corecrt_internal_time.h>
10 #include <sys/timeb.h>
11 #include <sys/types.h>
12 
13 
14 
15 // Cache for the minutes count for with DST status was last assessed
16 // CRT_REFACTOR TODO Check synchronization of access to this global variable.
17 static __time64_t elapsed_minutes_cache = 0;
18 
19 
20 
21 // Three values of dstflag_cache
22 #define DAYLIGHT_TIME   1
23 #define STANDARD_TIME   0
24 #define UNKNOWN_TIME   -1
25 
26 
27 
28 // Cache for the last determined DST status:
29 static int dstflag_cache = UNKNOWN_TIME;
30 
31 
32 
33 // Returns the system time in a structure; returns zero on success; returns an
34 // error code on failure.
35 template <typename TimeType, typename TimeBType>
common_ftime_s(TimeBType * const tp)36 static errno_t __cdecl common_ftime_s(TimeBType* const tp) throw()
37 {
38     _VALIDATE_RETURN_ERRCODE(tp != nullptr, EINVAL)
39 
40     __tzset();
41 
42     long timezone = 0;
43     _ERRCHECK(_get_timezone(&timezone));
44     tp->timezone = static_cast<short>(timezone / 60);
45 
46     __crt_filetime_union system_time;
47     __acrt_GetSystemTimePreciseAsFileTime(&system_time._filetime);
48 
49     // Obtain the current Daylight Savings Time status.  Note that the status is
50     // cached and only updated once per minute, if necessary.
51     TimeType const current_minutes_value = static_cast<TimeType>(system_time._scalar / 600000000ll);
52     if (static_cast<__time64_t>(current_minutes_value) != elapsed_minutes_cache)
53     {
54         TIME_ZONE_INFORMATION tz_info;
55         DWORD const tz_state = GetTimeZoneInformation(&tz_info);
56         if (tz_state == 0xFFFFFFFF)
57         {
58             dstflag_cache = UNKNOWN_TIME;
59         }
60         else
61         {
62             // Must be very careful when determining whether or not Daylight
63             // Savings Time is in effect:
64             if (tz_state == TIME_ZONE_ID_DAYLIGHT &&
65                 tz_info.DaylightDate.wMonth != 0 &&
66                 tz_info.DaylightBias != 0)
67             {
68                 dstflag_cache = DAYLIGHT_TIME;
69             }
70             else
71             {
72                 // Assume Standard Time:
73                 dstflag_cache = STANDARD_TIME;
74             }
75         }
76 
77         elapsed_minutes_cache = current_minutes_value;
78     }
79 
80     tp->dstflag = static_cast<short>(dstflag_cache);
81     tp->millitm = static_cast<unsigned short>((system_time._scalar / 10000ll) % 1000ll);
82     tp->time    = static_cast<TimeType>((system_time._scalar - _EPOCH_BIAS) / 10000000ll);
83 
84     return 0;
85 }
86 
_ftime32_s(__timeb32 * const tp)87 extern "C" errno_t __cdecl _ftime32_s(__timeb32* const tp)
88 {
89     return common_ftime_s<__time32_t>(tp);
90 }
91 
_ftime32(__timeb32 * const tp)92 extern "C" void __cdecl _ftime32(__timeb32* const tp)
93 {
94     _ftime32_s(tp);
95 }
96 
_ftime64_s(__timeb64 * const tp)97 extern "C" errno_t __cdecl _ftime64_s(__timeb64* const tp)
98 {
99     return common_ftime_s<__time64_t>(tp);
100 }
101 
_ftime64(__timeb64 * const tp)102 extern "C" void __cdecl _ftime64(__timeb64* const tp)
103 {
104     _ftime64_s(tp);
105 }
106