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