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