Synchronize with trunk r58528.
[reactos.git] / dll / win32 / kernel32 / client / time.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/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 << 16);
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 Status = STATUS_SUCCESS;
383 if (NT_SUCCESS(Status))
384 {
385 Status = NtSetSystemTime(&NewSystemTime, NULL);
386 RtlReleasePrivilege(State);
387 }
388
389 if (!NT_SUCCESS(Status))
390 {
391 BaseSetLastNTError(Status);
392 return FALSE;
393 }
394
395 return TRUE;
396 }
397
398 /*
399 * @implemented
400 */
401 BOOL
402 WINAPI
403 SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime)
404 {
405 LARGE_INTEGER NewSystemTime;
406 NTSTATUS Status;
407 ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE;
408 TIME_FIELDS TimeFields;
409 PVOID State;
410
411 TimeFields.Year = lpSystemTime->wYear;
412 TimeFields.Month = lpSystemTime->wMonth;
413 TimeFields.Day = lpSystemTime->wDay;
414 TimeFields.Hour = lpSystemTime->wHour;
415 TimeFields.Minute = lpSystemTime->wMinute;
416 TimeFields.Second = lpSystemTime->wSecond;
417 TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
418
419 if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime))
420 {
421 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
422 return FALSE;
423 }
424
425 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
426 Status = STATUS_SUCCESS;
427 if (NT_SUCCESS(Status))
428 {
429 Status = NtSetSystemTime(&NewSystemTime, NULL);
430 RtlReleasePrivilege(State);
431 }
432
433 if (!NT_SUCCESS(Status))
434 {
435 BaseSetLastNTError(Status);
436 return FALSE;
437 }
438
439 return TRUE;
440 }
441
442 /*
443 * @implemented
444 */
445 DWORD
446 WINAPI
447 GetTickCount(VOID)
448 {
449 ULARGE_INTEGER TickCount;
450
451 while (TRUE)
452 {
453 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
454 TickCount.LowPart = SharedUserData->TickCount.LowPart;
455
456 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
457 break;
458
459 YieldProcessor();
460 }
461
462 return (ULONG)((UInt32x32To64(TickCount.LowPart,
463 SharedUserData->TickCountMultiplier) >> 24) +
464 UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
465 SharedUserData->TickCountMultiplier));
466
467 }
468
469 /*
470 * @implemented
471 */
472 BOOL
473 WINAPI
474 GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment,
475 OUT PDWORD lpTimeIncrement,
476 OUT PBOOL lpTimeAdjustmentDisabled)
477 {
478 SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo;
479 NTSTATUS Status;
480
481 Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation,
482 &TimeInfo,
483 sizeof(TimeInfo),
484 NULL);
485 if (!NT_SUCCESS(Status))
486 {
487 BaseSetLastNTError(Status);
488 return FALSE;
489 }
490
491 *lpTimeAdjustment = (DWORD)TimeInfo.TimeAdjustment;
492 *lpTimeIncrement = (DWORD)TimeInfo.TimeIncrement;
493 *lpTimeAdjustmentDisabled = (BOOL)TimeInfo.Enable;
494
495 return TRUE;
496 }
497
498 /*
499 * @implemented
500 */
501 BOOL
502 WINAPI
503 SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment,
504 IN BOOL bTimeAdjustmentDisabled)
505 {
506 NTSTATUS Status;
507 SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo;
508
509 TimeInfo.TimeAdjustment = (ULONG)dwTimeAdjustment;
510 TimeInfo.Enable = (BOOLEAN)bTimeAdjustmentDisabled;
511
512 Status = NtSetSystemInformation(SystemTimeAdjustmentInformation,
513 &TimeInfo,
514 sizeof(TimeInfo));
515 if (!NT_SUCCESS(Status))
516 {
517 BaseSetLastNTError(Status);
518 return FALSE;
519 }
520
521 return TRUE;
522 }
523
524 /*
525 * @implemented
526 */
527 BOOL
528 WINAPI
529 GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL,
530 OUT LPFILETIME lpKernelTime OPTIONAL,
531 OUT LPFILETIME lpUserTime OPTIONAL)
532 {
533 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo;
534 LARGE_INTEGER TotalUserTime, TotalKernTime, TotalIdleTime;
535 SIZE_T BufferSize, ReturnLength;
536 ULONG i;
537 NTSTATUS Status;
538
539 TotalUserTime.QuadPart = TotalKernTime.QuadPart = TotalIdleTime.QuadPart = 0;
540
541 BufferSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) *
542 BaseStaticServerData->SysInfo.NumberOfProcessors;
543
544 ProcPerfInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
545 if (!ProcPerfInfo)
546 {
547 BaseSetLastNTError(STATUS_NO_MEMORY);
548 return FALSE;
549 }
550
551 Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
552 ProcPerfInfo,
553 BufferSize,
554 &ReturnLength);
555 if ((NT_SUCCESS(Status)) && (ReturnLength == BufferSize))
556 {
557 if (lpIdleTime)
558 {
559 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
560 {
561 TotalIdleTime.QuadPart += ProcPerfInfo[i].IdleTime.QuadPart;
562 }
563
564 lpIdleTime->dwLowDateTime = TotalIdleTime.LowPart;
565 lpIdleTime->dwHighDateTime = TotalIdleTime.HighPart;
566 }
567
568 if (lpKernelTime)
569 {
570 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
571 {
572 TotalKernTime.QuadPart += ProcPerfInfo[i].KernelTime.QuadPart;
573 }
574
575 lpKernelTime->dwLowDateTime = TotalKernTime.LowPart;
576 lpKernelTime->dwHighDateTime = TotalKernTime.HighPart;
577 }
578
579 if (lpUserTime)
580 {
581 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
582 {
583 TotalUserTime.QuadPart += ProcPerfInfo[i].UserTime.QuadPart;
584 }
585
586 lpUserTime->dwLowDateTime = TotalUserTime.LowPart;
587 lpUserTime->dwHighDateTime = TotalUserTime.HighPart;
588 }
589 }
590 else if (NT_SUCCESS(Status))
591 {
592 Status = STATUS_INTERNAL_ERROR;
593 }
594
595 RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo);
596 if (!NT_SUCCESS(Status))
597 {
598 BaseSetLastNTError(Status);
599 return FALSE;
600 }
601
602 return TRUE;
603 }
604
605 /*
606 * @unimplemented
607 */
608 BOOL
609 WINAPI
610 SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
611 {
612 STUB;
613 return 0;
614 }
615
616 /* EOF */