Remove duplicate code by using Nt* functions for PulseEvent,
[wine] / dlls / kernel / sync.c
1 /*
2  * Kernel synchronization objects
3  *
4  * Copyright 1998 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <string.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <errno.h>
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
31 #endif
32 #ifdef HAVE_SYS_POLL_H
33 #include <sys/poll.h>
34 #endif
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38 #include <stdarg.h>
39 #include <stdio.h>
40
41 #include "ntstatus.h"
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winnls.h"
46 #include "winreg.h"
47 #include "winternl.h"
48
49 #include "wine/server.h"
50 #include "wine/unicode.h"
51 #include "wine/winbase16.h"
52 #include "kernel_private.h"
53
54 #include "wine/debug.h"
55
56 WINE_DEFAULT_DEBUG_CHANNEL(sync);
57
58 /* check if current version is NT or Win95 */
59 inline static int is_version_nt(void)
60 {
61     return !(GetVersion() & 0x80000000);
62 }
63
64
65 /***********************************************************************
66  *              Sleep  (KERNEL32.@)
67  */
68 VOID WINAPI Sleep( DWORD timeout )
69 {
70     SleepEx( timeout, FALSE );
71 }
72
73 /******************************************************************************
74  *              SleepEx   (KERNEL32.@)
75  */
76 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
77 {
78     NTSTATUS status;
79
80     if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
81     else
82     {
83         LARGE_INTEGER time;
84
85         time.QuadPart = timeout * (ULONGLONG)10000;
86         time.QuadPart = -time.QuadPart;
87         status = NtDelayExecution( alertable, &time );
88     }
89     if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
90     return status;
91 }
92
93
94 /***********************************************************************
95  *           WaitForSingleObject   (KERNEL32.@)
96  */
97 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
98 {
99     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
100 }
101
102
103 /***********************************************************************
104  *           WaitForSingleObjectEx   (KERNEL32.@)
105  */
106 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
107                                     BOOL alertable )
108 {
109     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
110 }
111
112
113 /***********************************************************************
114  *           WaitForMultipleObjects   (KERNEL32.@)
115  */
116 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
117                                      BOOL wait_all, DWORD timeout )
118 {
119     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
120 }
121
122
123 /***********************************************************************
124  *           WaitForMultipleObjectsEx   (KERNEL32.@)
125  */
126 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
127                                        BOOL wait_all, DWORD timeout,
128                                        BOOL alertable )
129 {
130     NTSTATUS status;
131     HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
132     int i;
133
134     if (count >= MAXIMUM_WAIT_OBJECTS)
135     {
136         SetLastError(ERROR_INVALID_PARAMETER);
137         return WAIT_FAILED;
138     }
139     for (i = 0; i < count; i++)
140     {
141         if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
142             (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
143             (handles[i] == (HANDLE)STD_ERROR_HANDLE))
144             hloc[i] = GetStdHandle( (DWORD)handles[i] );
145         else
146             hloc[i] = handles[i];
147
148         /* yes, even screen buffer console handles are waitable, and are
149          * handled as a handle to the console itself !!
150          */
151         if (is_console_handle(hloc[i]))
152         {
153             if (!VerifyConsoleIoHandle(hloc[i]))
154             {
155                 return FALSE;
156             }
157             hloc[i] = GetConsoleInputWaitHandle();
158         }
159     }
160
161     if (timeout == INFINITE)
162     {
163         status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
164     }
165     else
166     {
167         LARGE_INTEGER time;
168
169         time.QuadPart = timeout * (ULONGLONG)10000;
170         time.QuadPart = -time.QuadPart;
171         status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
172     }
173
174     if (HIWORD(status))  /* is it an error code? */
175     {
176         SetLastError( RtlNtStatusToDosError(status) );
177         status = WAIT_FAILED;
178     }
179     return status;
180 }
181
182
183 /***********************************************************************
184  *           WaitForSingleObject   (KERNEL.460)
185  */
186 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
187 {
188     DWORD retval, mutex_count;
189
190     ReleaseThunkLock( &mutex_count );
191     retval = WaitForSingleObject( handle, timeout );
192     RestoreThunkLock( mutex_count );
193     return retval;
194 }
195
196 /***********************************************************************
197  *           WaitForMultipleObjects   (KERNEL.461)
198  */
199 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
200                                        BOOL wait_all, DWORD timeout )
201 {
202     DWORD retval, mutex_count;
203
204     ReleaseThunkLock( &mutex_count );
205     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
206     RestoreThunkLock( mutex_count );
207     return retval;
208 }
209
210 /***********************************************************************
211  *           WaitForMultipleObjectsEx   (KERNEL.495)
212  */
213 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
214                                          BOOL wait_all, DWORD timeout, BOOL alertable )
215 {
216     DWORD retval, mutex_count;
217
218     ReleaseThunkLock( &mutex_count );
219     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
220     RestoreThunkLock( mutex_count );
221     return retval;
222 }
223
224 /***********************************************************************
225  *           RegisterWaitForSingleObject   (KERNEL32.@)
226  */
227 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
228                 WAITORTIMERCALLBACK Callback, PVOID Context,
229                 ULONG dwMilliseconds, ULONG dwFlags)
230 {
231     FIXME("%p %p %p %p %ld %ld\n",
232           phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
233     return FALSE;
234 }
235
236 /***********************************************************************
237  *           RegisterWaitForSingleObjectEx   (KERNEL32.@)
238  */
239 BOOL WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject, 
240                 WAITORTIMERCALLBACK Callback, PVOID Context,
241                 ULONG dwMilliseconds, ULONG dwFlags ) 
242 {
243     FIXME("%p %p %p %ld %ld\n",
244           hObject,Callback,Context,dwMilliseconds,dwFlags);
245     return FALSE;
246 }
247
248 /***********************************************************************
249  *           UnregisterWait   (KERNEL32.@)
250  */
251 BOOL WINAPI UnregisterWait( HANDLE WaitHandle ) 
252 {
253     FIXME("%p\n",WaitHandle);
254     return FALSE;
255 }
256
257 /***********************************************************************
258  *           UnregisterWaitEx   (KERNEL32.@)
259  */
260 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent ) 
261 {
262     FIXME("%p %p\n",WaitHandle, CompletionEvent);
263     return FALSE;
264 }
265
266 /***********************************************************************
267  *           SignalObjectAndWait  (KERNEL32.@)
268  *
269  * Allows to atomically signal any of the synchro objects (semaphore,
270  * mutex, event) and wait on another.
271  */
272 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
273 {
274     FIXME("(%p %p %ld %d): stub\n",  hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable);
275     return WAIT_OBJECT_0;
276 }
277
278
279 /***********************************************************************
280  *           InitializeCriticalSection   (KERNEL32.@)
281  *
282  * Initialise a critical section before use.
283  *
284  * PARAMS
285  *  crit [O] Critical section to initialise.
286  *
287  * RETURNS
288  *  Nothing. If the function fails an exception is raised.
289  */
290 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
291 {
292     NTSTATUS ret = RtlInitializeCriticalSection( crit );
293     if (ret) RtlRaiseStatus( ret );
294 }
295
296 /***********************************************************************
297  *           InitializeCriticalSectionAndSpinCount   (KERNEL32.@)
298  *
299  * Initialise a critical section with a spin count.
300  *
301  * PARAMS
302  *  crit      [O] Critical section to initialise.
303  *  spincount [I] Number of times to spin upon contention.
304  *
305  * RETURNS
306  *  Success: TRUE.
307  *  Failure: Nothing. If the function fails an exception is raised.
308  *
309  * NOTES
310  *  spincount is ignored on uni-processor systems.
311  */
312 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
313 {
314     NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
315     if (ret) RtlRaiseStatus( ret );
316     return !ret;
317 }
318
319 /***********************************************************************
320  *           SetCriticalSectionSpinCount   (KERNEL32.@)
321  *
322  * Set the spin count for a critical section.
323  *
324  * PARAMS
325  *  crit      [O] Critical section to set the spin count for.
326  *  spincount [I] Number of times to spin upon contention.
327  *
328  * RETURNS
329  *  The previous spin count value of crit.
330  *
331  * NOTES
332  *  This function is available on NT4SP3 or later, but not Win98.
333  */
334 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
335 {
336     ULONG_PTR oldspincount = crit->SpinCount;
337     if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
338     crit->SpinCount = spincount;
339     return oldspincount;
340 }
341
342 /***********************************************************************
343  *           MakeCriticalSectionGlobal   (KERNEL32.@)
344  */
345 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
346 {
347     /* let's assume that only one thread at a time will try to do this */
348     HANDLE sem = crit->LockSemaphore;
349     if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
350     crit->LockSemaphore = ConvertToGlobalHandle( sem );
351     if (crit->DebugInfo)
352     {
353         RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
354         crit->DebugInfo = NULL;
355     }
356 }
357
358
359 /***********************************************************************
360  *           ReinitializeCriticalSection   (KERNEL32.@)
361  *
362  * Initialise an already used critical section.
363  *
364  * PARAMS
365  *  crit [O] Critical section to initialise.
366  *
367  * RETURNS
368  *  Nothing.
369  */
370 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
371 {
372     if ( !crit->LockSemaphore )
373         RtlInitializeCriticalSection( crit );
374 }
375
376
377 /***********************************************************************
378  *           UninitializeCriticalSection   (KERNEL32.@)
379  *
380  * UnInitialise a critical section after use.
381  *
382  * PARAMS
383  *  crit [O] Critical section to uninitialise (destroy).
384  *
385  * RETURNS
386  *  Nothing.
387  */
388 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
389 {
390     RtlDeleteCriticalSection( crit );
391 }
392
393
394 /***********************************************************************
395  *           CreateEventA    (KERNEL32.@)
396  */
397 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
398                             BOOL initial_state, LPCSTR name )
399 {
400     WCHAR buffer[MAX_PATH];
401
402     if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
403
404     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
405     {
406         SetLastError( ERROR_FILENAME_EXCED_RANGE );
407         return 0;
408     }
409     return CreateEventW( sa, manual_reset, initial_state, buffer );
410 }
411
412
413 /***********************************************************************
414  *           CreateEventW    (KERNEL32.@)
415  */
416 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
417                             BOOL initial_state, LPCWSTR name )
418 {
419     HANDLE ret;
420     DWORD len = name ? strlenW(name) : 0;
421     if (len >= MAX_PATH)
422     {
423         SetLastError( ERROR_FILENAME_EXCED_RANGE );
424         return 0;
425     }
426     /* one buggy program needs this
427      * ("Van Dale Groot woordenboek der Nederlandse taal")
428      */
429     if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
430     {
431         ERR("Bad security attributes pointer %p\n",sa);
432         SetLastError( ERROR_INVALID_PARAMETER);
433         return 0;
434     }
435     SERVER_START_REQ( create_event )
436     {
437         req->manual_reset = manual_reset;
438         req->initial_state = initial_state;
439         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
440         wine_server_add_data( req, name, len * sizeof(WCHAR) );
441         SetLastError(0);
442         wine_server_call_err( req );
443         ret = reply->handle;
444     }
445     SERVER_END_REQ;
446     return ret;
447 }
448
449
450 /***********************************************************************
451  *           CreateW32Event    (KERNEL.457)
452  */
453 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
454 {
455     return CreateEventA( NULL, manual_reset, initial_state, NULL );
456 }
457
458
459 /***********************************************************************
460  *           OpenEventA    (KERNEL32.@)
461  */
462 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
463 {
464     WCHAR buffer[MAX_PATH];
465
466     if (!name) return OpenEventW( access, inherit, NULL );
467
468     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
469     {
470         SetLastError( ERROR_FILENAME_EXCED_RANGE );
471         return 0;
472     }
473     return OpenEventW( access, inherit, buffer );
474 }
475
476
477 /***********************************************************************
478  *           OpenEventW    (KERNEL32.@)
479  */
480 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
481 {
482     HANDLE ret;
483     DWORD len = name ? strlenW(name) : 0;
484     if (len >= MAX_PATH)
485     {
486         SetLastError( ERROR_FILENAME_EXCED_RANGE );
487         return 0;
488     }
489     if (!is_version_nt()) access = EVENT_ALL_ACCESS;
490
491     SERVER_START_REQ( open_event )
492     {
493         req->access  = access;
494         req->inherit = inherit;
495         wine_server_add_data( req, name, len * sizeof(WCHAR) );
496         wine_server_call_err( req );
497         ret = reply->handle;
498     }
499     SERVER_END_REQ;
500     return ret;
501 }
502
503 /***********************************************************************
504  *           PulseEvent    (KERNEL32.@)
505  */
506 BOOL WINAPI PulseEvent( HANDLE handle )
507 {
508     NTSTATUS status;
509
510     if ((status = NtPulseEvent( handle, NULL )))
511         SetLastError( RtlNtStatusToDosError(status) );
512     return !status;
513 }
514
515
516 /***********************************************************************
517  *           SetW32Event (KERNEL.458)
518  *           SetEvent    (KERNEL32.@)
519  */
520 BOOL WINAPI SetEvent( HANDLE handle )
521 {
522     NTSTATUS status;
523
524     if ((status = NtSetEvent( handle, NULL )))
525         SetLastError( RtlNtStatusToDosError(status) );
526     return !status;
527 }
528
529
530 /***********************************************************************
531  *           ResetW32Event (KERNEL.459)
532  *           ResetEvent    (KERNEL32.@)
533  */
534 BOOL WINAPI ResetEvent( HANDLE handle )
535 {
536     NTSTATUS status;
537
538     if ((status = NtResetEvent( handle, NULL )))
539         SetLastError( RtlNtStatusToDosError(status) );
540     return !status;
541 }
542
543
544 /***********************************************************************
545  * NOTE: The Win95 VWin32_Event routines given below are really low-level
546  *       routines implemented directly by VWin32. The user-mode libraries
547  *       implement Win32 synchronisation routines on top of these low-level
548  *       primitives. We do it the other way around here :-)
549  */
550
551 /***********************************************************************
552  *       VWin32_EventCreate     (KERNEL.442)
553  */
554 HANDLE WINAPI VWin32_EventCreate(VOID)
555 {
556     HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
557     return ConvertToGlobalHandle( hEvent );
558 }
559
560 /***********************************************************************
561  *       VWin32_EventDestroy    (KERNEL.443)
562  */
563 VOID WINAPI VWin32_EventDestroy(HANDLE event)
564 {
565     CloseHandle( event );
566 }
567
568 /***********************************************************************
569  *       VWin32_EventWait       (KERNEL.450)
570  */
571 VOID WINAPI VWin32_EventWait(HANDLE event)
572 {
573     DWORD mutex_count;
574
575     ReleaseThunkLock( &mutex_count );
576     WaitForSingleObject( event, INFINITE );
577     RestoreThunkLock( mutex_count );
578 }
579
580 /***********************************************************************
581  *       VWin32_EventSet        (KERNEL.451)
582  *       KERNEL_479             (KERNEL.479)
583  */
584 VOID WINAPI VWin32_EventSet(HANDLE event)
585 {
586     SetEvent( event );
587 }
588
589
590
591 /***********************************************************************
592  *           CreateMutexA   (KERNEL32.@)
593  */
594 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
595 {
596     WCHAR buffer[MAX_PATH];
597
598     if (!name) return CreateMutexW( sa, owner, NULL );
599
600     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
601     {
602         SetLastError( ERROR_FILENAME_EXCED_RANGE );
603         return 0;
604     }
605     return CreateMutexW( sa, owner, buffer );
606 }
607
608
609 /***********************************************************************
610  *           CreateMutexW   (KERNEL32.@)
611  */
612 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
613 {
614     HANDLE ret;
615     DWORD len = name ? strlenW(name) : 0;
616     if (len >= MAX_PATH)
617     {
618         SetLastError( ERROR_FILENAME_EXCED_RANGE );
619         return 0;
620     }
621     SERVER_START_REQ( create_mutex )
622     {
623         req->owned   = owner;
624         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
625         wine_server_add_data( req, name, len * sizeof(WCHAR) );
626         SetLastError(0);
627         wine_server_call_err( req );
628         ret = reply->handle;
629     }
630     SERVER_END_REQ;
631     return ret;
632 }
633
634
635 /***********************************************************************
636  *           OpenMutexA   (KERNEL32.@)
637  */
638 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
639 {
640     WCHAR buffer[MAX_PATH];
641
642     if (!name) return OpenMutexW( access, inherit, NULL );
643
644     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
645     {
646         SetLastError( ERROR_FILENAME_EXCED_RANGE );
647         return 0;
648     }
649     return OpenMutexW( access, inherit, buffer );
650 }
651
652
653 /***********************************************************************
654  *           OpenMutexW   (KERNEL32.@)
655  */
656 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
657 {
658     HANDLE ret;
659     DWORD len = name ? strlenW(name) : 0;
660     if (len >= MAX_PATH)
661     {
662         SetLastError( ERROR_FILENAME_EXCED_RANGE );
663         return 0;
664     }
665     if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
666
667     SERVER_START_REQ( open_mutex )
668     {
669         req->access  = access;
670         req->inherit = inherit;
671         wine_server_add_data( req, name, len * sizeof(WCHAR) );
672         wine_server_call_err( req );
673         ret = reply->handle;
674     }
675     SERVER_END_REQ;
676     return ret;
677 }
678
679
680 /***********************************************************************
681  *           ReleaseMutex   (KERNEL32.@)
682  */
683 BOOL WINAPI ReleaseMutex( HANDLE handle )
684 {
685     BOOL ret;
686     SERVER_START_REQ( release_mutex )
687     {
688         req->handle = handle;
689         ret = !wine_server_call_err( req );
690     }
691     SERVER_END_REQ;
692     return ret;
693 }
694
695
696 /*
697  * Semaphores
698  */
699
700
701 /***********************************************************************
702  *           CreateSemaphoreA   (KERNEL32.@)
703  */
704 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
705 {
706     WCHAR buffer[MAX_PATH];
707
708     if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
709
710     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
711     {
712         SetLastError( ERROR_FILENAME_EXCED_RANGE );
713         return 0;
714     }
715     return CreateSemaphoreW( sa, initial, max, buffer );
716 }
717
718
719 /***********************************************************************
720  *           CreateSemaphoreW   (KERNEL32.@)
721  */
722 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
723                                     LONG max, LPCWSTR name )
724 {
725     HANDLE ret;
726     DWORD len = name ? strlenW(name) : 0;
727
728     /* Check parameters */
729
730     if ((max <= 0) || (initial < 0) || (initial > max))
731     {
732         SetLastError( ERROR_INVALID_PARAMETER );
733         return 0;
734     }
735     if (len >= MAX_PATH)
736     {
737         SetLastError( ERROR_FILENAME_EXCED_RANGE );
738         return 0;
739     }
740
741     SERVER_START_REQ( create_semaphore )
742     {
743         req->initial = (unsigned int)initial;
744         req->max     = (unsigned int)max;
745         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
746         wine_server_add_data( req, name, len * sizeof(WCHAR) );
747         SetLastError(0);
748         wine_server_call_err( req );
749         ret = reply->handle;
750     }
751     SERVER_END_REQ;
752     return ret;
753 }
754
755
756 /***********************************************************************
757  *           OpenSemaphoreA   (KERNEL32.@)
758  */
759 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
760 {
761     WCHAR buffer[MAX_PATH];
762
763     if (!name) return OpenSemaphoreW( access, inherit, NULL );
764
765     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
766     {
767         SetLastError( ERROR_FILENAME_EXCED_RANGE );
768         return 0;
769     }
770     return OpenSemaphoreW( access, inherit, buffer );
771 }
772
773
774 /***********************************************************************
775  *           OpenSemaphoreW   (KERNEL32.@)
776  */
777 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
778 {
779     HANDLE ret;
780     DWORD len = name ? strlenW(name) : 0;
781     if (len >= MAX_PATH)
782     {
783         SetLastError( ERROR_FILENAME_EXCED_RANGE );
784         return 0;
785     }
786     if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
787
788     SERVER_START_REQ( open_semaphore )
789     {
790         req->access  = access;
791         req->inherit = inherit;
792         wine_server_add_data( req, name, len * sizeof(WCHAR) );
793         wine_server_call_err( req );
794         ret = reply->handle;
795     }
796     SERVER_END_REQ;
797     return ret;
798 }
799
800
801 /***********************************************************************
802  *           ReleaseSemaphore   (KERNEL32.@)
803  */
804 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
805 {
806     NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
807     if (status) SetLastError( RtlNtStatusToDosError(status) );
808     return !status;
809 }
810
811
812 /*
813  * Timers
814  */
815
816
817 /***********************************************************************
818  *           CreateWaitableTimerA    (KERNEL32.@)
819  */
820 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
821 {
822     WCHAR buffer[MAX_PATH];
823
824     if (!name) return CreateWaitableTimerW( sa, manual, NULL );
825
826     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
827     {
828         SetLastError( ERROR_FILENAME_EXCED_RANGE );
829         return 0;
830     }
831     return CreateWaitableTimerW( sa, manual, buffer );
832 }
833
834
835 /***********************************************************************
836  *           CreateWaitableTimerW    (KERNEL32.@)
837  */
838 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
839 {
840     HANDLE              handle;
841     NTSTATUS            status;
842     UNICODE_STRING      us;
843     DWORD               attr = 0;
844     OBJECT_ATTRIBUTES   oa;
845
846     if (name) RtlInitUnicodeString(&us, name);
847     if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
848         attr |= OBJ_INHERIT;
849     InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
850                                NULL /* FIXME */, NULL /* FIXME */);
851     status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
852                            manual ? NotificationTimer : SynchronizationTimer);
853
854     if (status != STATUS_SUCCESS)
855     {
856         SetLastError( RtlNtStatusToDosError(status) );
857         return 0;
858     }
859     return handle;
860 }
861
862
863 /***********************************************************************
864  *           OpenWaitableTimerA    (KERNEL32.@)
865  */
866 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
867 {
868     WCHAR buffer[MAX_PATH];
869
870     if (!name) return OpenWaitableTimerW( access, inherit, NULL );
871
872     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
873     {
874         SetLastError( ERROR_FILENAME_EXCED_RANGE );
875         return 0;
876     }
877     return OpenWaitableTimerW( access, inherit, buffer );
878 }
879
880
881 /***********************************************************************
882  *           OpenWaitableTimerW    (KERNEL32.@)
883  */
884 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
885 {
886     NTSTATUS            status;
887     ULONG               attr = 0;
888     UNICODE_STRING      us;
889     HANDLE              handle;
890     OBJECT_ATTRIBUTES   oa;
891
892     if (inherit) attr |= OBJ_INHERIT;
893
894     if (name) RtlInitUnicodeString(&us, name);
895     InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
896     status = NtOpenTimer(&handle, access, &oa);
897     if (status != STATUS_SUCCESS)
898     {
899         SetLastError( RtlNtStatusToDosError(status) );
900         return 0;
901     }
902     return handle;
903 }
904
905
906 /***********************************************************************
907  *           SetWaitableTimer    (KERNEL32.@)
908  */
909 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
910                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
911 {
912     NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
913
914     if (status != STATUS_SUCCESS)
915     {
916         SetLastError( RtlNtStatusToDosError(status) );
917         if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
918     }
919     return TRUE;
920 }
921
922
923 /***********************************************************************
924  *           CancelWaitableTimer    (KERNEL32.@)
925  */
926 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
927 {
928     NTSTATUS status;
929
930     status = NtCancelTimer(handle, NULL);
931     if (status != STATUS_SUCCESS)
932     {
933         SetLastError( RtlNtStatusToDosError(status) );
934         return FALSE;
935     }
936     return TRUE;
937 }
938
939
940 /***********************************************************************
941  *           CreateTimerQueue  (KERNEL32.@)
942  */
943 HANDLE WINAPI CreateTimerQueue(void)
944 {
945     FIXME("stub\n");
946     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
947     return NULL;
948 }
949
950
951 /***********************************************************************
952  *           DeleteTimerQueueEx  (KERNEL32.@)
953  */
954 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
955 {
956     FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
957     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
958     return 0;
959 }
960
961 /***********************************************************************
962  *           CreateTimerQueueTimer  (KERNEL32.@)
963  *
964  * Creates a timer-queue timer. This timer expires at the specified due
965  * time (in ms), then after every specified period (in ms). When the timer
966  * expires, the callback function is called.
967  *
968  * RETURNS
969  *   nonzero on success or zero on faillure
970  *
971  * BUGS
972  *   Unimplemented
973  */
974 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
975                                    WAITORTIMERCALLBACK Callback, PVOID Parameter,
976                                    DWORD DueTime, DWORD Period, ULONG Flags )
977 {
978     FIXME("stub\n");
979     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
980     return TRUE;
981 }
982
983 /***********************************************************************
984  *           DeleteTimerQueueTimer  (KERNEL32.@)
985  *
986  * Cancels a timer-queue timer.
987  *
988  * RETURNS
989  *   nonzero on success or zero on faillure
990  *
991  * BUGS
992  *   Unimplemented
993  */
994 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
995                                    HANDLE CompletionEvent )
996 {
997     FIXME("stub\n");
998     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
999     return TRUE;
1000 }
1001
1002
1003 /*
1004  * Pipes
1005  */
1006
1007
1008 /***********************************************************************
1009  *           CreateNamedPipeA   (KERNEL32.@)
1010  */
1011 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1012                                 DWORD dwPipeMode, DWORD nMaxInstances,
1013                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1014                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1015 {
1016     WCHAR buffer[MAX_PATH];
1017
1018     if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1019                                         nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1020
1021     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1022     {
1023         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1024         return INVALID_HANDLE_VALUE;
1025     }
1026     return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1027                              nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1028 }
1029
1030
1031 /***********************************************************************
1032  *           CreateNamedPipeW   (KERNEL32.@)
1033  */
1034 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1035                                 DWORD dwPipeMode, DWORD nMaxInstances,
1036                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1037                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1038 {
1039     HANDLE ret;
1040     DWORD len;
1041     static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
1042
1043     TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1044           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1045           nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1046
1047     if (!name)
1048     {
1049         SetLastError( ERROR_PATH_NOT_FOUND );
1050         return INVALID_HANDLE_VALUE;
1051     }
1052     len = strlenW(name);
1053     if (len >= MAX_PATH)
1054     {
1055         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1056         return INVALID_HANDLE_VALUE;
1057     }
1058     if (strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0])))
1059     {
1060         SetLastError( ERROR_INVALID_NAME );
1061         return INVALID_HANDLE_VALUE;
1062     }
1063     SERVER_START_REQ( create_named_pipe )
1064     {
1065         req->openmode = dwOpenMode;
1066         req->pipemode = dwPipeMode;
1067         req->maxinstances = nMaxInstances;
1068         req->outsize = nOutBufferSize;
1069         req->insize = nInBufferSize;
1070         req->timeout = nDefaultTimeOut;
1071         req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1072         wine_server_add_data( req, name, len * sizeof(WCHAR) );
1073         SetLastError(0);
1074         if (!wine_server_call_err( req )) ret = reply->handle;
1075         else ret = INVALID_HANDLE_VALUE;
1076     }
1077     SERVER_END_REQ;
1078     return ret;
1079 }
1080
1081
1082 /***********************************************************************
1083  *           PeekNamedPipe   (KERNEL32.@)
1084  */
1085 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1086                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1087 {
1088 #ifdef FIONREAD
1089     int avail=0, fd, ret, flags;
1090
1091     ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, NULL, &flags );
1092     if (ret)
1093     {
1094         SetLastError( RtlNtStatusToDosError(ret) );
1095         return FALSE;
1096     }
1097     if (flags & FD_FLAG_RECV_SHUTDOWN)
1098     {
1099         wine_server_release_fd( hPipe, fd );
1100         SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1101         return FALSE;
1102     }
1103
1104     if (ioctl(fd,FIONREAD, &avail ) != 0)
1105     {
1106         TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1107         wine_server_release_fd( hPipe, fd );
1108         return FALSE;
1109     }
1110     if (!avail)  /* check for closed pipe */
1111     {
1112         struct pollfd pollfd;
1113         pollfd.fd = fd;
1114         pollfd.events = POLLIN;
1115         pollfd.revents = 0;
1116         switch (poll( &pollfd, 1, 0 ))
1117         {
1118         case 0:
1119             break;
1120         case 1:  /* got something */
1121             if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1122             TRACE("POLLHUP | POLLERR\n");
1123             /* fall through */
1124         case -1:
1125             wine_server_release_fd( hPipe, fd );
1126             SetLastError(ERROR_BROKEN_PIPE);
1127             return FALSE;
1128         }
1129     }
1130     TRACE(" 0x%08x bytes available\n", avail );
1131     ret = TRUE;
1132     if (lpcbAvail)
1133         *lpcbAvail = avail;
1134     if (lpcbRead)
1135         *lpcbRead = 0;
1136     if (avail && lpvBuffer)
1137     {
1138         int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1139         readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1140         if (readbytes < 0)
1141         {
1142             WARN("failed to peek socket (%d)\n", errno);
1143             ret = FALSE;
1144         }
1145         else if (lpcbRead)
1146             *lpcbRead = readbytes;
1147     }
1148     wine_server_release_fd( hPipe, fd );
1149     return ret;
1150 #endif /* defined(FIONREAD) */
1151
1152     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1153     FIXME("function not implemented\n");
1154     return FALSE;
1155 }
1156
1157 /***********************************************************************
1158  *           SYNC_CompletePipeOverlapped   (Internal)
1159  */
1160 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1161 {
1162     TRACE("for %p result %08lx\n",overlapped,result);
1163     if(!overlapped)
1164         return;
1165     overlapped->Internal = result;
1166     SetEvent(overlapped->hEvent);
1167 }
1168
1169
1170 /***********************************************************************
1171  *           WaitNamedPipeA   (KERNEL32.@)
1172  */
1173 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1174 {
1175     WCHAR buffer[MAX_PATH];
1176
1177     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1178
1179     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1180     {
1181         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1182         return 0;
1183     }
1184     return WaitNamedPipeW( buffer, nTimeOut );
1185 }
1186
1187
1188 /***********************************************************************
1189  *           WaitNamedPipeW   (KERNEL32.@)
1190  */
1191 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1192 {
1193     DWORD len = name ? strlenW(name) : 0;
1194     BOOL ret;
1195     OVERLAPPED ov;
1196
1197     if (len >= MAX_PATH)
1198     {
1199         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1200         return FALSE;
1201     }
1202
1203     TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1204
1205     memset(&ov,0,sizeof(ov));
1206     ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
1207     if (!ov.hEvent)
1208         return FALSE;
1209
1210     SERVER_START_REQ( wait_named_pipe )
1211     {
1212         req->timeout = nTimeOut;
1213         req->overlapped = &ov;
1214         req->func = SYNC_CompletePipeOverlapped;
1215         wine_server_add_data( req, name, len * sizeof(WCHAR) );
1216         ret = !wine_server_call_err( req );
1217     }
1218     SERVER_END_REQ;
1219
1220     if(ret)
1221     {
1222         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1223         {
1224             SetLastError(ov.Internal);
1225             ret = (ov.Internal==STATUS_SUCCESS);
1226         }
1227     }
1228     CloseHandle(ov.hEvent);
1229     return ret;
1230 }
1231
1232
1233 /***********************************************************************
1234  *           SYNC_ConnectNamedPipe   (Internal)
1235  */
1236 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1237 {
1238     BOOL ret;
1239
1240     if(!overlapped)
1241         return FALSE;
1242
1243     overlapped->Internal = STATUS_PENDING;
1244
1245     SERVER_START_REQ( connect_named_pipe )
1246     {
1247         req->handle = hPipe;
1248         req->overlapped = overlapped;
1249         req->func = SYNC_CompletePipeOverlapped;
1250         ret = !wine_server_call_err( req );
1251     }
1252     SERVER_END_REQ;
1253
1254     return ret;
1255 }
1256
1257 /***********************************************************************
1258  *           ConnectNamedPipe   (KERNEL32.@)
1259  */
1260 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1261 {
1262     OVERLAPPED ov;
1263     BOOL ret;
1264
1265     TRACE("(%p,%p)\n",hPipe, overlapped);
1266
1267     if(overlapped)
1268     {
1269         if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1270             SetLastError( ERROR_IO_PENDING );
1271         return FALSE;
1272     }
1273
1274     memset(&ov,0,sizeof(ov));
1275     ov.hEvent = CreateEventA(NULL,0,0,NULL);
1276     if (!ov.hEvent)
1277         return FALSE;
1278
1279     ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1280     if(ret)
1281     {
1282         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1283         {
1284             SetLastError(ov.Internal);
1285             ret = (ov.Internal==STATUS_SUCCESS);
1286         }
1287     }
1288
1289     CloseHandle(ov.hEvent);
1290
1291     return ret;
1292 }
1293
1294 /***********************************************************************
1295  *           DisconnectNamedPipe   (KERNEL32.@)
1296  */
1297 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1298 {
1299     BOOL ret;
1300
1301     TRACE("(%p)\n",hPipe);
1302
1303     SERVER_START_REQ( disconnect_named_pipe )
1304     {
1305         req->handle = hPipe;
1306         ret = !wine_server_call_err( req );
1307         if (ret && reply->fd != -1) close( reply->fd );
1308     }
1309     SERVER_END_REQ;
1310
1311     return ret;
1312 }
1313
1314 /***********************************************************************
1315  *           TransactNamedPipe   (KERNEL32.@)
1316  */
1317 BOOL WINAPI TransactNamedPipe(
1318     HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1319     DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1320 {
1321     FIXME("%p %p %ld %p %ld %p %p\n",
1322           hPipe, lpInput, dwInputSize, lpOutput,
1323           dwOutputSize, lpBytesRead, lpOverlapped);
1324     if(lpBytesRead)
1325         *lpBytesRead=0;
1326     return FALSE;
1327 }
1328
1329 /***********************************************************************
1330  *           GetNamedPipeInfo   (KERNEL32.@)
1331  */
1332 BOOL WINAPI GetNamedPipeInfo(
1333     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1334     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1335 {
1336     BOOL ret;
1337
1338     TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1339           lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1340
1341     SERVER_START_REQ( get_named_pipe_info )
1342     {
1343         req->handle = hNamedPipe;
1344         ret = !wine_server_call_err( req );
1345         if(lpFlags) *lpFlags = reply->flags;
1346         if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1347         if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1348         if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1349     }
1350     SERVER_END_REQ;
1351
1352     return ret;
1353 }
1354
1355 /***********************************************************************
1356  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1357  */
1358 BOOL WINAPI GetNamedPipeHandleStateA(
1359     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1360     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1361     LPSTR lpUsername, DWORD nUsernameMaxSize)
1362 {
1363     FIXME("%p %p %p %p %p %p %ld\n",
1364           hNamedPipe, lpState, lpCurInstances,
1365           lpMaxCollectionCount, lpCollectDataTimeout,
1366           lpUsername, nUsernameMaxSize);
1367
1368     return FALSE;
1369 }
1370
1371 /***********************************************************************
1372  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1373  */
1374 BOOL WINAPI GetNamedPipeHandleStateW(
1375     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1376     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1377     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1378 {
1379     FIXME("%p %p %p %p %p %p %ld\n",
1380           hNamedPipe, lpState, lpCurInstances,
1381           lpMaxCollectionCount, lpCollectDataTimeout,
1382           lpUsername, nUsernameMaxSize);
1383
1384     return FALSE;
1385 }
1386
1387 /***********************************************************************
1388  *           SetNamedPipeHandleState  (KERNEL32.@)
1389  */
1390 BOOL WINAPI SetNamedPipeHandleState(
1391     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1392     LPDWORD lpCollectDataTimeout)
1393 {
1394     FIXME("%p %p %p %p\n",
1395           hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1396     return FALSE;
1397 }
1398
1399 /***********************************************************************
1400  *           CallNamedPipeA  (KERNEL32.@)
1401  */
1402 BOOL WINAPI CallNamedPipeA(
1403     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1404     LPVOID lpOutput, DWORD lpOutputSize,
1405     LPDWORD lpBytesRead, DWORD nTimeout)
1406 {
1407     FIXME("%s %p %ld %p %ld %p %ld\n",
1408            debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1409            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1410     return FALSE;
1411 }
1412
1413 /***********************************************************************
1414  *           CallNamedPipeW  (KERNEL32.@)
1415  */
1416 BOOL WINAPI CallNamedPipeW(
1417     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1418     LPVOID lpOutput, DWORD lpOutputSize,
1419     LPDWORD lpBytesRead, DWORD nTimeout)
1420 {
1421     FIXME("%s %p %ld %p %ld %p %ld\n",
1422            debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1423            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1424     return FALSE;
1425 }
1426
1427 /******************************************************************
1428  *              CreatePipe (KERNEL32.@)
1429  *
1430  */
1431 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1432                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1433 {
1434     static unsigned  index = 0;
1435     char        name[64];
1436     HANDLE      hr, hw;
1437     unsigned    in_index = index;
1438
1439     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1440     /* generate a unique pipe name (system wide) */
1441     do
1442     {
1443         sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1444         hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, 
1445                               PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size, 
1446                               NMPWAIT_USE_DEFAULT_WAIT, sa);
1447     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1448     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1449     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1450
1451     hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1452     if (hw == INVALID_HANDLE_VALUE) 
1453     {
1454         CloseHandle(hr);
1455         return FALSE;
1456     }
1457
1458     *hReadPipe = hr;
1459     *hWritePipe = hw;
1460     return TRUE;
1461 }
1462
1463
1464 /******************************************************************************
1465  * CreateMailslotA [KERNEL32.@]
1466  */
1467 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1468                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1469 {
1470     DWORD len;
1471     HANDLE handle;
1472     LPWSTR name = NULL;
1473
1474     TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1475           nMaxMessageSize, lReadTimeout, sa);
1476
1477     if( lpName )
1478     {
1479         len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1480         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1481         MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1482     }
1483
1484     handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1485
1486     if( name )
1487         HeapFree( GetProcessHeap(), 0, name );
1488
1489     return handle;
1490 }
1491
1492
1493 /******************************************************************************
1494  * CreateMailslotW [KERNEL32.@]
1495  *
1496  * Create a mailslot with specified name.
1497  *
1498  * PARAMS
1499  *    lpName          [I] Pointer to string for mailslot name
1500  *    nMaxMessageSize [I] Maximum message size
1501  *    lReadTimeout    [I] Milliseconds before read time-out
1502  *    sa              [I] Pointer to security structure
1503  *
1504  * RETURNS
1505  *    Success: Handle to mailslot
1506  *    Failure: INVALID_HANDLE_VALUE
1507  */
1508 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1509                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1510 {
1511     FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1512           nMaxMessageSize, lReadTimeout, sa);
1513     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1514     return INVALID_HANDLE_VALUE;
1515 }
1516
1517
1518 /******************************************************************************
1519  * GetMailslotInfo [KERNEL32.@]
1520  *
1521  * Retrieve information about a mailslot.
1522  *
1523  * PARAMS
1524  *    hMailslot        [I] Mailslot handle
1525  *    lpMaxMessageSize [O] Address of maximum message size
1526  *    lpNextSize       [O] Address of size of next message
1527  *    lpMessageCount   [O] Address of number of messages
1528  *    lpReadTimeout    [O] Address of read time-out
1529  *
1530  * RETURNS
1531  *    Success: TRUE
1532  *    Failure: FALSE
1533  */
1534 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1535                                LPDWORD lpNextSize, LPDWORD lpMessageCount,
1536                                LPDWORD lpReadTimeout )
1537 {
1538     FIXME("(%p): stub\n",hMailslot);
1539     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1540     return FALSE;
1541 }
1542
1543
1544 /******************************************************************************
1545  * SetMailslotInfo [KERNEL32.@]
1546  *
1547  * Set the read timeout of a mailslot.
1548  *
1549  * PARAMS
1550  *  hMailslot     [I] Mailslot handle
1551  *  dwReadTimeout [I] Timeout in milliseconds.
1552  *
1553  * RETURNS
1554  *    Success: TRUE
1555  *    Failure: FALSE
1556  */
1557 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1558 {
1559     FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1560     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1561     return FALSE;
1562 }
1563
1564
1565 /******************************************************************************
1566  *              CreateIoCompletionPort (KERNEL32.@)
1567  */
1568 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1569                                      DWORD dwCompletionKey, DWORD dwNumberOfConcurrentThreads)
1570 {
1571     FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1572           hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads);
1573     return NULL;
1574 }
1575
1576
1577 /******************************************************************************
1578  *              GetQueuedCompletionStatus (KERNEL32.@)
1579  */
1580 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1581                                        LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped,
1582                                        DWORD dwMilliseconds )
1583 {
1584     FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1585           CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds);
1586     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1587     return FALSE;
1588 }
1589
1590 /******************************************************************************
1591  *              CreateJobObjectW (KERNEL32.@)
1592  */
1593 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1594 {
1595     FIXME("%p %s\n", attr, debugstr_w(name) );
1596     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1597     return 0;
1598 }
1599
1600 /******************************************************************************
1601  *              CreateJobObjectA (KERNEL32.@)
1602  */
1603 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1604 {
1605     LPWSTR str = NULL;
1606     UINT len;
1607     HANDLE r;
1608
1609     TRACE("%p %s\n", attr, debugstr_a(name) );
1610
1611     if( name )
1612     {
1613         len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1614         str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1615         if( !str )
1616         {
1617             SetLastError( ERROR_OUTOFMEMORY );
1618             return 0;
1619         }
1620         len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1621     }
1622
1623     r = CreateJobObjectW( attr, str );
1624
1625     if( str )
1626         HeapFree( GetProcessHeap(), 0, str );
1627
1628     return r;
1629 }
1630
1631 /******************************************************************************
1632  *              AssignProcessToJobObject (KERNEL32.@)
1633  */
1634 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1635 {
1636     FIXME("%p %p\n", hJob, hProcess);
1637     return TRUE;
1638 }
1639
1640 #ifdef __i386__
1641
1642 /***********************************************************************
1643  *              InterlockedCompareExchange (KERNEL32.@)
1644  */
1645 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1646 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1647                   "movl 12(%esp),%eax\n\t"
1648                   "movl 8(%esp),%ecx\n\t"
1649                   "movl 4(%esp),%edx\n\t"
1650                   "lock; cmpxchgl %ecx,(%edx)\n\t"
1651                   "ret $12");
1652
1653 /***********************************************************************
1654  *              InterlockedExchange (KERNEL32.@)
1655  */
1656 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1657 __ASM_GLOBAL_FUNC(InterlockedExchange,
1658                   "movl 8(%esp),%eax\n\t"
1659                   "movl 4(%esp),%edx\n\t"
1660                   "lock; xchgl %eax,(%edx)\n\t"
1661                   "ret $8");
1662
1663 /***********************************************************************
1664  *              InterlockedExchangeAdd (KERNEL32.@)
1665  */
1666 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1667 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1668                   "movl 8(%esp),%eax\n\t"
1669                   "movl 4(%esp),%edx\n\t"
1670                   "lock; xaddl %eax,(%edx)\n\t"
1671                   "ret $8");
1672
1673 /***********************************************************************
1674  *              InterlockedIncrement (KERNEL32.@)
1675  */
1676 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1677 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1678                   "movl 4(%esp),%edx\n\t"
1679                   "movl $1,%eax\n\t"
1680                   "lock; xaddl %eax,(%edx)\n\t"
1681                   "incl %eax\n\t"
1682                   "ret $4");
1683
1684 /***********************************************************************
1685  *              InterlockedDecrement (KERNEL32.@)
1686  */
1687 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1688                   "movl 4(%esp),%edx\n\t"
1689                   "movl $-1,%eax\n\t"
1690                   "lock; xaddl %eax,(%edx)\n\t"
1691                   "decl %eax\n\t"
1692                   "ret $4");
1693
1694 #else  /* __i386__ */
1695
1696 /***********************************************************************
1697  *              InterlockedCompareExchange (KERNEL32.@)
1698  *
1699  * Atomically swap one value with another.
1700  *
1701  * PARAMS
1702  *  dest    [I/O] The value to replace
1703  *  xchq    [I]   The value to be swapped
1704  *  compare [I]   The value to compare to dest
1705  *
1706  * RETURNS
1707  *  The resulting value of dest.
1708  *
1709  * NOTES
1710  *  dest is updated only if it is equal to compare, otherwise no swap is done.
1711  */
1712 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1713 {
1714     return interlocked_cmpxchg( dest, xchg, compare );
1715 }
1716
1717 /***********************************************************************
1718  *              InterlockedExchange (KERNEL32.@)
1719  *
1720  * Atomically swap one value with another.
1721  *
1722  * PARAMS
1723  *  dest [I/O] The value to replace
1724  *  val  [I]   The value to be swapped
1725  *
1726  * RETURNS
1727  *  The resulting value of dest.
1728  */
1729 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1730 {
1731     return interlocked_xchg( dest, val );
1732 }
1733
1734 /***********************************************************************
1735  *              InterlockedExchangeAdd (KERNEL32.@)
1736  *
1737  * Atomically add one value to another.
1738  *
1739  * PARAMS
1740  *  dest [I/O] The value to add to
1741  *  incr [I]   The value to be added
1742  *
1743  * RETURNS
1744  *  The resulting value of dest.
1745  */
1746 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1747 {
1748     return interlocked_xchg_add( dest, incr );
1749 }
1750
1751 /***********************************************************************
1752  *              InterlockedIncrement (KERNEL32.@)
1753  *
1754  * Atomically increment a value.
1755  *
1756  * PARAMS
1757  *  dest [I/O] The value to increment
1758  *
1759  * RETURNS
1760  *  The resulting value of dest.
1761  */
1762 LONG WINAPI InterlockedIncrement( PLONG dest )
1763 {
1764     return interlocked_xchg_add( dest, 1 ) + 1;
1765 }
1766
1767 /***********************************************************************
1768  *              InterlockedDecrement (KERNEL32.@)
1769  *
1770  * Atomically decrement a value.
1771  *
1772  * PARAMS
1773  *  dest [I/O] The value to decrement
1774  *
1775  * RETURNS
1776  *  The resulting value of dest.
1777  */
1778 LONG WINAPI InterlockedDecrement( PLONG dest )
1779 {
1780     return interlocked_xchg_add( dest, -1 ) - 1;
1781 }
1782
1783 #endif  /* __i386__ */