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