[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[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: 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 * @unimplemented
145 */
146 VOID
147 WINAPI
148 GetSystemTimePreciseAsFileTime(OUT PFILETIME lpFileTime)
149 {
150 STUB;
151 }
152
153 /*
154 * @implemented
155 */
156 BOOL
157 WINAPI
158 SystemTimeToFileTime(IN CONST SYSTEMTIME *lpSystemTime,
159 OUT LPFILETIME lpFileTime)
160 {
161 TIME_FIELDS TimeFields;
162 LARGE_INTEGER liTime;
163
164 TimeFields.Year = lpSystemTime->wYear;
165 TimeFields.Month = lpSystemTime->wMonth;
166 TimeFields.Day = lpSystemTime->wDay;
167 TimeFields.Hour = lpSystemTime->wHour;
168 TimeFields.Minute = lpSystemTime->wMinute;
169 TimeFields.Second = lpSystemTime->wSecond;
170 TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
171
172 if (RtlTimeFieldsToTime(&TimeFields, &liTime))
173 {
174 lpFileTime->dwLowDateTime = liTime.u.LowPart;
175 lpFileTime->dwHighDateTime = liTime.u.HighPart;
176 return TRUE;
177 }
178
179 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
180 return FALSE;
181 }
182
183 /*
184 * @implemented
185 */
186 BOOL
187 WINAPI
188 FileTimeToSystemTime(IN CONST FILETIME *lpFileTime,
189 OUT LPSYSTEMTIME lpSystemTime)
190 {
191 TIME_FIELDS TimeFields;
192 LARGE_INTEGER liTime;
193
194 liTime.u.LowPart = lpFileTime->dwLowDateTime;
195 liTime.u.HighPart = lpFileTime->dwHighDateTime;
196 if (liTime.QuadPart < 0)
197 {
198 SetLastError(ERROR_INVALID_PARAMETER);
199 return FALSE;
200 }
201
202 RtlTimeToTimeFields(&liTime, &TimeFields);
203
204 lpSystemTime->wYear = TimeFields.Year;
205 lpSystemTime->wMonth = TimeFields.Month;
206 lpSystemTime->wDay = TimeFields.Day;
207 lpSystemTime->wHour = TimeFields.Hour;
208 lpSystemTime->wMinute = TimeFields.Minute;
209 lpSystemTime->wSecond = TimeFields.Second;
210 lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
211 lpSystemTime->wDayOfWeek = TimeFields.Weekday;
212
213 return TRUE;
214 }
215
216 /*
217 * @implemented
218 */
219 BOOL
220 WINAPI
221 FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime,
222 OUT LPFILETIME lpLocalFileTime)
223 {
224 LARGE_INTEGER TimeZoneBias, FileTime;
225 volatile KSYSTEM_TIME *TimePtr;
226
227 TimePtr = IsTimeZoneRedirectionEnabled() ?
228 &BaseStaticServerData->ktTermsrvClientBias :
229 &SharedUserData->TimeZoneBias;
230 do
231 {
232 TimeZoneBias.HighPart = TimePtr->High1Time;
233 TimeZoneBias.LowPart = TimePtr->LowPart;
234 }
235 while (TimeZoneBias.HighPart != TimePtr->High2Time);
236
237 FileTime.LowPart = lpFileTime->dwLowDateTime;
238 FileTime.HighPart = lpFileTime->dwHighDateTime;
239
240 FileTime.QuadPart -= TimeZoneBias.QuadPart;
241
242 lpLocalFileTime->dwLowDateTime = FileTime.LowPart;
243 lpLocalFileTime->dwHighDateTime = FileTime.HighPart;
244
245 return TRUE;
246 }
247
248 /*
249 * @implemented
250 */
251 BOOL
252 WINAPI
253 LocalFileTimeToFileTime(IN CONST FILETIME *lpLocalFileTime,
254 OUT LPFILETIME lpFileTime)
255 {
256 LARGE_INTEGER TimeZoneBias, FileTime;
257 volatile KSYSTEM_TIME *TimePtr;
258
259 TimePtr = IsTimeZoneRedirectionEnabled() ?
260 &BaseStaticServerData->ktTermsrvClientBias :
261 &SharedUserData->TimeZoneBias;
262
263 do
264 {
265 TimeZoneBias.HighPart = TimePtr->High1Time;
266 TimeZoneBias.LowPart = TimePtr->LowPart;
267 }
268 while (TimeZoneBias.HighPart != TimePtr->High2Time);
269
270 FileTime.LowPart = lpLocalFileTime->dwLowDateTime;
271 FileTime.HighPart = lpLocalFileTime->dwHighDateTime;
272
273 FileTime.QuadPart += TimeZoneBias.QuadPart;
274
275 lpFileTime->dwLowDateTime = FileTime.LowPart;
276 lpFileTime->dwHighDateTime = FileTime.HighPart;
277
278 return TRUE;
279 }
280
281 /*
282 * @implemented
283 */
284 VOID
285 WINAPI
286 GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
287 {
288 LARGE_INTEGER SystemTime, TimeZoneBias;
289 TIME_FIELDS TimeFields;
290 volatile KSYSTEM_TIME *TimePtr;
291
292 do
293 {
294 SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
295 SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
296 }
297 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
298
299 TimePtr = IsTimeZoneRedirectionEnabled() ?
300 &BaseStaticServerData->ktTermsrvClientBias :
301 &SharedUserData->TimeZoneBias;
302 do
303 {
304 TimeZoneBias.HighPart = TimePtr->High1Time;
305 TimeZoneBias.LowPart = TimePtr->LowPart;
306 }
307 while (TimeZoneBias.HighPart != TimePtr->High2Time);
308
309 SystemTime.QuadPart -= TimeZoneBias.QuadPart;
310 RtlTimeToTimeFields(&SystemTime, &TimeFields);
311
312 lpSystemTime->wYear = TimeFields.Year;
313 lpSystemTime->wMonth = TimeFields.Month;
314 lpSystemTime->wDay = TimeFields.Day;
315 lpSystemTime->wHour = TimeFields.Hour;
316 lpSystemTime->wMinute = TimeFields.Minute;
317 lpSystemTime->wSecond = TimeFields.Second;
318 lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
319 lpSystemTime->wDayOfWeek = TimeFields.Weekday;
320 }
321
322 /*
323 * @implemented
324 */
325 VOID
326 WINAPI
327 GetSystemTime(OUT LPSYSTEMTIME lpSystemTime)
328 {
329 LARGE_INTEGER SystemTime;
330 TIME_FIELDS TimeFields;
331
332 do
333 {
334 SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
335 SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
336 }
337 while (SystemTime.HighPart != SharedUserData->SystemTime.High2Time);
338
339 RtlTimeToTimeFields(&SystemTime, &TimeFields);
340
341 lpSystemTime->wYear = TimeFields.Year;
342 lpSystemTime->wMonth = TimeFields.Month;
343 lpSystemTime->wDay = TimeFields.Day;
344 lpSystemTime->wHour = TimeFields.Hour;
345 lpSystemTime->wMinute = TimeFields.Minute;
346 lpSystemTime->wSecond = TimeFields.Second;
347 lpSystemTime->wMilliseconds = TimeFields.Milliseconds;
348 lpSystemTime->wDayOfWeek = TimeFields.Weekday;
349 }
350
351 /*
352 * @implemented
353 */
354 BOOL
355 WINAPI
356 SetLocalTime(IN CONST SYSTEMTIME *lpSystemTime)
357 {
358 LARGE_INTEGER NewSystemTime, TimeZoneBias;
359 NTSTATUS Status;
360 ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE;
361 TIME_FIELDS TimeFields;
362 PVOID State;
363 volatile KSYSTEM_TIME *TimePtr;
364
365 TimePtr = IsTimeZoneRedirectionEnabled() ?
366 &BaseStaticServerData->ktTermsrvClientBias :
367 &SharedUserData->TimeZoneBias;
368 do
369 {
370 TimeZoneBias.HighPart = TimePtr->High1Time;
371 TimeZoneBias.LowPart = TimePtr->LowPart;
372 }
373 while (TimeZoneBias.HighPart != TimePtr->High2Time);
374
375 TimeFields.Year = lpSystemTime->wYear;
376 TimeFields.Month = lpSystemTime->wMonth;
377 TimeFields.Day = lpSystemTime->wDay;
378 TimeFields.Hour = lpSystemTime->wHour;
379 TimeFields.Minute = lpSystemTime->wMinute;
380 TimeFields.Second = lpSystemTime->wSecond;
381 TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
382
383 if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime))
384 {
385 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
386 return FALSE;
387 }
388
389 NewSystemTime.QuadPart += TimeZoneBias.QuadPart;
390
391 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
392 if (NT_SUCCESS(Status))
393 {
394 Status = NtSetSystemTime(&NewSystemTime, NULL);
395 RtlReleasePrivilege(State);
396 }
397
398 if (!NT_SUCCESS(Status))
399 {
400 BaseSetLastNTError(Status);
401 return FALSE;
402 }
403
404 return TRUE;
405 }
406
407 /*
408 * @implemented
409 */
410 BOOL
411 WINAPI
412 SetSystemTime(IN CONST SYSTEMTIME *lpSystemTime)
413 {
414 LARGE_INTEGER NewSystemTime;
415 NTSTATUS Status;
416 ULONG Privilege = SE_SYSTEMTIME_PRIVILEGE;
417 TIME_FIELDS TimeFields;
418 PVOID State;
419
420 TimeFields.Year = lpSystemTime->wYear;
421 TimeFields.Month = lpSystemTime->wMonth;
422 TimeFields.Day = lpSystemTime->wDay;
423 TimeFields.Hour = lpSystemTime->wHour;
424 TimeFields.Minute = lpSystemTime->wMinute;
425 TimeFields.Second = lpSystemTime->wSecond;
426 TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
427
428 if (!RtlTimeFieldsToTime(&TimeFields, &NewSystemTime))
429 {
430 BaseSetLastNTError(STATUS_INVALID_PARAMETER);
431 return FALSE;
432 }
433
434 Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
435 if (NT_SUCCESS(Status))
436 {
437 Status = NtSetSystemTime(&NewSystemTime, NULL);
438 RtlReleasePrivilege(State);
439 }
440
441 if (!NT_SUCCESS(Status))
442 {
443 BaseSetLastNTError(Status);
444 return FALSE;
445 }
446
447 return TRUE;
448 }
449
450 /*
451 * @implemented
452 */
453 DWORD
454 WINAPI
455 GetTickCount(VOID)
456 {
457 ULARGE_INTEGER TickCount;
458
459 #ifdef _WIN64
460 TickCount.QuadPart = *((volatile ULONG64*)&SharedUserData->TickCount);
461 #else
462 while (TRUE)
463 {
464 TickCount.HighPart = (ULONG)SharedUserData->TickCount.High1Time;
465 TickCount.LowPart = SharedUserData->TickCount.LowPart;
466
467 if (TickCount.HighPart == (ULONG)SharedUserData->TickCount.High2Time)
468 break;
469
470 YieldProcessor();
471 }
472 #endif
473
474 return (ULONG)((UInt32x32To64(TickCount.LowPart,
475 SharedUserData->TickCountMultiplier) >> 24) +
476 UInt32x32To64((TickCount.HighPart << 8) & 0xFFFFFFFF,
477 SharedUserData->TickCountMultiplier));
478
479 }
480
481 /*
482 * @implemented
483 */
484 BOOL
485 WINAPI
486 GetSystemTimeAdjustment(OUT PDWORD lpTimeAdjustment,
487 OUT PDWORD lpTimeIncrement,
488 OUT PBOOL lpTimeAdjustmentDisabled)
489 {
490 SYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo;
491 NTSTATUS Status;
492
493 Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation,
494 &TimeInfo,
495 sizeof(TimeInfo),
496 NULL);
497 if (!NT_SUCCESS(Status))
498 {
499 BaseSetLastNTError(Status);
500 return FALSE;
501 }
502
503 *lpTimeAdjustment = (DWORD)TimeInfo.TimeAdjustment;
504 *lpTimeIncrement = (DWORD)TimeInfo.TimeIncrement;
505 *lpTimeAdjustmentDisabled = (BOOL)TimeInfo.Enable;
506
507 return TRUE;
508 }
509
510 /*
511 * @implemented
512 */
513 BOOL
514 WINAPI
515 SetSystemTimeAdjustment(IN DWORD dwTimeAdjustment,
516 IN BOOL bTimeAdjustmentDisabled)
517 {
518 NTSTATUS Status;
519 SYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo;
520
521 TimeInfo.TimeAdjustment = (ULONG)dwTimeAdjustment;
522 TimeInfo.Enable = (BOOLEAN)bTimeAdjustmentDisabled;
523
524 Status = NtSetSystemInformation(SystemTimeAdjustmentInformation,
525 &TimeInfo,
526 sizeof(TimeInfo));
527 if (!NT_SUCCESS(Status))
528 {
529 BaseSetLastNTError(Status);
530 return FALSE;
531 }
532
533 return TRUE;
534 }
535
536 /*
537 * @implemented
538 */
539 BOOL
540 WINAPI
541 GetSystemTimes(OUT LPFILETIME lpIdleTime OPTIONAL,
542 OUT LPFILETIME lpKernelTime OPTIONAL,
543 OUT LPFILETIME lpUserTime OPTIONAL)
544 {
545 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION ProcPerfInfo;
546 LARGE_INTEGER TotalUserTime, TotalKernTime, TotalIdleTime;
547 ULONG BufferSize, ReturnLength;
548 CCHAR i;
549 NTSTATUS Status;
550
551 TotalUserTime.QuadPart = TotalKernTime.QuadPart = TotalIdleTime.QuadPart = 0;
552
553 BufferSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) *
554 BaseStaticServerData->SysInfo.NumberOfProcessors;
555
556 ProcPerfInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
557 if (!ProcPerfInfo)
558 {
559 BaseSetLastNTError(STATUS_NO_MEMORY);
560 return FALSE;
561 }
562
563 Status = NtQuerySystemInformation(SystemProcessorPerformanceInformation,
564 ProcPerfInfo,
565 BufferSize,
566 &ReturnLength);
567 if ((NT_SUCCESS(Status)) && (ReturnLength == BufferSize))
568 {
569 if (lpIdleTime)
570 {
571 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
572 {
573 TotalIdleTime.QuadPart += ProcPerfInfo[i].IdleTime.QuadPart;
574 }
575
576 lpIdleTime->dwLowDateTime = TotalIdleTime.LowPart;
577 lpIdleTime->dwHighDateTime = TotalIdleTime.HighPart;
578 }
579
580 if (lpKernelTime)
581 {
582 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
583 {
584 TotalKernTime.QuadPart += ProcPerfInfo[i].KernelTime.QuadPart;
585 }
586
587 lpKernelTime->dwLowDateTime = TotalKernTime.LowPart;
588 lpKernelTime->dwHighDateTime = TotalKernTime.HighPart;
589 }
590
591 if (lpUserTime)
592 {
593 for (i = 0; i < BaseStaticServerData->SysInfo.NumberOfProcessors; i++)
594 {
595 TotalUserTime.QuadPart += ProcPerfInfo[i].UserTime.QuadPart;
596 }
597
598 lpUserTime->dwLowDateTime = TotalUserTime.LowPart;
599 lpUserTime->dwHighDateTime = TotalUserTime.HighPart;
600 }
601 }
602 else if (NT_SUCCESS(Status))
603 {
604 Status = STATUS_INTERNAL_ERROR;
605 }
606
607 RtlFreeHeap(RtlGetProcessHeap(), 0, ProcPerfInfo);
608 if (!NT_SUCCESS(Status))
609 {
610 BaseSetLastNTError(Status);
611 return FALSE;
612 }
613
614 return TRUE;
615 }
616
617 /*
618 * @unimplemented
619 */
620 BOOL
621 WINAPI
622 SetClientTimeZoneInformation(IN CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation)
623 {
624 STUB;
625 return 0;
626 }
627
628 /* EOF */