Added some missing prototypes.
[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 HANDLE 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 0;
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     UNICODE_STRING nt_name;
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 (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1048     {
1049         SetLastError( ERROR_PATH_NOT_FOUND );
1050         return INVALID_HANDLE_VALUE;
1051     }
1052     if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1053     {
1054         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1055         RtlFreeUnicodeString( &nt_name );
1056         return INVALID_HANDLE_VALUE;
1057     }
1058     if (nt_name.Length < sizeof(leadin) ||
1059         strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1060     {
1061         SetLastError( ERROR_INVALID_NAME );
1062         RtlFreeUnicodeString( &nt_name );
1063         return INVALID_HANDLE_VALUE;
1064     }
1065     SERVER_START_REQ( create_named_pipe )
1066     {
1067         req->openmode = dwOpenMode;
1068         req->pipemode = dwPipeMode;
1069         req->maxinstances = nMaxInstances;
1070         req->outsize = nOutBufferSize;
1071         req->insize = nInBufferSize;
1072         req->timeout = nDefaultTimeOut;
1073         req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1074         wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1075         SetLastError(0);
1076         if (!wine_server_call_err( req )) ret = reply->handle;
1077         else ret = INVALID_HANDLE_VALUE;
1078     }
1079     SERVER_END_REQ;
1080     RtlFreeUnicodeString( &nt_name );
1081     return ret;
1082 }
1083
1084
1085 /***********************************************************************
1086  *           PeekNamedPipe   (KERNEL32.@)
1087  */
1088 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1089                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1090 {
1091 #ifdef FIONREAD
1092     int avail=0, fd, ret, flags;
1093
1094     ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, NULL, &flags );
1095     if (ret)
1096     {
1097         SetLastError( RtlNtStatusToDosError(ret) );
1098         return FALSE;
1099     }
1100     if (flags & FD_FLAG_RECV_SHUTDOWN)
1101     {
1102         wine_server_release_fd( hPipe, fd );
1103         SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1104         return FALSE;
1105     }
1106
1107     if (ioctl(fd,FIONREAD, &avail ) != 0)
1108     {
1109         TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1110         wine_server_release_fd( hPipe, fd );
1111         return FALSE;
1112     }
1113     if (!avail)  /* check for closed pipe */
1114     {
1115         struct pollfd pollfd;
1116         pollfd.fd = fd;
1117         pollfd.events = POLLIN;
1118         pollfd.revents = 0;
1119         switch (poll( &pollfd, 1, 0 ))
1120         {
1121         case 0:
1122             break;
1123         case 1:  /* got something */
1124             if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1125             TRACE("POLLHUP | POLLERR\n");
1126             /* fall through */
1127         case -1:
1128             wine_server_release_fd( hPipe, fd );
1129             SetLastError(ERROR_BROKEN_PIPE);
1130             return FALSE;
1131         }
1132     }
1133     TRACE(" 0x%08x bytes available\n", avail );
1134     ret = TRUE;
1135     if (lpcbAvail)
1136         *lpcbAvail = avail;
1137     if (lpcbRead)
1138         *lpcbRead = 0;
1139     if (avail && lpvBuffer)
1140     {
1141         int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1142         readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1143         if (readbytes < 0)
1144         {
1145             WARN("failed to peek socket (%d)\n", errno);
1146             ret = FALSE;
1147         }
1148         else if (lpcbRead)
1149             *lpcbRead = readbytes;
1150     }
1151     wine_server_release_fd( hPipe, fd );
1152     return ret;
1153 #endif /* defined(FIONREAD) */
1154
1155     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1156     FIXME("function not implemented\n");
1157     return FALSE;
1158 }
1159
1160 /***********************************************************************
1161  *           SYNC_CompletePipeOverlapped   (Internal)
1162  */
1163 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1164 {
1165     TRACE("for %p result %08lx\n",overlapped,result);
1166     if(!overlapped)
1167         return;
1168     overlapped->Internal = result;
1169     SetEvent(overlapped->hEvent);
1170 }
1171
1172
1173 /***********************************************************************
1174  *           WaitNamedPipeA   (KERNEL32.@)
1175  */
1176 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1177 {
1178     WCHAR buffer[MAX_PATH];
1179
1180     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1181
1182     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1183     {
1184         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1185         return 0;
1186     }
1187     return WaitNamedPipeW( buffer, nTimeOut );
1188 }
1189
1190
1191 /***********************************************************************
1192  *           WaitNamedPipeW   (KERNEL32.@)
1193  */
1194 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1195 {
1196     DWORD len = name ? strlenW(name) : 0;
1197     BOOL ret;
1198     OVERLAPPED ov;
1199
1200     if (len >= MAX_PATH)
1201     {
1202         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1203         return FALSE;
1204     }
1205
1206     TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1207
1208     memset(&ov,0,sizeof(ov));
1209     ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1210     if (!ov.hEvent)
1211         return FALSE;
1212
1213     SERVER_START_REQ( wait_named_pipe )
1214     {
1215         req->timeout = nTimeOut;
1216         req->overlapped = &ov;
1217         req->func = SYNC_CompletePipeOverlapped;
1218         wine_server_add_data( req, name, len * sizeof(WCHAR) );
1219         ret = !wine_server_call_err( req );
1220     }
1221     SERVER_END_REQ;
1222
1223     if(ret)
1224     {
1225         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1226         {
1227             SetLastError(ov.Internal);
1228             ret = (ov.Internal==STATUS_SUCCESS);
1229         }
1230     }
1231     CloseHandle(ov.hEvent);
1232     return ret;
1233 }
1234
1235
1236 /***********************************************************************
1237  *           SYNC_ConnectNamedPipe   (Internal)
1238  */
1239 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1240 {
1241     BOOL ret;
1242
1243     if(!overlapped)
1244         return FALSE;
1245
1246     overlapped->Internal = STATUS_PENDING;
1247
1248     SERVER_START_REQ( connect_named_pipe )
1249     {
1250         req->handle = hPipe;
1251         req->overlapped = overlapped;
1252         req->func = SYNC_CompletePipeOverlapped;
1253         ret = !wine_server_call_err( req );
1254     }
1255     SERVER_END_REQ;
1256
1257     return ret;
1258 }
1259
1260 /***********************************************************************
1261  *           ConnectNamedPipe   (KERNEL32.@)
1262  */
1263 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1264 {
1265     OVERLAPPED ov;
1266     BOOL ret;
1267
1268     TRACE("(%p,%p)\n",hPipe, overlapped);
1269
1270     if(overlapped)
1271     {
1272         if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1273             SetLastError( ERROR_IO_PENDING );
1274         return FALSE;
1275     }
1276
1277     memset(&ov,0,sizeof(ov));
1278     ov.hEvent = CreateEventA(NULL,0,0,NULL);
1279     if (!ov.hEvent)
1280         return FALSE;
1281
1282     ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1283     if(ret)
1284     {
1285         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1286         {
1287             SetLastError(ov.Internal);
1288             ret = (ov.Internal==STATUS_SUCCESS);
1289         }
1290     }
1291
1292     CloseHandle(ov.hEvent);
1293
1294     return ret;
1295 }
1296
1297 /***********************************************************************
1298  *           DisconnectNamedPipe   (KERNEL32.@)
1299  */
1300 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1301 {
1302     BOOL ret;
1303
1304     TRACE("(%p)\n",hPipe);
1305
1306     SERVER_START_REQ( disconnect_named_pipe )
1307     {
1308         req->handle = hPipe;
1309         ret = !wine_server_call_err( req );
1310         if (ret && reply->fd != -1) close( reply->fd );
1311     }
1312     SERVER_END_REQ;
1313
1314     return ret;
1315 }
1316
1317 /***********************************************************************
1318  *           TransactNamedPipe   (KERNEL32.@)
1319  */
1320 BOOL WINAPI TransactNamedPipe(
1321     HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1322     DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1323 {
1324     FIXME("%p %p %ld %p %ld %p %p\n",
1325           hPipe, lpInput, dwInputSize, lpOutput,
1326           dwOutputSize, lpBytesRead, lpOverlapped);
1327     if(lpBytesRead)
1328         *lpBytesRead=0;
1329     return FALSE;
1330 }
1331
1332 /***********************************************************************
1333  *           GetNamedPipeInfo   (KERNEL32.@)
1334  */
1335 BOOL WINAPI GetNamedPipeInfo(
1336     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1337     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1338 {
1339     BOOL ret;
1340
1341     TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1342           lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1343
1344     SERVER_START_REQ( get_named_pipe_info )
1345     {
1346         req->handle = hNamedPipe;
1347         ret = !wine_server_call_err( req );
1348         if(lpFlags) *lpFlags = reply->flags;
1349         if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1350         if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1351         if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1352     }
1353     SERVER_END_REQ;
1354
1355     return ret;
1356 }
1357
1358 /***********************************************************************
1359  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1360  */
1361 BOOL WINAPI GetNamedPipeHandleStateA(
1362     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1363     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1364     LPSTR lpUsername, DWORD nUsernameMaxSize)
1365 {
1366     FIXME("%p %p %p %p %p %p %ld\n",
1367           hNamedPipe, lpState, lpCurInstances,
1368           lpMaxCollectionCount, lpCollectDataTimeout,
1369           lpUsername, nUsernameMaxSize);
1370
1371     return FALSE;
1372 }
1373
1374 /***********************************************************************
1375  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1376  */
1377 BOOL WINAPI GetNamedPipeHandleStateW(
1378     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1379     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1380     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1381 {
1382     FIXME("%p %p %p %p %p %p %ld\n",
1383           hNamedPipe, lpState, lpCurInstances,
1384           lpMaxCollectionCount, lpCollectDataTimeout,
1385           lpUsername, nUsernameMaxSize);
1386
1387     return FALSE;
1388 }
1389
1390 /***********************************************************************
1391  *           SetNamedPipeHandleState  (KERNEL32.@)
1392  */
1393 BOOL WINAPI SetNamedPipeHandleState(
1394     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1395     LPDWORD lpCollectDataTimeout)
1396 {
1397     FIXME("%p %p %p %p\n",
1398           hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1399     return FALSE;
1400 }
1401
1402 /***********************************************************************
1403  *           CallNamedPipeA  (KERNEL32.@)
1404  */
1405 BOOL WINAPI CallNamedPipeA(
1406     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1407     LPVOID lpOutput, DWORD lpOutputSize,
1408     LPDWORD lpBytesRead, DWORD nTimeout)
1409 {
1410     FIXME("%s %p %ld %p %ld %p %ld\n",
1411            debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1412            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1413     return FALSE;
1414 }
1415
1416 /***********************************************************************
1417  *           CallNamedPipeW  (KERNEL32.@)
1418  */
1419 BOOL WINAPI CallNamedPipeW(
1420     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1421     LPVOID lpOutput, DWORD lpOutputSize,
1422     LPDWORD lpBytesRead, DWORD nTimeout)
1423 {
1424     FIXME("%s %p %ld %p %ld %p %ld\n",
1425            debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1426            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1427     return FALSE;
1428 }
1429
1430 /******************************************************************
1431  *              CreatePipe (KERNEL32.@)
1432  *
1433  */
1434 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1435                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1436 {
1437     static unsigned  index = 0;
1438     char        name[64];
1439     HANDLE      hr, hw;
1440     unsigned    in_index = index;
1441
1442     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1443     /* generate a unique pipe name (system wide) */
1444     do
1445     {
1446         sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1447         hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, 
1448                               PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size, 
1449                               NMPWAIT_USE_DEFAULT_WAIT, sa);
1450     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1451     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1452     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1453
1454     hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1455     if (hw == INVALID_HANDLE_VALUE) 
1456     {
1457         CloseHandle(hr);
1458         return FALSE;
1459     }
1460
1461     *hReadPipe = hr;
1462     *hWritePipe = hw;
1463     return TRUE;
1464 }
1465
1466
1467 /******************************************************************************
1468  * CreateMailslotA [KERNEL32.@]
1469  */
1470 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1471                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1472 {
1473     DWORD len;
1474     HANDLE handle;
1475     LPWSTR name = NULL;
1476
1477     TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1478           nMaxMessageSize, lReadTimeout, sa);
1479
1480     if( lpName )
1481     {
1482         len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1483         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1484         MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1485     }
1486
1487     handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1488
1489     if( name )
1490         HeapFree( GetProcessHeap(), 0, name );
1491
1492     return handle;
1493 }
1494
1495
1496 /******************************************************************************
1497  * CreateMailslotW [KERNEL32.@]
1498  *
1499  * Create a mailslot with specified name.
1500  *
1501  * PARAMS
1502  *    lpName          [I] Pointer to string for mailslot name
1503  *    nMaxMessageSize [I] Maximum message size
1504  *    lReadTimeout    [I] Milliseconds before read time-out
1505  *    sa              [I] Pointer to security structure
1506  *
1507  * RETURNS
1508  *    Success: Handle to mailslot
1509  *    Failure: INVALID_HANDLE_VALUE
1510  */
1511 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1512                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1513 {
1514     FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1515           nMaxMessageSize, lReadTimeout, sa);
1516     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1517     return INVALID_HANDLE_VALUE;
1518 }
1519
1520
1521 /******************************************************************************
1522  * GetMailslotInfo [KERNEL32.@]
1523  *
1524  * Retrieve information about a mailslot.
1525  *
1526  * PARAMS
1527  *    hMailslot        [I] Mailslot handle
1528  *    lpMaxMessageSize [O] Address of maximum message size
1529  *    lpNextSize       [O] Address of size of next message
1530  *    lpMessageCount   [O] Address of number of messages
1531  *    lpReadTimeout    [O] Address of read time-out
1532  *
1533  * RETURNS
1534  *    Success: TRUE
1535  *    Failure: FALSE
1536  */
1537 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1538                                LPDWORD lpNextSize, LPDWORD lpMessageCount,
1539                                LPDWORD lpReadTimeout )
1540 {
1541     FIXME("(%p): stub\n",hMailslot);
1542     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1543     return FALSE;
1544 }
1545
1546
1547 /******************************************************************************
1548  * SetMailslotInfo [KERNEL32.@]
1549  *
1550  * Set the read timeout of a mailslot.
1551  *
1552  * PARAMS
1553  *  hMailslot     [I] Mailslot handle
1554  *  dwReadTimeout [I] Timeout in milliseconds.
1555  *
1556  * RETURNS
1557  *    Success: TRUE
1558  *    Failure: FALSE
1559  */
1560 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1561 {
1562     FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1563     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1564     return FALSE;
1565 }
1566
1567
1568 /******************************************************************************
1569  *              CreateIoCompletionPort (KERNEL32.@)
1570  */
1571 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1572                                      DWORD dwCompletionKey, DWORD dwNumberOfConcurrentThreads)
1573 {
1574     FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1575           hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads);
1576     return NULL;
1577 }
1578
1579
1580 /******************************************************************************
1581  *              GetQueuedCompletionStatus (KERNEL32.@)
1582  */
1583 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1584                                        LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped,
1585                                        DWORD dwMilliseconds )
1586 {
1587     FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1588           CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds);
1589     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1590     return FALSE;
1591 }
1592
1593 /******************************************************************************
1594  *              CreateJobObjectW (KERNEL32.@)
1595  */
1596 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1597 {
1598     FIXME("%p %s\n", attr, debugstr_w(name) );
1599     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1600     return 0;
1601 }
1602
1603 /******************************************************************************
1604  *              CreateJobObjectA (KERNEL32.@)
1605  */
1606 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1607 {
1608     LPWSTR str = NULL;
1609     UINT len;
1610     HANDLE r;
1611
1612     TRACE("%p %s\n", attr, debugstr_a(name) );
1613
1614     if( name )
1615     {
1616         len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1617         str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1618         if( !str )
1619         {
1620             SetLastError( ERROR_OUTOFMEMORY );
1621             return 0;
1622         }
1623         len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1624     }
1625
1626     r = CreateJobObjectW( attr, str );
1627
1628     if( str )
1629         HeapFree( GetProcessHeap(), 0, str );
1630
1631     return r;
1632 }
1633
1634 /******************************************************************************
1635  *              AssignProcessToJobObject (KERNEL32.@)
1636  */
1637 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1638 {
1639     FIXME("%p %p\n", hJob, hProcess);
1640     return TRUE;
1641 }
1642
1643 #ifdef __i386__
1644
1645 /***********************************************************************
1646  *              InterlockedCompareExchange (KERNEL32.@)
1647  */
1648 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1649 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1650                   "movl 12(%esp),%eax\n\t"
1651                   "movl 8(%esp),%ecx\n\t"
1652                   "movl 4(%esp),%edx\n\t"
1653                   "lock; cmpxchgl %ecx,(%edx)\n\t"
1654                   "ret $12");
1655
1656 /***********************************************************************
1657  *              InterlockedExchange (KERNEL32.@)
1658  */
1659 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1660 __ASM_GLOBAL_FUNC(InterlockedExchange,
1661                   "movl 8(%esp),%eax\n\t"
1662                   "movl 4(%esp),%edx\n\t"
1663                   "lock; xchgl %eax,(%edx)\n\t"
1664                   "ret $8");
1665
1666 /***********************************************************************
1667  *              InterlockedExchangeAdd (KERNEL32.@)
1668  */
1669 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1670 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1671                   "movl 8(%esp),%eax\n\t"
1672                   "movl 4(%esp),%edx\n\t"
1673                   "lock; xaddl %eax,(%edx)\n\t"
1674                   "ret $8");
1675
1676 /***********************************************************************
1677  *              InterlockedIncrement (KERNEL32.@)
1678  */
1679 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1680 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1681                   "movl 4(%esp),%edx\n\t"
1682                   "movl $1,%eax\n\t"
1683                   "lock; xaddl %eax,(%edx)\n\t"
1684                   "incl %eax\n\t"
1685                   "ret $4");
1686
1687 /***********************************************************************
1688  *              InterlockedDecrement (KERNEL32.@)
1689  */
1690 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1691                   "movl 4(%esp),%edx\n\t"
1692                   "movl $-1,%eax\n\t"
1693                   "lock; xaddl %eax,(%edx)\n\t"
1694                   "decl %eax\n\t"
1695                   "ret $4");
1696
1697 #else  /* __i386__ */
1698
1699 /***********************************************************************
1700  *              InterlockedCompareExchange (KERNEL32.@)
1701  *
1702  * Atomically swap one value with another.
1703  *
1704  * PARAMS
1705  *  dest    [I/O] The value to replace
1706  *  xchq    [I]   The value to be swapped
1707  *  compare [I]   The value to compare to dest
1708  *
1709  * RETURNS
1710  *  The resulting value of dest.
1711  *
1712  * NOTES
1713  *  dest is updated only if it is equal to compare, otherwise no swap is done.
1714  */
1715 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1716 {
1717     return interlocked_cmpxchg( dest, xchg, compare );
1718 }
1719
1720 /***********************************************************************
1721  *              InterlockedExchange (KERNEL32.@)
1722  *
1723  * Atomically swap one value with another.
1724  *
1725  * PARAMS
1726  *  dest [I/O] The value to replace
1727  *  val  [I]   The value to be swapped
1728  *
1729  * RETURNS
1730  *  The resulting value of dest.
1731  */
1732 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1733 {
1734     return interlocked_xchg( dest, val );
1735 }
1736
1737 /***********************************************************************
1738  *              InterlockedExchangeAdd (KERNEL32.@)
1739  *
1740  * Atomically add one value to another.
1741  *
1742  * PARAMS
1743  *  dest [I/O] The value to add to
1744  *  incr [I]   The value to be added
1745  *
1746  * RETURNS
1747  *  The resulting value of dest.
1748  */
1749 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1750 {
1751     return interlocked_xchg_add( dest, incr );
1752 }
1753
1754 /***********************************************************************
1755  *              InterlockedIncrement (KERNEL32.@)
1756  *
1757  * Atomically increment a value.
1758  *
1759  * PARAMS
1760  *  dest [I/O] The value to increment
1761  *
1762  * RETURNS
1763  *  The resulting value of dest.
1764  */
1765 LONG WINAPI InterlockedIncrement( PLONG dest )
1766 {
1767     return interlocked_xchg_add( dest, 1 ) + 1;
1768 }
1769
1770 /***********************************************************************
1771  *              InterlockedDecrement (KERNEL32.@)
1772  *
1773  * Atomically decrement a value.
1774  *
1775  * PARAMS
1776  *  dest [I/O] The value to decrement
1777  *
1778  * RETURNS
1779  *  The resulting value of dest.
1780  */
1781 LONG WINAPI InterlockedDecrement( PLONG dest )
1782 {
1783     return interlocked_xchg_add( dest, -1 ) - 1;
1784 }
1785
1786 #endif  /* __i386__ */