Correct the test for the ODS_SELECTED bit in the WM_DRAWITEM message
[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, ret, flags;
1079
1080     ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, NULL, &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     wine_server_release_fd( hPipe, fd );
1120     TRACE(" 0x%08x bytes available\n", avail );
1121     if (!lpvBuffer && lpcbAvail)
1122       {
1123         *lpcbAvail= avail;
1124         return TRUE;
1125       }
1126 #endif /* defined(FIONREAD) */
1127
1128     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1129     FIXME("function not implemented\n");
1130     return FALSE;
1131 }
1132
1133 /***********************************************************************
1134  *           SYNC_CompletePipeOverlapped   (Internal)
1135  */
1136 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1137 {
1138     TRACE("for %p result %08lx\n",overlapped,result);
1139     if(!overlapped)
1140         return;
1141     overlapped->Internal = result;
1142     SetEvent(overlapped->hEvent);
1143 }
1144
1145
1146 /***********************************************************************
1147  *           WaitNamedPipeA   (KERNEL32.@)
1148  */
1149 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1150 {
1151     WCHAR buffer[MAX_PATH];
1152
1153     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1154
1155     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1156     {
1157         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1158         return 0;
1159     }
1160     return WaitNamedPipeW( buffer, nTimeOut );
1161 }
1162
1163
1164 /***********************************************************************
1165  *           WaitNamedPipeW   (KERNEL32.@)
1166  */
1167 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1168 {
1169     DWORD len = name ? strlenW(name) : 0;
1170     BOOL ret;
1171     OVERLAPPED ov;
1172
1173     if (len >= MAX_PATH)
1174     {
1175         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1176         return FALSE;
1177     }
1178
1179     TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1180
1181     memset(&ov,0,sizeof(ov));
1182     ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
1183     if (!ov.hEvent)
1184         return FALSE;
1185
1186     SERVER_START_REQ( wait_named_pipe )
1187     {
1188         req->timeout = nTimeOut;
1189         req->overlapped = &ov;
1190         req->func = SYNC_CompletePipeOverlapped;
1191         wine_server_add_data( req, name, len * sizeof(WCHAR) );
1192         ret = !wine_server_call_err( req );
1193     }
1194     SERVER_END_REQ;
1195
1196     if(ret)
1197     {
1198         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1199         {
1200             SetLastError(ov.Internal);
1201             ret = (ov.Internal==STATUS_SUCCESS);
1202         }
1203     }
1204     CloseHandle(ov.hEvent);
1205     return ret;
1206 }
1207
1208
1209 /***********************************************************************
1210  *           SYNC_ConnectNamedPipe   (Internal)
1211  */
1212 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1213 {
1214     BOOL ret;
1215
1216     if(!overlapped)
1217         return FALSE;
1218
1219     overlapped->Internal = STATUS_PENDING;
1220
1221     SERVER_START_REQ( connect_named_pipe )
1222     {
1223         req->handle = hPipe;
1224         req->overlapped = overlapped;
1225         req->func = SYNC_CompletePipeOverlapped;
1226         ret = !wine_server_call_err( req );
1227     }
1228     SERVER_END_REQ;
1229
1230     return ret;
1231 }
1232
1233 /***********************************************************************
1234  *           ConnectNamedPipe   (KERNEL32.@)
1235  */
1236 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1237 {
1238     OVERLAPPED ov;
1239     BOOL ret;
1240
1241     TRACE("(%p,%p)\n",hPipe, overlapped);
1242
1243     if(overlapped)
1244     {
1245         if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1246             SetLastError( ERROR_IO_PENDING );
1247         return FALSE;
1248     }
1249
1250     memset(&ov,0,sizeof(ov));
1251     ov.hEvent = CreateEventA(NULL,0,0,NULL);
1252     if (!ov.hEvent)
1253         return FALSE;
1254
1255     ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1256     if(ret)
1257     {
1258         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1259         {
1260             SetLastError(ov.Internal);
1261             ret = (ov.Internal==STATUS_SUCCESS);
1262         }
1263     }
1264
1265     CloseHandle(ov.hEvent);
1266
1267     return ret;
1268 }
1269
1270 /***********************************************************************
1271  *           DisconnectNamedPipe   (KERNEL32.@)
1272  */
1273 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1274 {
1275     BOOL ret;
1276
1277     TRACE("(%p)\n",hPipe);
1278
1279     SERVER_START_REQ( disconnect_named_pipe )
1280     {
1281         req->handle = hPipe;
1282         ret = !wine_server_call_err( req );
1283         if (ret && reply->fd != -1) close( reply->fd );
1284     }
1285     SERVER_END_REQ;
1286
1287     return ret;
1288 }
1289
1290 /***********************************************************************
1291  *           TransactNamedPipe   (KERNEL32.@)
1292  */
1293 BOOL WINAPI TransactNamedPipe(
1294     HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1295     DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1296 {
1297     FIXME("%p %p %ld %p %ld %p %p\n",
1298           hPipe, lpInput, dwInputSize, lpOutput,
1299           dwOutputSize, lpBytesRead, lpOverlapped);
1300     if(lpBytesRead)
1301         *lpBytesRead=0;
1302     return FALSE;
1303 }
1304
1305 /***********************************************************************
1306  *           GetNamedPipeInfo   (KERNEL32.@)
1307  */
1308 BOOL WINAPI GetNamedPipeInfo(
1309     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1310     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1311 {
1312     BOOL ret;
1313
1314     TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1315           lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1316
1317     SERVER_START_REQ( get_named_pipe_info )
1318     {
1319         req->handle = hNamedPipe;
1320         ret = !wine_server_call_err( req );
1321         if(lpFlags) *lpFlags = reply->flags;
1322         if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1323         if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1324         if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1325     }
1326     SERVER_END_REQ;
1327
1328     return ret;
1329 }
1330
1331 /***********************************************************************
1332  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1333  */
1334 BOOL WINAPI GetNamedPipeHandleStateA(
1335     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1336     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1337     LPSTR lpUsername, DWORD nUsernameMaxSize)
1338 {
1339     FIXME("%p %p %p %p %p %p %ld\n",
1340           hNamedPipe, lpState, lpCurInstances,
1341           lpMaxCollectionCount, lpCollectDataTimeout,
1342           lpUsername, nUsernameMaxSize);
1343
1344     return FALSE;
1345 }
1346
1347 /***********************************************************************
1348  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1349  */
1350 BOOL WINAPI GetNamedPipeHandleStateW(
1351     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1352     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1353     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1354 {
1355     FIXME("%p %p %p %p %p %p %ld\n",
1356           hNamedPipe, lpState, lpCurInstances,
1357           lpMaxCollectionCount, lpCollectDataTimeout,
1358           lpUsername, nUsernameMaxSize);
1359
1360     return FALSE;
1361 }
1362
1363 /***********************************************************************
1364  *           SetNamedPipeHandleState  (KERNEL32.@)
1365  */
1366 BOOL WINAPI SetNamedPipeHandleState(
1367     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1368     LPDWORD lpCollectDataTimeout)
1369 {
1370     FIXME("%p %p %p %p\n",
1371           hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1372     return FALSE;
1373 }
1374
1375 /***********************************************************************
1376  *           CallNamedPipeA  (KERNEL32.@)
1377  */
1378 BOOL WINAPI CallNamedPipeA(
1379     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1380     LPVOID lpOutput, DWORD lpOutputSize,
1381     LPDWORD lpBytesRead, DWORD nTimeout)
1382 {
1383     FIXME("%s %p %ld %p %ld %p %ld\n",
1384            debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1385            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1386     return FALSE;
1387 }
1388
1389 /***********************************************************************
1390  *           CallNamedPipeW  (KERNEL32.@)
1391  */
1392 BOOL WINAPI CallNamedPipeW(
1393     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1394     LPVOID lpOutput, DWORD lpOutputSize,
1395     LPDWORD lpBytesRead, DWORD nTimeout)
1396 {
1397     FIXME("%s %p %ld %p %ld %p %ld\n",
1398            debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1399            lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1400     return FALSE;
1401 }
1402
1403 /******************************************************************
1404  *              CreatePipe (KERNEL32.@)
1405  *
1406  */
1407 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1408                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1409 {
1410     static unsigned  index = 0;
1411     char        name[64];
1412     HANDLE      hr, hw;
1413     unsigned    in_index = index;
1414
1415     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1416     /* generate a unique pipe name (system wide) */
1417     do
1418     {
1419         sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1420         hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, 
1421                               PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size, 
1422                               NMPWAIT_USE_DEFAULT_WAIT, sa);
1423     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1424     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1425     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1426
1427     hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1428     if (hw == INVALID_HANDLE_VALUE) 
1429     {
1430         CloseHandle(hr);
1431         return FALSE;
1432     }
1433
1434     *hReadPipe = hr;
1435     *hWritePipe = hw;
1436     return TRUE;
1437 }
1438
1439
1440 /******************************************************************************
1441  * CreateMailslotA [KERNEL32.@]
1442  */
1443 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1444                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1445 {
1446     DWORD len;
1447     HANDLE handle;
1448     LPWSTR name = NULL;
1449
1450     TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1451           nMaxMessageSize, lReadTimeout, sa);
1452
1453     if( lpName )
1454     {
1455         len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1456         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1457         MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1458     }
1459
1460     handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1461
1462     if( name )
1463         HeapFree( GetProcessHeap(), 0, name );
1464
1465     return handle;
1466 }
1467
1468
1469 /******************************************************************************
1470  * CreateMailslotW [KERNEL32.@]
1471  *
1472  * Create a mailslot with specified name.
1473  *
1474  * PARAMS
1475  *    lpName          [I] Pointer to string for mailslot name
1476  *    nMaxMessageSize [I] Maximum message size
1477  *    lReadTimeout    [I] Milliseconds before read time-out
1478  *    sa              [I] Pointer to security structure
1479  *
1480  * RETURNS
1481  *    Success: Handle to mailslot
1482  *    Failure: INVALID_HANDLE_VALUE
1483  */
1484 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1485                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1486 {
1487     FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1488           nMaxMessageSize, lReadTimeout, sa);
1489     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1490     return INVALID_HANDLE_VALUE;
1491 }
1492
1493
1494 /******************************************************************************
1495  * GetMailslotInfo [KERNEL32.@]
1496  *
1497  * Retrieve information about a mailslot.
1498  *
1499  * PARAMS
1500  *    hMailslot        [I] Mailslot handle
1501  *    lpMaxMessageSize [O] Address of maximum message size
1502  *    lpNextSize       [O] Address of size of next message
1503  *    lpMessageCount   [O] Address of number of messages
1504  *    lpReadTimeout    [O] Address of read time-out
1505  *
1506  * RETURNS
1507  *    Success: TRUE
1508  *    Failure: FALSE
1509  */
1510 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1511                                LPDWORD lpNextSize, LPDWORD lpMessageCount,
1512                                LPDWORD lpReadTimeout )
1513 {
1514     FIXME("(%p): stub\n",hMailslot);
1515     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1516     return FALSE;
1517 }
1518
1519
1520 /******************************************************************************
1521  * SetMailslotInfo [KERNEL32.@]
1522  *
1523  * Set the read timeout of a mailslot.
1524  *
1525  * PARAMS
1526  *  hMailslot     [I] Mailslot handle
1527  *  dwReadTimeout [I] Timeout in milliseconds.
1528  *
1529  * RETURNS
1530  *    Success: TRUE
1531  *    Failure: FALSE
1532  */
1533 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1534 {
1535     FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1536     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1537     return FALSE;
1538 }
1539
1540
1541 /******************************************************************************
1542  *              CreateIoCompletionPort (KERNEL32.@)
1543  */
1544 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1545                                      DWORD dwCompletionKey, DWORD dwNumberOfConcurrentThreads)
1546 {
1547     FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1548           hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads);
1549     return NULL;
1550 }
1551
1552
1553 /******************************************************************************
1554  *              GetQueuedCompletionStatus (KERNEL32.@)
1555  */
1556 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1557                                        LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped,
1558                                        DWORD dwMilliseconds )
1559 {
1560     FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1561           CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds);
1562     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1563     return FALSE;
1564 }
1565
1566 /******************************************************************************
1567  *              CreateJobObjectW (KERNEL32.@)
1568  */
1569 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1570 {
1571     FIXME("%p %s\n", attr, debugstr_w(name) );
1572     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1573     return 0;
1574 }
1575
1576 /******************************************************************************
1577  *              CreateJobObjectA (KERNEL32.@)
1578  */
1579 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1580 {
1581     LPWSTR str = NULL;
1582     UINT len;
1583     HANDLE r;
1584
1585     TRACE("%p %s\n", attr, debugstr_a(name) );
1586
1587     if( name )
1588     {
1589         len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1590         str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1591         if( !str )
1592         {
1593             SetLastError( ERROR_OUTOFMEMORY );
1594             return 0;
1595         }
1596         len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1597     }
1598
1599     r = CreateJobObjectW( attr, str );
1600
1601     if( str )
1602         HeapFree( GetProcessHeap(), 0, str );
1603
1604     return r;
1605 }
1606
1607 /******************************************************************************
1608  *              AssignProcessToJobObject (KERNEL32.@)
1609  */
1610 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1611 {
1612     FIXME("%p %p\n", hJob, hProcess);
1613     return TRUE;
1614 }
1615
1616 #ifdef __i386__
1617
1618 /***********************************************************************
1619  *              InterlockedCompareExchange (KERNEL32.@)
1620  */
1621 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1622 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1623                   "movl 12(%esp),%eax\n\t"
1624                   "movl 8(%esp),%ecx\n\t"
1625                   "movl 4(%esp),%edx\n\t"
1626                   "lock; cmpxchgl %ecx,(%edx)\n\t"
1627                   "ret $12");
1628
1629 /***********************************************************************
1630  *              InterlockedExchange (KERNEL32.@)
1631  */
1632 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1633 __ASM_GLOBAL_FUNC(InterlockedExchange,
1634                   "movl 8(%esp),%eax\n\t"
1635                   "movl 4(%esp),%edx\n\t"
1636                   "lock; xchgl %eax,(%edx)\n\t"
1637                   "ret $8");
1638
1639 /***********************************************************************
1640  *              InterlockedExchangeAdd (KERNEL32.@)
1641  */
1642 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1643 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1644                   "movl 8(%esp),%eax\n\t"
1645                   "movl 4(%esp),%edx\n\t"
1646                   "lock; xaddl %eax,(%edx)\n\t"
1647                   "ret $8");
1648
1649 /***********************************************************************
1650  *              InterlockedIncrement (KERNEL32.@)
1651  */
1652 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1653 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1654                   "movl 4(%esp),%edx\n\t"
1655                   "movl $1,%eax\n\t"
1656                   "lock; xaddl %eax,(%edx)\n\t"
1657                   "incl %eax\n\t"
1658                   "ret $4");
1659
1660 /***********************************************************************
1661  *              InterlockedDecrement (KERNEL32.@)
1662  */
1663 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1664                   "movl 4(%esp),%edx\n\t"
1665                   "movl $-1,%eax\n\t"
1666                   "lock; xaddl %eax,(%edx)\n\t"
1667                   "decl %eax\n\t"
1668                   "ret $4");
1669
1670 #else  /* __i386__ */
1671
1672 /***********************************************************************
1673  *              InterlockedCompareExchange (KERNEL32.@)
1674  *
1675  * Atomically swap one value with another.
1676  *
1677  * PARAMS
1678  *  dest    [I/O] The value to replace
1679  *  xchq    [I]   The value to be swapped
1680  *  compare [I]   The value to compare to dest
1681  *
1682  * RETURNS
1683  *  The resulting value of dest.
1684  *
1685  * NOTES
1686  *  dest is updated only if it is equal to compare, otherwise no swap is done.
1687  */
1688 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1689 {
1690     return interlocked_cmpxchg( dest, xchg, compare );
1691 }
1692
1693 /***********************************************************************
1694  *              InterlockedExchange (KERNEL32.@)
1695  *
1696  * Atomically swap one value with another.
1697  *
1698  * PARAMS
1699  *  dest [I/O] The value to replace
1700  *  val  [I]   The value to be swapped
1701  *
1702  * RETURNS
1703  *  The resulting value of dest.
1704  */
1705 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1706 {
1707     return interlocked_xchg( dest, val );
1708 }
1709
1710 /***********************************************************************
1711  *              InterlockedExchangeAdd (KERNEL32.@)
1712  *
1713  * Atomically add one value to another.
1714  *
1715  * PARAMS
1716  *  dest [I/O] The value to add to
1717  *  incr [I]   The value to be added
1718  *
1719  * RETURNS
1720  *  The resulting value of dest.
1721  */
1722 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1723 {
1724     return interlocked_xchg_add( dest, incr );
1725 }
1726
1727 /***********************************************************************
1728  *              InterlockedIncrement (KERNEL32.@)
1729  *
1730  * Atomically increment a value.
1731  *
1732  * PARAMS
1733  *  dest [I/O] The value to increment
1734  *
1735  * RETURNS
1736  *  The resulting value of dest.
1737  */
1738 LONG WINAPI InterlockedIncrement( PLONG dest )
1739 {
1740     return interlocked_xchg_add( dest, 1 ) + 1;
1741 }
1742
1743 /***********************************************************************
1744  *              InterlockedDecrement (KERNEL32.@)
1745  *
1746  * Atomically decrement a value.
1747  *
1748  * PARAMS
1749  *  dest [I/O] The value to decrement
1750  *
1751  * RETURNS
1752  *  The resulting value of dest.
1753  */
1754 LONG WINAPI InterlockedDecrement( PLONG dest )
1755 {
1756     return interlocked_xchg_add( dest, -1 ) - 1;
1757 }
1758
1759 #endif  /* __i386__ */