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