1 /* 2 * PROJECT: ReactOS Win32 Base API 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/kernel32/client/synch.c 5 * PURPOSE: Wrappers for the NT Wait Implementation 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 #include <k32.h> 11 12 #define NDEBUG 13 #include <debug.h> 14 15 #undef InterlockedIncrement 16 #undef InterlockedDecrement 17 #undef InterlockedExchange 18 #undef InterlockedExchangeAdd 19 #undef InterlockedCompareExchange 20 21 /* FUNCTIONS *****************************************************************/ 22 23 /* 24 * @implemented 25 */ 26 LONG 27 WINAPI 28 InterlockedIncrement(IN OUT LONG volatile *lpAddend) 29 { 30 return _InterlockedIncrement(lpAddend); 31 } 32 33 /* 34 * @implemented 35 */ 36 LONG 37 WINAPI 38 InterlockedDecrement(IN OUT LONG volatile *lpAddend) 39 { 40 return _InterlockedDecrement(lpAddend); 41 } 42 43 /* 44 * @implemented 45 */ 46 LONG 47 WINAPI 48 InterlockedExchange(IN OUT LONG volatile *Target, 49 IN LONG Value) 50 { 51 return _InterlockedExchange(Target, Value); 52 } 53 54 /* 55 * @implemented 56 */ 57 LONG 58 WINAPI 59 InterlockedExchangeAdd(IN OUT LONG volatile *Addend, 60 IN LONG Value) 61 { 62 return _InterlockedExchangeAdd(Addend, Value); 63 } 64 65 /* 66 * @implemented 67 */ 68 LONG 69 WINAPI 70 InterlockedCompareExchange(IN OUT LONG volatile *Destination, 71 IN LONG Exchange, 72 IN LONG Comperand) 73 { 74 return _InterlockedCompareExchange(Destination, Exchange, Comperand); 75 } 76 77 /* 78 * @implemented 79 */ 80 DWORD 81 WINAPI 82 WaitForSingleObject(IN HANDLE hHandle, 83 IN DWORD dwMilliseconds) 84 { 85 /* Call the extended API */ 86 return WaitForSingleObjectEx(hHandle, dwMilliseconds, FALSE); 87 } 88 89 /* 90 * @implemented 91 */ 92 DWORD 93 WINAPI 94 WaitForSingleObjectEx(IN HANDLE hHandle, 95 IN DWORD dwMilliseconds, 96 IN BOOL bAlertable) 97 { 98 PLARGE_INTEGER TimePtr; 99 LARGE_INTEGER Time; 100 NTSTATUS Status; 101 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; 102 103 /* APCs must execute with the default activation context */ 104 if (bAlertable) 105 { 106 /* Setup the frame */ 107 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 108 ActCtx.Size = sizeof(ActCtx); 109 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 110 RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); 111 } 112 113 /* Get real handle */ 114 hHandle = TranslateStdHandle(hHandle); 115 116 /* Check for console handle */ 117 if ((IsConsoleHandle(hHandle)) && (VerifyConsoleIoHandle(hHandle))) 118 { 119 /* Get the real wait handle */ 120 hHandle = GetConsoleInputWaitHandle(); 121 } 122 123 /* Convert the timeout */ 124 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); 125 126 /* Start wait loop */ 127 do 128 { 129 /* Do the wait */ 130 Status = NtWaitForSingleObject(hHandle, (BOOLEAN)bAlertable, TimePtr); 131 if (!NT_SUCCESS(Status)) 132 { 133 /* The wait failed */ 134 BaseSetLastNTError(Status); 135 Status = WAIT_FAILED; 136 } 137 } while ((Status == STATUS_ALERTED) && (bAlertable)); 138 139 /* Cleanup the activation context */ 140 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 141 142 /* Return wait status */ 143 return Status; 144 } 145 146 /* 147 * @implemented 148 */ 149 DWORD 150 WINAPI 151 WaitForMultipleObjects(IN DWORD nCount, 152 IN CONST HANDLE *lpHandles, 153 IN BOOL bWaitAll, 154 IN DWORD dwMilliseconds) 155 { 156 /* Call the extended API */ 157 return WaitForMultipleObjectsEx(nCount, 158 lpHandles, 159 bWaitAll, 160 dwMilliseconds, 161 FALSE); 162 } 163 164 /* 165 * @implemented 166 */ 167 DWORD 168 WINAPI 169 WaitForMultipleObjectsEx(IN DWORD nCount, 170 IN CONST HANDLE *lpHandles, 171 IN BOOL bWaitAll, 172 IN DWORD dwMilliseconds, 173 IN BOOL bAlertable) 174 { 175 PLARGE_INTEGER TimePtr; 176 LARGE_INTEGER Time; 177 PHANDLE HandleBuffer; 178 HANDLE Handle[8]; 179 DWORD i; 180 NTSTATUS Status; 181 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; 182 183 /* APCs must execute with the default activation context */ 184 if (bAlertable) 185 { 186 /* Setup the frame */ 187 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 188 ActCtx.Size = sizeof(ActCtx); 189 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 190 RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); 191 } 192 193 /* Check if we have more handles then we locally optimize */ 194 if (nCount > 8) 195 { 196 /* Allocate a buffer for them */ 197 HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 198 0, 199 nCount * sizeof(HANDLE)); 200 if (!HandleBuffer) 201 { 202 /* No buffer, fail the wait */ 203 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 204 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 205 return WAIT_FAILED; 206 } 207 } 208 else 209 { 210 /* Otherwise, use our local buffer */ 211 HandleBuffer = Handle; 212 } 213 214 /* Copy the handles into our buffer and loop them all */ 215 RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE)); 216 for (i = 0; i < nCount; i++) 217 { 218 /* Check what kind of handle this is */ 219 HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]); 220 221 /* Check for console handle */ 222 if ((IsConsoleHandle(HandleBuffer[i])) && 223 (VerifyConsoleIoHandle(HandleBuffer[i]))) 224 { 225 /* Get the real wait handle */ 226 HandleBuffer[i] = GetConsoleInputWaitHandle(); 227 } 228 } 229 230 /* Convert the timeout */ 231 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); 232 233 /* Start wait loop */ 234 do 235 { 236 /* Do the wait */ 237 Status = NtWaitForMultipleObjects(nCount, 238 HandleBuffer, 239 bWaitAll ? WaitAll : WaitAny, 240 (BOOLEAN)bAlertable, 241 TimePtr); 242 if (!NT_SUCCESS(Status)) 243 { 244 /* Wait failed */ 245 BaseSetLastNTError(Status); 246 Status = WAIT_FAILED; 247 } 248 } while ((Status == STATUS_ALERTED) && (bAlertable)); 249 250 /* Check if we didn't use our local buffer */ 251 if (HandleBuffer != Handle) 252 { 253 /* Free the allocated one */ 254 RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); 255 } 256 257 /* Cleanup the activation context */ 258 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 259 260 /* Return wait status */ 261 return Status; 262 } 263 264 /* 265 * @implemented 266 */ 267 DWORD 268 WINAPI 269 SignalObjectAndWait(IN HANDLE hObjectToSignal, 270 IN HANDLE hObjectToWaitOn, 271 IN DWORD dwMilliseconds, 272 IN BOOL bAlertable) 273 { 274 PLARGE_INTEGER TimePtr; 275 LARGE_INTEGER Time; 276 NTSTATUS Status; 277 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; 278 279 /* APCs must execute with the default activation context */ 280 if (bAlertable) 281 { 282 /* Setup the frame */ 283 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 284 ActCtx.Size = sizeof(ActCtx); 285 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 286 RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); 287 } 288 289 /* Get real handle */ 290 hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn); 291 292 /* Check for console handle */ 293 if ((IsConsoleHandle(hObjectToWaitOn)) && 294 (VerifyConsoleIoHandle(hObjectToWaitOn))) 295 { 296 /* Get the real wait handle */ 297 hObjectToWaitOn = GetConsoleInputWaitHandle(); 298 } 299 300 /* Convert the timeout */ 301 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); 302 303 /* Start wait loop */ 304 do 305 { 306 /* Do the wait */ 307 Status = NtSignalAndWaitForSingleObject(hObjectToSignal, 308 hObjectToWaitOn, 309 (BOOLEAN)bAlertable, 310 TimePtr); 311 if (!NT_SUCCESS(Status)) 312 { 313 /* The wait failed */ 314 BaseSetLastNTError(Status); 315 Status = WAIT_FAILED; 316 } 317 } while ((Status == STATUS_ALERTED) && (bAlertable)); 318 319 /* Cleanup the activation context */ 320 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 321 322 /* Return wait status */ 323 return Status; 324 } 325 326 /* 327 * @implemented 328 */ 329 HANDLE 330 WINAPI 331 CreateWaitableTimerW(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, 332 IN BOOL bManualReset, 333 IN LPCWSTR lpTimerName OPTIONAL) 334 { 335 CreateNtObjectFromWin32Api(WaitableTimer, Timer, TIMER_ALL_ACCESS, 336 lpTimerAttributes, 337 lpTimerName, 338 bManualReset ? NotificationTimer : SynchronizationTimer); 339 } 340 341 /* 342 * @implemented 343 */ 344 HANDLE 345 WINAPI 346 CreateWaitableTimerA(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL, 347 IN BOOL bManualReset, 348 IN LPCSTR lpTimerName OPTIONAL) 349 { 350 ConvertWin32AnsiObjectApiToUnicodeApi(WaitableTimer, lpTimerName, lpTimerAttributes, bManualReset); 351 } 352 353 /* 354 * @implemented 355 */ 356 HANDLE 357 WINAPI 358 OpenWaitableTimerW(IN DWORD dwDesiredAccess, 359 IN BOOL bInheritHandle, 360 IN LPCWSTR lpTimerName) 361 { 362 OpenNtObjectFromWin32Api(Timer, dwDesiredAccess, bInheritHandle, lpTimerName); 363 } 364 365 /* 366 * @implemented 367 */ 368 HANDLE 369 WINAPI 370 OpenWaitableTimerA(IN DWORD dwDesiredAccess, 371 IN BOOL bInheritHandle, 372 IN LPCSTR lpTimerName) 373 { 374 ConvertOpenWin32AnsiObjectApiToUnicodeApi(WaitableTimer, dwDesiredAccess, bInheritHandle, lpTimerName); 375 } 376 377 /* 378 * @implemented 379 */ 380 BOOL 381 WINAPI 382 SetWaitableTimer(IN HANDLE hTimer, 383 IN const LARGE_INTEGER *pDueTime, 384 IN LONG lPeriod, 385 IN PTIMERAPCROUTINE pfnCompletionRoutine OPTIONAL, 386 IN OPTIONAL LPVOID lpArgToCompletionRoutine, 387 IN BOOL fResume) 388 { 389 NTSTATUS Status; 390 391 /* Set the timer */ 392 Status = NtSetTimer(hTimer, 393 (PLARGE_INTEGER)pDueTime, 394 (PTIMER_APC_ROUTINE)pfnCompletionRoutine, 395 lpArgToCompletionRoutine, 396 (BOOLEAN)fResume, 397 lPeriod, 398 NULL); 399 if (NT_SUCCESS(Status)) return TRUE; 400 401 /* If we got here, then we failed */ 402 BaseSetLastNTError(Status); 403 return FALSE; 404 } 405 406 /* 407 * @implemented 408 */ 409 BOOL 410 WINAPI 411 CancelWaitableTimer(IN HANDLE hTimer) 412 { 413 NTSTATUS Status; 414 415 /* Cancel the timer */ 416 Status = NtCancelTimer(hTimer, NULL); 417 if (NT_SUCCESS(Status)) return TRUE; 418 419 /* If we got here, then we failed */ 420 BaseSetLastNTError(Status); 421 return FALSE; 422 } 423 424 /* 425 * @implemented 426 */ 427 HANDLE 428 WINAPI 429 DECLSPEC_HOTPATCH 430 CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, 431 IN LONG lInitialCount, 432 IN LONG lMaximumCount, 433 IN LPCSTR lpName OPTIONAL) 434 { 435 ConvertWin32AnsiObjectApiToUnicodeApi(Semaphore, lpName, lpSemaphoreAttributes, lInitialCount, lMaximumCount); 436 } 437 438 /* 439 * @implemented 440 */ 441 HANDLE 442 WINAPI 443 DECLSPEC_HOTPATCH 444 CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, 445 IN LONG lInitialCount, 446 IN LONG lMaximumCount, 447 IN LPCWSTR lpName OPTIONAL) 448 { 449 CreateNtObjectFromWin32Api(Semaphore, Semaphore, SEMAPHORE_ALL_ACCESS, 450 lpSemaphoreAttributes, 451 lpName, 452 lInitialCount, 453 lMaximumCount); 454 } 455 456 HANDLE 457 WINAPI 458 DECLSPEC_HOTPATCH 459 CreateSemaphoreExW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, 460 IN LONG lInitialCount, 461 IN LONG lMaximumCount, 462 IN LPCWSTR lpName OPTIONAL, 463 IN DWORD dwFlags OPTIONAL, 464 IN DWORD dwDesiredAccess OPTIONAL) 465 { 466 CreateNtObjectFromWin32Api(Semaphore, Semaphore, dwDesiredAccess, 467 lpSemaphoreAttributes, 468 lpName, 469 lInitialCount, 470 lMaximumCount); 471 } 472 473 HANDLE 474 WINAPI 475 DECLSPEC_HOTPATCH 476 CreateSemaphoreExA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, 477 IN LONG lInitialCount, 478 IN LONG lMaximumCount, 479 IN LPCSTR lpName OPTIONAL, 480 IN DWORD dwFlags OPTIONAL, 481 IN DWORD dwDesiredAccess OPTIONAL) 482 { 483 ConvertAnsiToUnicodePrologue 484 485 if (!lpName) 486 { 487 return CreateSemaphoreExW(lpSemaphoreAttributes, 488 lInitialCount, 489 lMaximumCount, 490 NULL, 491 dwFlags, 492 dwDesiredAccess); 493 } 494 495 ConvertAnsiToUnicodeBody(lpName) 496 497 if (NT_SUCCESS(Status)) 498 { 499 return CreateSemaphoreExW(lpSemaphoreAttributes, 500 lInitialCount, 501 lMaximumCount, 502 UnicodeCache->Buffer, 503 dwFlags, 504 dwDesiredAccess); 505 } 506 507 ConvertAnsiToUnicodeEpilogue 508 } 509 510 /* 511 * @implemented 512 */ 513 HANDLE 514 WINAPI 515 DECLSPEC_HOTPATCH 516 OpenSemaphoreA(IN DWORD dwDesiredAccess, 517 IN BOOL bInheritHandle, 518 IN LPCSTR lpName) 519 { 520 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Semaphore, dwDesiredAccess, bInheritHandle, lpName); 521 } 522 523 /* 524 * @implemented 525 */ 526 HANDLE 527 WINAPI 528 DECLSPEC_HOTPATCH 529 OpenSemaphoreW(IN DWORD dwDesiredAccess, 530 IN BOOL bInheritHandle, 531 IN LPCWSTR lpName) 532 { 533 OpenNtObjectFromWin32Api(Semaphore, dwDesiredAccess, bInheritHandle, lpName); 534 } 535 536 /* 537 * @implemented 538 */ 539 BOOL 540 WINAPI 541 DECLSPEC_HOTPATCH 542 ReleaseSemaphore(IN HANDLE hSemaphore, 543 IN LONG lReleaseCount, 544 IN LPLONG lpPreviousCount) 545 { 546 NTSTATUS Status; 547 548 /* Release the semaphore */ 549 Status = NtReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); 550 if (NT_SUCCESS(Status)) return TRUE; 551 552 /* If we got here, then we failed */ 553 BaseSetLastNTError(Status); 554 return FALSE; 555 } 556 557 /* 558 * @implemented 559 */ 560 HANDLE 561 WINAPI 562 DECLSPEC_HOTPATCH 563 CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, 564 IN BOOL bInitialOwner, 565 IN LPCSTR lpName OPTIONAL) 566 { 567 ConvertWin32AnsiObjectApiToUnicodeApi(Mutex, lpName, lpMutexAttributes, bInitialOwner); 568 } 569 570 /* 571 * @implemented 572 */ 573 HANDLE 574 WINAPI 575 DECLSPEC_HOTPATCH 576 CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, 577 IN BOOL bInitialOwner, 578 IN LPCWSTR lpName OPTIONAL) 579 { 580 CreateNtObjectFromWin32Api(Mutex, Mutant, MUTEX_ALL_ACCESS, 581 lpMutexAttributes, 582 lpName, 583 bInitialOwner); 584 } 585 586 /* 587 * @implemented 588 */ 589 HANDLE 590 WINAPI 591 DECLSPEC_HOTPATCH 592 OpenMutexA(IN DWORD dwDesiredAccess, 593 IN BOOL bInheritHandle, 594 IN LPCSTR lpName) 595 { 596 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Mutex, dwDesiredAccess, bInheritHandle, lpName); 597 } 598 599 /* 600 * @implemented 601 */ 602 HANDLE 603 WINAPI 604 DECLSPEC_HOTPATCH 605 OpenMutexW(IN DWORD dwDesiredAccess, 606 IN BOOL bInheritHandle, 607 IN LPCWSTR lpName) 608 { 609 OpenNtObjectFromWin32Api(Mutant, dwDesiredAccess, bInheritHandle, lpName); 610 } 611 612 /* 613 * @implemented 614 */ 615 BOOL 616 WINAPI 617 DECLSPEC_HOTPATCH 618 ReleaseMutex(IN HANDLE hMutex) 619 { 620 NTSTATUS Status; 621 622 /* Release the mutant */ 623 Status = NtReleaseMutant(hMutex, NULL); 624 if (NT_SUCCESS(Status)) return TRUE; 625 626 /* If we got here, then we failed */ 627 BaseSetLastNTError(Status); 628 return FALSE; 629 } 630 631 /* 632 * @implemented 633 */ 634 HANDLE 635 WINAPI 636 DECLSPEC_HOTPATCH 637 CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, 638 IN BOOL bManualReset, 639 IN BOOL bInitialState, 640 IN LPCSTR lpName OPTIONAL) 641 { 642 ConvertWin32AnsiObjectApiToUnicodeApi(Event, lpName, lpEventAttributes, bManualReset, bInitialState); 643 } 644 645 /* 646 * @implemented 647 */ 648 HANDLE 649 WINAPI 650 DECLSPEC_HOTPATCH 651 CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, 652 IN BOOL bManualReset, 653 IN BOOL bInitialState, 654 IN LPCWSTR lpName OPTIONAL) 655 { 656 CreateNtObjectFromWin32Api(Event, Event, EVENT_ALL_ACCESS, 657 lpEventAttributes, 658 lpName, 659 bManualReset ? NotificationEvent : SynchronizationEvent, 660 bInitialState); 661 } 662 663 /* 664 * @implemented 665 */ 666 HANDLE 667 WINAPI 668 DECLSPEC_HOTPATCH 669 OpenEventA(IN DWORD dwDesiredAccess, 670 IN BOOL bInheritHandle, 671 IN LPCSTR lpName) 672 { 673 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Event, dwDesiredAccess, bInheritHandle, lpName); 674 } 675 676 /* 677 * @implemented 678 */ 679 HANDLE 680 WINAPI 681 DECLSPEC_HOTPATCH 682 OpenEventW(IN DWORD dwDesiredAccess, 683 IN BOOL bInheritHandle, 684 IN LPCWSTR lpName) 685 { 686 OpenNtObjectFromWin32Api(Event, dwDesiredAccess, bInheritHandle, lpName); 687 } 688 689 /* 690 * @implemented 691 */ 692 BOOL 693 WINAPI 694 DECLSPEC_HOTPATCH 695 PulseEvent(IN HANDLE hEvent) 696 { 697 NTSTATUS Status; 698 699 /* Pulse the event */ 700 Status = NtPulseEvent(hEvent, NULL); 701 if (NT_SUCCESS(Status)) return TRUE; 702 703 /* If we got here, then we failed */ 704 BaseSetLastNTError(Status); 705 return FALSE; 706 } 707 708 /* 709 * @implemented 710 */ 711 BOOL 712 WINAPI 713 DECLSPEC_HOTPATCH 714 ResetEvent(IN HANDLE hEvent) 715 { 716 NTSTATUS Status; 717 718 /* Clear the event */ 719 Status = NtResetEvent(hEvent, NULL); 720 if (NT_SUCCESS(Status)) return TRUE; 721 722 /* If we got here, then we failed */ 723 BaseSetLastNTError(Status); 724 return FALSE; 725 } 726 727 /* 728 * @implemented 729 */ 730 BOOL 731 WINAPI 732 DECLSPEC_HOTPATCH 733 SetEvent(IN HANDLE hEvent) 734 { 735 NTSTATUS Status; 736 737 /* Set the event */ 738 Status = NtSetEvent(hEvent, NULL); 739 if (NT_SUCCESS(Status)) return TRUE; 740 741 /* If we got here, then we failed */ 742 BaseSetLastNTError(Status); 743 return FALSE; 744 } 745 746 /* 747 * @implemented 748 */ 749 VOID 750 WINAPI 751 InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection) 752 { 753 NTSTATUS Status; 754 755 /* Initialize the critical section and raise an exception if we failed */ 756 Status = RtlInitializeCriticalSection((PVOID)lpCriticalSection); 757 if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); 758 } 759 760 /* 761 * @implemented 762 */ 763 BOOL 764 WINAPI 765 InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection, 766 IN DWORD dwSpinCount) 767 { 768 NTSTATUS Status; 769 770 /* Initialize the critical section */ 771 Status = RtlInitializeCriticalSectionAndSpinCount((PVOID)lpCriticalSection, 772 dwSpinCount); 773 if (!NT_SUCCESS(Status)) 774 { 775 /* Set failure code */ 776 BaseSetLastNTError(Status); 777 return FALSE; 778 } 779 780 /* Success */ 781 return TRUE; 782 } 783 784 /* 785 * @implemented 786 */ 787 VOID 788 WINAPI 789 DECLSPEC_HOTPATCH 790 Sleep(IN DWORD dwMilliseconds) 791 { 792 /* Call the new API */ 793 SleepEx(dwMilliseconds, FALSE); 794 } 795 796 797 /* 798 * @implemented 799 */ 800 DWORD 801 WINAPI 802 SleepEx(IN DWORD dwMilliseconds, 803 IN BOOL bAlertable) 804 { 805 LARGE_INTEGER Time; 806 PLARGE_INTEGER TimePtr; 807 NTSTATUS errCode; 808 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; 809 810 /* APCs must execute with the default activation context */ 811 if (bAlertable) 812 { 813 /* Setup the frame */ 814 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 815 ActCtx.Size = sizeof(ActCtx); 816 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 817 RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); 818 } 819 820 /* Convert the timeout */ 821 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); 822 if (!TimePtr) 823 { 824 /* Turn an infinite wait into a really long wait */ 825 Time.LowPart = 0; 826 Time.HighPart = 0x80000000; 827 TimePtr = &Time; 828 } 829 830 /* Loop the delay while APCs are alerting us */ 831 do 832 { 833 /* Do the delay */ 834 errCode = NtDelayExecution((BOOLEAN)bAlertable, TimePtr); 835 } 836 while ((bAlertable) && (errCode == STATUS_ALERTED)); 837 838 /* Cleanup the activation context */ 839 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 840 841 /* Return the correct code */ 842 return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; 843 } 844 845 /* 846 * @implemented 847 */ 848 BOOL 849 WINAPI 850 RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject, 851 IN HANDLE hObject, 852 IN WAITORTIMERCALLBACK Callback, 853 IN PVOID Context, 854 IN ULONG dwMilliseconds, 855 IN ULONG dwFlags) 856 { 857 NTSTATUS Status; 858 859 /* Get real handle */ 860 hObject = TranslateStdHandle(hObject); 861 862 /* Check for console handle */ 863 if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) 864 { 865 /* Get the real wait handle */ 866 hObject = GetConsoleInputWaitHandle(); 867 } 868 869 /* Register the wait now */ 870 Status = RtlRegisterWait(phNewWaitObject, 871 hObject, 872 Callback, 873 Context, 874 dwMilliseconds, 875 dwFlags); 876 if (!NT_SUCCESS(Status)) 877 { 878 /* Return failure */ 879 BaseSetLastNTError(Status); 880 return FALSE; 881 } 882 883 /* All good */ 884 return TRUE; 885 } 886 887 /* 888 * @implemented 889 */ 890 HANDLE 891 WINAPI 892 RegisterWaitForSingleObjectEx(IN HANDLE hObject, 893 IN WAITORTIMERCALLBACK Callback, 894 IN PVOID Context, 895 IN ULONG dwMilliseconds, 896 IN ULONG dwFlags) 897 { 898 NTSTATUS Status; 899 HANDLE hNewWaitObject; 900 901 /* Get real handle */ 902 hObject = TranslateStdHandle(hObject); 903 904 /* Check for console handle */ 905 if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) 906 { 907 /* Get the real wait handle */ 908 hObject = GetConsoleInputWaitHandle(); 909 } 910 911 /* Register the wait */ 912 Status = RtlRegisterWait(&hNewWaitObject, 913 hObject, 914 Callback, 915 Context, 916 dwMilliseconds, 917 dwFlags); 918 if (!NT_SUCCESS(Status)) 919 { 920 /* Return failure */ 921 BaseSetLastNTError(Status); 922 return NULL; 923 } 924 925 /* Return the object */ 926 return hNewWaitObject; 927 } 928 929 /* 930 * @implemented 931 */ 932 BOOL 933 WINAPI 934 UnregisterWait(IN HANDLE WaitHandle) 935 { 936 NTSTATUS Status; 937 938 /* Check for invalid handle */ 939 if (!WaitHandle) 940 { 941 /* Fail */ 942 SetLastError(ERROR_INVALID_HANDLE); 943 return FALSE; 944 } 945 946 /* Deregister the wait and check status */ 947 Status = RtlDeregisterWaitEx(WaitHandle, NULL); 948 if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING)) 949 { 950 /* Failure or non-blocking call */ 951 BaseSetLastNTError(Status); 952 return FALSE; 953 } 954 955 /* All good */ 956 return TRUE; 957 } 958 959 /* 960 * @implemented 961 */ 962 BOOL 963 WINAPI 964 UnregisterWaitEx(IN HANDLE WaitHandle, 965 IN HANDLE CompletionEvent) 966 { 967 NTSTATUS Status; 968 969 /* Check for invalid handle */ 970 if (!WaitHandle) 971 { 972 /* Fail */ 973 SetLastError(ERROR_INVALID_HANDLE); 974 return FALSE; 975 } 976 977 /* Deregister the wait and check status */ 978 Status = RtlDeregisterWaitEx(WaitHandle, CompletionEvent); 979 if (!(NT_SUCCESS(Status)) || 980 ((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING))) 981 { 982 /* Failure or non-blocking call */ 983 BaseSetLastNTError(Status); 984 return FALSE; 985 } 986 987 /* All good */ 988 return TRUE; 989 } 990 991 /* EOF */ 992