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