- BuildCommDCB16() uses int instead of BOOL
[wine] / dlls / kernel / sync.c
1 /*
2  * Kernel synchronization objects
3  *
4  * Copyright 1998 Alexandre Julliard
5  */
6
7 #include <string.h>
8 #include "winerror.h"
9 #include "winnls.h"
10 #include "wine/unicode.h"
11 #include "server.h"
12 #include "debugtools.h"
13
14 DEFAULT_DEBUG_CHANNEL(win32);
15
16 /*
17  * Events
18  */
19
20
21 /***********************************************************************
22  *           CreateEventA    (KERNEL32.156)
23  */
24 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
25                             BOOL initial_state, LPCSTR name )
26 {
27     HANDLE ret;
28     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
29     if (len >= MAX_PATH)
30     {
31         SetLastError( ERROR_FILENAME_EXCED_RANGE );
32         return 0;
33     }
34     SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
35     {
36         req->manual_reset = manual_reset;
37         req->initial_state = initial_state;
38         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
39         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
40         SetLastError(0);
41         SERVER_CALL_ERR();
42         ret = req->handle;
43     }
44     SERVER_END_VAR_REQ;
45     return ret;
46 }
47
48
49 /***********************************************************************
50  *           CreateEventW    (KERNEL32.157)
51  */
52 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
53                             BOOL initial_state, LPCWSTR name )
54 {
55     HANDLE ret;
56     DWORD len = name ? strlenW(name) : 0;
57     if (len >= MAX_PATH)
58     {
59         SetLastError( ERROR_FILENAME_EXCED_RANGE );
60         return 0;
61     }
62     /* one buggy program needs this
63      * ("Van Dale Groot woordenboek der Nederlandse taal")
64      */
65     if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
66     {
67         ERR("Bad security attributes pointer %p\n",sa);
68         SetLastError( ERROR_INVALID_PARAMETER);
69         return 0;
70     }
71     SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
72     {
73         req->manual_reset = manual_reset;
74         req->initial_state = initial_state;
75         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
76         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
77         SetLastError(0);
78         SERVER_CALL_ERR();
79         ret = req->handle;
80     }
81     SERVER_END_VAR_REQ;
82     return ret;
83 }
84
85
86 /***********************************************************************
87  *           WIN16_CreateEvent    (KERNEL.457)
88  */
89 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
90 {
91     return CreateEventA( NULL, manual_reset, initial_state, NULL );
92 }
93
94
95 /***********************************************************************
96  *           OpenEventA    (KERNEL32.536)
97  */
98 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
99 {
100     HANDLE ret;
101     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
102     if (len >= MAX_PATH)
103     {
104         SetLastError( ERROR_FILENAME_EXCED_RANGE );
105         return 0;
106     }
107     SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
108     {
109         req->access  = access;
110         req->inherit = inherit;
111         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
112         SERVER_CALL_ERR();
113         ret = req->handle;
114     }
115     SERVER_END_VAR_REQ;
116     return ret;
117 }
118
119
120 /***********************************************************************
121  *           OpenEventW    (KERNEL32.537)
122  */
123 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
124 {
125     HANDLE ret;
126     DWORD len = name ? strlenW(name) : 0;
127     if (len >= MAX_PATH)
128     {
129         SetLastError( ERROR_FILENAME_EXCED_RANGE );
130         return 0;
131     }
132     SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
133     {
134         req->access  = access;
135         req->inherit = inherit;
136         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
137         SERVER_CALL_ERR();
138         ret = req->handle;
139     }
140     SERVER_END_VAR_REQ;
141     return ret;
142 }
143
144
145 /***********************************************************************
146  *           EVENT_Operation
147  *
148  * Execute an event operation (set,reset,pulse).
149  */
150 static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
151 {
152     BOOL ret;
153     SERVER_START_REQ( event_op )
154     {
155         req->handle = handle;
156         req->op     = op;
157         ret = !SERVER_CALL_ERR();
158     }
159     SERVER_END_REQ;
160     return ret;
161 }
162
163
164 /***********************************************************************
165  *           PulseEvent    (KERNEL32.557)
166  */
167 BOOL WINAPI PulseEvent( HANDLE handle )
168 {
169     return EVENT_Operation( handle, PULSE_EVENT );
170 }
171
172
173 /***********************************************************************
174  *           SetEvent    (KERNEL.458)
175  *           SetEvent    (KERNEL32.644)
176  */
177 BOOL WINAPI SetEvent( HANDLE handle )
178 {
179     return EVENT_Operation( handle, SET_EVENT );
180 }
181
182
183 /***********************************************************************
184  *           ResetEvent    (KERNEL.459)
185  *           ResetEvent    (KERNEL32.586)
186  */
187 BOOL WINAPI ResetEvent( HANDLE handle )
188 {
189     return EVENT_Operation( handle, RESET_EVENT );
190 }
191
192
193 /***********************************************************************
194  * NOTE: The Win95 VWin32_Event routines given below are really low-level
195  *       routines implemented directly by VWin32. The user-mode libraries
196  *       implement Win32 synchronisation routines on top of these low-level
197  *       primitives. We do it the other way around here :-)
198  */
199
200 /***********************************************************************
201  *       VWin32_EventCreate     (KERNEL.442)
202  */
203 HANDLE WINAPI VWin32_EventCreate(VOID)
204 {
205     HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
206     return ConvertToGlobalHandle( hEvent );
207 }
208
209 /***********************************************************************
210  *       VWin32_EventDestroy    (KERNEL.443)
211  */
212 VOID WINAPI VWin32_EventDestroy(HANDLE event)
213 {
214     CloseHandle( event );
215 }
216
217 /***********************************************************************
218  *       VWin32_EventWait       (KERNEL.450) 
219  */
220 VOID WINAPI VWin32_EventWait(HANDLE event)
221 {
222     DWORD mutex_count;
223
224     ReleaseThunkLock( &mutex_count );
225     WaitForSingleObject( event, INFINITE );
226     RestoreThunkLock( mutex_count );
227 }
228
229 /***********************************************************************
230  *       VWin32_EventSet        (KERNEL.479)
231  */
232 VOID WINAPI VWin32_EventSet(HANDLE event)
233 {
234     SetEvent( event );
235 }
236
237
238
239 /***********************************************************************
240  *           CreateMutexA   (KERNEL32.166)
241  */
242 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
243 {
244     HANDLE ret;
245     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
246     if (len >= MAX_PATH)
247     {
248         SetLastError( ERROR_FILENAME_EXCED_RANGE );
249         return 0;
250     }
251     SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
252     {
253         req->owned   = owner;
254         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
255         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
256         SetLastError(0);
257         SERVER_CALL_ERR();
258         ret = req->handle;
259     }
260     SERVER_END_VAR_REQ;
261     return ret;
262 }
263
264
265 /***********************************************************************
266  *           CreateMutexW   (KERNEL32.167)
267  */
268 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
269 {
270     HANDLE ret;
271     DWORD len = name ? strlenW(name) : 0;
272     if (len >= MAX_PATH)
273     {
274         SetLastError( ERROR_FILENAME_EXCED_RANGE );
275         return 0;
276     }
277     SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
278     {
279         req->owned   = owner;
280         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
281         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
282         SetLastError(0);
283         SERVER_CALL_ERR();
284         ret = req->handle;
285     }
286     SERVER_END_VAR_REQ;
287     return ret;
288 }
289
290
291 /*
292  * Mutexes
293  */
294
295
296 /***********************************************************************
297  *           OpenMutexA   (KERNEL32.541)
298  */
299 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
300 {
301     HANDLE ret;
302     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
303     if (len >= MAX_PATH)
304     {
305         SetLastError( ERROR_FILENAME_EXCED_RANGE );
306         return 0;
307     }
308     SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
309     {
310         req->access  = access;
311         req->inherit = inherit;
312         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
313         SERVER_CALL_ERR();
314         ret = req->handle;
315     }
316     SERVER_END_VAR_REQ;
317     return ret;
318 }
319
320
321 /***********************************************************************
322  *           OpenMutexW   (KERNEL32.542)
323  */
324 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
325 {
326     HANDLE ret;
327     DWORD len = name ? strlenW(name) : 0;
328     if (len >= MAX_PATH)
329     {
330         SetLastError( ERROR_FILENAME_EXCED_RANGE );
331         return 0;
332     }
333     SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
334     {
335         req->access  = access;
336         req->inherit = inherit;
337         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
338         SERVER_CALL_ERR();
339         ret = req->handle;
340     }
341     SERVER_END_VAR_REQ;
342     return ret;
343 }
344
345
346 /***********************************************************************
347  *           ReleaseMutex   (KERNEL32.582)
348  */
349 BOOL WINAPI ReleaseMutex( HANDLE handle )
350 {
351     BOOL ret;
352     SERVER_START_REQ( release_mutex )
353     {
354         req->handle = handle;
355         ret = !SERVER_CALL_ERR();
356     }
357     SERVER_END_REQ;
358     return ret;
359 }
360
361
362 /*
363  * Semaphores
364  */
365
366
367 /***********************************************************************
368  *           CreateSemaphoreA   (KERNEL32.174)
369  */
370 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
371 {
372     HANDLE ret;
373     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
374
375     /* Check parameters */
376
377     if ((max <= 0) || (initial < 0) || (initial > max))
378     {
379         SetLastError( ERROR_INVALID_PARAMETER );
380         return 0;
381     }
382     if (len >= MAX_PATH)
383     {
384         SetLastError( ERROR_FILENAME_EXCED_RANGE );
385         return 0;
386     }
387
388     SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
389     {
390         req->initial = (unsigned int)initial;
391         req->max     = (unsigned int)max;
392         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
393         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
394         SetLastError(0);
395         SERVER_CALL_ERR();
396         ret = req->handle;
397     }
398     SERVER_END_VAR_REQ;
399     return ret;
400 }
401
402
403 /***********************************************************************
404  *           CreateSemaphoreW   (KERNEL32.175)
405  */
406 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
407                                     LONG max, LPCWSTR name )
408 {
409     HANDLE ret;
410     DWORD len = name ? strlenW(name) : 0;
411
412     /* Check parameters */
413
414     if ((max <= 0) || (initial < 0) || (initial > max))
415     {
416         SetLastError( ERROR_INVALID_PARAMETER );
417         return 0;
418     }
419     if (len >= MAX_PATH)
420     {
421         SetLastError( ERROR_FILENAME_EXCED_RANGE );
422         return 0;
423     }
424
425     SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
426     {
427         req->initial = (unsigned int)initial;
428         req->max     = (unsigned int)max;
429         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
430         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
431         SetLastError(0);
432         SERVER_CALL_ERR();
433         ret = req->handle;
434     }
435     SERVER_END_VAR_REQ;
436     return ret;
437 }
438
439
440 /***********************************************************************
441  *           OpenSemaphoreA   (KERNEL32.545)
442  */
443 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
444 {
445     HANDLE ret;
446     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
447     if (len >= MAX_PATH)
448     {
449         SetLastError( ERROR_FILENAME_EXCED_RANGE );
450         return 0;
451     }
452     SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
453     {
454         req->access  = access;
455         req->inherit = inherit;
456         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
457         SERVER_CALL_ERR();
458         ret = req->handle;
459     }
460     SERVER_END_VAR_REQ;
461     return ret;
462 }
463
464
465 /***********************************************************************
466  *           OpenSemaphoreW   (KERNEL32.546)
467  */
468 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
469 {
470     HANDLE ret;
471     DWORD len = name ? strlenW(name) : 0;
472     if (len >= MAX_PATH)
473     {
474         SetLastError( ERROR_FILENAME_EXCED_RANGE );
475         return 0;
476     }
477     SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
478     {
479         req->access  = access;
480         req->inherit = inherit;
481         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
482         SERVER_CALL_ERR();
483         ret = req->handle;
484     }
485     SERVER_END_VAR_REQ;
486     return ret;
487 }
488
489
490 /***********************************************************************
491  *           ReleaseSemaphore   (KERNEL32.583)
492  */
493 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
494 {
495     NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
496     if (status) SetLastError( RtlNtStatusToDosError(status) );
497     return !status;
498 }
499
500
501 /*
502  * Pipes
503  */
504
505
506 /***********************************************************************
507  *           CreateNamedPipeA   (KERNEL32.168)
508  */
509 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
510                                 DWORD dwPipeMode, DWORD nMaxInstances,
511                                 DWORD nOutBufferSize, DWORD nInBufferSize,
512                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
513 {
514     FIXME("(Name=%s, OpenMode=%#08lx, dwPipeMode=%#08lx, MaxInst=%ld, OutBSize=%ld, InBuffSize=%ld, DefTimeOut=%ld, SecAttr=%p): stub\n",
515           debugstr_a(name), dwOpenMode, dwPipeMode, nMaxInstances,
516           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
517     SetLastError (ERROR_UNKNOWN);
518     return INVALID_HANDLE_VALUE;
519 }
520
521
522 /***********************************************************************
523  *           CreateNamedPipeW   (KERNEL32.169)
524  */
525 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
526                                 DWORD dwPipeMode, DWORD nMaxInstances,
527                                 DWORD nOutBufferSize, DWORD nInBufferSize,
528                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
529 {
530     FIXME("(Name=%s, OpenMode=%#08lx, dwPipeMode=%#08lx, MaxInst=%ld, OutBSize=%ld, InBuffSize=%ld, DefTimeOut=%ld, SecAttr=%p): stub\n",
531           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
532           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
533
534     SetLastError (ERROR_UNKNOWN);
535     return INVALID_HANDLE_VALUE;
536 }
537
538
539 /***********************************************************************
540  *           PeekNamedPipe   (KERNEL32.552)
541  */
542 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
543                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
544 {
545     FIXME("(%08x, %p, %08lx, %p, %p, %p): stub\n",
546           hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage);
547     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
548     return FALSE;
549 }
550
551
552 /***********************************************************************
553  *           WaitNamedPipeA   (KERNEL32.725)
554  */
555 BOOL WINAPI WaitNamedPipeA (LPCSTR lpNamedPipeName, DWORD nTimeOut)
556 {
557     FIXME("%s 0x%08lx\n",lpNamedPipeName,nTimeOut);
558     SetLastError(ERROR_PIPE_NOT_CONNECTED);
559     return FALSE;
560 }
561
562
563 /***********************************************************************
564  *           WaitNamedPipeW   (KERNEL32.726)
565  */
566 BOOL WINAPI WaitNamedPipeW (LPCWSTR lpNamedPipeName, DWORD nTimeOut)
567 {
568     FIXME("%s 0x%08lx\n",debugstr_w(lpNamedPipeName),nTimeOut);
569     SetLastError(ERROR_PIPE_NOT_CONNECTED);
570     return FALSE;
571 }