xref: /reactos/dll/win32/kernel32/client/synch.c (revision 9393fc32)
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
InterlockedIncrement(IN OUT LONG volatile * lpAddend)28 InterlockedIncrement(IN OUT LONG volatile *lpAddend)
29 {
30     return _InterlockedIncrement(lpAddend);
31 }
32 
33 /*
34  * @implemented
35  */
36 LONG
37 WINAPI
InterlockedDecrement(IN OUT LONG volatile * lpAddend)38 InterlockedDecrement(IN OUT LONG volatile *lpAddend)
39 {
40     return _InterlockedDecrement(lpAddend);
41 }
42 
43 /*
44  * @implemented
45  */
46 LONG
47 WINAPI
InterlockedExchange(IN OUT LONG volatile * Target,IN LONG Value)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
InterlockedExchangeAdd(IN OUT LONG volatile * Addend,IN LONG Value)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
InterlockedCompareExchange(IN OUT LONG volatile * Destination,IN LONG Exchange,IN LONG Comperand)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
WaitForSingleObject(IN HANDLE hHandle,IN DWORD dwMilliseconds)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
WaitForSingleObjectEx(IN HANDLE hHandle,IN DWORD dwMilliseconds,IN BOOL bAlertable)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
WaitForMultipleObjects(IN DWORD nCount,IN CONST HANDLE * lpHandles,IN BOOL bWaitAll,IN DWORD dwMilliseconds)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
WaitForMultipleObjectsEx(IN DWORD nCount,IN CONST HANDLE * lpHandles,IN BOOL bWaitAll,IN DWORD dwMilliseconds,IN BOOL bAlertable)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
SignalObjectAndWait(IN HANDLE hObjectToSignal,IN HANDLE hObjectToWaitOn,IN DWORD dwMilliseconds,IN BOOL bAlertable)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
CreateWaitableTimerW(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL,IN BOOL bManualReset,IN LPCWSTR lpTimerName OPTIONAL)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
CreateWaitableTimerA(IN LPSECURITY_ATTRIBUTES lpTimerAttributes OPTIONAL,IN BOOL bManualReset,IN LPCSTR lpTimerName OPTIONAL)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
OpenWaitableTimerW(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCWSTR lpTimerName)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
OpenWaitableTimerA(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCSTR lpTimerName)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
SetWaitableTimer(IN HANDLE hTimer,IN const LARGE_INTEGER * pDueTime,IN LONG lPeriod,IN PTIMERAPCROUTINE pfnCompletionRoutine OPTIONAL,IN OPTIONAL LPVOID lpArgToCompletionRoutine,IN BOOL fResume)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
CancelWaitableTimer(IN HANDLE hTimer)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
CreateSemaphoreA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL,IN LONG lInitialCount,IN LONG lMaximumCount,IN LPCSTR lpName OPTIONAL)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
CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL,IN LONG lInitialCount,IN LONG lMaximumCount,IN LPCWSTR lpName OPTIONAL)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
CreateSemaphoreExW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL,IN LONG lInitialCount,IN LONG lMaximumCount,IN LPCWSTR lpName OPTIONAL,IN DWORD dwFlags OPTIONAL,IN DWORD dwDesiredAccess OPTIONAL)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
CreateSemaphoreExA(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL,IN LONG lInitialCount,IN LONG lMaximumCount,IN LPCSTR lpName OPTIONAL,IN DWORD dwFlags OPTIONAL,IN DWORD dwDesiredAccess OPTIONAL)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
OpenSemaphoreA(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCSTR lpName)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
OpenSemaphoreW(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCWSTR lpName)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
ReleaseSemaphore(IN HANDLE hSemaphore,IN LONG lReleaseCount,IN LPLONG lpPreviousCount)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
CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL,IN BOOL bInitialOwner,IN LPCSTR lpName OPTIONAL)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
CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL,IN BOOL bInitialOwner,IN LPCWSTR lpName OPTIONAL)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
OpenMutexA(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCSTR lpName)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
OpenMutexW(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCWSTR lpName)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
ReleaseMutex(IN HANDLE hMutex)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
CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL,IN BOOL bManualReset,IN BOOL bInitialState,IN LPCSTR lpName OPTIONAL)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
CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL,IN BOOL bManualReset,IN BOOL bInitialState,IN LPCWSTR lpName OPTIONAL)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
OpenEventA(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCSTR lpName)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
OpenEventW(IN DWORD dwDesiredAccess,IN BOOL bInheritHandle,IN LPCWSTR lpName)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
PulseEvent(IN HANDLE hEvent)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
ResetEvent(IN HANDLE hEvent)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
SetEvent(IN HANDLE hEvent)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
InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)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
InitializeCriticalSectionAndSpinCount(OUT LPCRITICAL_SECTION lpCriticalSection,IN DWORD dwSpinCount)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
Sleep(IN DWORD dwMilliseconds)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
SleepEx(IN DWORD dwMilliseconds,IN BOOL bAlertable)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
RegisterWaitForSingleObject(OUT PHANDLE phNewWaitObject,IN HANDLE hObject,IN WAITORTIMERCALLBACK Callback,IN PVOID Context,IN ULONG dwMilliseconds,IN ULONG dwFlags)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
RegisterWaitForSingleObjectEx(IN HANDLE hObject,IN WAITORTIMERCALLBACK Callback,IN PVOID Context,IN ULONG dwMilliseconds,IN ULONG dwFlags)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
UnregisterWait(IN HANDLE WaitHandle)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
UnregisterWaitEx(IN HANDLE WaitHandle,IN HANDLE CompletionEvent)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