[KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / synch.c
1 /*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/synch/wait.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 */