c52dcc3dae0f8a63849316399df1c47f36ca6f96
[reactos.git] / reactos / dll / win32 / kernel32 / client / time.c
1 /*
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
6 * PROGRAMMER: Ariadne
7 * DOSDATE and DOSTIME structures from Onno Hovers
8 * UPDATE HISTORY:
9 * Created 19/01/99
10 */
11
12 /* INCLUDES *******************************************************************/
13
14 #include <k32.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS ******************************************************************/
20
21 /*
22 * @implemented
23 */
24 BOOL
25 WINAPI
26 IsTimeZoneRedirectionEnabled(VOID)
27 {
28 /* Return if a TS Timezone ID is active */
29 return (BaseStaticServerData->TermsrvClientTimeZoneId != TIME_ZONE_ID_INVALID);
30 }
31
32 /*
33 * @implemented
34 */
35 BOOL
36 WINAPI
37 FileTimeToDosDateTime(IN CONST FILETIME *lpFileTime,
38 OUT LPWORD lpFatDate,
39 OUT LPWORD lpFatTime)
40 {
41 LARGE_INTEGER FileTime;
42 TIME_FIELDS TimeFields;
43
44 FileTime.HighPart = lpFileTime->dwHighDateTime;
45 FileTime.LowPart = lpFileTime->dwLowDateTime;
46
47 if (FileTime.QuadPart < 0)
48 {
49 SetLastError(ERROR_INVALID_PARAMETER);
50 return FALSE;
51 }
52
53 RtlTimeToTimeFields(&FileTime, &TimeFields);
54 if ((TimeFields.Year < 1980) || (TimeFields.Year > 2107))
55 {
56 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
57 return FALSE;
58 }
59
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);
66
67 return TRUE;
68 }
69
70 /*
71 * @implemented
72 */
73 BOOL
74 WINAPI
75 DosDateTimeToFileTime(IN WORD wFatDate,
76 IN WORD wFatTime,
77 OUT LPFILETIME lpFileTime)
78 {
79 TIME_FIELDS TimeFields;
80 LARGE_INTEGER SystemTime;
81
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;
89
90 if (RtlTimeFieldsToTime(&TimeFields, &SystemTime))
91 {
92 lpFileTime->dwLowDateTime = SystemTime.LowPart;
93 lpFileTime->dwHighDateTime = SystemTime.HighPart;
94 return TRUE;
95 }
96
97 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
98 return FALSE;
99 }
100
101 /*
102 * @implemented
103 */
104 LONG
105 WINAPI
106 CompareFileTime(IN CONST FILETIME *lpFileTime1,
107 IN CONST FILETIME *lpFileTime2)
108 {
109 LARGE_INTEGER Time1, Time2, Diff;
110
111 Time1.LowPart = lpFileTime1->dwLowDateTime;
112 Time2.LowPart = lpFileTime2->dwLowDateTime;
113 Time1.HighPart = lpFileTime1->dwHighDateTime;
114 Time2.HighPart = lpFileTime2->dwHighDateTime;
115
116 Diff.QuadPart = Time1.QuadPart - Time2.QuadPart;
117
118 if (Diff.HighPart < 0) return -1;
119 if (Diff.QuadPart == 0) return 0;
120 return 1;
121 }
122
123 /*
124 * @implemented
125 */
126 VOID
127 WINAPI
128 GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
129 {
130 LARGE_INTEGER SystemTime;
131
132 do
133 {
134 SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
135 SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
136 }
137 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
138
139 lpFileTime->dwLowDateTime = SystemTime.LowPart;
140 lpFileTime->dwHighDateTime = SystemTime.HighPart;
141 }
142
143 /*
144 * @implemented
145 */
146 BOOL
147 WINAPI
148 SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime,
149 OUT LPFILETIME lpFileTime)
150 {
151 TIME_FIELDS TimeFields;
152 LARGE_INTEGER liTime;
153
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;
161
162 if (RtlTimeFieldsToTime(&TimeFields, &liTime))
163 {
164 lpFileTime->dwLowDateTime = liTime.u.LowPart;
165 lpFileTime->dwHighDateTime = liTime.u.HighPart;
166 return TRUE;
167 }
168
169 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
170 return FALSE;
171 }
172
173 /*
174 * @implemented
175 */
176 BOOL
177 WINAPI
178 FileTimeToSystemTime(IN CONST FILETIME *lpFileTime,
179 OUT LPSYSTEMTIME lpSystemTime)
180 {
181 TIME_FIELDS TimeFields;
182 LARGE_INTEGER liTime;
183
184 liTime.u.LowPart = lpFileTime->dwLowDateTime;
185 liTime.u.HighPart = lpFileTime->dwHighDateTime;
186 if (liTime.QuadPart < 0)
187 {
188 SetLastError(ERROR_INVALID_PARAMETER);
189 return FALSE;
190 }
191
192 RtlTimeToTimeFields(&liTime, &TimeFields);
193
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;
202
203 return TRUE;
204 }
205
206 /*
207 * @implemented
208 */
209 BOOL
210 WINAPI
211 FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime,
212 OUT LPFILETIME lpLocalFileTime)
213 {
214 LARGE_INTEGER TimeZoneBias, FileTime;
215 volatile KSYSTEM_TIME *TimePtr;
216
217 TimePtr = IsTimeZoneRedirectionEnabled() ?
218 &BaseStaticServerData->ktTermsrvClientBias :
219 &SharedUserData->TimeZoneBias;
220 do
221 {
222 TimeZoneBias.HighPart = TimePtr->High1Time;
223 TimeZoneBias.LowPart = TimePtr->LowPart;
224 }
225 while (TimeZoneBias.HighPart != TimePtr->High2Time);
226
227 FileTime.LowPart = lpFileTime->dwLowDateTime;
228 FileTime.HighPart = lpFileTime->dwHighDateTime;
229
230 FileTime.QuadPart -= TimeZoneBias.QuadPart;
231
232 lpLocalFileTime->dwLowDateTime = FileTime.LowPart;
233 lpLocalFileTime->dwHighDateTime = FileTime.HighPart;
234
235 return TRUE;
236 }
237
238 /*
239 * @implemented
240 */
241 BOOL
242 WINAPI
243 LocalFileTimeToFileTime(IN CONST FILETIME *lpLocalFileTime,
244 OUT LPFILETIME lpFileTime)
245 {
246 LARGE_INTEGER TimeZoneBias, FileTime;
247 volatile KSYSTEM_TIME *TimePtr;
248
249 TimePtr = IsTimeZoneRedirectionEnabled() ?
250 &BaseStaticServerData->ktTermsrvClientBias :
251 &SharedUserData->TimeZoneBias;
252
253 do
254 {
255 TimeZoneBias.HighPart = TimePtr->High1Time;
256 TimeZoneBias.LowPart = TimePtr->LowPart;
257 }
258 while (TimeZoneBias.HighPart != TimePtr->High2Time);
259
260 FileTime.LowPart = lpLocalFileTime->dwLowDateTime;
261 FileTime.HighPart = lpLocalFileTime->dwHighDateTime;
262
263 FileTime.QuadPart += TimeZoneBias.QuadPart;
264
265 lpFileTime->dwLowDateTime = FileTime.LowPart;
266 lpFileTime->dwHighDateTime = FileTime.HighPart;
267
268 return TRUE;
269 }
270
271 /*
272 * @implemented
273 */
274 VOID
275 WINAPI
276 GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
277 {
278 LARGE_INTEGER SystemTime, TimeZoneBias;
279 TIME_FIELDS TimeFields;
280 volatile KSYSTEM_TIME *TimePtr;
281
282 do
283 {
284 SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
285 SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
286 }
287 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
288
289 TimePtr = IsTimeZoneRedirectionEnabled() ?
290 &BaseStaticServerData->ktTermsrvClientBias :
291 &SharedUserData->TimeZoneBias;
292 do
293 {
294 TimeZoneBias.HighPart = TimePtr->High1Time;
295 TimeZoneBias.LowPart = TimePtr->LowPart;
296 }
297 while (TimeZoneBias.HighPart != TimePtr->High2Time);
298
299 SystemTime.QuadPart -= TimeZoneBias.QuadPart;
300 RtlTimeToTimeFields(&SystemTime, &TimeFields);
301
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;
310 }
311
312 /*
313 * @implemented
314 */
315 VOID
316 WINAPI
317 GetSystemTime(OUT LPSYSTEMTIME lpSystemTime)
318 {
319 LARGE_INTEGER SystemTime;
320 TIME_FIELDS TimeFields;
321
322 do
323 {
324 SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
325 SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
326 }
327 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
328
329 RtlTimeToTimeFields(&SystemTime, &TimeFields);
330
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;
339 }
340
341 /*
342 * @implemented
343 */
344 BOOL
345 WINAPI
346 SetLocalTime(IN CONST SYSTEMTIME *lpSystemTime)
347 {
348 LARGE_INTEGER NewSystemTime, TimeZoneBias;
349 NTSTATUS Status;
350 ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE;
351 TIME_FIELDS TimeFields;
352 PVOID State;
353 volatile KSYSTEM_TIME *TimePtr;
354
355 TimePtr = IsTimeZoneRedirectionEnabled() ?
356 &BaseStaticServerData->ktTermsrvClientBias :
357 &SharedUserData->TimeZoneBias;
358 do
359 {
360 TimeZoneBias.HighPart = TimePtr->High1Time;
361 TimeZoneBias.LowPart = TimePtr->LowPart;
362 }
363 while (TimeZoneBias.HighPart != TimePtr->High2Time);
364
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;
372
373 if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime))
374 {
375 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
376 return FALSE;
377 }
378
379 NewSystemTime.QuadPart += TimeZoneBias.QuadPart;
380
381 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
382 if (NT_SUCCESS(Status))
383 {
384 Status = NtSetSystemTime(&NewSystemTime, NULL);
385 RtlReleasePrivilege(State);
386 }
387
388 if (!NT_SUCCESS(Status))
389 {
390 BaseSetLastNTError(Status);
391 return FALSE;
392 }
393
394 return TRUE;
395 }
396
397 /*
398 * @implemented
399 */
400 BOOL
401 WINAPI
402 SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime)
403 {
404 LARGE_INTEGER NewSystemTime;
405 NTSTATUS Status;
406 ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE;
407 TIME_FIELDS TimeFields;
408 PVOID State;
409
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;
417
418 if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime))
419 {
420 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
421 return FALSE;
422 }
423
424 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
425 if (NT_SUCCESS(Status))
426 {
427 Status = NtSetSystemTime(&NewSystemTime, NULL);
428 RtlReleasePrivilege(State);
429 }
430
431 if (!NT_SUCCESS(Status))
432 {
433 BaseSetLastNTError(Status);
434 return FALSE;
435 }
436
437 return TRUE;
438 }
439
440 /*
441 * @implemented
442 */
443 DWORD
444 WINAPI
445 GetTickCount(VOID)
446 {
447 ULARGE_INTEGER TickCount;
448
449 #ifdef _WIN64
450 TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
451 #else
452 while (TRUE)
453 {
454 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
455 TickCount.LowPart = SharedUserData->TickCount.LowPart;
456
457 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
458 break;
459
460 YieldProcessor();
461 }
462 #endif
463
464 return (ULONG)((UInt32x32To64(TickCount.LowPart,
465 SharedUserData->TickCountMultiplier) >> 24) +
466 UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
467 SharedUserData->TickCountMultiplier));
468
469 }
470
471 /*
472 * @implemented
473 */
474 BOOL
475 WINAPI
476 GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment,
477 OUT PDWORD lpTimeIncrement,
478 OUT PBOOL lpTimeAdjustmentDisabled)
479 {
480 SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo;
481 NTSTATUS Status;
482
483 Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation,
484 &TimeInfo,
485 sizeof(TimeInfo),
486 NULL);
487 if (!NT_SUCCESS(Status))
488 {
489 BaseSetLastNTError(Status);
490 return FALSE;
491 }
492
493 *lpTimeAdjustment = (DWORD)TimeInfo.TimeAdjustment;
494 *lpTimeIncrement = (DWORD)TimeInfo.TimeIncrement;
495 *lpTimeAdjustmentDisabled = (BOOL)TimeInfo.Enable;
496
497 return TRUE;
498 }
499
500 /*
501 * @implemented
502 */
503 BOOL
504 WINAPI
505 SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment,
506 IN BOOL bTimeAdjustmentDisabled)
507 {
508 NTSTATUS Status;
509 SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo;
510
511 TimeInfo.TimeAdjustment = (ULONG)dwTimeAdjustment;
512 TimeInfo.Enable = (BOOLEAN)bTimeAdjustmentDisabled;
513
514 Status = NtSetSystemInformation(SystemTimeAdjustmentInformation,
515 &TimeInfo,
516 sizeof(TimeInfo));
517 if (!NT_SUCCESS(Status))
518 {
519 BaseSetLastNTError(Status);
520 return FALSE;
521 }
522
523 return TRUE;
524 }
525
526 /*
527 * @implemented
528 */
529 BOOL
530 WINAPI
531 GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL,
532 OUT LPFILETIME lpKernelTime OPTIONAL,
533 OUT LPFILETIME lpUserTime OPTIONAL)
534 {
535 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo;
536 LARGE_INTEGER TotalUserTime, TotalKernTime, TotalIdleTime;
537 SIZE_T BufferSize, ReturnLength;
538 CCHAR i;
539 NTSTATUS Status;
540
541 TotalUserTime.QuadPart = TotalKernTime.QuadPart = TotalIdleTime.QuadPart = 0;
542
543 BufferSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) *
544 BaseStaticServerData->SysInfo.NumberOfProcessors;
545
546 ProcPerfInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
547 if (!ProcPerfInfo)
548 {
549 BaseSetLastNTError(STATUS_NO_MEMORY);
550 return FALSE;
551 }
552
553 Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
554 ProcPerfInfo,
555 BufferSize,
556 &ReturnLength);
557 if ((NT_SUCCESS(Status)) && (ReturnLength == BufferSize))
558 {
559 if (lpIdleTime)
560 {
561 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
562 {
563 TotalIdleTime.QuadPart += ProcPerfInfo[i].IdleTime.QuadPart;
564 }
565
566 lpIdleTime->dwLowDateTime = TotalIdleTime.LowPart;
567 lpIdleTime->dwHighDateTime = TotalIdleTime.HighPart;
568 }
569
570 if (lpKernelTime)
571 {
572 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
573 {
574 TotalKernTime.QuadPart += ProcPerfInfo[i].KernelTime.QuadPart;
575 }
576
577 lpKernelTime->dwLowDateTime = TotalKernTime.LowPart;
578 lpKernelTime->dwHighDateTime = TotalKernTime.HighPart;
579 }
580
581 if (lpUserTime)
582 {
583 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
584 {
585 TotalUserTime.QuadPart += ProcPerfInfo[i].UserTime.QuadPart;
586 }
587
588 lpUserTime->dwLowDateTime = TotalUserTime.LowPart;
589 lpUserTime->dwHighDateTime = TotalUserTime.HighPart;
590 }
591 }
592 else if (NT_SUCCESS(Status))
593 {
594 Status = STATUS_INTERNAL_ERROR;
595 }
596
597 RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo);
598 if (!NT_SUCCESS(Status))
599 {
600 BaseSetLastNTError(Status);
601 return FALSE;
602 }
603
604 return TRUE;
605 }
606
607 /*
608 * @unimplemented
609 */
610 BOOL
611 WINAPI
612 SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
613 {
614 STUB;
615 return 0;
616 }
617
618 /* EOF */