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