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, 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, 450 lpSemaphoreAttributes, 451 lpName, 452 lInitialCount, 453 lMaximumCount); 454 } 455 456 /* 457 * @implemented 458 */ 459 HANDLE 460 WINAPI 461 DECLSPEC_HOTPATCH 462 OpenSemaphoreA(IN DWORD dwDesiredAccess, 463 IN BOOL bInheritHandle, 464 IN LPCSTR lpName) 465 { 466 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Semaphore, dwDesiredAccess, bInheritHandle, lpName); 467 } 468 469 /* 470 * @implemented 471 */ 472 HANDLE 473 WINAPI 474 DECLSPEC_HOTPATCH 475 OpenSemaphoreW(IN DWORD dwDesiredAccess, 476 IN BOOL bInheritHandle, 477 IN LPCWSTR lpName) 478 { 479 OpenNtObjectFromWin32Api(Semaphore, dwDesiredAccess, bInheritHandle, lpName); 480 } 481 482 /* 483 * @implemented 484 */ 485 BOOL 486 WINAPI 487 DECLSPEC_HOTPATCH 488 ReleaseSemaphore(IN HANDLE hSemaphore, 489 IN LONG lReleaseCount, 490 IN LPLONG lpPreviousCount) 491 { 492 NTSTATUS Status; 493 494 /* Release the semaphore */ 495 Status = NtReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount); 496 if (NT_SUCCESS(Status)) return TRUE; 497 498 /* If we got here, then we failed */ 499 BaseSetLastNTError(Status); 500 return FALSE; 501 } 502 503 /* 504 * @implemented 505 */ 506 HANDLE 507 WINAPI 508 DECLSPEC_HOTPATCH 509 CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, 510 IN BOOL bInitialOwner, 511 IN LPCSTR lpName OPTIONAL) 512 { 513 ConvertWin32AnsiObjectApiToUnicodeApi(Mutex, lpName, lpMutexAttributes, bInitialOwner); 514 } 515 516 /* 517 * @implemented 518 */ 519 HANDLE 520 WINAPI 521 DECLSPEC_HOTPATCH 522 CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, 523 IN BOOL bInitialOwner, 524 IN LPCWSTR lpName OPTIONAL) 525 { 526 CreateNtObjectFromWin32Api(Mutex, Mutant, MUTEX, 527 lpMutexAttributes, 528 lpName, 529 bInitialOwner); 530 } 531 532 /* 533 * @implemented 534 */ 535 HANDLE 536 WINAPI 537 DECLSPEC_HOTPATCH 538 OpenMutexA(IN DWORD dwDesiredAccess, 539 IN BOOL bInheritHandle, 540 IN LPCSTR lpName) 541 { 542 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Mutex, dwDesiredAccess, bInheritHandle, lpName); 543 } 544 545 /* 546 * @implemented 547 */ 548 HANDLE 549 WINAPI 550 DECLSPEC_HOTPATCH 551 OpenMutexW(IN DWORD dwDesiredAccess, 552 IN BOOL bInheritHandle, 553 IN LPCWSTR lpName) 554 { 555 OpenNtObjectFromWin32Api(Mutant, dwDesiredAccess, bInheritHandle, lpName); 556 } 557 558 /* 559 * @implemented 560 */ 561 BOOL 562 WINAPI 563 DECLSPEC_HOTPATCH 564 ReleaseMutex(IN HANDLE hMutex) 565 { 566 NTSTATUS Status; 567 568 /* Release the mutant */ 569 Status = NtReleaseMutant(hMutex, NULL); 570 if (NT_SUCCESS(Status)) return TRUE; 571 572 /* If we got here, then we failed */ 573 BaseSetLastNTError(Status); 574 return FALSE; 575 } 576 577 /* 578 * @implemented 579 */ 580 HANDLE 581 WINAPI 582 DECLSPEC_HOTPATCH 583 CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, 584 IN BOOL bManualReset, 585 IN BOOL bInitialState, 586 IN LPCSTR lpName OPTIONAL) 587 { 588 ConvertWin32AnsiObjectApiToUnicodeApi(Event, lpName, lpEventAttributes, bManualReset, bInitialState); 589 } 590 591 /* 592 * @implemented 593 */ 594 HANDLE 595 WINAPI 596 DECLSPEC_HOTPATCH 597 CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, 598 IN BOOL bManualReset, 599 IN BOOL bInitialState, 600 IN LPCWSTR lpName OPTIONAL) 601 { 602 CreateNtObjectFromWin32Api(Event, Event, EVENT, 603 lpEventAttributes, 604 lpName, 605 bManualReset ? NotificationEvent : SynchronizationEvent, 606 bInitialState); 607 } 608 609 /* 610 * @implemented 611 */ 612 HANDLE 613 WINAPI 614 DECLSPEC_HOTPATCH 615 OpenEventA(IN DWORD dwDesiredAccess, 616 IN BOOL bInheritHandle, 617 IN LPCSTR lpName) 618 { 619 ConvertOpenWin32AnsiObjectApiToUnicodeApi(Event, dwDesiredAccess, bInheritHandle, lpName); 620 } 621 622 /* 623 * @implemented 624 */ 625 HANDLE 626 WINAPI 627 DECLSPEC_HOTPATCH 628 OpenEventW(IN DWORD dwDesiredAccess, 629 IN BOOL bInheritHandle, 630 IN LPCWSTR lpName) 631 { 632 OpenNtObjectFromWin32Api(Event, dwDesiredAccess, bInheritHandle, lpName); 633 } 634 635 /* 636 * @implemented 637 */ 638 BOOL 639 WINAPI 640 DECLSPEC_HOTPATCH 641 PulseEvent(IN HANDLE hEvent) 642 { 643 NTSTATUS Status; 644 645 /* Pulse the event */ 646 Status = NtPulseEvent(hEvent, NULL); 647 if (NT_SUCCESS(Status)) return TRUE; 648 649 /* If we got here, then we failed */ 650 BaseSetLastNTError(Status); 651 return FALSE; 652 } 653 654 /* 655 * @implemented 656 */ 657 BOOL 658 WINAPI 659 DECLSPEC_HOTPATCH 660 ResetEvent(IN HANDLE hEvent) 661 { 662 NTSTATUS Status; 663 664 /* Clear the event */ 665 Status = NtResetEvent(hEvent, NULL); 666 if (NT_SUCCESS(Status)) return TRUE; 667 668 /* If we got here, then we failed */ 669 BaseSetLastNTError(Status); 670 return FALSE; 671 } 672 673 /* 674 * @implemented 675 */ 676 BOOL 677 WINAPI 678 DECLSPEC_HOTPATCH 679 SetEvent(IN HANDLE hEvent) 680 { 681 NTSTATUS Status; 682 683 /* Set the event */ 684 Status = NtSetEvent(hEvent, NULL); 685 if (NT_SUCCESS(Status)) return TRUE; 686 687 /* If we got here, then we failed */ 688 BaseSetLastNTError(Status); 689 return FALSE; 690 } 691 692 /* 693 * @implemented 694 */ 695 VOID 696 WINAPI 697 InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection) 698 { 699 NTSTATUS Status; 700 701 /* Initialize the critical section and raise an exception if we failed */ 702 Status = RtlInitializeCriticalSection((PVOID)lpCriticalSection); 703 if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); 704 } 705 706 /* 707 * @implemented 708 */ 709 BOOL 710 WINAPI 711 InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection, 712 IN DWORD dwSpinCount) 713 { 714 NTSTATUS Status; 715 716 /* Initialize the critical section */ 717 Status = RtlInitializeCriticalSectionAndSpinCount((PVOID)lpCriticalSection, 718 dwSpinCount); 719 if (!NT_SUCCESS(Status)) 720 { 721 /* Set failure code */ 722 BaseSetLastNTError(Status); 723 return FALSE; 724 } 725 726 /* Success */ 727 return TRUE; 728 } 729 730 /* 731 * @implemented 732 */ 733 VOID 734 WINAPI 735 DECLSPEC_HOTPATCH 736 Sleep(IN DWORD dwMilliseconds) 737 { 738 /* Call the new API */ 739 SleepEx(dwMilliseconds, FALSE); 740 } 741 742 743 /* 744 * @implemented 745 */ 746 DWORD 747 WINAPI 748 SleepEx(IN DWORD dwMilliseconds, 749 IN BOOL bAlertable) 750 { 751 LARGE_INTEGER Time; 752 PLARGE_INTEGER TimePtr; 753 NTSTATUS errCode; 754 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; 755 756 /* APCs must execute with the default activation context */ 757 if (bAlertable) 758 { 759 /* Setup the frame */ 760 RtlZeroMemory(&ActCtx, sizeof(ActCtx)); 761 ActCtx.Size = sizeof(ActCtx); 762 ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; 763 RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); 764 } 765 766 /* Convert the timeout */ 767 TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); 768 if (!TimePtr) 769 { 770 /* Turn an infinite wait into a really long wait */ 771 Time.LowPart = 0; 772 Time.HighPart = 0x80000000; 773 TimePtr = &Time; 774 } 775 776 /* Loop the delay while APCs are alerting us */ 777 do 778 { 779 /* Do the delay */ 780 errCode = NtDelayExecution((BOOLEAN)bAlertable, TimePtr); 781 } 782 while ((bAlertable) && (errCode == STATUS_ALERTED)); 783 784 /* Cleanup the activation context */ 785 if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); 786 787 /* Return the correct code */ 788 return (errCode == STATUS_USER_APC) ? WAIT_IO_COMPLETION : 0; 789 } 790 791 /* 792 * @implemented 793 */ 794 BOOL 795 WINAPI 796 RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject, 797 IN HANDLE hObject, 798 IN WAITORTIMERCALLBACK Callback, 799 IN PVOID Context, 800 IN ULONG dwMilliseconds, 801 IN ULONG dwFlags) 802 { 803 NTSTATUS Status; 804 805 /* Get real handle */ 806 hObject = TranslateStdHandle(hObject); 807 808 /* Check for console handle */ 809 if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) 810 { 811 /* Get the real wait handle */ 812 hObject = GetConsoleInputWaitHandle(); 813 } 814 815 /* Register the wait now */ 816 Status = RtlRegisterWait(phNewWaitObject, 817 hObject, 818 Callback, 819 Context, 820 dwMilliseconds, 821 dwFlags); 822 if (!NT_SUCCESS(Status)) 823 { 824 /* Return failure */ 825 BaseSetLastNTError(Status); 826 return FALSE; 827 } 828 829 /* All good */ 830 return TRUE; 831 } 832 833 /* 834 * @implemented 835 */ 836 HANDLE 837 WINAPI 838 RegisterWaitForSingleObjectEx(IN HANDLE hObject, 839 IN WAITORTIMERCALLBACK Callback, 840 IN PVOID Context, 841 IN ULONG dwMilliseconds, 842 IN ULONG dwFlags) 843 { 844 NTSTATUS Status; 845 HANDLE hNewWaitObject; 846 847 /* Get real handle */ 848 hObject = TranslateStdHandle(hObject); 849 850 /* Check for console handle */ 851 if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) 852 { 853 /* Get the real wait handle */ 854 hObject = GetConsoleInputWaitHandle(); 855 } 856 857 /* Register the wait */ 858 Status = RtlRegisterWait(&hNewWaitObject, 859 hObject, 860 Callback, 861 Context, 862 dwMilliseconds, 863 dwFlags); 864 if (!NT_SUCCESS(Status)) 865 { 866 /* Return failure */ 867 BaseSetLastNTError(Status); 868 return NULL; 869 } 870 871 /* Return the object */ 872 return hNewWaitObject; 873 } 874 875 /* 876 * @implemented 877 */ 878 BOOL 879 WINAPI 880 UnregisterWait(IN HANDLE WaitHandle) 881 { 882 NTSTATUS Status; 883 884 /* Check for invalid handle */ 885 if (!WaitHandle) 886 { 887 /* Fail */ 888 SetLastError(ERROR_INVALID_HANDLE); 889 return FALSE; 890 } 891 892 /* Deregister the wait and check status */ 893 Status = RtlDeregisterWaitEx(WaitHandle, NULL); 894 if (!(NT_SUCCESS(Status)) || (Status == STATUS_PENDING)) 895 { 896 /* Failure or non-blocking call */ 897 BaseSetLastNTError(Status); 898 return FALSE; 899 } 900 901 /* All good */ 902 return TRUE; 903 } 904 905 /* 906 * @implemented 907 */ 908 BOOL 909 WINAPI 910 UnregisterWaitEx(IN HANDLE WaitHandle, 911 IN HANDLE CompletionEvent) 912 { 913 NTSTATUS Status; 914 915 /* Check for invalid handle */ 916 if (!WaitHandle) 917 { 918 /* Fail */ 919 SetLastError(ERROR_INVALID_HANDLE); 920 return FALSE; 921 } 922 923 /* Deregister the wait and check status */ 924 Status = RtlDeregisterWaitEx(WaitHandle, CompletionEvent); 925 if (!(NT_SUCCESS(Status)) || 926 ((CompletionEvent != INVALID_HANDLE_VALUE) && (Status == STATUS_PENDING))) 927 { 928 /* Failure or non-blocking call */ 929 BaseSetLastNTError(Status); 930 return FALSE; 931 } 932 933 /* All good */ 934 return TRUE; 935 } 936 937 /* EOF */ 938