Fixed regression in process creation (std handle inheritance).
[wine] / scheduler / synchro.c
1 /*
2  * Win32 process and thread synchronisation
3  *
4  * Copyright 1997 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "winbase.h"
24 #include "winternl.h"
25 #include "../kernel/kernel_private.h" /* FIXME: to be changed when moving file to dlls/kernel */
26
27
28 /***********************************************************************
29  *              Sleep  (KERNEL32.@)
30  */
31 VOID WINAPI Sleep( DWORD timeout )
32 {
33     SleepEx( timeout, FALSE );
34 }
35
36 /******************************************************************************
37  *              SleepEx   (KERNEL32.@)
38  */
39 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
40 {
41     NTSTATUS status;
42
43     if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
44     else
45     {
46         LARGE_INTEGER time;
47
48         time.QuadPart = timeout * (ULONGLONG)10000;
49         time.QuadPart = -time.QuadPart;
50         status = NtDelayExecution( alertable, &time );
51     }
52     if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
53     return status;
54 }
55
56
57 /***********************************************************************
58  *           WaitForSingleObject   (KERNEL32.@)
59  */
60 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
61 {
62     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
63 }
64
65
66 /***********************************************************************
67  *           WaitForSingleObjectEx   (KERNEL32.@)
68  */
69 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
70                                     BOOL alertable )
71 {
72     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
73 }
74
75
76 /***********************************************************************
77  *           WaitForMultipleObjects   (KERNEL32.@)
78  */
79 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
80                                      BOOL wait_all, DWORD timeout )
81 {
82     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
83 }
84
85
86 /***********************************************************************
87  *           WaitForMultipleObjectsEx   (KERNEL32.@)
88  */
89 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
90                                        BOOL wait_all, DWORD timeout,
91                                        BOOL alertable )
92 {
93     NTSTATUS status;
94     HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
95     int i;
96
97     if (count >= MAXIMUM_WAIT_OBJECTS)
98     {
99         SetLastError(ERROR_INVALID_PARAMETER);
100         return WAIT_FAILED;
101     }
102     for (i = 0; i < count; i++)
103     {
104         if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
105             (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
106             (handles[i] == (HANDLE)STD_ERROR_HANDLE))
107             hloc[i] = GetStdHandle( (DWORD)handles[i] );
108         else
109             hloc[i] = handles[i];
110
111         /* yes, even screen buffer console handles are waitable, and are
112          * handled as a handle to the console itself !!
113          */
114         if (is_console_handle(hloc[i]))
115         {
116             if (!VerifyConsoleIoHandle(hloc[i]))
117             {
118                 return FALSE;
119             }
120             hloc[i] = GetConsoleInputWaitHandle();
121         }
122     }
123
124     if (timeout == INFINITE)
125     {
126         status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
127     }
128     else
129     {
130         LARGE_INTEGER time;
131
132         time.QuadPart = timeout * (ULONGLONG)10000;
133         time.QuadPart = -time.QuadPart;
134         status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
135     }
136
137     if (HIWORD(status))  /* is it an error code? */
138     {
139         SetLastError( RtlNtStatusToDosError(status) );
140         status = WAIT_FAILED;
141     }
142     return status;
143 }
144
145
146 /***********************************************************************
147  *           WaitForSingleObject   (KERNEL.460)
148  */
149 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
150 {
151     DWORD retval, mutex_count;
152
153     ReleaseThunkLock( &mutex_count );
154     retval = WaitForSingleObject( handle, timeout );
155     RestoreThunkLock( mutex_count );
156     return retval;
157 }
158
159 /***********************************************************************
160  *           WaitForMultipleObjects   (KERNEL.461)
161  */
162 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
163                                        BOOL wait_all, DWORD timeout )
164 {
165     DWORD retval, mutex_count;
166
167     ReleaseThunkLock( &mutex_count );
168     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
169     RestoreThunkLock( mutex_count );
170     return retval;
171 }
172
173 /***********************************************************************
174  *           WaitForMultipleObjectsEx   (KERNEL.495)
175  */
176 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
177                                          BOOL wait_all, DWORD timeout, BOOL alertable )
178 {
179     DWORD retval, mutex_count;
180
181     ReleaseThunkLock( &mutex_count );
182     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
183     RestoreThunkLock( mutex_count );
184     return retval;
185 }