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