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