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