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