- volume.c: replace HeapAlloc to RtlAllocateHeap, HeapFree to RtlFreeHeap
[reactos.git] / reactos / dll / win32 / kernel32 / misc / time.c
1 /* $Id$
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 /* TYPES *********************************************************************/
21
22 typedef struct __DOSTIME
23 {
24 WORD Second:5;
25 WORD Minute:6;
26 WORD Hour:5;
27 } DOSTIME, *PDOSTIME;
28
29 typedef struct __DOSDATE
30 {
31 WORD Day:5;
32 WORD Month:4;
33 WORD Year:5;
34 } DOSDATE, *PDOSDATE;
35
36 #define TICKSPERMIN 600000000
37
38 #define LL2FILETIME( ll, pft )\
39 (pft)->dwLowDateTime = (UINT)(ll); \
40 (pft)->dwHighDateTime = (UINT)((ll) >> 32);
41 #define FILETIME2LL( pft, ll) \
42 ll = (((LONGLONG)((pft)->dwHighDateTime))<<32) + (pft)-> dwLowDateTime ;
43
44 static const int MonthLengths[2][12] =
45 {
46 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
47 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
48 };
49
50 /* STATIC FUNTIONS **********************************************************/
51
52 static inline int IsLeapYear(int Year)
53 {
54 return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0;
55 }
56
57 /***********************************************************************
58 * TIME_DayLightCompareDate
59 *
60 * Compares two dates without looking at the year.
61 *
62 * PARAMS
63 * date [in] The local time to compare.
64 * compareDate [in] The daylight savings begin or end date.
65 *
66 * RETURNS
67 *
68 * -1 if date < compareDate
69 * 0 if date == compareDate
70 * 1 if date > compareDate
71 * -2 if an error occurs
72 */
73 static int TIME_DayLightCompareDate( const SYSTEMTIME *date,
74 const SYSTEMTIME *compareDate )
75 {
76 int limit_day, dayinsecs;
77
78 if (date->wMonth < compareDate->wMonth)
79 return -1; /* We are in a month before the date limit. */
80
81 if (date->wMonth > compareDate->wMonth)
82 return 1; /* We are in a month after the date limit. */
83
84 /* if year is 0 then date is in day-of-week format, otherwise
85 * it's absolute date.
86 */
87 if (compareDate->wYear == 0)
88 {
89 WORD First;
90 /* compareDate->wDay is interpreted as number of the week in the month
91 * 5 means: the last week in the month */
92 int weekofmonth = compareDate->wDay;
93 /* calculate the day of the first DayOfWeek in the month */
94 First = ( 6 + compareDate->wDayOfWeek - date->wDayOfWeek + date->wDay
95 ) % 7 + 1;
96 limit_day = First + 7 * (weekofmonth - 1);
97 /* check needed for the 5th weekday of the month */
98 if(limit_day > MonthLengths[date->wMonth==2 && IsLeapYear(date->wYear)]
99 [date->wMonth - 1])
100 limit_day -= 7;
101 }
102 else
103 {
104 limit_day = compareDate->wDay;
105 }
106
107 /* convert to seconds */
108 limit_day = ((limit_day * 24 + compareDate->wHour) * 60 +
109 compareDate->wMinute ) * 60;
110 dayinsecs = ((date->wDay * 24 + date->wHour) * 60 +
111 date->wMinute ) * 60 + date->wSecond;
112 /* and compare */
113 return dayinsecs < limit_day ? -1 :
114 dayinsecs > limit_day ? 1 :
115 0; /* date is equal to the date limit. */
116 }
117
118 /***********************************************************************
119 * TIME_CompTimeZoneID
120 *
121 * Computes the local time bias for a given time and time zone.
122 *
123 * PARAMS
124 * pTZinfo [in] The time zone data.
125 * lpFileTime [in] The system or local time.
126 * islocal [in] it is local time.
127 *
128 * RETURNS
129 * TIME_ZONE_ID_INVALID An error occurred
130 * TIME_ZONE_ID_UNKNOWN There are no transition time known
131 * TIME_ZONE_ID_STANDARD Current time is standard time
132 * TIME_ZONE_ID_DAYLIGHT Current time is daylight savings time
133 */
134 static DWORD TIME_CompTimeZoneID ( const TIME_ZONE_INFORMATION *pTZinfo,
135 FILETIME *lpFileTime, BOOL islocal )
136 {
137 int ret;
138 BOOL beforeStandardDate, afterDaylightDate;
139 DWORD retval = TIME_ZONE_ID_INVALID;
140 LONGLONG llTime = 0; /* initialized to prevent gcc complaining */
141 SYSTEMTIME SysTime;
142 FILETIME ftTemp;
143
144 if (pTZinfo->DaylightDate.wMonth != 0)
145 {
146 /* if year is 0 then date is in day-of-week format, otherwise
147 * it's absolute date.
148 */
149 if (pTZinfo->StandardDate.wMonth == 0 ||
150 (pTZinfo->StandardDate.wYear == 0 &&
151 (pTZinfo->StandardDate.wDay<1 ||
152 pTZinfo->StandardDate.wDay>5 ||
153 pTZinfo->DaylightDate.wDay<1 ||
154 pTZinfo->DaylightDate.wDay>5)))
155 {
156 SetLastError(ERROR_INVALID_PARAMETER);
157 return TIME_ZONE_ID_INVALID;
158 }
159
160 if (!islocal) {
161 FILETIME2LL( lpFileTime, llTime );
162 llTime -= ( pTZinfo->Bias + pTZinfo->DaylightBias )
163 * (LONGLONG) TICKSPERMIN;
164 LL2FILETIME( llTime, &ftTemp)
165 lpFileTime = &ftTemp;
166 }
167
168 FileTimeToSystemTime(lpFileTime, &SysTime);
169
170 /* check for daylight savings */
171 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->StandardDate);
172 if (ret == -2)
173 return TIME_ZONE_ID_INVALID;
174
175 beforeStandardDate = ret < 0;
176
177 if (!islocal) {
178 llTime -= ( pTZinfo->StandardBias - pTZinfo->DaylightBias )
179 * (LONGLONG) TICKSPERMIN;
180 LL2FILETIME( llTime, &ftTemp)
181 FileTimeToSystemTime(lpFileTime, &SysTime);
182 }
183
184 ret = TIME_DayLightCompareDate( &SysTime, &pTZinfo->DaylightDate);
185 if (ret == -2)
186 return TIME_ZONE_ID_INVALID;
187
188 afterDaylightDate = ret >= 0;
189
190 retval = TIME_ZONE_ID_STANDARD;
191 if( pTZinfo->DaylightDate.wMonth < pTZinfo->StandardDate.wMonth ) {
192 /* Northern hemisphere */
193 if( beforeStandardDate && afterDaylightDate )
194 retval = TIME_ZONE_ID_DAYLIGHT;
195 } else /* Down south */
196 if( beforeStandardDate || afterDaylightDate )
197 retval = TIME_ZONE_ID_DAYLIGHT;
198 } else
199 /* No transition date */
200 retval = TIME_ZONE_ID_UNKNOWN;
201
202 return retval;
203 }
204
205 /***********************************************************************
206 * TIME_GetTimezoneBias
207 *
208 * Calculates the local time bias for a given time zone.
209 *
210 * PARAMS
211 * pTZinfo [in] The time zone data.
212 * lpFileTime [in] The system or local time.
213 * islocal [in] It is local time.
214 * pBias [out] The calculated bias in minutes.
215 *
216 * RETURNS
217 * TRUE when the time zone bias was calculated.
218 */
219 static BOOL TIME_GetTimezoneBias( const TIME_ZONE_INFORMATION *pTZinfo,
220 FILETIME *lpFileTime, BOOL islocal, LONG *pBias )
221 {
222 LONG bias = pTZinfo->Bias;
223 DWORD tzid = TIME_CompTimeZoneID( pTZinfo, lpFileTime, islocal);
224
225 if( tzid == TIME_ZONE_ID_INVALID)
226 return FALSE;
227 if (tzid == TIME_ZONE_ID_DAYLIGHT)
228 bias += pTZinfo->DaylightBias;
229 else if (tzid == TIME_ZONE_ID_STANDARD)
230 bias += pTZinfo->StandardBias;
231 *pBias = bias;
232 return TRUE;
233 }
234
235
236 /* FUNCTIONS ****************************************************************/
237
238 /*
239 * @implemented
240 */
241 BOOL
242 STDCALL
243 FileTimeToDosDateTime(
244 CONST FILETIME *lpFileTime,
245 LPWORD lpFatDate,
246 LPWORD lpFatTime
247 )
248 {
249 PDOSTIME pdtime=(PDOSTIME) lpFatTime;
250 PDOSDATE pddate=(PDOSDATE) lpFatDate;
251 SYSTEMTIME SystemTime = { 0 };
252
253 if ( lpFileTime == NULL )
254 return FALSE;
255
256 if ( lpFatDate == NULL )
257 return FALSE;
258
259 if ( lpFatTime == NULL )
260 return FALSE;
261
262 FileTimeToSystemTime(
263 lpFileTime,
264 &SystemTime
265 );
266
267 pdtime->Second = SystemTime.wSecond / 2;
268 pdtime->Minute = SystemTime.wMinute;
269 pdtime->Hour = SystemTime.wHour;
270
271 pddate->Day = SystemTime.wDay;
272 pddate->Month = SystemTime.wMonth;
273 pddate->Year = SystemTime.wYear - 1980;
274
275 return TRUE;
276 }
277
278
279 /*
280 * @implemented
281 */
282 BOOL
283 STDCALL
284 DosDateTimeToFileTime(
285 WORD wFatDate,
286 WORD wFatTime,
287 LPFILETIME lpFileTime
288 )
289 {
290 PDOSTIME pdtime = (PDOSTIME) &wFatTime;
291 PDOSDATE pddate = (PDOSDATE) &wFatDate;
292 SYSTEMTIME SystemTime;
293
294 if ( lpFileTime == NULL )
295 return FALSE;
296
297 SystemTime.wMilliseconds = 0;
298 SystemTime.wSecond = pdtime->Second * 2;
299 SystemTime.wMinute = pdtime->Minute;
300 SystemTime.wHour = pdtime->Hour;
301
302 SystemTime.wDay = pddate->Day;
303 SystemTime.wMonth = pddate->Month;
304 SystemTime.wYear = 1980 + pddate->Year;
305
306 SystemTimeToFileTime(&SystemTime,lpFileTime);
307
308 return TRUE;
309 }
310
311
312 /*
313 * @implemented
314 */
315 LONG
316 STDCALL
317 CompareFileTime(
318 CONST FILETIME *lpFileTime1,
319 CONST FILETIME *lpFileTime2
320 )
321 {
322 if ( lpFileTime1 == NULL )
323 return 0;
324 if ( lpFileTime2 == NULL )
325 return 0;
326
327 if (*((PLONGLONG)lpFileTime1) > *((PLONGLONG)lpFileTime2))
328 return 1;
329 else if (*((PLONGLONG)lpFileTime1) < *((PLONGLONG)lpFileTime2))
330 return -1;
331
332 return 0;
333 }
334
335
336 /*
337 * @implemented
338 */
339 VOID STDCALL
340 GetSystemTimeAsFileTime (PFILETIME lpFileTime)
341 {
342 do
343 {
344 lpFileTime->dwHighDateTime = SharedUserData->SystemTime.High1Time;
345 lpFileTime->dwLowDateTime = SharedUserData->SystemTime.LowPart;
346 }
347 while (lpFileTime->dwHighDateTime != (DWORD)SharedUserData->SystemTime.High2Time);
348 }
349
350
351 /*
352 * @implemented
353 */
354 BOOL
355 STDCALL
356 SystemTimeToFileTime(
357 CONST SYSTEMTIME * lpSystemTime,
358 LPFILETIME lpFileTime
359 )
360
361 {
362 TIME_FIELDS TimeFields;
363 LARGE_INTEGER liTime;
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, &liTime))
374 {
375 lpFileTime->dwLowDateTime = liTime.u.LowPart;
376 lpFileTime->dwHighDateTime = liTime.u.HighPart;
377 return TRUE;
378 }
379 return FALSE;
380 }
381
382
383 /*
384 * @implemented
385 */
386 BOOL
387 STDCALL
388 FileTimeToSystemTime(
389 CONST FILETIME *lpFileTime,
390 LPSYSTEMTIME lpSystemTime
391 )
392 {
393 TIME_FIELDS TimeFields;
394 LARGE_INTEGER liTime;
395
396 if(lpFileTime->dwHighDateTime & 0x80000000)
397 return FALSE;
398
399 liTime.u.LowPart = lpFileTime->dwLowDateTime;
400 liTime.u.HighPart = lpFileTime->dwHighDateTime;
401
402 RtlTimeToTimeFields(&liTime, &TimeFields);
403
404 lpSystemTime->wYear = TimeFields.Year;
405 lpSystemTime->wMonth = TimeFields.Month;
406 lpSystemTime->wDay = TimeFields.Day;
407 lpSystemTime->wHour = TimeFields.Hour;
408 lpSystemTime->wMinute = TimeFields.Minute;
409 lpSystemTime->wSecond = TimeFields.Second;
410 lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
411 lpSystemTime->wDayOfWeek = TimeFields.Weekday;
412
413 return TRUE;
414 }
415
416
417 /*
418 * @implemented
419 */
420 BOOL
421 STDCALL
422 FileTimeToLocalFileTime(
423 CONST FILETIME *lpFileTime,
424 LPFILETIME lpLocalFileTime
425 )
426 {
427 LARGE_INTEGER TimeZoneBias;
428
429 do
430 {
431 TimeZoneBias.HighPart = SharedUserData->TimeZoneBias.High1Time;
432 TimeZoneBias.LowPart = SharedUserData->TimeZoneBias.LowPart;
433 }
434 while (TimeZoneBias.HighPart != SharedUserData->TimeZoneBias.High2Time);
435
436 *((PLONGLONG)lpLocalFileTime) =
437 *((PLONGLONG)lpFileTime) - TimeZoneBias.QuadPart;
438
439 return TRUE;
440 }
441
442
443 /*
444 * @implemented
445 */
446 BOOL
447 STDCALL
448 LocalFileTimeToFileTime(
449 CONST FILETIME *lpLocalFileTime,
450 LPFILETIME lpFileTime
451 )
452 {
453 LARGE_INTEGER TimeZoneBias;
454
455 do
456 {
457 TimeZoneBias.HighPart = SharedUserData->TimeZoneBias.High1Time;
458 TimeZoneBias.LowPart = SharedUserData->TimeZoneBias.LowPart;
459 }
460 while (TimeZoneBias.HighPart != SharedUserData->TimeZoneBias.High2Time);
461
462 *((PLONGLONG)lpFileTime) =
463 *((PLONGLONG)lpLocalFileTime) + TimeZoneBias.QuadPart;
464
465 return TRUE;
466 }
467
468
469 /*
470 * @implemented
471 */
472 VOID STDCALL
473 GetLocalTime(LPSYSTEMTIME lpSystemTime)
474 {
475 FILETIME FileTime;
476 FILETIME LocalFileTime;
477
478 GetSystemTimeAsFileTime(&FileTime);
479 FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
480 FileTimeToSystemTime(&LocalFileTime, lpSystemTime);
481 }
482
483
484 /*
485 * @implemented
486 */
487 VOID STDCALL
488 GetSystemTime(LPSYSTEMTIME lpSystemTime)
489 {
490 FILETIME FileTime;
491
492 GetSystemTimeAsFileTime(&FileTime);
493 FileTimeToSystemTime(&FileTime, lpSystemTime);
494 }
495
496
497 /*
498 * @implemented
499 */
500 BOOL STDCALL
501 SetLocalTime(CONST SYSTEMTIME *lpSystemTime)
502 {
503 FILETIME LocalFileTime;
504 LARGE_INTEGER FileTime;
505 NTSTATUS Status;
506
507 SystemTimeToFileTime(lpSystemTime, &LocalFileTime);
508 LocalFileTimeToFileTime(&LocalFileTime, (FILETIME *)&FileTime);
509 Status = NtSetSystemTime(&FileTime, &FileTime);
510 if (!NT_SUCCESS(Status))
511 return FALSE;
512 return TRUE;
513 }
514
515
516 /*
517 * @implemented
518 */
519 BOOL STDCALL
520 SetSystemTime(CONST SYSTEMTIME *lpSystemTime)
521 {
522 LARGE_INTEGER NewSystemTime;
523 NTSTATUS Status;
524
525 SystemTimeToFileTime(lpSystemTime, (PFILETIME)&NewSystemTime);
526 Status = NtSetSystemTime(&NewSystemTime, &NewSystemTime);
527 if (!NT_SUCCESS(Status))
528 return FALSE;
529 return TRUE;
530 }
531
532
533 /*
534 * @implemented
535 */
536 DWORD STDCALL
537 GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation)
538 {
539 NTSTATUS Status;
540
541 DPRINT("GetTimeZoneInformation()\n");
542
543 Status = NtQuerySystemInformation(SystemCurrentTimeZoneInformation,
544 lpTimeZoneInformation,
545 sizeof(TIME_ZONE_INFORMATION),
546 NULL);
547 if (!NT_SUCCESS(Status))
548 {
549 SetLastErrorByStatus(Status);
550 return TIME_ZONE_ID_INVALID;
551 }
552
553 return(SharedUserData->TimeZoneId);
554 }
555
556
557 /*
558 * @implemented
559 */
560 BOOL STDCALL
561 SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
562 {
563 NTSTATUS Status;
564
565 DPRINT("SetTimeZoneInformation()\n");
566
567 Status = RtlSetTimeZoneInformation((LPTIME_ZONE_INFORMATION)lpTimeZoneInformation);
568 if (!NT_SUCCESS(Status))
569 {
570 DPRINT1("RtlSetTimeZoneInformation() failed (Status %lx)\n", Status);
571 SetLastErrorByStatus(Status);
572 return FALSE;
573 }
574
575 Status = NtSetSystemInformation(SystemCurrentTimeZoneInformation,
576 (PVOID)lpTimeZoneInformation,
577 sizeof(TIME_ZONE_INFORMATION));
578 if (!NT_SUCCESS(Status))
579 {
580 DPRINT1("NtSetSystemInformation() failed (Status %lx)\n", Status);
581 SetLastErrorByStatus(Status);
582 return FALSE;
583 }
584
585 return TRUE;
586 }
587
588
589 /*
590 * @implemented
591 */
592 DWORD STDCALL
593 GetTickCount(VOID)
594 {
595 return (DWORD)((ULONGLONG)SharedUserData->TickCountLowDeprecated * SharedUserData->TickCountMultiplier / 16777216);
596 }
597
598
599 /*
600 * @implemented
601 */
602 ULONGLONG WINAPI
603 GetTickCount64(VOID)
604 {
605 return (ULONGLONG)SharedUserData->TickCountLowDeprecated * (ULONGLONG)SharedUserData->TickCountMultiplier / 16777216;
606 }
607
608
609 /*
610 * @implemented
611 */
612 BOOL STDCALL
613 SystemTimeToTzSpecificLocalTime(
614 CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation,
615 CONST SYSTEMTIME *lpUniversalTime,
616 LPSYSTEMTIME lpLocalTime
617 )
618 {
619 TIME_ZONE_INFORMATION TimeZoneInformation;
620 LPTIME_ZONE_INFORMATION lpTzInfo;
621 LARGE_INTEGER FileTime;
622
623 if (!lpTimeZoneInformation)
624 {
625 GetTimeZoneInformation(&TimeZoneInformation);
626 lpTzInfo = &TimeZoneInformation;
627 }
628 else
629 lpTzInfo = (LPTIME_ZONE_INFORMATION)lpTimeZoneInformation;
630
631 if (!lpUniversalTime)
632 return FALSE;
633
634 if (!lpLocalTime)
635 return FALSE;
636
637 SystemTimeToFileTime(lpUniversalTime, (PFILETIME)&FileTime);
638 FileTime.QuadPart -= (lpTzInfo->Bias * TICKSPERMIN);
639 FileTimeToSystemTime((PFILETIME)&FileTime, lpLocalTime);
640
641 return TRUE;
642 }
643
644
645 /*
646 * @implemented (Wine 13 sep 2008)
647 */
648 BOOL
649 STDCALL
650 TzSpecificLocalTimeToSystemTime(
651 CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation,
652 CONST SYSTEMTIME *lpLocalTime,
653 LPSYSTEMTIME lpUniversalTime
654 )
655 {
656 FILETIME ft;
657 LONG lBias;
658 LONGLONG t;
659 TIME_ZONE_INFORMATION tzinfo;
660
661 if (lpTimeZoneInformation != NULL)
662 {
663 tzinfo = *lpTimeZoneInformation;
664 }
665 else
666 {
667 if (GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_INVALID)
668 return FALSE;
669 }
670
671 if (!SystemTimeToFileTime(lpLocalTime, &ft))
672 return FALSE;
673 FILETIME2LL( &ft, t)
674 if (!TIME_GetTimezoneBias(&tzinfo, &ft, TRUE, &lBias))
675 return FALSE;
676 /* convert minutes to 100-nanoseconds-ticks */
677 t += (LONGLONG)lBias * TICKSPERMIN;
678 LL2FILETIME( t, &ft)
679 return FileTimeToSystemTime(&ft, lpUniversalTime);
680 }
681
682
683 /*
684 * @implemented
685 */
686 BOOL STDCALL
687 GetSystemTimeAdjustment(PDWORD lpTimeAdjustment,
688 PDWORD lpTimeIncrement,
689 PBOOL lpTimeAdjustmentDisabled)
690 {
691 SYSTEM_QUERY_TIME_ADJUST_INFORMATION Buffer;
692 NTSTATUS Status;
693
694 Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation,
695 &Buffer,
696 sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION),
697 NULL);
698 if (!NT_SUCCESS(Status))
699 {
700 SetLastErrorByStatus(Status);
701 return FALSE;
702 }
703
704 *lpTimeAdjustment = (DWORD)Buffer.TimeAdjustment;
705 *lpTimeIncrement = (DWORD)Buffer.TimeIncrement;
706 *lpTimeAdjustmentDisabled = (BOOL)Buffer.Enable;
707
708 return TRUE;
709 }
710
711
712 /*
713 * @implemented
714 */
715 BOOL STDCALL
716 SetSystemTimeAdjustment(DWORD dwTimeAdjustment,
717 BOOL bTimeAdjustmentDisabled)
718 {
719 NTSTATUS Status;
720 SYSTEM_SET_TIME_ADJUST_INFORMATION Buffer;
721
722 Buffer.TimeAdjustment = (ULONG)dwTimeAdjustment;
723 Buffer.Enable = (BOOLEAN)bTimeAdjustmentDisabled;
724
725 Status = NtSetSystemInformation(SystemTimeAdjustmentInformation,
726 &Buffer,
727 sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION));
728 if (!NT_SUCCESS(Status))
729 {
730 SetLastErrorByStatus(Status);
731 return FALSE;
732 }
733
734 return TRUE;
735 }
736
737
738 /*
739 * @implemented
740 */
741 BOOL
742 STDCALL
743 GetSystemTimes(
744 LPFILETIME lpIdleTime,
745 LPFILETIME lpKernelTime,
746 LPFILETIME lpUserTime
747 )
748 {
749 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcPerfInfo;
750 NTSTATUS Status;
751
752 Status = ZwQuerySystemInformation(SystemProcessorPerformanceInformation,
753 &SysProcPerfInfo,
754 sizeof(SysProcPerfInfo),
755 NULL);
756
757 if (!NT_SUCCESS(Status))
758 {
759 SetLastErrorByStatus(Status);
760 return FALSE;
761 }
762 /*
763 Good only for one processor system.
764 */
765
766 lpIdleTime->dwLowDateTime = SysProcPerfInfo.IdleTime.LowPart;
767 lpIdleTime->dwHighDateTime = SysProcPerfInfo.IdleTime.HighPart;
768
769 lpKernelTime->dwLowDateTime = SysProcPerfInfo.KernelTime.LowPart;
770 lpKernelTime->dwHighDateTime = SysProcPerfInfo.KernelTime.HighPart;
771
772 lpUserTime->dwLowDateTime = SysProcPerfInfo.UserTime.LowPart;
773 lpUserTime->dwHighDateTime = SysProcPerfInfo.UserTime.HighPart;
774
775 return TRUE;
776 }
777
778 /* EOF */