2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/time.c
5 * PURPOSE: Time conversion functions
7 * DOSDATE and DOSTIME structures from Onno Hovers
12 /* INCLUDES *******************************************************************/
19 /* FUNCTIONS ******************************************************************/
26 IsTimeZoneRedirectionEnabled(VOID
)
28 /* Return if a TS Timezone ID is active */
29 return (BaseStaticServerData
->TermsrvClientTimeZoneId
!= TIME_ZONE_ID_INVALID
);
37 FileTimeToDosDateTime(IN CONST FILETIME
*lpFileTime
,
41 LARGE_INTEGER FileTime
;
42 TIME_FIELDS TimeFields
;
44 FileTime
.HighPart
= lpFileTime
->dwHighDateTime
;
45 FileTime
.LowPart
= lpFileTime
->dwLowDateTime
;
47 if (FileTime
.QuadPart
< 0)
49 SetLastError(ERROR_INVALID_PARAMETER
);
53 RtlTimeToTimeFields(&FileTime
, &TimeFields
);
54 if ((TimeFields
.Year
< 1980) || (TimeFields
.Year
> 2107))
56 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
60 *lpFatDate
= (TimeFields
.Day
) |
61 (TimeFields
.Month
<< 5) |
62 ((TimeFields
.Year
- 1980) << 9);
63 *lpFatTime
= (TimeFields
.Second
>> 1) |
64 (TimeFields
.Minute
<< 5) |
65 (TimeFields
.Hour
<< 11);
75 DosDateTimeToFileTime(IN WORD wFatDate
,
77 OUT LPFILETIME lpFileTime
)
79 TIME_FIELDS TimeFields
;
80 LARGE_INTEGER SystemTime
;
82 TimeFields
.Year
= (wFatDate
>> 9) + 1980;
83 TimeFields
.Month
= (wFatDate
>> 5) & 0xF;
84 TimeFields
.Day
= (wFatDate
& 0x1F);
85 TimeFields
.Hour
= (wFatTime
>> 11);
86 TimeFields
.Minute
= (wFatTime
>> 5) & 0x3F;
87 TimeFields
.Second
= (wFatTime
& 0x1F) << 1;
88 TimeFields
.Milliseconds
= 0;
90 if (RtlTimeFieldsToTime(&TimeFields
, &SystemTime
))
92 lpFileTime
->dwLowDateTime
= SystemTime
.LowPart
;
93 lpFileTime
->dwHighDateTime
= SystemTime
.HighPart
;
97 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
106 CompareFileTime(IN CONST FILETIME
*lpFileTime1
,
107 IN CONST FILETIME
*lpFileTime2
)
109 LARGE_INTEGER Time1
, Time2
, Diff
;
111 Time1
.LowPart
= lpFileTime1
->dwLowDateTime
;
112 Time2
.LowPart
= lpFileTime2
->dwLowDateTime
;
113 Time1
.HighPart
= lpFileTime1
->dwHighDateTime
;
114 Time2
.HighPart
= lpFileTime2
->dwHighDateTime
;
116 Diff
.QuadPart
= Time1
.QuadPart
- Time2
.QuadPart
;
118 if (Diff
.HighPart
< 0) return -1;
119 if (Diff
.QuadPart
== 0) return 0;
128 GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime
)
130 LARGE_INTEGER SystemTime
;
134 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
135 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
137 while (SystemTime
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
139 lpFileTime
->dwLowDateTime
= SystemTime
.LowPart
;
140 lpFileTime
->dwHighDateTime
= SystemTime
.HighPart
;
148 GetSystemTimePreciseAsFileTime(OUT PFILETIME lpFileTime
)
158 SystemTimeToFileTime(IN CONST SYSTEMTIME
*lpSystemTime
,
159 OUT LPFILETIME lpFileTime
)
161 TIME_FIELDS TimeFields
;
162 LARGE_INTEGER liTime
;
164 TimeFields
.Year
= lpSystemTime
->wYear
;
165 TimeFields
.Month
= lpSystemTime
->wMonth
;
166 TimeFields
.Day
= lpSystemTime
->wDay
;
167 TimeFields
.Hour
= lpSystemTime
->wHour
;
168 TimeFields
.Minute
= lpSystemTime
->wMinute
;
169 TimeFields
.Second
= lpSystemTime
->wSecond
;
170 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
172 if (RtlTimeFieldsToTime(&TimeFields
, &liTime
))
174 lpFileTime
->dwLowDateTime
= liTime
.u
.LowPart
;
175 lpFileTime
->dwHighDateTime
= liTime
.u
.HighPart
;
179 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
188 FileTimeToSystemTime(IN CONST FILETIME
*lpFileTime
,
189 OUT LPSYSTEMTIME lpSystemTime
)
191 TIME_FIELDS TimeFields
;
192 LARGE_INTEGER liTime
;
194 liTime
.u
.LowPart
= lpFileTime
->dwLowDateTime
;
195 liTime
.u
.HighPart
= lpFileTime
->dwHighDateTime
;
196 if (liTime
.QuadPart
< 0)
198 SetLastError(ERROR_INVALID_PARAMETER
);
202 RtlTimeToTimeFields(&liTime
, &TimeFields
);
204 lpSystemTime
->wYear
= TimeFields
.Year
;
205 lpSystemTime
->wMonth
= TimeFields
.Month
;
206 lpSystemTime
->wDay
= TimeFields
.Day
;
207 lpSystemTime
->wHour
= TimeFields
.Hour
;
208 lpSystemTime
->wMinute
= TimeFields
.Minute
;
209 lpSystemTime
->wSecond
= TimeFields
.Second
;
210 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
211 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
221 FileTimeToLocalFileTime(IN CONST FILETIME
*lpFileTime
,
222 OUT LPFILETIME lpLocalFileTime
)
224 LARGE_INTEGER TimeZoneBias
, FileTime
;
225 volatile KSYSTEM_TIME
*TimePtr
;
227 TimePtr
= IsTimeZoneRedirectionEnabled() ?
228 &BaseStaticServerData
->ktTermsrvClientBias
:
229 &SharedUserData
->TimeZoneBias
;
232 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
233 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
235 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
237 FileTime
.LowPart
= lpFileTime
->dwLowDateTime
;
238 FileTime
.HighPart
= lpFileTime
->dwHighDateTime
;
240 FileTime
.QuadPart
-= TimeZoneBias
.QuadPart
;
242 lpLocalFileTime
->dwLowDateTime
= FileTime
.LowPart
;
243 lpLocalFileTime
->dwHighDateTime
= FileTime
.HighPart
;
253 LocalFileTimeToFileTime(IN CONST FILETIME
*lpLocalFileTime
,
254 OUT LPFILETIME lpFileTime
)
256 LARGE_INTEGER TimeZoneBias
, FileTime
;
257 volatile KSYSTEM_TIME
*TimePtr
;
259 TimePtr
= IsTimeZoneRedirectionEnabled() ?
260 &BaseStaticServerData
->ktTermsrvClientBias
:
261 &SharedUserData
->TimeZoneBias
;
265 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
266 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
268 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
270 FileTime
.LowPart
= lpLocalFileTime
->dwLowDateTime
;
271 FileTime
.HighPart
= lpLocalFileTime
->dwHighDateTime
;
273 FileTime
.QuadPart
+= TimeZoneBias
.QuadPart
;
275 lpFileTime
->dwLowDateTime
= FileTime
.LowPart
;
276 lpFileTime
->dwHighDateTime
= FileTime
.HighPart
;
286 GetLocalTime(OUT LPSYSTEMTIME lpSystemTime
)
288 LARGE_INTEGER SystemTime
, TimeZoneBias
;
289 TIME_FIELDS TimeFields
;
290 volatile KSYSTEM_TIME
*TimePtr
;
294 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
295 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
297 while (SystemTime
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
299 TimePtr
= IsTimeZoneRedirectionEnabled() ?
300 &BaseStaticServerData
->ktTermsrvClientBias
:
301 &SharedUserData
->TimeZoneBias
;
304 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
305 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
307 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
309 SystemTime
.QuadPart
-= TimeZoneBias
.QuadPart
;
310 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
312 lpSystemTime
->wYear
= TimeFields
.Year
;
313 lpSystemTime
->wMonth
= TimeFields
.Month
;
314 lpSystemTime
->wDay
= TimeFields
.Day
;
315 lpSystemTime
->wHour
= TimeFields
.Hour
;
316 lpSystemTime
->wMinute
= TimeFields
.Minute
;
317 lpSystemTime
->wSecond
= TimeFields
.Second
;
318 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
319 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
327 GetSystemTime(OUT LPSYSTEMTIME lpSystemTime
)
329 LARGE_INTEGER SystemTime
;
330 TIME_FIELDS TimeFields
;
334 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
335 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
337 while (SystemTime
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
339 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
341 lpSystemTime
->wYear
= TimeFields
.Year
;
342 lpSystemTime
->wMonth
= TimeFields
.Month
;
343 lpSystemTime
->wDay
= TimeFields
.Day
;
344 lpSystemTime
->wHour
= TimeFields
.Hour
;
345 lpSystemTime
->wMinute
= TimeFields
.Minute
;
346 lpSystemTime
->wSecond
= TimeFields
.Second
;
347 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
348 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
356 SetLocalTime(IN CONST SYSTEMTIME
*lpSystemTime
)
358 LARGE_INTEGER NewSystemTime
, TimeZoneBias
;
360 ULONG Privilege
= SE_SYSTEMTIME_PRIVILEGE
;
361 TIME_FIELDS TimeFields
;
363 volatile KSYSTEM_TIME
*TimePtr
;
365 TimePtr
= IsTimeZoneRedirectionEnabled() ?
366 &BaseStaticServerData
->ktTermsrvClientBias
:
367 &SharedUserData
->TimeZoneBias
;
370 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
371 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
373 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
375 TimeFields
.Year
= lpSystemTime
->wYear
;
376 TimeFields
.Month
= lpSystemTime
->wMonth
;
377 TimeFields
.Day
= lpSystemTime
->wDay
;
378 TimeFields
.Hour
= lpSystemTime
->wHour
;
379 TimeFields
.Minute
= lpSystemTime
->wMinute
;
380 TimeFields
.Second
= lpSystemTime
->wSecond
;
381 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
383 if (!RtlTimeFieldsToTime(&TimeFields
, &NewSystemTime
))
385 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
389 NewSystemTime
.QuadPart
+= TimeZoneBias
.QuadPart
;
391 Status
= RtlAcquirePrivilege(&Privilege
, 1, 0, &State
);
392 if (NT_SUCCESS(Status
))
394 Status
= NtSetSystemTime(&NewSystemTime
, NULL
);
395 RtlReleasePrivilege(State
);
398 if (!NT_SUCCESS(Status
))
400 BaseSetLastNTError(Status
);
412 SetSystemTime(IN CONST SYSTEMTIME
*lpSystemTime
)
414 LARGE_INTEGER NewSystemTime
;
416 ULONG Privilege
= SE_SYSTEMTIME_PRIVILEGE
;
417 TIME_FIELDS TimeFields
;
420 TimeFields
.Year
= lpSystemTime
->wYear
;
421 TimeFields
.Month
= lpSystemTime
->wMonth
;
422 TimeFields
.Day
= lpSystemTime
->wDay
;
423 TimeFields
.Hour
= lpSystemTime
->wHour
;
424 TimeFields
.Minute
= lpSystemTime
->wMinute
;
425 TimeFields
.Second
= lpSystemTime
->wSecond
;
426 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
428 if (!RtlTimeFieldsToTime(&TimeFields
, &NewSystemTime
))
430 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
434 Status
= RtlAcquirePrivilege(&Privilege
, 1, 0, &State
);
435 if (NT_SUCCESS(Status
))
437 Status
= NtSetSystemTime(&NewSystemTime
, NULL
);
438 RtlReleasePrivilege(State
);
441 if (!NT_SUCCESS(Status
))
443 BaseSetLastNTError(Status
);
457 ULARGE_INTEGER TickCount
;
460 TickCount
.QuadPart
= *((volatile ULONG64
*)&SharedUserData
->TickCount
);
464 TickCount
.HighPart
= (ULONG
)SharedUserData
->TickCount
.High1Time
;
465 TickCount
.LowPart
= SharedUserData
->TickCount
.LowPart
;
467 if (TickCount
.HighPart
== (ULONG
)SharedUserData
->TickCount
.High2Time
)
474 return (ULONG
)((UInt32x32To64(TickCount
.LowPart
,
475 SharedUserData
->TickCountMultiplier
) >> 24) +
476 UInt32x32To64((TickCount
.HighPart
<< 8) & 0xFFFFFFFF,
477 SharedUserData
->TickCountMultiplier
));
486 GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment
,
487 OUT PDWORD lpTimeIncrement
,
488 OUT PBOOL lpTimeAdjustmentDisabled
)
490 SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
;
493 Status
= NtQuerySystemInformation(SystemTimeAdjustmentInformation
,
497 if (!NT_SUCCESS(Status
))
499 BaseSetLastNTError(Status
);
503 *lpTimeAdjustment
= (DWORD
)TimeInfo
.TimeAdjustment
;
504 *lpTimeIncrement
= (DWORD
)TimeInfo
.TimeIncrement
;
505 *lpTimeAdjustmentDisabled
= (BOOL
)TimeInfo
.Enable
;
515 SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment
,
516 IN BOOL bTimeAdjustmentDisabled
)
519 SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
;
521 TimeInfo
.TimeAdjustment
= (ULONG
)dwTimeAdjustment
;
522 TimeInfo
.Enable
= (BOOLEAN
)bTimeAdjustmentDisabled
;
524 Status
= NtSetSystemInformation(SystemTimeAdjustmentInformation
,
527 if (!NT_SUCCESS(Status
))
529 BaseSetLastNTError(Status
);
541 GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL
,
542 OUT LPFILETIME lpKernelTime OPTIONAL
,
543 OUT LPFILETIME lpUserTime OPTIONAL
)
545 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo
;
546 LARGE_INTEGER TotalUserTime
, TotalKernTime
, TotalIdleTime
;
547 ULONG BufferSize
, ReturnLength
;
551 TotalUserTime
.QuadPart
= TotalKernTime
.QuadPart
= TotalIdleTime
.QuadPart
= 0;
553 BufferSize
= sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) *
554 BaseStaticServerData
->SysInfo
.NumberOfProcessors
;
556 ProcPerfInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
559 BaseSetLastNTError(STATUS_NO_MEMORY
);
563 Status
= NtQuerySystemInformation(SystemProcessorPerformanceInformation
,
567 if ((NT_SUCCESS(Status
)) && (ReturnLength
== BufferSize
))
571 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
573 TotalIdleTime
.QuadPart
+= ProcPerfInfo
[i
].IdleTime
.QuadPart
;
576 lpIdleTime
->dwLowDateTime
= TotalIdleTime
.LowPart
;
577 lpIdleTime
->dwHighDateTime
= TotalIdleTime
.HighPart
;
582 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
584 TotalKernTime
.QuadPart
+= ProcPerfInfo
[i
].KernelTime
.QuadPart
;
587 lpKernelTime
->dwLowDateTime
= TotalKernTime
.LowPart
;
588 lpKernelTime
->dwHighDateTime
= TotalKernTime
.HighPart
;
593 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
595 TotalUserTime
.QuadPart
+= ProcPerfInfo
[i
].UserTime
.QuadPart
;
598 lpUserTime
->dwLowDateTime
= TotalUserTime
.LowPart
;
599 lpUserTime
->dwHighDateTime
= TotalUserTime
.HighPart
;
602 else if (NT_SUCCESS(Status
))
604 Status
= STATUS_INTERNAL_ERROR
;
607 RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo
);
608 if (!NT_SUCCESS(Status
))
610 BaseSetLastNTError(Status
);
622 SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION
*lpTimeZoneInformation
)