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