xref: /reactos/dll/win32/kernel32/client/synch.c (revision 18a9993d)
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