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 */ 629