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 SystemTimeToFileTime(IN CONST SYSTEMTIME
*lpSystemTime
,
149 OUT LPFILETIME lpFileTime
)
151 TIME_FIELDS TimeFields
;
152 LARGE_INTEGER liTime
;
154 TimeFields
.Year
= lpSystemTime
->wYear
;
155 TimeFields
.Month
= lpSystemTime
->wMonth
;
156 TimeFields
.Day
= lpSystemTime
->wDay
;
157 TimeFields
.Hour
= lpSystemTime
->wHour
;
158 TimeFields
.Minute
= lpSystemTime
->wMinute
;
159 TimeFields
.Second
= lpSystemTime
->wSecond
;
160 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
162 if (RtlTimeFieldsToTime(&TimeFields
, &liTime
))
164 lpFileTime
->dwLowDateTime
= liTime
.u
.LowPart
;
165 lpFileTime
->dwHighDateTime
= liTime
.u
.HighPart
;
169 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
178 FileTimeToSystemTime(IN CONST FILETIME
*lpFileTime
,
179 OUT LPSYSTEMTIME lpSystemTime
)
181 TIME_FIELDS TimeFields
;
182 LARGE_INTEGER liTime
;
184 liTime
.u
.LowPart
= lpFileTime
->dwLowDateTime
;
185 liTime
.u
.HighPart
= lpFileTime
->dwHighDateTime
;
186 if (liTime
.QuadPart
< 0)
188 SetLastError(ERROR_INVALID_PARAMETER
);
192 RtlTimeToTimeFields(&liTime
, &TimeFields
);
194 lpSystemTime
->wYear
= TimeFields
.Year
;
195 lpSystemTime
->wMonth
= TimeFields
.Month
;
196 lpSystemTime
->wDay
= TimeFields
.Day
;
197 lpSystemTime
->wHour
= TimeFields
.Hour
;
198 lpSystemTime
->wMinute
= TimeFields
.Minute
;
199 lpSystemTime
->wSecond
= TimeFields
.Second
;
200 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
201 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
211 FileTimeToLocalFileTime(IN CONST FILETIME
*lpFileTime
,
212 OUT LPFILETIME lpLocalFileTime
)
214 LARGE_INTEGER TimeZoneBias
, FileTime
;
215 volatile KSYSTEM_TIME
*TimePtr
;
217 TimePtr
= IsTimeZoneRedirectionEnabled() ?
218 &BaseStaticServerData
->ktTermsrvClientBias
:
219 &SharedUserData
->TimeZoneBias
;
222 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
223 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
225 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
227 FileTime
.LowPart
= lpFileTime
->dwLowDateTime
;
228 FileTime
.HighPart
= lpFileTime
->dwHighDateTime
;
230 FileTime
.QuadPart
-= TimeZoneBias
.QuadPart
;
232 lpLocalFileTime
->dwLowDateTime
= FileTime
.LowPart
;
233 lpLocalFileTime
->dwHighDateTime
= FileTime
.HighPart
;
243 LocalFileTimeToFileTime(IN CONST FILETIME
*lpLocalFileTime
,
244 OUT LPFILETIME lpFileTime
)
246 LARGE_INTEGER TimeZoneBias
, FileTime
;
247 volatile KSYSTEM_TIME
*TimePtr
;
249 TimePtr
= IsTimeZoneRedirectionEnabled() ?
250 &BaseStaticServerData
->ktTermsrvClientBias
:
251 &SharedUserData
->TimeZoneBias
;
255 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
256 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
258 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
260 FileTime
.LowPart
= lpLocalFileTime
->dwLowDateTime
;
261 FileTime
.HighPart
= lpLocalFileTime
->dwHighDateTime
;
263 FileTime
.QuadPart
+= TimeZoneBias
.QuadPart
;
265 lpFileTime
->dwLowDateTime
= FileTime
.LowPart
;
266 lpFileTime
->dwHighDateTime
= FileTime
.HighPart
;
276 GetLocalTime(OUT LPSYSTEMTIME lpSystemTime
)
278 LARGE_INTEGER SystemTime
, TimeZoneBias
;
279 TIME_FIELDS TimeFields
;
280 volatile KSYSTEM_TIME
*TimePtr
;
284 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
285 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
287 while (SystemTime
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
289 TimePtr
= IsTimeZoneRedirectionEnabled() ?
290 &BaseStaticServerData
->ktTermsrvClientBias
:
291 &SharedUserData
->TimeZoneBias
;
294 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
295 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
297 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
299 SystemTime
.QuadPart
-= TimeZoneBias
.QuadPart
;
300 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
302 lpSystemTime
->wYear
= TimeFields
.Year
;
303 lpSystemTime
->wMonth
= TimeFields
.Month
;
304 lpSystemTime
->wDay
= TimeFields
.Day
;
305 lpSystemTime
->wHour
= TimeFields
.Hour
;
306 lpSystemTime
->wMinute
= TimeFields
.Minute
;
307 lpSystemTime
->wSecond
= TimeFields
.Second
;
308 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
309 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
317 GetSystemTime(OUT LPSYSTEMTIME lpSystemTime
)
319 LARGE_INTEGER SystemTime
;
320 TIME_FIELDS TimeFields
;
324 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
325 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
327 while (SystemTime
.HighPart
!= SharedUserData
->SystemTime
.High2Time
);
329 RtlTimeToTimeFields(&SystemTime
, &TimeFields
);
331 lpSystemTime
->wYear
= TimeFields
.Year
;
332 lpSystemTime
->wMonth
= TimeFields
.Month
;
333 lpSystemTime
->wDay
= TimeFields
.Day
;
334 lpSystemTime
->wHour
= TimeFields
.Hour
;
335 lpSystemTime
->wMinute
= TimeFields
.Minute
;
336 lpSystemTime
->wSecond
= TimeFields
.Second
;
337 lpSystemTime
->wMilliseconds
= TimeFields
.Milliseconds
;
338 lpSystemTime
->wDayOfWeek
= TimeFields
.Weekday
;
346 SetLocalTime(IN CONST SYSTEMTIME
*lpSystemTime
)
348 LARGE_INTEGER NewSystemTime
, TimeZoneBias
;
350 ULONG Privilege
= SE_SYSTEMTIME_PRIVILEGE
;
351 TIME_FIELDS TimeFields
;
353 volatile KSYSTEM_TIME
*TimePtr
;
355 TimePtr
= IsTimeZoneRedirectionEnabled() ?
356 &BaseStaticServerData
->ktTermsrvClientBias
:
357 &SharedUserData
->TimeZoneBias
;
360 TimeZoneBias
.HighPart
= TimePtr
->High1Time
;
361 TimeZoneBias
.LowPart
= TimePtr
->LowPart
;
363 while (TimeZoneBias
.HighPart
!= TimePtr
->High2Time
);
365 TimeFields
.Year
= lpSystemTime
->wYear
;
366 TimeFields
.Month
= lpSystemTime
->wMonth
;
367 TimeFields
.Day
= lpSystemTime
->wDay
;
368 TimeFields
.Hour
= lpSystemTime
->wHour
;
369 TimeFields
.Minute
= lpSystemTime
->wMinute
;
370 TimeFields
.Second
= lpSystemTime
->wSecond
;
371 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
373 if (!RtlTimeFieldsToTime(&TimeFields
, &NewSystemTime
))
375 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
379 NewSystemTime
.QuadPart
+= TimeZoneBias
.QuadPart
;
381 Status
= RtlAcquirePrivilege(&Privilege
, 1, 0, &State
);
382 if (NT_SUCCESS(Status
))
384 Status
= NtSetSystemTime(&NewSystemTime
, NULL
);
385 RtlReleasePrivilege(State
);
388 if (!NT_SUCCESS(Status
))
390 BaseSetLastNTError(Status
);
402 SetSystemTime(IN CONST SYSTEMTIME
*lpSystemTime
)
404 LARGE_INTEGER NewSystemTime
;
406 ULONG Privilege
= SE_SYSTEMTIME_PRIVILEGE
;
407 TIME_FIELDS TimeFields
;
410 TimeFields
.Year
= lpSystemTime
->wYear
;
411 TimeFields
.Month
= lpSystemTime
->wMonth
;
412 TimeFields
.Day
= lpSystemTime
->wDay
;
413 TimeFields
.Hour
= lpSystemTime
->wHour
;
414 TimeFields
.Minute
= lpSystemTime
->wMinute
;
415 TimeFields
.Second
= lpSystemTime
->wSecond
;
416 TimeFields
.Milliseconds
= lpSystemTime
->wMilliseconds
;
418 if (!RtlTimeFieldsToTime(&TimeFields
, &NewSystemTime
))
420 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
424 Status
= RtlAcquirePrivilege(&Privilege
, 1, 0, &State
);
425 if (NT_SUCCESS(Status
))
427 Status
= NtSetSystemTime(&NewSystemTime
, NULL
);
428 RtlReleasePrivilege(State
);
431 if (!NT_SUCCESS(Status
))
433 BaseSetLastNTError(Status
);
447 ULARGE_INTEGER TickCount
;
450 TickCount
.QuadPart
= *((volatile ULONG64
*)&SharedUserData
->TickCount
);
454 TickCount
.HighPart
= (ULONG
)SharedUserData
->TickCount
.High1Time
;
455 TickCount
.LowPart
= SharedUserData
->TickCount
.LowPart
;
457 if (TickCount
.HighPart
== (ULONG
)SharedUserData
->TickCount
.High2Time
)
464 return (ULONG
)((UInt32x32To64(TickCount
.LowPart
,
465 SharedUserData
->TickCountMultiplier
) >> 24) +
466 UInt32x32To64((TickCount
.HighPart
<< 8) & 0xFFFFFFFF,
467 SharedUserData
->TickCountMultiplier
));
476 GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment
,
477 OUT PDWORD lpTimeIncrement
,
478 OUT PBOOL lpTimeAdjustmentDisabled
)
480 SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo
;
483 Status
= NtQuerySystemInformation(SystemTimeAdjustmentInformation
,
487 if (!NT_SUCCESS(Status
))
489 BaseSetLastNTError(Status
);
493 *lpTimeAdjustment
= (DWORD
)TimeInfo
.TimeAdjustment
;
494 *lpTimeIncrement
= (DWORD
)TimeInfo
.TimeIncrement
;
495 *lpTimeAdjustmentDisabled
= (BOOL
)TimeInfo
.Enable
;
505 SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment
,
506 IN BOOL bTimeAdjustmentDisabled
)
509 SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo
;
511 TimeInfo
.TimeAdjustment
= (ULONG
)dwTimeAdjustment
;
512 TimeInfo
.Enable
= (BOOLEAN
)bTimeAdjustmentDisabled
;
514 Status
= NtSetSystemInformation(SystemTimeAdjustmentInformation
,
517 if (!NT_SUCCESS(Status
))
519 BaseSetLastNTError(Status
);
531 GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL
,
532 OUT LPFILETIME lpKernelTime OPTIONAL
,
533 OUT LPFILETIME lpUserTime OPTIONAL
)
535 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo
;
536 LARGE_INTEGER TotalUserTime
, TotalKernTime
, TotalIdleTime
;
537 SIZE_T BufferSize
, ReturnLength
;
541 TotalUserTime
.QuadPart
= TotalKernTime
.QuadPart
= TotalIdleTime
.QuadPart
= 0;
543 BufferSize
= sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
) *
544 BaseStaticServerData
->SysInfo
.NumberOfProcessors
;
546 ProcPerfInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize
);
549 BaseSetLastNTError(STATUS_NO_MEMORY
);
553 Status
= NtQuerySystemInformation(SystemProcessorPerformanceInformation
,
557 if ((NT_SUCCESS(Status
)) && (ReturnLength
== BufferSize
))
561 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
563 TotalIdleTime
.QuadPart
+= ProcPerfInfo
[i
].IdleTime
.QuadPart
;
566 lpIdleTime
->dwLowDateTime
= TotalIdleTime
.LowPart
;
567 lpIdleTime
->dwHighDateTime
= TotalIdleTime
.HighPart
;
572 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
574 TotalKernTime
.QuadPart
+= ProcPerfInfo
[i
].KernelTime
.QuadPart
;
577 lpKernelTime
->dwLowDateTime
= TotalKernTime
.LowPart
;
578 lpKernelTime
->dwHighDateTime
= TotalKernTime
.HighPart
;
583 for (i
= 0; i
< BaseStaticServerData
->SysInfo
.NumberOfProcessors
; i
++)
585 TotalUserTime
.QuadPart
+= ProcPerfInfo
[i
].UserTime
.QuadPart
;
588 lpUserTime
->dwLowDateTime
= TotalUserTime
.LowPart
;
589 lpUserTime
->dwHighDateTime
= TotalUserTime
.HighPart
;
592 else if (NT_SUCCESS(Status
))
594 Status
= STATUS_INTERNAL_ERROR
;
597 RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo
);
598 if (!NT_SUCCESS(Status
))
600 BaseSetLastNTError(Status
);
612 SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION
*lpTimeZoneInformation
)