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