dmime: Remove DECLSPEC_HIDDEN usage.
[wine.git] / dlls / ntdll / time.c
blob105a6cf5bc8bdd449bd9c969522414d5b4f6522b
1 /*
2 * Nt time functions.
4 * RtlTimeToTimeFields, RtlTimeFieldsToTime and defines are taken from ReactOS and
5 * adapted to wine with special permissions of the author. This code is
6 * Copyright 2002 Rex Jolliff (rex@lvcablemodem.com)
8 * Copyright 1999 Juergen Schmied
9 * Copyright 2007 Dmitry Timoshkov
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <time.h>
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "windef.h"
36 #include "winternl.h"
37 #include "ddk/wdm.h"
38 #include "wine/exception.h"
39 #include "wine/debug.h"
40 #include "ntdll_misc.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
44 #define TICKSPERSEC 10000000
45 #define TICKSPERMSEC 10000
46 #define SECSPERDAY 86400
47 #define SECSPERHOUR 3600
48 #define SECSPERMIN 60
49 #define MINSPERHOUR 60
50 #define HOURSPERDAY 24
51 #define EPOCHWEEKDAY 1 /* Jan 1, 1601 was Monday */
52 #define DAYSPERWEEK 7
53 #define MONSPERYEAR 12
54 #define DAYSPERQUADRICENTENNIUM (365 * 400 + 97)
55 #define DAYSPERNORMALQUADRENNIUM (365 * 4 + 1)
57 /* 1601 to 1970 is 369 years plus 89 leap days */
58 #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
59 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
60 /* 1601 to 1980 is 379 years plus 91 leap days */
61 #define SECS_1601_TO_1980 ((379 * 365 + 91) * (ULONGLONG)SECSPERDAY)
62 #define TICKS_1601_TO_1980 (SECS_1601_TO_1980 * TICKSPERSEC)
65 static const int MonthLengths[2][MONSPERYEAR] =
67 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
68 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
71 static inline BOOL IsLeapYear(int Year)
73 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0);
77 /******************************************************************************
78 * RtlTimeToTimeFields [NTDLL.@]
80 * Convert a time into a TIME_FIELDS structure.
82 * PARAMS
83 * liTime [I] Time to convert.
84 * TimeFields [O] Destination for the converted time.
86 * RETURNS
87 * Nothing.
89 VOID WINAPI RtlTimeToTimeFields(
90 const LARGE_INTEGER *liTime,
91 PTIME_FIELDS TimeFields)
93 int SecondsInDay;
94 long int cleaps, years, yearday, months;
95 long int Days;
96 LONGLONG Time;
98 /* Extract millisecond from time and convert time into seconds */
99 TimeFields->Milliseconds =
100 (CSHORT) (( liTime->QuadPart % TICKSPERSEC) / TICKSPERMSEC);
101 Time = liTime->QuadPart / TICKSPERSEC;
103 /* The native version of RtlTimeToTimeFields does not take leap seconds
104 * into account */
106 /* Split the time into days and seconds within the day */
107 Days = Time / SECSPERDAY;
108 SecondsInDay = Time % SECSPERDAY;
110 /* compute time of day */
111 TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR);
112 SecondsInDay = SecondsInDay % SECSPERHOUR;
113 TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN);
114 TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN);
116 /* compute day of week */
117 TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK);
119 /* compute year, month and day of month. */
120 cleaps=( 3 * ((4 * Days + 1227) / DAYSPERQUADRICENTENNIUM) + 3 ) / 4;
121 Days += 28188 + cleaps;
122 years = (20 * Days - 2442) / (5 * DAYSPERNORMALQUADRENNIUM);
123 yearday = Days - (years * DAYSPERNORMALQUADRENNIUM)/4;
124 months = (64 * yearday) / 1959;
125 /* the result is based on a year starting on March.
126 * To convert take 12 from Januari and Februari and
127 * increase the year by one. */
128 if( months < 14 ) {
129 TimeFields->Month = months - 1;
130 TimeFields->Year = years + 1524;
131 } else {
132 TimeFields->Month = months - 13;
133 TimeFields->Year = years + 1525;
135 /* calculation of day of month is based on the wonderful
136 * sequence of INT( n * 30.6): it reproduces the
137 * 31-30-31-30-31-31 month lengths exactly for small n's */
138 TimeFields->Day = yearday - (1959 * months) / 64 ;
139 return;
142 /******************************************************************************
143 * RtlTimeFieldsToTime [NTDLL.@]
145 * Convert a TIME_FIELDS structure into a time.
147 * PARAMS
148 * ftTimeFields [I] TIME_FIELDS structure to convert.
149 * Time [O] Destination for the converted time.
151 * RETURNS
152 * Success: TRUE.
153 * Failure: FALSE.
155 BOOLEAN WINAPI RtlTimeFieldsToTime(
156 PTIME_FIELDS tfTimeFields,
157 PLARGE_INTEGER Time)
159 int month, year, cleaps, day;
161 /* FIXME: normalize the TIME_FIELDS structure here */
162 /* No, native just returns 0 (error) if the fields are not */
163 if( tfTimeFields->Milliseconds< 0 || tfTimeFields->Milliseconds > 999 ||
164 tfTimeFields->Second < 0 || tfTimeFields->Second > 59 ||
165 tfTimeFields->Minute < 0 || tfTimeFields->Minute > 59 ||
166 tfTimeFields->Hour < 0 || tfTimeFields->Hour > 23 ||
167 tfTimeFields->Month < 1 || tfTimeFields->Month > 12 ||
168 tfTimeFields->Day < 1 ||
169 tfTimeFields->Day > MonthLengths
170 [ tfTimeFields->Month ==2 || IsLeapYear(tfTimeFields->Year)]
171 [ tfTimeFields->Month - 1] ||
172 tfTimeFields->Year < 1601 )
173 return FALSE;
175 /* now calculate a day count from the date
176 * First start counting years from March. This way the leap days
177 * are added at the end of the year, not somewhere in the middle.
178 * Formula's become so much less complicate that way.
179 * To convert: add 12 to the month numbers of Jan and Feb, and
180 * take 1 from the year */
181 if(tfTimeFields->Month < 3) {
182 month = tfTimeFields->Month + 13;
183 year = tfTimeFields->Year - 1;
184 } else {
185 month = tfTimeFields->Month + 1;
186 year = tfTimeFields->Year;
188 cleaps = (3 * (year / 100) + 3) / 4; /* nr of "century leap years"*/
189 day = (36525 * year) / 100 - cleaps + /* year * dayperyr, corrected */
190 (1959 * month) / 64 + /* months * daypermonth */
191 tfTimeFields->Day - /* day of the month */
192 584817 ; /* zero that on 1601-01-01 */
193 /* done */
195 Time->QuadPart = (((((LONGLONG) day * HOURSPERDAY +
196 tfTimeFields->Hour) * MINSPERHOUR +
197 tfTimeFields->Minute) * SECSPERMIN +
198 tfTimeFields->Second ) * 1000 +
199 tfTimeFields->Milliseconds ) * TICKSPERMSEC;
201 return TRUE;
205 /******************************************************************************
206 * RtlLocalTimeToSystemTime [NTDLL.@]
208 * Convert a local time into system time.
210 * PARAMS
211 * LocalTime [I] Local time to convert.
212 * SystemTime [O] Destination for the converted time.
214 * RETURNS
215 * Success: STATUS_SUCCESS.
216 * Failure: An NTSTATUS error code indicating the problem.
218 NTSTATUS WINAPI RtlLocalTimeToSystemTime( const LARGE_INTEGER *LocalTime,
219 PLARGE_INTEGER SystemTime)
221 SYSTEM_TIMEOFDAY_INFORMATION info;
223 TRACE("(%p, %p)\n", LocalTime, SystemTime);
225 NtQuerySystemInformation( SystemTimeOfDayInformation, &info, sizeof(info), NULL );
226 SystemTime->QuadPart = LocalTime->QuadPart + info.TimeZoneBias.QuadPart;
227 return STATUS_SUCCESS;
230 /******************************************************************************
231 * RtlSystemTimeToLocalTime [NTDLL.@]
233 * Convert a system time into a local time.
235 * PARAMS
236 * SystemTime [I] System time to convert.
237 * LocalTime [O] Destination for the converted time.
239 * RETURNS
240 * Success: STATUS_SUCCESS.
241 * Failure: An NTSTATUS error code indicating the problem.
243 NTSTATUS WINAPI RtlSystemTimeToLocalTime( const LARGE_INTEGER *SystemTime,
244 PLARGE_INTEGER LocalTime )
246 SYSTEM_TIMEOFDAY_INFORMATION info;
248 TRACE("(%p, %p)\n", SystemTime, LocalTime);
250 NtQuerySystemInformation( SystemTimeOfDayInformation, &info, sizeof(info), NULL );
251 LocalTime->QuadPart = SystemTime->QuadPart - info.TimeZoneBias.QuadPart;
252 return STATUS_SUCCESS;
255 /******************************************************************************
256 * RtlTimeToSecondsSince1970 [NTDLL.@]
258 * Convert a time into a count of seconds since 1970.
260 * PARAMS
261 * Time [I] Time to convert.
262 * Seconds [O] Destination for the converted time.
264 * RETURNS
265 * Success: TRUE.
266 * Failure: FALSE, if the resulting value will not fit in a DWORD.
268 BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, LPDWORD Seconds )
270 ULONGLONG tmp = Time->QuadPart / TICKSPERSEC - SECS_1601_TO_1970;
271 if (tmp > 0xffffffff) return FALSE;
272 *Seconds = tmp;
273 return TRUE;
276 /******************************************************************************
277 * RtlTimeToSecondsSince1980 [NTDLL.@]
279 * Convert a time into a count of seconds since 1980.
281 * PARAMS
282 * Time [I] Time to convert.
283 * Seconds [O] Destination for the converted time.
285 * RETURNS
286 * Success: TRUE.
287 * Failure: FALSE, if the resulting value will not fit in a DWORD.
289 BOOLEAN WINAPI RtlTimeToSecondsSince1980( const LARGE_INTEGER *Time, LPDWORD Seconds )
291 ULONGLONG tmp = Time->QuadPart / TICKSPERSEC - SECS_1601_TO_1980;
292 if (tmp > 0xffffffff) return FALSE;
293 *Seconds = tmp;
294 return TRUE;
297 /******************************************************************************
298 * RtlSecondsSince1970ToTime [NTDLL.@]
300 * Convert a count of seconds since 1970 to a time.
302 * PARAMS
303 * Seconds [I] Time to convert.
304 * Time [O] Destination for the converted time.
306 * RETURNS
307 * Nothing.
309 void WINAPI RtlSecondsSince1970ToTime( DWORD Seconds, LARGE_INTEGER *Time )
311 Time->QuadPart = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
314 /******************************************************************************
315 * RtlSecondsSince1980ToTime [NTDLL.@]
317 * Convert a count of seconds since 1980 to a time.
319 * PARAMS
320 * Seconds [I] Time to convert.
321 * Time [O] Destination for the converted time.
323 * RETURNS
324 * Nothing.
326 void WINAPI RtlSecondsSince1980ToTime( DWORD Seconds, LARGE_INTEGER *Time )
328 Time->QuadPart = Seconds * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1980;
331 /******************************************************************************
332 * RtlTimeToElapsedTimeFields [NTDLL.@]
334 * Convert a time to a count of elapsed seconds.
336 * PARAMS
337 * Time [I] Time to convert.
338 * TimeFields [O] Destination for the converted time.
340 * RETURNS
341 * Nothing.
343 void WINAPI RtlTimeToElapsedTimeFields( const LARGE_INTEGER *Time, PTIME_FIELDS TimeFields )
345 LONGLONG time;
346 INT rem;
348 time = Time->QuadPart / TICKSPERSEC;
349 TimeFields->Milliseconds = (Time->QuadPart % TICKSPERSEC) / TICKSPERMSEC;
351 /* time is now in seconds */
352 TimeFields->Year = 0;
353 TimeFields->Month = 0;
354 TimeFields->Day = time / SECSPERDAY;
356 /* rem is now the remaining seconds in the last day */
357 rem = time % SECSPERDAY;
358 TimeFields->Second = rem % 60;
359 rem /= 60;
360 TimeFields->Minute = rem % 60;
361 TimeFields->Hour = rem / 60;
364 /***********************************************************************
365 * RtlGetSystemTimePrecise [NTDLL.@]
367 * Get a more accurate current system time.
369 * RETURNS
370 * The current system time.
372 LONGLONG WINAPI RtlGetSystemTimePrecise( void )
374 LONGLONG ret;
376 WINE_UNIX_CALL( unix_system_time_precise, &ret );
377 return ret;
380 /******************************************************************************
381 * RtlQueryPerformanceCounter [NTDLL.@]
383 BOOL WINAPI DECLSPEC_HOTPATCH RtlQueryPerformanceCounter( LARGE_INTEGER *counter )
385 NtQueryPerformanceCounter( counter, NULL );
386 return TRUE;
389 /******************************************************************************
390 * RtlQueryPerformanceFrequency [NTDLL.@]
392 BOOL WINAPI DECLSPEC_HOTPATCH RtlQueryPerformanceFrequency( LARGE_INTEGER *frequency )
394 frequency->QuadPart = TICKSPERSEC;
395 return TRUE;
398 /******************************************************************************
399 * NtGetTickCount (NTDLL.@)
400 * ZwGetTickCount (NTDLL.@)
402 ULONG WINAPI DECLSPEC_HOTPATCH NtGetTickCount(void)
404 /* note: we ignore TickCountMultiplier */
405 return user_shared_data->TickCount.LowPart;
408 /***********************************************************************
409 * RtlQueryTimeZoneInformation [NTDLL.@]
411 * Get information about the current timezone.
413 * PARAMS
414 * tzinfo [O] Destination for the retrieved timezone info.
416 * RETURNS
417 * Success: STATUS_SUCCESS.
418 * Failure: An NTSTATUS error code indicating the problem.
420 NTSTATUS WINAPI RtlQueryTimeZoneInformation(RTL_TIME_ZONE_INFORMATION *ret)
422 return NtQuerySystemInformation( SystemCurrentTimeZoneInformation, ret, sizeof(*ret), NULL );
425 /***********************************************************************
426 * RtlQueryDynamicTimeZoneInformation [NTDLL.@]
428 * Get information about the current timezone.
430 * PARAMS
431 * tzinfo [O] Destination for the retrieved timezone info.
433 * RETURNS
434 * Success: STATUS_SUCCESS.
435 * Failure: An NTSTATUS error code indicating the problem.
437 NTSTATUS WINAPI RtlQueryDynamicTimeZoneInformation(RTL_DYNAMIC_TIME_ZONE_INFORMATION *ret)
439 return NtQuerySystemInformation( SystemDynamicTimeZoneInformation, ret, sizeof(*ret), NULL );
442 /***********************************************************************
443 * RtlSetTimeZoneInformation [NTDLL.@]
445 * Set the current time zone information.
447 * PARAMS
448 * tzinfo [I] Timezone information to set.
450 * RETURNS
451 * Success: STATUS_SUCCESS.
452 * Failure: An NTSTATUS error code indicating the problem.
455 NTSTATUS WINAPI RtlSetTimeZoneInformation( const RTL_TIME_ZONE_INFORMATION *tzinfo )
457 return STATUS_PRIVILEGE_NOT_HELD;
460 /***********************************************************************
461 * RtlQueryUnbiasedInterruptTime [NTDLL.@]
463 BOOL WINAPI RtlQueryUnbiasedInterruptTime(ULONGLONG *time)
465 ULONG high, low;
467 if (!time)
469 RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
470 return FALSE;
475 high = user_shared_data->InterruptTime.High1Time;
476 low = user_shared_data->InterruptTime.LowPart;
478 while (high != user_shared_data->InterruptTime.High2Time);
479 /* FIXME: should probably subtract InterruptTimeBias */
480 *time = (ULONGLONG)high << 32 | low;
481 return TRUE;