- Merge from trunk up to r45543
[reactos.git] / dll / win32 / kernel32 / synch / wait.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
11 #include <k32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 /*
19 * @implemented
20 */
21 DWORD
22 WINAPI
23 WaitForSingleObject(IN HANDLE hHandle,
24 IN DWORD dwMilliseconds)
25 {
26 /* Call the extended API */
27 return WaitForSingleObjectEx(hHandle, dwMilliseconds, FALSE);
28 }
29
30 /*
31 * @implemented
32 */
33 DWORD
34 WINAPI
35 WaitForSingleObjectEx(IN HANDLE hHandle,
36 IN DWORD dwMilliseconds,
37 IN BOOL bAlertable)
38 {
39 PLARGE_INTEGER TimePtr;
40 LARGE_INTEGER Time;
41 NTSTATUS Status;
42
43 /* Get real handle */
44 hHandle = TranslateStdHandle(hHandle);
45
46 /* Check for console handle */
47 if ((IsConsoleHandle(hHandle)) && (VerifyConsoleIoHandle(hHandle)))
48 {
49 /* Get the real wait handle */
50 hHandle = GetConsoleInputWaitHandle();
51 }
52
53 /* Check if this is an infinite wait */
54 if (dwMilliseconds == INFINITE)
55 {
56 /* Under NT, this means no timer argument */
57 TimePtr = NULL;
58 }
59 else
60 {
61 /* Otherwise, convert the time to NT Format */
62 Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds);
63 TimePtr = &Time;
64 }
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 SetLastErrorByStatus (Status);
75 return WAIT_FAILED;
76 }
77 } while ((Status == STATUS_ALERTED) && (bAlertable));
78
79 /* Return wait status */
80 return Status;
81 }
82
83 /*
84 * @implemented
85 */
86 DWORD
87 WINAPI
88 WaitForMultipleObjects(IN DWORD nCount,
89 IN CONST HANDLE *lpHandles,
90 IN BOOL bWaitAll,
91 IN DWORD dwMilliseconds)
92 {
93 /* Call the extended API */
94 return WaitForMultipleObjectsEx(nCount,
95 lpHandles,
96 bWaitAll,
97 dwMilliseconds,
98 FALSE);
99 }
100
101 /*
102 * @implemented
103 */
104 DWORD
105 WINAPI
106 WaitForMultipleObjectsEx(IN DWORD nCount,
107 IN CONST HANDLE *lpHandles,
108 IN BOOL bWaitAll,
109 IN DWORD dwMilliseconds,
110 IN BOOL bAlertable)
111 {
112 PLARGE_INTEGER TimePtr;
113 LARGE_INTEGER Time;
114 PHANDLE HandleBuffer;
115 HANDLE Handle[8];
116 DWORD i;
117 NTSTATUS Status;
118
119 /* Check if we have more handles then we locally optimize */
120 if (nCount > 8)
121 {
122 /* Allocate a buffer for them */
123 HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
124 0,
125 nCount * sizeof(HANDLE));
126 if (!HandleBuffer)
127 {
128 /* No buffer, fail the wait */
129 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
130 return WAIT_FAILED;
131 }
132 }
133 else
134 {
135 /* Otherwise, use our local buffer */
136 HandleBuffer = Handle;
137 }
138
139 /* Copy the handles into our buffer and loop them all */
140 RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE));
141 for (i = 0; i < nCount; i++)
142 {
143 /* Check what kind of handle this is */
144 HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]);
145
146 /* Check for console handle */
147 if ((IsConsoleHandle(HandleBuffer[i])) &&
148 (VerifyConsoleIoHandle(HandleBuffer[i])))
149 {
150 /* Get the real wait handle */
151 HandleBuffer[i] = GetConsoleInputWaitHandle();
152 }
153 }
154
155 /* Check if this is an infinite wait */
156 if (dwMilliseconds == INFINITE)
157 {
158 /* Under NT, this means no timer argument */
159 TimePtr = NULL;
160 }
161 else
162 {
163 /* Otherwise, convert the time to NT Format */
164 Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds);
165 TimePtr = &Time;
166 }
167
168 /* Start wait loop */
169 do
170 {
171 /* Do the wait */
172 Status = NtWaitForMultipleObjects(nCount,
173 HandleBuffer,
174 bWaitAll ? WaitAll : WaitAny,
175 (BOOLEAN)bAlertable,
176 TimePtr);
177 if (!NT_SUCCESS(Status))
178 {
179 /* Wait failed */
180 SetLastErrorByStatus (Status);
181 return WAIT_FAILED;
182 }
183 } while ((Status == STATUS_ALERTED) && (bAlertable));
184
185 /* Check if we didn't use our local buffer */
186 if (HandleBuffer != Handle)
187 {
188 /* Free the allocated one */
189 RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
190 }
191
192 /* Return wait status */
193 return Status;
194 }
195
196 /*
197 * @implemented
198 */
199 DWORD
200 WINAPI
201 SignalObjectAndWait(IN HANDLE hObjectToSignal,
202 IN HANDLE hObjectToWaitOn,
203 IN DWORD dwMilliseconds,
204 IN BOOL bAlertable)
205 {
206 PLARGE_INTEGER TimePtr;
207 LARGE_INTEGER Time;
208 NTSTATUS Status;
209
210 /* Get real handle */
211 hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn);
212
213 /* Check for console handle */
214 if ((IsConsoleHandle(hObjectToWaitOn)) &&
215 (VerifyConsoleIoHandle(hObjectToWaitOn)))
216 {
217 /* Get the real wait handle */
218 hObjectToWaitOn = GetConsoleInputWaitHandle();
219 }
220
221 /* Check if this is an infinite wait */
222 if (dwMilliseconds == INFINITE)
223 {
224 /* Under NT, this means no timer argument */
225 TimePtr = NULL;
226 }
227 else
228 {
229 /* Otherwise, convert the time to NT Format */
230 Time.QuadPart = UInt32x32To64(-10000, dwMilliseconds);
231 TimePtr = &Time;
232 }
233
234 /* Start wait loop */
235 do
236 {
237 /* Do the wait */
238 Status = NtSignalAndWaitForSingleObject(hObjectToSignal,
239 hObjectToWaitOn,
240 (BOOLEAN)bAlertable,
241 TimePtr);
242 if (!NT_SUCCESS(Status))
243 {
244 /* The wait failed */
245 SetLastErrorByStatus (Status);
246 return WAIT_FAILED;
247 }
248 } while ((Status == STATUS_ALERTED) && (bAlertable));
249
250 /* Return wait status */
251 return Status;
252 }
253
254 /* EOF */