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