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