ddraw: Display fixme only once in IDirectDrawImpl_WaitForVerticalBlank.
[wine] / dlls / kernel32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #include <stdarg.h>
30 #include <stdio.h>
31
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winerror.h"
40 #include "winnls.h"
41 #include "winternl.h"
42 #include "winioctl.h"
43 #include "ddk/wdm.h"
44
45 #include "wine/unicode.h"
46 #include "wine/winbase16.h"
47 #include "kernel_private.h"
48
49 #include "wine/debug.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL(sync);
52
53 /* check if current version is NT or Win95 */
54 static inline int is_version_nt(void)
55 {
56     return !(GetVersion() & 0x80000000);
57 }
58
59 /* returns directory handle to \\BaseNamedObjects */
60 HANDLE get_BaseNamedObjects_handle(void)
61 {
62     static HANDLE handle = NULL;
63     static const WCHAR basenameW[] =
64         {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',0};
65     UNICODE_STRING str;
66     OBJECT_ATTRIBUTES attr;
67
68     if (!handle)
69     {
70         HANDLE dir;
71
72         RtlInitUnicodeString(&str, basenameW);
73         InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
74         NtOpenDirectoryObject(&dir, DIRECTORY_CREATE_OBJECT|DIRECTORY_TRAVERSE,
75                               &attr);
76         if (InterlockedCompareExchangePointer( (PVOID)&handle, dir, 0 ) != 0)
77         {
78             /* someone beat us here... */
79             CloseHandle( dir );
80         }
81     }
82     return handle;
83 }
84
85 /* helper for kernel32->ntdll timeout format conversion */
86 static inline PLARGE_INTEGER get_nt_timeout( PLARGE_INTEGER pTime, DWORD timeout )
87 {
88     if (timeout == INFINITE) return NULL;
89     pTime->QuadPart = (ULONGLONG)timeout * -10000;
90     return pTime;
91 }
92
93 /***********************************************************************
94  *              Sleep  (KERNEL32.@)
95  */
96 VOID WINAPI Sleep( DWORD timeout )
97 {
98     SleepEx( timeout, FALSE );
99 }
100
101 /******************************************************************************
102  *              SleepEx   (KERNEL32.@)
103  */
104 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
105 {
106     NTSTATUS status;
107     LARGE_INTEGER time;
108
109     status = NtDelayExecution( alertable, get_nt_timeout( &time, timeout ) );
110     if (status == STATUS_USER_APC) return WAIT_IO_COMPLETION;
111     return 0;
112 }
113
114
115 /***********************************************************************
116  *              SwitchToThread (KERNEL32.@)
117  */
118 BOOL WINAPI SwitchToThread(void)
119 {
120     return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
121 }
122
123
124 /***********************************************************************
125  *           WaitForSingleObject   (KERNEL32.@)
126  */
127 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
128 {
129     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
130 }
131
132
133 /***********************************************************************
134  *           WaitForSingleObjectEx   (KERNEL32.@)
135  */
136 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
137                                     BOOL alertable )
138 {
139     return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
140 }
141
142
143 /***********************************************************************
144  *           WaitForMultipleObjects   (KERNEL32.@)
145  */
146 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
147                                      BOOL wait_all, DWORD timeout )
148 {
149     return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
150 }
151
152
153 /***********************************************************************
154  *           WaitForMultipleObjectsEx   (KERNEL32.@)
155  */
156 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
157                                        BOOL wait_all, DWORD timeout,
158                                        BOOL alertable )
159 {
160     NTSTATUS status;
161     HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
162     LARGE_INTEGER time;
163     unsigned int i;
164
165     if (count > MAXIMUM_WAIT_OBJECTS)
166     {
167         SetLastError(ERROR_INVALID_PARAMETER);
168         return WAIT_FAILED;
169     }
170     for (i = 0; i < count; i++)
171     {
172         if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
173             (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
174             (handles[i] == (HANDLE)STD_ERROR_HANDLE))
175             hloc[i] = GetStdHandle( HandleToULong(handles[i]) );
176         else
177             hloc[i] = handles[i];
178
179         /* yes, even screen buffer console handles are waitable, and are
180          * handled as a handle to the console itself !!
181          */
182         if (is_console_handle(hloc[i]))
183         {
184             if (!VerifyConsoleIoHandle(hloc[i]))
185             {
186                 return FALSE;
187             }
188             hloc[i] = GetConsoleInputWaitHandle();
189         }
190     }
191
192     status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable,
193                                        get_nt_timeout( &time, timeout ) );
194
195     if (HIWORD(status))  /* is it an error code? */
196     {
197         SetLastError( RtlNtStatusToDosError(status) );
198         status = WAIT_FAILED;
199     }
200     return status;
201 }
202
203
204 /***********************************************************************
205  *           WaitForSingleObject   (KERNEL.460)
206  */
207 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
208 {
209     DWORD retval, mutex_count;
210
211     ReleaseThunkLock( &mutex_count );
212     retval = WaitForSingleObject( handle, timeout );
213     RestoreThunkLock( mutex_count );
214     return retval;
215 }
216
217 /***********************************************************************
218  *           WaitForMultipleObjects   (KERNEL.461)
219  */
220 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
221                                        BOOL wait_all, DWORD timeout )
222 {
223     DWORD retval, mutex_count;
224
225     ReleaseThunkLock( &mutex_count );
226     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
227     RestoreThunkLock( mutex_count );
228     return retval;
229 }
230
231 /***********************************************************************
232  *           WaitForMultipleObjectsEx   (KERNEL.495)
233  */
234 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
235                                          BOOL wait_all, DWORD timeout, BOOL alertable )
236 {
237     DWORD retval, mutex_count;
238
239     ReleaseThunkLock( &mutex_count );
240     retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
241     RestoreThunkLock( mutex_count );
242     return retval;
243 }
244
245 /***********************************************************************
246  *           RegisterWaitForSingleObject   (KERNEL32.@)
247  */
248 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
249                 WAITORTIMERCALLBACK Callback, PVOID Context,
250                 ULONG dwMilliseconds, ULONG dwFlags)
251 {
252     NTSTATUS status;
253
254     TRACE("%p %p %p %p %d %d\n",
255           phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
256
257     status = RtlRegisterWait( phNewWaitObject, hObject, Callback, Context, dwMilliseconds, dwFlags );
258     if (status != STATUS_SUCCESS)
259     {
260         SetLastError( RtlNtStatusToDosError(status) );
261         return FALSE;
262     }
263     return TRUE;
264 }
265
266 /***********************************************************************
267  *           RegisterWaitForSingleObjectEx   (KERNEL32.@)
268  */
269 HANDLE WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject, 
270                 WAITORTIMERCALLBACK Callback, PVOID Context,
271                 ULONG dwMilliseconds, ULONG dwFlags ) 
272 {
273     NTSTATUS status;
274     HANDLE hNewWaitObject;
275
276     TRACE("%p %p %p %d %d\n",
277           hObject,Callback,Context,dwMilliseconds,dwFlags);
278
279     status = RtlRegisterWait( &hNewWaitObject, hObject, Callback, Context, dwMilliseconds, dwFlags );
280     if (status != STATUS_SUCCESS)
281     {
282         SetLastError( RtlNtStatusToDosError(status) );
283         return NULL;
284     }
285     return hNewWaitObject;
286 }
287
288 /***********************************************************************
289  *           UnregisterWait   (KERNEL32.@)
290  */
291 BOOL WINAPI UnregisterWait( HANDLE WaitHandle ) 
292 {
293     NTSTATUS status;
294
295     TRACE("%p\n",WaitHandle);
296
297     status = RtlDeregisterWait( WaitHandle );
298     if (status != STATUS_SUCCESS)
299     {
300         SetLastError( RtlNtStatusToDosError(status) );
301         return FALSE;
302     }
303     return TRUE;
304 }
305
306 /***********************************************************************
307  *           UnregisterWaitEx   (KERNEL32.@)
308  */
309 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent ) 
310 {
311     NTSTATUS status;
312
313     TRACE("%p %p\n",WaitHandle, CompletionEvent);
314
315     status = RtlDeregisterWaitEx( WaitHandle, CompletionEvent );
316     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
317     return !status;
318 }
319
320 /***********************************************************************
321  *           SignalObjectAndWait  (KERNEL32.@)
322  *
323  * Allows to atomically signal any of the synchro objects (semaphore,
324  * mutex, event) and wait on another.
325  */
326 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn,
327                                   DWORD dwMilliseconds, BOOL bAlertable )
328 {
329     NTSTATUS status;
330     LARGE_INTEGER timeout;
331
332     TRACE("%p %p %d %d\n", hObjectToSignal,
333           hObjectToWaitOn, dwMilliseconds, bAlertable);
334
335     status = NtSignalAndWaitForSingleObject( hObjectToSignal, hObjectToWaitOn, bAlertable,
336                                              get_nt_timeout( &timeout, dwMilliseconds ) );
337     if (HIWORD(status))
338     {
339         SetLastError( RtlNtStatusToDosError(status) );
340         status = WAIT_FAILED;
341     }
342     return status;
343 }
344
345 /***********************************************************************
346  *           InitializeCriticalSection   (KERNEL32.@)
347  *
348  * Initialise a critical section before use.
349  *
350  * PARAMS
351  *  crit [O] Critical section to initialise.
352  *
353  * RETURNS
354  *  Nothing. If the function fails an exception is raised.
355  */
356 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
357 {
358     InitializeCriticalSectionEx( crit, 0, 0 );
359 }
360
361 /***********************************************************************
362  *           InitializeCriticalSectionAndSpinCount   (KERNEL32.@)
363  *
364  * Initialise a critical section with a spin count.
365  *
366  * PARAMS
367  *  crit      [O] Critical section to initialise.
368  *  spincount [I] Number of times to spin upon contention.
369  *
370  * RETURNS
371  *  Success: TRUE.
372  *  Failure: Nothing. If the function fails an exception is raised.
373  *
374  * NOTES
375  *  spincount is ignored on uni-processor systems.
376  */
377 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
378 {
379     return InitializeCriticalSectionEx( crit, spincount, 0 );
380 }
381
382 /***********************************************************************
383  *           InitializeCriticalSectionEx   (KERNEL32.@)
384  *
385  * Initialise a critical section with a spin count and flags.
386  *
387  * PARAMS
388  *  crit      [O] Critical section to initialise.
389  *  spincount [I] Number of times to spin upon contention.
390  *  flags     [I] CRITICAL_SECTION_ flags from winbase.h.
391  *
392  * RETURNS
393  *  Success: TRUE.
394  *  Failure: Nothing. If the function fails an exception is raised.
395  *
396  * NOTES
397  *  spincount is ignored on uni-processor systems.
398  */
399 BOOL WINAPI InitializeCriticalSectionEx( CRITICAL_SECTION *crit, DWORD spincount, DWORD flags )
400 {
401     NTSTATUS ret = RtlInitializeCriticalSectionEx( crit, spincount, flags );
402     if (ret) RtlRaiseStatus( ret );
403     return !ret;
404 }
405
406 /***********************************************************************
407  *           MakeCriticalSectionGlobal   (KERNEL32.@)
408  */
409 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
410 {
411     /* let's assume that only one thread at a time will try to do this */
412     HANDLE sem = crit->LockSemaphore;
413     if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
414     crit->LockSemaphore = ConvertToGlobalHandle( sem );
415     RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
416     crit->DebugInfo = NULL;
417 }
418
419
420 /***********************************************************************
421  *           ReinitializeCriticalSection   (KERNEL32.@)
422  *
423  * Initialise an already used critical section.
424  *
425  * PARAMS
426  *  crit [O] Critical section to initialise.
427  *
428  * RETURNS
429  *  Nothing.
430  */
431 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
432 {
433     if ( !crit->LockSemaphore )
434         RtlInitializeCriticalSection( crit );
435 }
436
437
438 /***********************************************************************
439  *           UninitializeCriticalSection   (KERNEL32.@)
440  *
441  * UnInitialise a critical section after use.
442  *
443  * PARAMS
444  *  crit [O] Critical section to uninitialise (destroy).
445  *
446  * RETURNS
447  *  Nothing.
448  */
449 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
450 {
451     RtlDeleteCriticalSection( crit );
452 }
453
454
455 /***********************************************************************
456  *           CreateEventA    (KERNEL32.@)
457  */
458 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
459                             BOOL initial_state, LPCSTR name )
460 {
461     DWORD flags = 0;
462
463     if (manual_reset) flags |= CREATE_EVENT_MANUAL_RESET;
464     if (initial_state) flags |= CREATE_EVENT_INITIAL_SET;
465     return CreateEventExA( sa, name, flags, EVENT_ALL_ACCESS );
466 }
467
468
469 /***********************************************************************
470  *           CreateEventW    (KERNEL32.@)
471  */
472 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
473                             BOOL initial_state, LPCWSTR name )
474 {
475     DWORD flags = 0;
476
477     if (manual_reset) flags |= CREATE_EVENT_MANUAL_RESET;
478     if (initial_state) flags |= CREATE_EVENT_INITIAL_SET;
479     return CreateEventExW( sa, name, flags, EVENT_ALL_ACCESS );
480 }
481
482
483 /***********************************************************************
484  *           CreateEventExA    (KERNEL32.@)
485  */
486 HANDLE WINAPI CreateEventExA( SECURITY_ATTRIBUTES *sa, LPCSTR name, DWORD flags, DWORD access )
487 {
488     WCHAR buffer[MAX_PATH];
489
490     if (!name) return CreateEventExW( sa, NULL, flags, access );
491
492     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
493     {
494         SetLastError( ERROR_FILENAME_EXCED_RANGE );
495         return 0;
496     }
497     return CreateEventExW( sa, buffer, flags, access );
498 }
499
500
501 /***********************************************************************
502  *           CreateEventExW    (KERNEL32.@)
503  */
504 HANDLE WINAPI CreateEventExW( SECURITY_ATTRIBUTES *sa, LPCWSTR name, DWORD flags, DWORD access )
505 {
506     HANDLE ret;
507     UNICODE_STRING nameW;
508     OBJECT_ATTRIBUTES attr;
509     NTSTATUS status;
510
511     /* one buggy program needs this
512      * ("Van Dale Groot woordenboek der Nederlandse taal")
513      */
514     if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
515     {
516         ERR("Bad security attributes pointer %p\n",sa);
517         SetLastError( ERROR_INVALID_PARAMETER);
518         return 0;
519     }
520
521     attr.Length                   = sizeof(attr);
522     attr.RootDirectory            = 0;
523     attr.ObjectName               = NULL;
524     attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
525     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
526     attr.SecurityQualityOfService = NULL;
527     if (name)
528     {
529         RtlInitUnicodeString( &nameW, name );
530         attr.ObjectName = &nameW;
531         attr.RootDirectory = get_BaseNamedObjects_handle();
532     }
533
534     status = NtCreateEvent( &ret, access, &attr, (flags & CREATE_EVENT_MANUAL_RESET) != 0,
535                             (flags & CREATE_EVENT_INITIAL_SET) != 0 );
536     if (status == STATUS_OBJECT_NAME_EXISTS)
537         SetLastError( ERROR_ALREADY_EXISTS );
538     else
539         SetLastError( RtlNtStatusToDosError(status) );
540     return ret;
541 }
542
543
544 /***********************************************************************
545  *           CreateW32Event    (KERNEL.457)
546  */
547 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
548 {
549     return CreateEventW( NULL, manual_reset, initial_state, NULL );
550 }
551
552
553 /***********************************************************************
554  *           OpenEventA    (KERNEL32.@)
555  */
556 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
557 {
558     WCHAR buffer[MAX_PATH];
559
560     if (!name) return OpenEventW( access, inherit, NULL );
561
562     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
563     {
564         SetLastError( ERROR_FILENAME_EXCED_RANGE );
565         return 0;
566     }
567     return OpenEventW( access, inherit, buffer );
568 }
569
570
571 /***********************************************************************
572  *           OpenEventW    (KERNEL32.@)
573  */
574 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
575 {
576     HANDLE ret;
577     UNICODE_STRING nameW;
578     OBJECT_ATTRIBUTES attr;
579     NTSTATUS status;
580
581     if (!is_version_nt()) access = EVENT_ALL_ACCESS;
582
583     attr.Length                   = sizeof(attr);
584     attr.RootDirectory            = 0;
585     attr.ObjectName               = NULL;
586     attr.Attributes               = inherit ? OBJ_INHERIT : 0;
587     attr.SecurityDescriptor       = NULL;
588     attr.SecurityQualityOfService = NULL;
589     if (name)
590     {
591         RtlInitUnicodeString( &nameW, name );
592         attr.ObjectName = &nameW;
593         attr.RootDirectory = get_BaseNamedObjects_handle();
594     }
595
596     status = NtOpenEvent( &ret, access, &attr );
597     if (status != STATUS_SUCCESS)
598     {
599         SetLastError( RtlNtStatusToDosError(status) );
600         return 0;
601     }
602     return ret;
603 }
604
605 /***********************************************************************
606  *           PulseEvent    (KERNEL32.@)
607  */
608 BOOL WINAPI PulseEvent( HANDLE handle )
609 {
610     NTSTATUS status;
611
612     if ((status = NtPulseEvent( handle, NULL )))
613         SetLastError( RtlNtStatusToDosError(status) );
614     return !status;
615 }
616
617
618 /***********************************************************************
619  *           SetW32Event (KERNEL.458)
620  *           SetEvent    (KERNEL32.@)
621  */
622 BOOL WINAPI SetEvent( HANDLE handle )
623 {
624     NTSTATUS status;
625
626     if ((status = NtSetEvent( handle, NULL )))
627         SetLastError( RtlNtStatusToDosError(status) );
628     return !status;
629 }
630
631
632 /***********************************************************************
633  *           ResetW32Event (KERNEL.459)
634  *           ResetEvent    (KERNEL32.@)
635  */
636 BOOL WINAPI ResetEvent( HANDLE handle )
637 {
638     NTSTATUS status;
639
640     if ((status = NtResetEvent( handle, NULL )))
641         SetLastError( RtlNtStatusToDosError(status) );
642     return !status;
643 }
644
645
646 /***********************************************************************
647  * NOTE: The Win95 VWin32_Event routines given below are really low-level
648  *       routines implemented directly by VWin32. The user-mode libraries
649  *       implement Win32 synchronisation routines on top of these low-level
650  *       primitives. We do it the other way around here :-)
651  */
652
653 /***********************************************************************
654  *       VWin32_EventCreate     (KERNEL.442)
655  */
656 HANDLE WINAPI VWin32_EventCreate(VOID)
657 {
658     HANDLE hEvent = CreateEventW( NULL, FALSE, 0, NULL );
659     return ConvertToGlobalHandle( hEvent );
660 }
661
662 /***********************************************************************
663  *       VWin32_EventDestroy    (KERNEL.443)
664  */
665 VOID WINAPI VWin32_EventDestroy(HANDLE event)
666 {
667     CloseHandle( event );
668 }
669
670 /***********************************************************************
671  *       VWin32_EventWait       (KERNEL.450)
672  */
673 VOID WINAPI VWin32_EventWait(HANDLE event)
674 {
675     DWORD mutex_count;
676
677     ReleaseThunkLock( &mutex_count );
678     WaitForSingleObject( event, INFINITE );
679     RestoreThunkLock( mutex_count );
680 }
681
682 /***********************************************************************
683  *       VWin32_EventSet        (KERNEL.451)
684  *       KERNEL_479             (KERNEL.479)
685  */
686 VOID WINAPI VWin32_EventSet(HANDLE event)
687 {
688     SetEvent( event );
689 }
690
691
692
693 /***********************************************************************
694  *           CreateMutexA   (KERNEL32.@)
695  */
696 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
697 {
698     return CreateMutexExA( sa, name, owner ? CREATE_MUTEX_INITIAL_OWNER : 0, MUTEX_ALL_ACCESS );
699 }
700
701
702 /***********************************************************************
703  *           CreateMutexW   (KERNEL32.@)
704  */
705 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
706 {
707     return CreateMutexExW( sa, name, owner ? CREATE_MUTEX_INITIAL_OWNER : 0, MUTEX_ALL_ACCESS );
708 }
709
710
711 /***********************************************************************
712  *           CreateMutexExA   (KERNEL32.@)
713  */
714 HANDLE WINAPI CreateMutexExA( SECURITY_ATTRIBUTES *sa, LPCSTR name, DWORD flags, DWORD access )
715 {
716     WCHAR buffer[MAX_PATH];
717
718     if (!name) return CreateMutexExW( sa, NULL, flags, access );
719
720     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
721     {
722         SetLastError( ERROR_FILENAME_EXCED_RANGE );
723         return 0;
724     }
725     return CreateMutexExW( sa, buffer, flags, access );
726 }
727
728
729 /***********************************************************************
730  *           CreateMutexExW   (KERNEL32.@)
731  */
732 HANDLE WINAPI CreateMutexExW( SECURITY_ATTRIBUTES *sa, LPCWSTR name, DWORD flags, DWORD access )
733 {
734     HANDLE ret;
735     UNICODE_STRING nameW;
736     OBJECT_ATTRIBUTES attr;
737     NTSTATUS status;
738
739     attr.Length                   = sizeof(attr);
740     attr.RootDirectory            = 0;
741     attr.ObjectName               = NULL;
742     attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
743     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
744     attr.SecurityQualityOfService = NULL;
745     if (name)
746     {
747         RtlInitUnicodeString( &nameW, name );
748         attr.ObjectName = &nameW;
749         attr.RootDirectory = get_BaseNamedObjects_handle();
750     }
751
752     status = NtCreateMutant( &ret, access, &attr, (flags & CREATE_MUTEX_INITIAL_OWNER) != 0 );
753     if (status == STATUS_OBJECT_NAME_EXISTS)
754         SetLastError( ERROR_ALREADY_EXISTS );
755     else
756         SetLastError( RtlNtStatusToDosError(status) );
757     return ret;
758 }
759
760
761 /***********************************************************************
762  *           OpenMutexA   (KERNEL32.@)
763  */
764 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
765 {
766     WCHAR buffer[MAX_PATH];
767
768     if (!name) return OpenMutexW( access, inherit, NULL );
769
770     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
771     {
772         SetLastError( ERROR_FILENAME_EXCED_RANGE );
773         return 0;
774     }
775     return OpenMutexW( access, inherit, buffer );
776 }
777
778
779 /***********************************************************************
780  *           OpenMutexW   (KERNEL32.@)
781  */
782 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
783 {
784     HANDLE ret;
785     UNICODE_STRING nameW;
786     OBJECT_ATTRIBUTES attr;
787     NTSTATUS status;
788
789     if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
790
791     attr.Length                   = sizeof(attr);
792     attr.RootDirectory            = 0;
793     attr.ObjectName               = NULL;
794     attr.Attributes               = inherit ? OBJ_INHERIT : 0;
795     attr.SecurityDescriptor       = NULL;
796     attr.SecurityQualityOfService = NULL;
797     if (name)
798     {
799         RtlInitUnicodeString( &nameW, name );
800         attr.ObjectName = &nameW;
801         attr.RootDirectory = get_BaseNamedObjects_handle();
802     }
803
804     status = NtOpenMutant( &ret, access, &attr );
805     if (status != STATUS_SUCCESS)
806     {
807         SetLastError( RtlNtStatusToDosError(status) );
808         return 0;
809     }
810     return ret;
811 }
812
813
814 /***********************************************************************
815  *           ReleaseMutex   (KERNEL32.@)
816  */
817 BOOL WINAPI ReleaseMutex( HANDLE handle )
818 {
819     NTSTATUS    status;
820
821     status = NtReleaseMutant(handle, NULL);
822     if (status != STATUS_SUCCESS)
823     {
824         SetLastError( RtlNtStatusToDosError(status) );
825         return FALSE;
826     }
827     return TRUE;
828 }
829
830
831 /*
832  * Semaphores
833  */
834
835
836 /***********************************************************************
837  *           CreateSemaphoreA   (KERNEL32.@)
838  */
839 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
840 {
841     return CreateSemaphoreExA( sa, initial, max, name, 0, SEMAPHORE_ALL_ACCESS );
842 }
843
844
845 /***********************************************************************
846  *           CreateSemaphoreW   (KERNEL32.@)
847  */
848 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
849                                 LONG max, LPCWSTR name )
850 {
851     return CreateSemaphoreExW( sa, initial, max, name, 0, SEMAPHORE_ALL_ACCESS );
852 }
853
854
855 /***********************************************************************
856  *           CreateSemaphoreExA   (KERNEL32.@)
857  */
858 HANDLE WINAPI CreateSemaphoreExA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name,
859                                   DWORD flags, DWORD access )
860 {
861     WCHAR buffer[MAX_PATH];
862
863     if (!name) return CreateSemaphoreExW( sa, initial, max, NULL, flags, access );
864
865     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
866     {
867         SetLastError( ERROR_FILENAME_EXCED_RANGE );
868         return 0;
869     }
870     return CreateSemaphoreExW( sa, initial, max, buffer, flags, access );
871 }
872
873
874 /***********************************************************************
875  *           CreateSemaphoreExW   (KERNEL32.@)
876  */
877 HANDLE WINAPI CreateSemaphoreExW( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCWSTR name,
878                                   DWORD flags, DWORD access )
879 {
880     HANDLE ret;
881     UNICODE_STRING nameW;
882     OBJECT_ATTRIBUTES attr;
883     NTSTATUS status;
884
885     attr.Length                   = sizeof(attr);
886     attr.RootDirectory            = 0;
887     attr.ObjectName               = NULL;
888     attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
889     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
890     attr.SecurityQualityOfService = NULL;
891     if (name)
892     {
893         RtlInitUnicodeString( &nameW, name );
894         attr.ObjectName = &nameW;
895         attr.RootDirectory = get_BaseNamedObjects_handle();
896     }
897
898     status = NtCreateSemaphore( &ret, access, &attr, initial, max );
899     if (status == STATUS_OBJECT_NAME_EXISTS)
900         SetLastError( ERROR_ALREADY_EXISTS );
901     else
902         SetLastError( RtlNtStatusToDosError(status) );
903     return ret;
904 }
905
906
907 /***********************************************************************
908  *           OpenSemaphoreA   (KERNEL32.@)
909  */
910 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
911 {
912     WCHAR buffer[MAX_PATH];
913
914     if (!name) return OpenSemaphoreW( access, inherit, NULL );
915
916     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
917     {
918         SetLastError( ERROR_FILENAME_EXCED_RANGE );
919         return 0;
920     }
921     return OpenSemaphoreW( access, inherit, buffer );
922 }
923
924
925 /***********************************************************************
926  *           OpenSemaphoreW   (KERNEL32.@)
927  */
928 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
929 {
930     HANDLE ret;
931     UNICODE_STRING nameW;
932     OBJECT_ATTRIBUTES attr;
933     NTSTATUS status;
934
935     if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
936
937     attr.Length                   = sizeof(attr);
938     attr.RootDirectory            = 0;
939     attr.ObjectName               = NULL;
940     attr.Attributes               = inherit ? OBJ_INHERIT : 0;
941     attr.SecurityDescriptor       = NULL;
942     attr.SecurityQualityOfService = NULL;
943     if (name)
944     {
945         RtlInitUnicodeString( &nameW, name );
946         attr.ObjectName = &nameW;
947         attr.RootDirectory = get_BaseNamedObjects_handle();
948     }
949
950     status = NtOpenSemaphore( &ret, access, &attr );
951     if (status != STATUS_SUCCESS)
952     {
953         SetLastError( RtlNtStatusToDosError(status) );
954         return 0;
955     }
956     return ret;
957 }
958
959
960 /***********************************************************************
961  *           ReleaseSemaphore   (KERNEL32.@)
962  */
963 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
964 {
965     NTSTATUS status = NtReleaseSemaphore( handle, count, (PULONG)previous );
966     if (status) SetLastError( RtlNtStatusToDosError(status) );
967     return !status;
968 }
969
970
971 /*
972  * Jobs
973  */
974
975 /******************************************************************************
976  *              CreateJobObjectW (KERNEL32.@)
977  */
978 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES sa, LPCWSTR name )
979 {
980     HANDLE ret = 0;
981     UNICODE_STRING nameW;
982     OBJECT_ATTRIBUTES attr;
983     NTSTATUS status;
984
985     attr.Length                   = sizeof(attr);
986     attr.RootDirectory            = 0;
987     attr.ObjectName               = NULL;
988     attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
989     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
990     attr.SecurityQualityOfService = NULL;
991     if (name)
992     {
993         RtlInitUnicodeString( &nameW, name );
994         attr.ObjectName = &nameW;
995         attr.RootDirectory = get_BaseNamedObjects_handle();
996     }
997
998     status = NtCreateJobObject( &ret, JOB_OBJECT_ALL_ACCESS, &attr );
999     if (status == STATUS_OBJECT_NAME_EXISTS)
1000         SetLastError( ERROR_ALREADY_EXISTS );
1001     else
1002         SetLastError( RtlNtStatusToDosError(status) );
1003     return ret;
1004 }
1005
1006 /******************************************************************************
1007  *              CreateJobObjectA (KERNEL32.@)
1008  */
1009 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1010 {
1011     WCHAR buffer[MAX_PATH];
1012
1013     if (!name) return CreateJobObjectW( attr, NULL );
1014
1015     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1016     {
1017         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1018         return 0;
1019     }
1020     return CreateJobObjectW( attr, buffer );
1021 }
1022
1023 /******************************************************************************
1024  *              OpenJobObjectW (KERNEL32.@)
1025  */
1026 HANDLE WINAPI OpenJobObjectW( DWORD access, BOOL inherit, LPCWSTR name )
1027 {
1028     HANDLE ret;
1029     UNICODE_STRING nameW;
1030     OBJECT_ATTRIBUTES attr;
1031     NTSTATUS status;
1032
1033     attr.Length                   = sizeof(attr);
1034     attr.RootDirectory            = 0;
1035     attr.ObjectName               = NULL;
1036     attr.Attributes               = inherit ? OBJ_INHERIT : 0;
1037     attr.SecurityDescriptor       = NULL;
1038     attr.SecurityQualityOfService = NULL;
1039     if (name)
1040     {
1041         RtlInitUnicodeString( &nameW, name );
1042         attr.ObjectName = &nameW;
1043         attr.RootDirectory = get_BaseNamedObjects_handle();
1044     }
1045
1046     status = NtOpenJobObject( &ret, access, &attr );
1047     if (status != STATUS_SUCCESS)
1048     {
1049         SetLastError( RtlNtStatusToDosError(status) );
1050         return 0;
1051     }
1052     return ret;
1053 }
1054
1055 /******************************************************************************
1056  *              OpenJobObjectA (KERNEL32.@)
1057  */
1058 HANDLE WINAPI OpenJobObjectA( DWORD access, BOOL inherit, LPCSTR name )
1059 {
1060     WCHAR buffer[MAX_PATH];
1061
1062     if (!name) return OpenJobObjectW( access, inherit, NULL );
1063
1064     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1065     {
1066         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1067         return 0;
1068     }
1069     return OpenJobObjectW( access, inherit, buffer );
1070 }
1071
1072 /******************************************************************************
1073  *              TerminateJobObject (KERNEL32.@)
1074  */
1075 BOOL WINAPI TerminateJobObject( HANDLE job, UINT exit_code )
1076 {
1077     NTSTATUS status = NtTerminateJobObject( job, exit_code );
1078     if (status) SetLastError( RtlNtStatusToDosError(status) );
1079     return !status;
1080 }
1081
1082 /******************************************************************************
1083  *              QueryInformationJobObject (KERNEL32.@)
1084  */
1085 BOOL WINAPI QueryInformationJobObject( HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info,
1086                                        DWORD len, DWORD *ret_len )
1087 {
1088     NTSTATUS status = NtQueryInformationJobObject( job, class, info, len, ret_len );
1089     if (status) SetLastError( RtlNtStatusToDosError(status) );
1090     return !status;
1091 }
1092
1093 /******************************************************************************
1094  *              SetInformationJobObject (KERNEL32.@)
1095  */
1096 BOOL WINAPI SetInformationJobObject( HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len )
1097 {
1098     NTSTATUS status = NtSetInformationJobObject( job, class, info, len );
1099     if (status) SetLastError( RtlNtStatusToDosError(status) );
1100     return !status;
1101 }
1102
1103 /******************************************************************************
1104  *              AssignProcessToJobObject (KERNEL32.@)
1105  */
1106 BOOL WINAPI AssignProcessToJobObject( HANDLE job, HANDLE process )
1107 {
1108     NTSTATUS status = NtAssignProcessToJobObject( job, process );
1109     if (status) SetLastError( RtlNtStatusToDosError(status) );
1110     return !status;
1111 }
1112
1113 /******************************************************************************
1114  *              IsProcessInJob (KERNEL32.@)
1115  */
1116 BOOL WINAPI IsProcessInJob( HANDLE process, HANDLE job, PBOOL result )
1117 {
1118     NTSTATUS status = NtIsProcessInJob( job, process );
1119     switch(status)
1120     {
1121     case STATUS_PROCESS_IN_JOB:
1122         *result = TRUE;
1123         return TRUE;
1124     case STATUS_PROCESS_NOT_IN_JOB:
1125         *result = FALSE;
1126         return TRUE;
1127     default:
1128         SetLastError( RtlNtStatusToDosError(status) );
1129         return FALSE;
1130     }
1131 }
1132
1133
1134 /*
1135  * Timers
1136  */
1137
1138
1139 /***********************************************************************
1140  *           CreateWaitableTimerA    (KERNEL32.@)
1141  */
1142 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
1143 {
1144     return CreateWaitableTimerExA( sa, name, manual ? CREATE_WAITABLE_TIMER_MANUAL_RESET : 0,
1145                                    TIMER_ALL_ACCESS );
1146 }
1147
1148
1149 /***********************************************************************
1150  *           CreateWaitableTimerW    (KERNEL32.@)
1151  */
1152 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
1153 {
1154     return CreateWaitableTimerExW( sa, name, manual ? CREATE_WAITABLE_TIMER_MANUAL_RESET : 0,
1155                                    TIMER_ALL_ACCESS );
1156 }
1157
1158
1159 /***********************************************************************
1160  *           CreateWaitableTimerExA    (KERNEL32.@)
1161  */
1162 HANDLE WINAPI CreateWaitableTimerExA( SECURITY_ATTRIBUTES *sa, LPCSTR name, DWORD flags, DWORD access )
1163 {
1164     WCHAR buffer[MAX_PATH];
1165
1166     if (!name) return CreateWaitableTimerExW( sa, NULL, flags, access );
1167
1168     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1169     {
1170         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1171         return 0;
1172     }
1173     return CreateWaitableTimerExW( sa, buffer, flags, access );
1174 }
1175
1176
1177 /***********************************************************************
1178  *           CreateWaitableTimerExW    (KERNEL32.@)
1179  */
1180 HANDLE WINAPI CreateWaitableTimerExW( SECURITY_ATTRIBUTES *sa, LPCWSTR name, DWORD flags, DWORD access )
1181 {
1182     HANDLE handle;
1183     NTSTATUS status;
1184     UNICODE_STRING nameW;
1185     OBJECT_ATTRIBUTES attr;
1186
1187     attr.Length                   = sizeof(attr);
1188     attr.RootDirectory            = 0;
1189     attr.ObjectName               = NULL;
1190     attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1191     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
1192     attr.SecurityQualityOfService = NULL;
1193     if (name)
1194     {
1195         RtlInitUnicodeString( &nameW, name );
1196         attr.ObjectName = &nameW;
1197         attr.RootDirectory = get_BaseNamedObjects_handle();
1198     }
1199
1200     status = NtCreateTimer( &handle, access, &attr,
1201                  (flags & CREATE_WAITABLE_TIMER_MANUAL_RESET) ? NotificationTimer : SynchronizationTimer );
1202     if (status == STATUS_OBJECT_NAME_EXISTS)
1203         SetLastError( ERROR_ALREADY_EXISTS );
1204     else
1205         SetLastError( RtlNtStatusToDosError(status) );
1206     return handle;
1207 }
1208
1209
1210 /***********************************************************************
1211  *           OpenWaitableTimerA    (KERNEL32.@)
1212  */
1213 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
1214 {
1215     WCHAR buffer[MAX_PATH];
1216
1217     if (!name) return OpenWaitableTimerW( access, inherit, NULL );
1218
1219     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1220     {
1221         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1222         return 0;
1223     }
1224     return OpenWaitableTimerW( access, inherit, buffer );
1225 }
1226
1227
1228 /***********************************************************************
1229  *           OpenWaitableTimerW    (KERNEL32.@)
1230  */
1231 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
1232 {
1233     HANDLE handle;
1234     UNICODE_STRING nameW;
1235     OBJECT_ATTRIBUTES attr;
1236     NTSTATUS status;
1237
1238     if (!is_version_nt()) access = TIMER_ALL_ACCESS;
1239
1240     attr.Length                   = sizeof(attr);
1241     attr.RootDirectory            = 0;
1242     attr.ObjectName               = NULL;
1243     attr.Attributes               = inherit ? OBJ_INHERIT : 0;
1244     attr.SecurityDescriptor       = NULL;
1245     attr.SecurityQualityOfService = NULL;
1246     if (name)
1247     {
1248         RtlInitUnicodeString( &nameW, name );
1249         attr.ObjectName = &nameW;
1250         attr.RootDirectory = get_BaseNamedObjects_handle();
1251     }
1252
1253     status = NtOpenTimer(&handle, access, &attr);
1254     if (status != STATUS_SUCCESS)
1255     {
1256         SetLastError( RtlNtStatusToDosError(status) );
1257         return 0;
1258     }
1259     return handle;
1260 }
1261
1262
1263 /***********************************************************************
1264  *           SetWaitableTimer    (KERNEL32.@)
1265  */
1266 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
1267                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
1268 {
1269     NTSTATUS status = NtSetTimer(handle, when, (PTIMER_APC_ROUTINE)callback,
1270                                  arg, resume, period, NULL);
1271
1272     if (status != STATUS_SUCCESS)
1273     {
1274         SetLastError( RtlNtStatusToDosError(status) );
1275         if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
1276     }
1277     return TRUE;
1278 }
1279
1280
1281 /***********************************************************************
1282  *           CancelWaitableTimer    (KERNEL32.@)
1283  */
1284 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
1285 {
1286     NTSTATUS status;
1287
1288     status = NtCancelTimer(handle, NULL);
1289     if (status != STATUS_SUCCESS)
1290     {
1291         SetLastError( RtlNtStatusToDosError(status) );
1292         return FALSE;
1293     }
1294     return TRUE;
1295 }
1296
1297
1298 /***********************************************************************
1299  *           CreateTimerQueue  (KERNEL32.@)
1300  */
1301 HANDLE WINAPI CreateTimerQueue(void)
1302 {
1303     HANDLE q;
1304     NTSTATUS status = RtlCreateTimerQueue(&q);
1305
1306     if (status != STATUS_SUCCESS)
1307     {
1308         SetLastError( RtlNtStatusToDosError(status) );
1309         return NULL;
1310     }
1311
1312     return q;
1313 }
1314
1315
1316 /***********************************************************************
1317  *           DeleteTimerQueueEx  (KERNEL32.@)
1318  */
1319 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
1320 {
1321     NTSTATUS status = RtlDeleteTimerQueueEx(TimerQueue, CompletionEvent);
1322
1323     if (status != STATUS_SUCCESS)
1324     {
1325         SetLastError( RtlNtStatusToDosError(status) );
1326         return FALSE;
1327     }
1328
1329     return TRUE;
1330 }
1331
1332 /***********************************************************************
1333  *           CreateTimerQueueTimer  (KERNEL32.@)
1334  *
1335  * Creates a timer-queue timer. This timer expires at the specified due
1336  * time (in ms), then after every specified period (in ms). When the timer
1337  * expires, the callback function is called.
1338  *
1339  * RETURNS
1340  *   nonzero on success or zero on failure
1341  */
1342 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
1343                                    WAITORTIMERCALLBACK Callback, PVOID Parameter,
1344                                    DWORD DueTime, DWORD Period, ULONG Flags )
1345 {
1346     NTSTATUS status = RtlCreateTimer(phNewTimer, TimerQueue, Callback,
1347                                      Parameter, DueTime, Period, Flags);
1348
1349     if (status != STATUS_SUCCESS)
1350     {
1351         SetLastError( RtlNtStatusToDosError(status) );
1352         return FALSE;
1353     }
1354
1355     return TRUE;
1356 }
1357
1358 /***********************************************************************
1359  *           ChangeTimerQueueTimer  (KERNEL32.@)
1360  *
1361  * Changes the times at which the timer expires.
1362  *
1363  * RETURNS
1364  *   nonzero on success or zero on failure
1365  */
1366 BOOL WINAPI ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1367                                    ULONG DueTime, ULONG Period )
1368 {
1369     NTSTATUS status = RtlUpdateTimer(TimerQueue, Timer, DueTime, Period);
1370
1371     if (status != STATUS_SUCCESS)
1372     {
1373         SetLastError( RtlNtStatusToDosError(status) );
1374         return FALSE;
1375     }
1376
1377     return TRUE;
1378 }
1379
1380 /***********************************************************************
1381  *           DeleteTimerQueueTimer  (KERNEL32.@)
1382  *
1383  * Cancels a timer-queue timer.
1384  *
1385  * RETURNS
1386  *   nonzero on success or zero on failure
1387  */
1388 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1389                                    HANDLE CompletionEvent )
1390 {
1391     NTSTATUS status = RtlDeleteTimer(TimerQueue, Timer, CompletionEvent);
1392     if (status != STATUS_SUCCESS)
1393     {
1394         SetLastError( RtlNtStatusToDosError(status) );
1395         return FALSE;
1396     }
1397     return TRUE;
1398 }
1399
1400
1401 /*
1402  * Pipes
1403  */
1404
1405
1406 /***********************************************************************
1407  *           CreateNamedPipeA   (KERNEL32.@)
1408  */
1409 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1410                                 DWORD dwPipeMode, DWORD nMaxInstances,
1411                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1412                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1413 {
1414     WCHAR buffer[MAX_PATH];
1415
1416     if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1417                                         nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1418
1419     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1420     {
1421         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1422         return INVALID_HANDLE_VALUE;
1423     }
1424     return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1425                              nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1426 }
1427
1428
1429 /***********************************************************************
1430  *           CreateNamedPipeW   (KERNEL32.@)
1431  */
1432 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1433                                 DWORD dwPipeMode, DWORD nMaxInstances,
1434                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1435                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
1436 {
1437     HANDLE handle;
1438     UNICODE_STRING nt_name;
1439     OBJECT_ATTRIBUTES attr;
1440     DWORD access, options;
1441     BOOLEAN pipe_type, read_mode, non_block;
1442     NTSTATUS status;
1443     IO_STATUS_BLOCK iosb;
1444     LARGE_INTEGER timeout;
1445
1446     TRACE("(%s, %#08x, %#08x, %d, %d, %d, %d, %p)\n",
1447           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1448           nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
1449
1450     if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1451     {
1452         SetLastError( ERROR_PATH_NOT_FOUND );
1453         return INVALID_HANDLE_VALUE;
1454     }
1455     if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1456     {
1457         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1458         RtlFreeUnicodeString( &nt_name );
1459         return INVALID_HANDLE_VALUE;
1460     }
1461
1462     attr.Length                   = sizeof(attr);
1463     attr.RootDirectory            = 0;
1464     attr.ObjectName               = &nt_name;
1465     attr.Attributes               = OBJ_CASE_INSENSITIVE |
1466                                     ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1467     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
1468     attr.SecurityQualityOfService = NULL;
1469
1470     switch(dwOpenMode & 3)
1471     {
1472     case PIPE_ACCESS_INBOUND:
1473         options = FILE_PIPE_INBOUND;
1474         access  = GENERIC_READ;
1475         break;
1476     case PIPE_ACCESS_OUTBOUND:
1477         options = FILE_PIPE_OUTBOUND;
1478         access  = GENERIC_WRITE;
1479         break;
1480     case PIPE_ACCESS_DUPLEX:
1481         options = FILE_PIPE_FULL_DUPLEX;
1482         access  = GENERIC_READ | GENERIC_WRITE;
1483         break;
1484     default:
1485         SetLastError( ERROR_INVALID_PARAMETER );
1486         return INVALID_HANDLE_VALUE;
1487     }
1488     access |= SYNCHRONIZE;
1489     if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
1490     if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT;
1491     pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) ? TRUE : FALSE;
1492     read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) ? TRUE : FALSE;
1493     non_block = (dwPipeMode & PIPE_NOWAIT) ? TRUE : FALSE;
1494     if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ~0U;
1495
1496     timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
1497
1498     SetLastError(0);
1499
1500     status = NtCreateNamedPipeFile(&handle, access, &attr, &iosb, 0,
1501                                    FILE_OVERWRITE_IF, options, pipe_type,
1502                                    read_mode, non_block, nMaxInstances,
1503                                    nInBufferSize, nOutBufferSize, &timeout);
1504
1505     RtlFreeUnicodeString( &nt_name );
1506     if (status)
1507     {
1508         handle = INVALID_HANDLE_VALUE;
1509         SetLastError( RtlNtStatusToDosError(status) );
1510     }
1511     return handle;
1512 }
1513
1514
1515 /***********************************************************************
1516  *           PeekNamedPipe   (KERNEL32.@)
1517  */
1518 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1519                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1520 {
1521     FILE_PIPE_PEEK_BUFFER local_buffer;
1522     FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
1523     IO_STATUS_BLOCK io;
1524     NTSTATUS status;
1525
1526     if (cbBuffer && !(buffer = HeapAlloc( GetProcessHeap(), 0,
1527                                           FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ))))
1528     {
1529         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1530         return FALSE;
1531     }
1532
1533     status = NtFsControlFile( hPipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
1534                               buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ) );
1535     if (!status)
1536     {
1537         ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
1538         if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
1539         if (lpcbRead) *lpcbRead = read_size;
1540         if (lpcbMessage) *lpcbMessage = 0;  /* FIXME */
1541         if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
1542     }
1543     else SetLastError( RtlNtStatusToDosError(status) );
1544
1545     if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
1546     return !status;
1547 }
1548
1549 /***********************************************************************
1550  *           WaitNamedPipeA   (KERNEL32.@)
1551  */
1552 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1553 {
1554     WCHAR buffer[MAX_PATH];
1555
1556     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1557
1558     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1559     {
1560         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1561         return 0;
1562     }
1563     return WaitNamedPipeW( buffer, nTimeOut );
1564 }
1565
1566
1567 /***********************************************************************
1568  *           WaitNamedPipeW   (KERNEL32.@)
1569  *
1570  *  Waits for a named pipe instance to become available
1571  *
1572  *  PARAMS
1573  *   name     [I] Pointer to a named pipe name to wait for
1574  *   nTimeOut [I] How long to wait in ms
1575  *
1576  *  RETURNS
1577  *   TRUE: Success, named pipe can be opened with CreateFile
1578  *   FALSE: Failure, GetLastError can be called for further details
1579  */
1580 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1581 {
1582     static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1583     NTSTATUS status;
1584     UNICODE_STRING nt_name, pipe_dev_name;
1585     FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
1586     IO_STATUS_BLOCK iosb;
1587     OBJECT_ATTRIBUTES attr;
1588     ULONG sz_pipe_wait;
1589     HANDLE pipe_dev;
1590
1591     TRACE("%s 0x%08x\n",debugstr_w(name),nTimeOut);
1592
1593     if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1594         return FALSE;
1595
1596     if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ||
1597         nt_name.Length < sizeof(leadin) ||
1598         strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(WCHAR)) != 0)
1599     {
1600         RtlFreeUnicodeString( &nt_name );
1601         SetLastError( ERROR_PATH_NOT_FOUND );
1602         return FALSE;
1603     }
1604
1605     sz_pipe_wait = sizeof(*pipe_wait) + nt_name.Length - sizeof(leadin) - sizeof(WCHAR);
1606     if (!(pipe_wait = HeapAlloc( GetProcessHeap(), 0,  sz_pipe_wait)))
1607     {
1608         RtlFreeUnicodeString( &nt_name );
1609         SetLastError( ERROR_OUTOFMEMORY );
1610         return FALSE;
1611     }
1612
1613     pipe_dev_name.Buffer = nt_name.Buffer;
1614     pipe_dev_name.Length = sizeof(leadin);
1615     pipe_dev_name.MaximumLength = sizeof(leadin);
1616     InitializeObjectAttributes(&attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
1617     status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES, &attr,
1618                          &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
1619                          FILE_SYNCHRONOUS_IO_NONALERT);
1620     if (status != ERROR_SUCCESS)
1621     {
1622         SetLastError( ERROR_PATH_NOT_FOUND );
1623         return FALSE;
1624     }
1625
1626     pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT);
1627     if (nTimeOut == NMPWAIT_WAIT_FOREVER)
1628         pipe_wait->Timeout.QuadPart = ((ULONGLONG)0x7fffffff << 32) | 0xffffffff;
1629     else
1630         pipe_wait->Timeout.QuadPart = (ULONGLONG)nTimeOut * -10000;
1631     pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
1632     memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
1633            pipe_wait->NameLength);
1634     RtlFreeUnicodeString( &nt_name );
1635
1636     status = NtFsControlFile( pipe_dev, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
1637                               pipe_wait, sz_pipe_wait, NULL, 0 );
1638
1639     HeapFree( GetProcessHeap(), 0, pipe_wait );
1640     NtClose( pipe_dev );
1641
1642     if(status != STATUS_SUCCESS)
1643     {
1644         SetLastError(RtlNtStatusToDosError(status));
1645         return FALSE;
1646     }
1647     else
1648         return TRUE;
1649 }
1650
1651
1652 /***********************************************************************
1653  *           ConnectNamedPipe   (KERNEL32.@)
1654  *
1655  *  Connects to a named pipe
1656  *
1657  *  Parameters
1658  *  hPipe: A handle to a named pipe returned by CreateNamedPipe
1659  *  overlapped: Optional OVERLAPPED struct
1660  *
1661  *  Return values
1662  *  TRUE: Success
1663  *  FALSE: Failure, GetLastError can be called for further details
1664  */
1665 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1666 {
1667     NTSTATUS status;
1668     IO_STATUS_BLOCK status_block;
1669     LPVOID   cvalue = NULL;
1670
1671     TRACE("(%p,%p)\n", hPipe, overlapped);
1672
1673     if(overlapped)
1674     {
1675         overlapped->Internal = STATUS_PENDING;
1676         overlapped->InternalHigh = 0;
1677         if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
1678     }
1679
1680     status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, cvalue,
1681                              overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
1682                              FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
1683
1684     if (status == STATUS_SUCCESS) return TRUE;
1685     SetLastError( RtlNtStatusToDosError(status) );
1686     return FALSE;
1687 }
1688
1689 /***********************************************************************
1690  *           DisconnectNamedPipe   (KERNEL32.@)
1691  *
1692  *  Disconnects from a named pipe
1693  *
1694  *  Parameters
1695  *  hPipe: A handle to a named pipe returned by CreateNamedPipe
1696  *
1697  *  Return values
1698  *  TRUE: Success
1699  *  FALSE: Failure, GetLastError can be called for further details
1700  */
1701 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1702 {
1703     NTSTATUS status;
1704     IO_STATUS_BLOCK io_block;
1705
1706     TRACE("(%p)\n",hPipe);
1707
1708     status = NtFsControlFile(hPipe, 0, NULL, NULL, &io_block, FSCTL_PIPE_DISCONNECT,
1709                              NULL, 0, NULL, 0);
1710     if (status == STATUS_SUCCESS) return TRUE;
1711     SetLastError( RtlNtStatusToDosError(status) );
1712     return FALSE;
1713 }
1714
1715 /***********************************************************************
1716  *           TransactNamedPipe   (KERNEL32.@)
1717  *
1718  * BUGS
1719  *  should be done as a single operation in the wineserver or kernel
1720  */
1721 BOOL WINAPI TransactNamedPipe(
1722     HANDLE handle, LPVOID write_buf, DWORD write_size, LPVOID read_buf,
1723     DWORD read_size, LPDWORD bytes_read, LPOVERLAPPED overlapped)
1724 {
1725     BOOL r;
1726     DWORD count;
1727
1728     TRACE("%p %p %d %p %d %p %p\n",
1729           handle, write_buf, write_size, read_buf,
1730           read_size, bytes_read, overlapped);
1731
1732     if (overlapped)
1733     {
1734         FIXME("Doesn't support overlapped operation as yet\n");
1735         return FALSE;
1736     }
1737
1738     r = WriteFile(handle, write_buf, write_size, &count, NULL);
1739     if (r)
1740         r = ReadFile(handle, read_buf, read_size, bytes_read, NULL);
1741
1742     return r;
1743 }
1744
1745 /***********************************************************************
1746  *           GetNamedPipeInfo   (KERNEL32.@)
1747  */
1748 BOOL WINAPI GetNamedPipeInfo(
1749     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1750     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1751 {
1752     FILE_PIPE_LOCAL_INFORMATION fpli;
1753     IO_STATUS_BLOCK iosb;
1754     NTSTATUS status;
1755
1756     status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
1757                                     FilePipeLocalInformation);
1758     if (status)
1759     {
1760         SetLastError( RtlNtStatusToDosError(status) );
1761         return FALSE;
1762     }
1763
1764     if (lpFlags)
1765     {
1766         *lpFlags = (fpli.NamedPipeEnd & FILE_PIPE_SERVER_END) ?
1767             PIPE_SERVER_END : PIPE_CLIENT_END;
1768         *lpFlags |= (fpli.NamedPipeType & FILE_PIPE_TYPE_MESSAGE) ?
1769             PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
1770     }
1771
1772     if (lpOutputBufferSize) *lpOutputBufferSize = fpli.OutboundQuota;
1773     if (lpInputBufferSize) *lpInputBufferSize = fpli.InboundQuota;
1774     if (lpMaxInstances) *lpMaxInstances = fpli.MaximumInstances;
1775
1776     return TRUE;
1777 }
1778
1779 /***********************************************************************
1780  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1781  */
1782 BOOL WINAPI GetNamedPipeHandleStateA(
1783     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1784     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1785     LPSTR lpUsername, DWORD nUsernameMaxSize)
1786 {
1787     FIXME("%p %p %p %p %p %p %d\n",
1788           hNamedPipe, lpState, lpCurInstances,
1789           lpMaxCollectionCount, lpCollectDataTimeout,
1790           lpUsername, nUsernameMaxSize);
1791
1792     return FALSE;
1793 }
1794
1795 /***********************************************************************
1796  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1797  */
1798 BOOL WINAPI GetNamedPipeHandleStateW(
1799     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1800     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1801     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1802 {
1803     FIXME("%p %p %p %p %p %p %d\n",
1804           hNamedPipe, lpState, lpCurInstances,
1805           lpMaxCollectionCount, lpCollectDataTimeout,
1806           lpUsername, nUsernameMaxSize);
1807
1808     return FALSE;
1809 }
1810
1811 /***********************************************************************
1812  *           SetNamedPipeHandleState  (KERNEL32.@)
1813  */
1814 BOOL WINAPI SetNamedPipeHandleState(
1815     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1816     LPDWORD lpCollectDataTimeout)
1817 {
1818     /* should be a fixme, but this function is called a lot by the RPC
1819      * runtime, and it slows down InstallShield a fair bit. */
1820     WARN("stub: %p %p/%d %p %p\n",
1821           hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
1822     return FALSE;
1823 }
1824
1825 /***********************************************************************
1826  *           CallNamedPipeA  (KERNEL32.@)
1827  */
1828 BOOL WINAPI CallNamedPipeA(
1829     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1830     LPVOID lpOutput, DWORD dwOutputSize,
1831     LPDWORD lpBytesRead, DWORD nTimeout)
1832 {
1833     DWORD len;
1834     LPWSTR str = NULL;
1835     BOOL ret;
1836
1837     TRACE("%s %p %d %p %d %p %d\n",
1838            debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1839            lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1840
1841     if( lpNamedPipeName )
1842     {
1843         len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1844         str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1845         MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1846     }
1847     ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1848                           dwOutputSize, lpBytesRead, nTimeout );
1849     if( lpNamedPipeName )
1850         HeapFree( GetProcessHeap(), 0, str );
1851
1852     return ret;
1853 }
1854
1855 /***********************************************************************
1856  *           CallNamedPipeW  (KERNEL32.@)
1857  */
1858 BOOL WINAPI CallNamedPipeW(
1859     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1860     LPVOID lpOutput, DWORD lpOutputSize,
1861     LPDWORD lpBytesRead, DWORD nTimeout)
1862 {
1863     HANDLE pipe;
1864     BOOL ret;
1865     DWORD mode;
1866
1867     TRACE("%s %p %d %p %d %p %d\n",
1868           debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1869           lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1870
1871     pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1872     if (pipe == INVALID_HANDLE_VALUE)
1873     {
1874         ret = WaitNamedPipeW(lpNamedPipeName, nTimeout);
1875         if (!ret)
1876             return FALSE;
1877         pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1878         if (pipe == INVALID_HANDLE_VALUE)
1879             return FALSE;
1880     }
1881
1882     mode = PIPE_READMODE_MESSAGE;
1883     ret = SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
1884
1885     /* Currently SetNamedPipeHandleState() is a stub returning FALSE */
1886     if (ret) FIXME("Now that SetNamedPipeHandleState() is more than a stub, please update CallNamedPipeW\n");
1887     /*
1888     if (!ret)
1889     {
1890         CloseHandle(pipe);
1891         return FALSE;
1892     }*/
1893
1894     ret = TransactNamedPipe(pipe, lpInput, lpInputSize, lpOutput, lpOutputSize, lpBytesRead, NULL);
1895     CloseHandle(pipe);
1896     if (!ret)
1897         return FALSE;
1898
1899     return TRUE;
1900 }
1901
1902 /******************************************************************
1903  *              CreatePipe (KERNEL32.@)
1904  *
1905  */
1906 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1907                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1908 {
1909     static unsigned     index /* = 0 */;
1910     WCHAR               name[64];
1911     HANDLE              hr, hw;
1912     unsigned            in_index = index;
1913     UNICODE_STRING      nt_name;
1914     OBJECT_ATTRIBUTES   attr;
1915     NTSTATUS            status;
1916     IO_STATUS_BLOCK     iosb;
1917     LARGE_INTEGER       timeout;
1918
1919     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1920
1921     attr.Length                   = sizeof(attr);
1922     attr.RootDirectory            = 0;
1923     attr.ObjectName               = &nt_name;
1924     attr.Attributes               = OBJ_CASE_INSENSITIVE |
1925                                     ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1926     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
1927     attr.SecurityQualityOfService = NULL;
1928
1929     timeout.QuadPart = (ULONGLONG)NMPWAIT_USE_DEFAULT_WAIT * -10000;
1930     /* generate a unique pipe name (system wide) */
1931     do
1932     {
1933         static const WCHAR nameFmt[] = { '\\','?','?','\\','p','i','p','e',
1934          '\\','W','i','n','3','2','.','P','i','p','e','s','.','%','0','8','l',
1935          'u','.','%','0','8','u','\0' };
1936
1937         snprintfW(name, sizeof(name) / sizeof(name[0]), nameFmt,
1938                   GetCurrentProcessId(), ++index);
1939         RtlInitUnicodeString(&nt_name, name);
1940         status = NtCreateNamedPipeFile(&hr, GENERIC_READ | SYNCHRONIZE, &attr, &iosb,
1941                                        0, FILE_OVERWRITE_IF,
1942                                        FILE_SYNCHRONOUS_IO_ALERT | FILE_PIPE_INBOUND,
1943                                        FALSE, FALSE, FALSE, 
1944                                        1, size, size, &timeout);
1945         if (status)
1946         {
1947             SetLastError( RtlNtStatusToDosError(status) );
1948             hr = INVALID_HANDLE_VALUE;
1949         }
1950     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1951     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1952     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1953
1954     status = NtOpenFile(&hw, GENERIC_WRITE | SYNCHRONIZE, &attr, &iosb, 0,
1955                         FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE);
1956
1957     if (status) 
1958     {
1959         SetLastError( RtlNtStatusToDosError(status) );
1960         NtClose(hr);
1961         return FALSE;
1962     }
1963
1964     *hReadPipe = hr;
1965     *hWritePipe = hw;
1966     return TRUE;
1967 }
1968
1969
1970 /******************************************************************************
1971  * CreateMailslotA [KERNEL32.@]
1972  *
1973  * See CreateMailslotW.
1974  */
1975 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1976                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1977 {
1978     DWORD len;
1979     HANDLE handle;
1980     LPWSTR name = NULL;
1981
1982     TRACE("%s %d %d %p\n", debugstr_a(lpName),
1983           nMaxMessageSize, lReadTimeout, sa);
1984
1985     if( lpName )
1986     {
1987         len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1988         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1989         MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1990     }
1991
1992     handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1993
1994     HeapFree( GetProcessHeap(), 0, name );
1995
1996     return handle;
1997 }
1998
1999
2000 /******************************************************************************
2001  * CreateMailslotW [KERNEL32.@]
2002  *
2003  * Create a mailslot with specified name.
2004  *
2005  * PARAMS
2006  *    lpName          [I] Pointer to string for mailslot name
2007  *    nMaxMessageSize [I] Maximum message size
2008  *    lReadTimeout    [I] Milliseconds before read time-out
2009  *    sa              [I] Pointer to security structure
2010  *
2011  * RETURNS
2012  *    Success: Handle to mailslot
2013  *    Failure: INVALID_HANDLE_VALUE
2014  */
2015 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
2016                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
2017 {
2018     HANDLE handle = INVALID_HANDLE_VALUE;
2019     OBJECT_ATTRIBUTES attr;
2020     UNICODE_STRING nameW;
2021     LARGE_INTEGER timeout;
2022     IO_STATUS_BLOCK iosb;
2023     NTSTATUS status;
2024
2025     TRACE("%s %d %d %p\n", debugstr_w(lpName),
2026           nMaxMessageSize, lReadTimeout, sa);
2027
2028     if (!RtlDosPathNameToNtPathName_U( lpName, &nameW, NULL, NULL ))
2029     {
2030         SetLastError( ERROR_PATH_NOT_FOUND );
2031         return INVALID_HANDLE_VALUE;
2032     }
2033
2034     if (nameW.Length >= MAX_PATH * sizeof(WCHAR) )
2035     {
2036         SetLastError( ERROR_FILENAME_EXCED_RANGE );
2037         RtlFreeUnicodeString( &nameW );
2038         return INVALID_HANDLE_VALUE;
2039     }
2040
2041     attr.Length = sizeof(attr);
2042     attr.RootDirectory = 0;
2043     attr.Attributes = OBJ_CASE_INSENSITIVE;
2044     attr.ObjectName = &nameW;
2045     attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
2046     attr.SecurityQualityOfService = NULL;
2047
2048     if (lReadTimeout != MAILSLOT_WAIT_FOREVER)
2049         timeout.QuadPart = (ULONGLONG) lReadTimeout * -10000;
2050     else
2051         timeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
2052
2053     status = NtCreateMailslotFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr,
2054                                    &iosb, 0, 0, nMaxMessageSize, &timeout );
2055     if (status)
2056     {
2057         SetLastError( RtlNtStatusToDosError(status) );
2058         handle = INVALID_HANDLE_VALUE;
2059     }
2060
2061     RtlFreeUnicodeString( &nameW );
2062     return handle;
2063 }
2064
2065
2066 /******************************************************************************
2067  * GetMailslotInfo [KERNEL32.@]
2068  *
2069  * Retrieve information about a mailslot.
2070  *
2071  * PARAMS
2072  *    hMailslot        [I] Mailslot handle
2073  *    lpMaxMessageSize [O] Address of maximum message size
2074  *    lpNextSize       [O] Address of size of next message
2075  *    lpMessageCount   [O] Address of number of messages
2076  *    lpReadTimeout    [O] Address of read time-out
2077  *
2078  * RETURNS
2079  *    Success: TRUE
2080  *    Failure: FALSE
2081  */
2082 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
2083                                LPDWORD lpNextSize, LPDWORD lpMessageCount,
2084                                LPDWORD lpReadTimeout )
2085 {
2086     FILE_MAILSLOT_QUERY_INFORMATION info;
2087     IO_STATUS_BLOCK iosb;
2088     NTSTATUS status;
2089
2090     TRACE("%p %p %p %p %p\n",hMailslot, lpMaxMessageSize,
2091           lpNextSize, lpMessageCount, lpReadTimeout);
2092
2093     status = NtQueryInformationFile( hMailslot, &iosb, &info, sizeof info,
2094                                      FileMailslotQueryInformation );
2095
2096     if( status != STATUS_SUCCESS )
2097     {
2098         SetLastError( RtlNtStatusToDosError(status) );
2099         return FALSE;
2100     }
2101
2102     if( lpMaxMessageSize )
2103         *lpMaxMessageSize = info.MaximumMessageSize;
2104     if( lpNextSize )
2105         *lpNextSize = info.NextMessageSize;
2106     if( lpMessageCount )
2107         *lpMessageCount = info.MessagesAvailable;
2108     if( lpReadTimeout )
2109     {
2110         if (info.ReadTimeout.QuadPart == (((LONGLONG)0x7fffffff << 32) | 0xffffffff))
2111             *lpReadTimeout = MAILSLOT_WAIT_FOREVER;
2112         else
2113             *lpReadTimeout = info.ReadTimeout.QuadPart / -10000;
2114     }
2115     return TRUE;
2116 }
2117
2118
2119 /******************************************************************************
2120  * SetMailslotInfo [KERNEL32.@]
2121  *
2122  * Set the read timeout of a mailslot.
2123  *
2124  * PARAMS
2125  *  hMailslot     [I] Mailslot handle
2126  *  dwReadTimeout [I] Timeout in milliseconds.
2127  *
2128  * RETURNS
2129  *    Success: TRUE
2130  *    Failure: FALSE
2131  */
2132 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
2133 {
2134     FILE_MAILSLOT_SET_INFORMATION info;
2135     IO_STATUS_BLOCK iosb;
2136     NTSTATUS status;
2137
2138     TRACE("%p %d\n", hMailslot, dwReadTimeout);
2139
2140     if (dwReadTimeout != MAILSLOT_WAIT_FOREVER)
2141         info.ReadTimeout.QuadPart = (ULONGLONG)dwReadTimeout * -10000;
2142     else
2143         info.ReadTimeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
2144     status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info,
2145                                    FileMailslotSetInformation );
2146     if( status != STATUS_SUCCESS )
2147     {
2148         SetLastError( RtlNtStatusToDosError(status) );
2149         return FALSE;
2150     }
2151     return TRUE;
2152 }
2153
2154
2155 /******************************************************************************
2156  *              CreateIoCompletionPort (KERNEL32.@)
2157  */
2158 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
2159                                      ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
2160 {
2161     NTSTATUS status;
2162     HANDLE ret = 0;
2163
2164     TRACE("(%p, %p, %08lx, %08x)\n",
2165           hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
2166
2167     if (hExistingCompletionPort && hFileHandle == INVALID_HANDLE_VALUE)
2168     {
2169         SetLastError( ERROR_INVALID_PARAMETER);
2170         return NULL;
2171     }
2172
2173     if (hExistingCompletionPort)
2174         ret = hExistingCompletionPort;
2175     else
2176     {
2177         status = NtCreateIoCompletion( &ret, IO_COMPLETION_ALL_ACCESS, NULL, dwNumberOfConcurrentThreads );
2178         if (status != STATUS_SUCCESS) goto fail;
2179     }
2180
2181     if (hFileHandle != INVALID_HANDLE_VALUE)
2182     {
2183         FILE_COMPLETION_INFORMATION info;
2184         IO_STATUS_BLOCK iosb;
2185
2186         info.CompletionPort = ret;
2187         info.CompletionKey = CompletionKey;
2188         status = NtSetInformationFile( hFileHandle, &iosb, &info, sizeof(info), FileCompletionInformation );
2189         if (status != STATUS_SUCCESS) goto fail;
2190     }
2191
2192     return ret;
2193
2194 fail:
2195     if (ret && !hExistingCompletionPort)
2196         CloseHandle( ret );
2197     SetLastError( RtlNtStatusToDosError(status) );
2198     return 0;
2199 }
2200
2201 /******************************************************************************
2202  *              GetQueuedCompletionStatus (KERNEL32.@)
2203  */
2204 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
2205                                        PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
2206                                        DWORD dwMilliseconds )
2207 {
2208     NTSTATUS status;
2209     IO_STATUS_BLOCK iosb;
2210     LARGE_INTEGER wait_time;
2211
2212     TRACE("(%p,%p,%p,%p,%d)\n",
2213           CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
2214
2215     *lpOverlapped = NULL;
2216
2217     status = NtRemoveIoCompletion( CompletionPort, pCompletionKey, (PULONG_PTR)lpOverlapped,
2218                                    &iosb, get_nt_timeout( &wait_time, dwMilliseconds ) );
2219     if (status == STATUS_SUCCESS)
2220     {
2221         *lpNumberOfBytesTransferred = iosb.Information;
2222         return TRUE;
2223     }
2224
2225     SetLastError( RtlNtStatusToDosError(status) );
2226     return FALSE;
2227 }
2228
2229
2230 /******************************************************************************
2231  *              PostQueuedCompletionStatus (KERNEL32.@)
2232  */
2233 BOOL WINAPI PostQueuedCompletionStatus( HANDLE CompletionPort, DWORD dwNumberOfBytes,
2234                                         ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
2235 {
2236     NTSTATUS status;
2237
2238     TRACE("%p %d %08lx %p\n", CompletionPort, dwNumberOfBytes, dwCompletionKey, lpOverlapped );
2239
2240     status = NtSetIoCompletion( CompletionPort, dwCompletionKey, (ULONG_PTR)lpOverlapped,
2241                                 STATUS_SUCCESS, dwNumberOfBytes );
2242
2243     if (status == STATUS_SUCCESS) return TRUE;
2244     SetLastError( RtlNtStatusToDosError(status) );
2245     return FALSE;
2246 }
2247
2248 /******************************************************************************
2249  *              BindIoCompletionCallback (KERNEL32.@)
2250  */
2251 BOOL WINAPI BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags)
2252 {
2253     NTSTATUS status;
2254
2255     TRACE("(%p, %p, %d)\n", FileHandle, Function, Flags);
2256
2257     status = RtlSetIoCompletionCallback( FileHandle, (PRTL_OVERLAPPED_COMPLETION_ROUTINE)Function, Flags );
2258     if (status == STATUS_SUCCESS) return TRUE;
2259     SetLastError( RtlNtStatusToDosError(status) );
2260     return FALSE;
2261 }
2262
2263 #ifdef __i386__
2264
2265 /***********************************************************************
2266  *              InterlockedCompareExchange (KERNEL32.@)
2267  */
2268 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
2269 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
2270                   "movl 12(%esp),%eax\n\t"
2271                   "movl 8(%esp),%ecx\n\t"
2272                   "movl 4(%esp),%edx\n\t"
2273                   "lock; cmpxchgl %ecx,(%edx)\n\t"
2274                   "ret $12")
2275
2276 /***********************************************************************
2277  *              InterlockedExchange (KERNEL32.@)
2278  */
2279 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
2280 __ASM_GLOBAL_FUNC(InterlockedExchange,
2281                   "movl 8(%esp),%eax\n\t"
2282                   "movl 4(%esp),%edx\n\t"
2283                   "lock; xchgl %eax,(%edx)\n\t"
2284                   "ret $8")
2285
2286 /***********************************************************************
2287  *              InterlockedExchangeAdd (KERNEL32.@)
2288  */
2289 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
2290 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
2291                   "movl 8(%esp),%eax\n\t"
2292                   "movl 4(%esp),%edx\n\t"
2293                   "lock; xaddl %eax,(%edx)\n\t"
2294                   "ret $8")
2295
2296 /***********************************************************************
2297  *              InterlockedIncrement (KERNEL32.@)
2298  */
2299 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
2300 __ASM_GLOBAL_FUNC(InterlockedIncrement,
2301                   "movl 4(%esp),%edx\n\t"
2302                   "movl $1,%eax\n\t"
2303                   "lock; xaddl %eax,(%edx)\n\t"
2304                   "incl %eax\n\t"
2305                   "ret $4")
2306
2307 /***********************************************************************
2308  *              InterlockedDecrement (KERNEL32.@)
2309  */
2310 __ASM_GLOBAL_FUNC(InterlockedDecrement,
2311                   "movl 4(%esp),%edx\n\t"
2312                   "movl $-1,%eax\n\t"
2313                   "lock; xaddl %eax,(%edx)\n\t"
2314                   "decl %eax\n\t"
2315                   "ret $4")
2316
2317 #endif  /* __i386__ */