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