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 ULONG 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 */ 619