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