update for HEAD-2003091401
[reactos.git] / lib / kernel32 / synch / wait.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/synch/wait.c
6  * PURPOSE:         Wait functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  *                  Created 01/11/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <k32.h>
15
16 #define NDEBUG
17 #include <kernel32/kernel32.h>
18
19 /* FUNCTIONS ****************************************************************/
20
21 /*
22  * @implemented
23  */
24 DWORD STDCALL
25 WaitForSingleObject(HANDLE hHandle,
26                     DWORD dwMilliseconds)
27 {
28    return WaitForSingleObjectEx(hHandle,
29                                 dwMilliseconds,
30                                 FALSE);
31 }
32
33
34 /*
35  * @implemented
36  */
37 DWORD STDCALL
38 WaitForSingleObjectEx(HANDLE hHandle,
39                       DWORD  dwMilliseconds,
40                       BOOL   bAlertable)
41 {
42   PLARGE_INTEGER TimePtr;
43   LARGE_INTEGER Time;
44   NTSTATUS Status;
45
46   /* Get real handle */
47   switch ((ULONG)hHandle)
48     {
49       case STD_INPUT_HANDLE:
50         hHandle = NtCurrentPeb()->ProcessParameters->hStdInput;
51         break;
52
53       case STD_OUTPUT_HANDLE:
54         hHandle = NtCurrentPeb()->ProcessParameters->hStdOutput;
55         break;
56
57       case STD_ERROR_HANDLE:
58         hHandle = NtCurrentPeb()->ProcessParameters->hStdError;
59         break;
60     }
61
62   /* Check for console handle */
63   if (IsConsoleHandle(hHandle))
64     {
65       if (VerifyConsoleIoHandle(hHandle))
66         {
67           DPRINT1("Console handles are not supported yet!\n");
68           SetLastError(ERROR_INVALID_HANDLE);
69           return WAIT_FAILED;
70         }
71     }
72
73   if (dwMilliseconds == INFINITE)
74     {
75       TimePtr = NULL;
76     }
77   else
78     {
79       Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
80       TimePtr = &Time;
81     }
82
83   Status = NtWaitForSingleObject(hHandle,
84                                  (BOOLEAN) bAlertable,
85                                  TimePtr);
86   if (Status == STATUS_TIMEOUT)
87     {
88       return WAIT_TIMEOUT;
89     }
90   else if ((Status == WAIT_OBJECT_0) ||
91            (Status == WAIT_ABANDONED_0))
92     {
93       return Status;
94     }
95
96   SetLastErrorByStatus (Status);
97
98   return WAIT_FAILED;
99 }
100
101
102 /*
103  * @implemented
104  */
105 DWORD STDCALL
106 WaitForMultipleObjects(DWORD nCount,
107                        CONST HANDLE *lpHandles,
108                        BOOL  bWaitAll,
109                        DWORD dwMilliseconds)
110 {
111   return WaitForMultipleObjectsEx(nCount,
112                                   lpHandles,
113                                   bWaitAll,
114                                   dwMilliseconds,
115                                   FALSE);
116 }
117
118
119 /*
120  * @implemented
121  */
122 DWORD STDCALL
123 WaitForMultipleObjectsEx(DWORD nCount,
124                          CONST HANDLE *lpHandles,
125                          BOOL  bWaitAll,
126                          DWORD dwMilliseconds,
127                          BOOL  bAlertable)
128 {
129   PLARGE_INTEGER TimePtr;
130   LARGE_INTEGER Time;
131   PHANDLE HandleBuffer;
132   DWORD i;
133   NTSTATUS Status;
134
135   DPRINT("nCount %lu\n", nCount);
136
137   HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HANDLE));
138   if (HandleBuffer == NULL)
139     {
140       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
141       return WAIT_FAILED;
142     }
143
144   for (i = 0; i < nCount; i++)
145     {
146       switch ((DWORD)lpHandles[i])
147         {
148           case STD_INPUT_HANDLE:
149             HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->hStdInput;
150             break;
151
152           case STD_OUTPUT_HANDLE:
153             HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->hStdOutput;
154             break;
155
156           case STD_ERROR_HANDLE:
157             HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->hStdError;
158             break;
159
160           default:
161             HandleBuffer[i] = lpHandles[i];
162             break;
163         }
164
165       /* Check for console handle */
166       if (IsConsoleHandle(HandleBuffer[i]))
167         {
168           if (VerifyConsoleIoHandle(HandleBuffer[i]))
169             {
170               DPRINT1("Console handles are not supported yet!\n");
171               RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
172               SetLastError(ERROR_INVALID_HANDLE);
173               return FALSE;
174             }
175         }
176     }
177
178   if (dwMilliseconds == INFINITE)
179     {
180       TimePtr = NULL;
181     }
182   else
183     {
184       Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
185       TimePtr = &Time;
186     }
187
188   Status = NtWaitForMultipleObjects (nCount,
189                                      HandleBuffer,
190                                      bWaitAll  ? WaitAll : WaitAny,
191                                      (BOOLEAN)bAlertable,
192                                      TimePtr);
193
194   RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
195
196   if (Status == STATUS_TIMEOUT)
197     {
198       return WAIT_TIMEOUT;
199     }
200   else if (((Status >= WAIT_OBJECT_0) &&
201             (Status <= WAIT_OBJECT_0 + nCount - 1)) ||
202            ((Status >= WAIT_ABANDONED_0) &&
203             (Status <= WAIT_ABANDONED_0 + nCount - 1)))
204     {
205       return Status;
206     }
207
208   DPRINT("Status %lx\n", Status);
209   SetLastErrorByStatus (Status);
210
211   return WAIT_FAILED;
212 }
213
214
215 /*
216  * @implemented
217  */
218 DWORD STDCALL
219 SignalObjectAndWait(HANDLE hObjectToSignal,
220                     HANDLE hObjectToWaitOn,
221                     DWORD dwMilliseconds,
222                     WINBOOL bAlertable)
223 {
224   PLARGE_INTEGER TimePtr;
225   LARGE_INTEGER Time;
226   NTSTATUS Status;
227
228   /* Get real handle */
229   switch ((ULONG)hObjectToWaitOn)
230     {
231       case STD_INPUT_HANDLE:
232         hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->hStdInput;
233         break;
234
235       case STD_OUTPUT_HANDLE:
236         hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->hStdOutput;
237         break;
238
239       case STD_ERROR_HANDLE:
240         hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->hStdError;
241         break;
242     }
243
244   /* Check for console handle */
245   if (IsConsoleHandle(hObjectToWaitOn))
246     {
247       if (VerifyConsoleIoHandle(hObjectToWaitOn))
248         {
249           DPRINT1("Console handles are not supported yet!\n");
250           SetLastError(ERROR_INVALID_HANDLE);
251           return FALSE;
252         }
253     }
254
255   if (dwMilliseconds == INFINITE)
256     {
257       TimePtr = NULL;
258     }
259   else
260     {
261       Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
262       TimePtr = &Time;
263     }
264
265   Status = NtSignalAndWaitForSingleObject (hObjectToSignal,
266                                            hObjectToWaitOn,
267                                            (BOOLEAN)bAlertable,
268                                            TimePtr);
269   if (!NT_SUCCESS(Status))
270     {
271       SetLastErrorByStatus (Status);
272       return FALSE;
273     }
274
275   return TRUE;
276 }
277
278 /* EOF */