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