kernel32: Add support for loading stand-alone 16-bit modules.
[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  *           DeleteTimerQueue  (KERNEL32.@)
1334  */
1335 BOOL WINAPI DeleteTimerQueue(HANDLE TimerQueue)
1336 {
1337     return DeleteTimerQueueEx(TimerQueue, NULL);
1338 }
1339
1340 /***********************************************************************
1341  *           CreateTimerQueueTimer  (KERNEL32.@)
1342  *
1343  * Creates a timer-queue timer. This timer expires at the specified due
1344  * time (in ms), then after every specified period (in ms). When the timer
1345  * expires, the callback function is called.
1346  *
1347  * RETURNS
1348  *   nonzero on success or zero on failure
1349  */
1350 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
1351                                    WAITORTIMERCALLBACK Callback, PVOID Parameter,
1352                                    DWORD DueTime, DWORD Period, ULONG Flags )
1353 {
1354     NTSTATUS status = RtlCreateTimer(phNewTimer, TimerQueue, Callback,
1355                                      Parameter, DueTime, Period, Flags);
1356
1357     if (status != STATUS_SUCCESS)
1358     {
1359         SetLastError( RtlNtStatusToDosError(status) );
1360         return FALSE;
1361     }
1362
1363     return TRUE;
1364 }
1365
1366 /***********************************************************************
1367  *           ChangeTimerQueueTimer  (KERNEL32.@)
1368  *
1369  * Changes the times at which the timer expires.
1370  *
1371  * RETURNS
1372  *   nonzero on success or zero on failure
1373  */
1374 BOOL WINAPI ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1375                                    ULONG DueTime, ULONG Period )
1376 {
1377     NTSTATUS status = RtlUpdateTimer(TimerQueue, Timer, DueTime, Period);
1378
1379     if (status != STATUS_SUCCESS)
1380     {
1381         SetLastError( RtlNtStatusToDosError(status) );
1382         return FALSE;
1383     }
1384
1385     return TRUE;
1386 }
1387
1388 /***********************************************************************
1389  *           DeleteTimerQueueTimer  (KERNEL32.@)
1390  *
1391  * Cancels a timer-queue timer.
1392  *
1393  * RETURNS
1394  *   nonzero on success or zero on failure
1395  */
1396 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1397                                    HANDLE CompletionEvent )
1398 {
1399     NTSTATUS status = RtlDeleteTimer(TimerQueue, Timer, CompletionEvent);
1400     if (status != STATUS_SUCCESS)
1401     {
1402         SetLastError( RtlNtStatusToDosError(status) );
1403         return FALSE;
1404     }
1405     return TRUE;
1406 }
1407
1408
1409 /*
1410  * Pipes
1411  */
1412
1413
1414 /***********************************************************************
1415  *           CreateNamedPipeA   (KERNEL32.@)
1416  */
1417 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1418                                 DWORD dwPipeMode, DWORD nMaxInstances,
1419                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1420                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1421 {
1422     WCHAR buffer[MAX_PATH];
1423
1424     if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1425                                         nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1426
1427     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1428     {
1429         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1430         return INVALID_HANDLE_VALUE;
1431     }
1432     return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1433                              nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1434 }
1435
1436
1437 /***********************************************************************
1438  *           CreateNamedPipeW   (KERNEL32.@)
1439  */
1440 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1441                                 DWORD dwPipeMode, DWORD nMaxInstances,
1442                                 DWORD nOutBufferSize, DWORD nInBufferSize,
1443                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
1444 {
1445     HANDLE handle;
1446     UNICODE_STRING nt_name;
1447     OBJECT_ATTRIBUTES attr;
1448     DWORD access, options;
1449     BOOLEAN pipe_type, read_mode, non_block;
1450     NTSTATUS status;
1451     IO_STATUS_BLOCK iosb;
1452     LARGE_INTEGER timeout;
1453
1454     TRACE("(%s, %#08x, %#08x, %d, %d, %d, %d, %p)\n",
1455           debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1456           nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
1457
1458     if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1459     {
1460         SetLastError( ERROR_PATH_NOT_FOUND );
1461         return INVALID_HANDLE_VALUE;
1462     }
1463     if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1464     {
1465         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1466         RtlFreeUnicodeString( &nt_name );
1467         return INVALID_HANDLE_VALUE;
1468     }
1469
1470     attr.Length                   = sizeof(attr);
1471     attr.RootDirectory            = 0;
1472     attr.ObjectName               = &nt_name;
1473     attr.Attributes               = OBJ_CASE_INSENSITIVE |
1474                                     ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1475     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
1476     attr.SecurityQualityOfService = NULL;
1477
1478     switch(dwOpenMode & 3)
1479     {
1480     case PIPE_ACCESS_INBOUND:
1481         options = FILE_PIPE_INBOUND;
1482         access  = GENERIC_READ;
1483         break;
1484     case PIPE_ACCESS_OUTBOUND:
1485         options = FILE_PIPE_OUTBOUND;
1486         access  = GENERIC_WRITE;
1487         break;
1488     case PIPE_ACCESS_DUPLEX:
1489         options = FILE_PIPE_FULL_DUPLEX;
1490         access  = GENERIC_READ | GENERIC_WRITE;
1491         break;
1492     default:
1493         SetLastError( ERROR_INVALID_PARAMETER );
1494         return INVALID_HANDLE_VALUE;
1495     }
1496     access |= SYNCHRONIZE;
1497     if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
1498     if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT;
1499     pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) ? TRUE : FALSE;
1500     read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) ? TRUE : FALSE;
1501     non_block = (dwPipeMode & PIPE_NOWAIT) ? TRUE : FALSE;
1502     if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ~0U;
1503
1504     timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
1505
1506     SetLastError(0);
1507
1508     status = NtCreateNamedPipeFile(&handle, access, &attr, &iosb, 0,
1509                                    FILE_OVERWRITE_IF, options, pipe_type,
1510                                    read_mode, non_block, nMaxInstances,
1511                                    nInBufferSize, nOutBufferSize, &timeout);
1512
1513     RtlFreeUnicodeString( &nt_name );
1514     if (status)
1515     {
1516         handle = INVALID_HANDLE_VALUE;
1517         SetLastError( RtlNtStatusToDosError(status) );
1518     }
1519     return handle;
1520 }
1521
1522
1523 /***********************************************************************
1524  *           PeekNamedPipe   (KERNEL32.@)
1525  */
1526 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1527                            LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1528 {
1529     FILE_PIPE_PEEK_BUFFER local_buffer;
1530     FILE_PIPE_PEEK_BUFFER *buffer = &local_buffer;
1531     IO_STATUS_BLOCK io;
1532     NTSTATUS status;
1533
1534     if (cbBuffer && !(buffer = HeapAlloc( GetProcessHeap(), 0,
1535                                           FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ))))
1536     {
1537         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1538         return FALSE;
1539     }
1540
1541     status = NtFsControlFile( hPipe, 0, NULL, NULL, &io, FSCTL_PIPE_PEEK, NULL, 0,
1542                               buffer, FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data[cbBuffer] ) );
1543     if (!status)
1544     {
1545         ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
1546         if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
1547         if (lpcbRead) *lpcbRead = read_size;
1548         if (lpcbMessage) *lpcbMessage = 0;  /* FIXME */
1549         if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
1550     }
1551     else SetLastError( RtlNtStatusToDosError(status) );
1552
1553     if (buffer != &local_buffer) HeapFree( GetProcessHeap(), 0, buffer );
1554     return !status;
1555 }
1556
1557 /***********************************************************************
1558  *           WaitNamedPipeA   (KERNEL32.@)
1559  */
1560 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1561 {
1562     WCHAR buffer[MAX_PATH];
1563
1564     if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1565
1566     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1567     {
1568         SetLastError( ERROR_FILENAME_EXCED_RANGE );
1569         return 0;
1570     }
1571     return WaitNamedPipeW( buffer, nTimeOut );
1572 }
1573
1574
1575 /***********************************************************************
1576  *           WaitNamedPipeW   (KERNEL32.@)
1577  *
1578  *  Waits for a named pipe instance to become available
1579  *
1580  *  PARAMS
1581  *   name     [I] Pointer to a named pipe name to wait for
1582  *   nTimeOut [I] How long to wait in ms
1583  *
1584  *  RETURNS
1585  *   TRUE: Success, named pipe can be opened with CreateFile
1586  *   FALSE: Failure, GetLastError can be called for further details
1587  */
1588 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1589 {
1590     static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1591     NTSTATUS status;
1592     UNICODE_STRING nt_name, pipe_dev_name;
1593     FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
1594     IO_STATUS_BLOCK iosb;
1595     OBJECT_ATTRIBUTES attr;
1596     ULONG sz_pipe_wait;
1597     HANDLE pipe_dev;
1598
1599     TRACE("%s 0x%08x\n",debugstr_w(name),nTimeOut);
1600
1601     if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1602         return FALSE;
1603
1604     if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) ||
1605         nt_name.Length < sizeof(leadin) ||
1606         strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(WCHAR)) != 0)
1607     {
1608         RtlFreeUnicodeString( &nt_name );
1609         SetLastError( ERROR_PATH_NOT_FOUND );
1610         return FALSE;
1611     }
1612
1613     sz_pipe_wait = sizeof(*pipe_wait) + nt_name.Length - sizeof(leadin) - sizeof(WCHAR);
1614     if (!(pipe_wait = HeapAlloc( GetProcessHeap(), 0,  sz_pipe_wait)))
1615     {
1616         RtlFreeUnicodeString( &nt_name );
1617         SetLastError( ERROR_OUTOFMEMORY );
1618         return FALSE;
1619     }
1620
1621     pipe_dev_name.Buffer = nt_name.Buffer;
1622     pipe_dev_name.Length = sizeof(leadin);
1623     pipe_dev_name.MaximumLength = sizeof(leadin);
1624     InitializeObjectAttributes(&attr,&pipe_dev_name, OBJ_CASE_INSENSITIVE, NULL, NULL);
1625     status = NtOpenFile( &pipe_dev, FILE_READ_ATTRIBUTES, &attr,
1626                          &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
1627                          FILE_SYNCHRONOUS_IO_NONALERT);
1628     if (status != ERROR_SUCCESS)
1629     {
1630         SetLastError( ERROR_PATH_NOT_FOUND );
1631         return FALSE;
1632     }
1633
1634     pipe_wait->TimeoutSpecified = !(nTimeOut == NMPWAIT_USE_DEFAULT_WAIT);
1635     if (nTimeOut == NMPWAIT_WAIT_FOREVER)
1636         pipe_wait->Timeout.QuadPart = ((ULONGLONG)0x7fffffff << 32) | 0xffffffff;
1637     else
1638         pipe_wait->Timeout.QuadPart = (ULONGLONG)nTimeOut * -10000;
1639     pipe_wait->NameLength = nt_name.Length - sizeof(leadin);
1640     memcpy(pipe_wait->Name, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
1641            pipe_wait->NameLength);
1642     RtlFreeUnicodeString( &nt_name );
1643
1644     status = NtFsControlFile( pipe_dev, NULL, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
1645                               pipe_wait, sz_pipe_wait, NULL, 0 );
1646
1647     HeapFree( GetProcessHeap(), 0, pipe_wait );
1648     NtClose( pipe_dev );
1649
1650     if(status != STATUS_SUCCESS)
1651     {
1652         SetLastError(RtlNtStatusToDosError(status));
1653         return FALSE;
1654     }
1655     else
1656         return TRUE;
1657 }
1658
1659
1660 /***********************************************************************
1661  *           ConnectNamedPipe   (KERNEL32.@)
1662  *
1663  *  Connects to a named pipe
1664  *
1665  *  Parameters
1666  *  hPipe: A handle to a named pipe returned by CreateNamedPipe
1667  *  overlapped: Optional OVERLAPPED struct
1668  *
1669  *  Return values
1670  *  TRUE: Success
1671  *  FALSE: Failure, GetLastError can be called for further details
1672  */
1673 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1674 {
1675     NTSTATUS status;
1676     IO_STATUS_BLOCK status_block;
1677     LPVOID   cvalue = NULL;
1678
1679     TRACE("(%p,%p)\n", hPipe, overlapped);
1680
1681     if(overlapped)
1682     {
1683         overlapped->Internal = STATUS_PENDING;
1684         overlapped->InternalHigh = 0;
1685         if (((ULONG_PTR)overlapped->hEvent & 1) == 0) cvalue = overlapped;
1686     }
1687
1688     status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, cvalue,
1689                              overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
1690                              FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
1691
1692     if (status == STATUS_SUCCESS) return TRUE;
1693     SetLastError( RtlNtStatusToDosError(status) );
1694     return FALSE;
1695 }
1696
1697 /***********************************************************************
1698  *           DisconnectNamedPipe   (KERNEL32.@)
1699  *
1700  *  Disconnects from a named pipe
1701  *
1702  *  Parameters
1703  *  hPipe: A handle to a named pipe returned by CreateNamedPipe
1704  *
1705  *  Return values
1706  *  TRUE: Success
1707  *  FALSE: Failure, GetLastError can be called for further details
1708  */
1709 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1710 {
1711     NTSTATUS status;
1712     IO_STATUS_BLOCK io_block;
1713
1714     TRACE("(%p)\n",hPipe);
1715
1716     status = NtFsControlFile(hPipe, 0, NULL, NULL, &io_block, FSCTL_PIPE_DISCONNECT,
1717                              NULL, 0, NULL, 0);
1718     if (status == STATUS_SUCCESS) return TRUE;
1719     SetLastError( RtlNtStatusToDosError(status) );
1720     return FALSE;
1721 }
1722
1723 /***********************************************************************
1724  *           TransactNamedPipe   (KERNEL32.@)
1725  *
1726  * BUGS
1727  *  should be done as a single operation in the wineserver or kernel
1728  */
1729 BOOL WINAPI TransactNamedPipe(
1730     HANDLE handle, LPVOID write_buf, DWORD write_size, LPVOID read_buf,
1731     DWORD read_size, LPDWORD bytes_read, LPOVERLAPPED overlapped)
1732 {
1733     BOOL r;
1734     DWORD count;
1735
1736     TRACE("%p %p %d %p %d %p %p\n",
1737           handle, write_buf, write_size, read_buf,
1738           read_size, bytes_read, overlapped);
1739
1740     if (overlapped)
1741     {
1742         FIXME("Doesn't support overlapped operation as yet\n");
1743         return FALSE;
1744     }
1745
1746     r = WriteFile(handle, write_buf, write_size, &count, NULL);
1747     if (r)
1748         r = ReadFile(handle, read_buf, read_size, bytes_read, NULL);
1749
1750     return r;
1751 }
1752
1753 /***********************************************************************
1754  *           GetNamedPipeInfo   (KERNEL32.@)
1755  */
1756 BOOL WINAPI GetNamedPipeInfo(
1757     HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1758     LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1759 {
1760     FILE_PIPE_LOCAL_INFORMATION fpli;
1761     IO_STATUS_BLOCK iosb;
1762     NTSTATUS status;
1763
1764     status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
1765                                     FilePipeLocalInformation);
1766     if (status)
1767     {
1768         SetLastError( RtlNtStatusToDosError(status) );
1769         return FALSE;
1770     }
1771
1772     if (lpFlags)
1773     {
1774         *lpFlags = (fpli.NamedPipeEnd & FILE_PIPE_SERVER_END) ?
1775             PIPE_SERVER_END : PIPE_CLIENT_END;
1776         *lpFlags |= (fpli.NamedPipeType & FILE_PIPE_TYPE_MESSAGE) ?
1777             PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
1778     }
1779
1780     if (lpOutputBufferSize) *lpOutputBufferSize = fpli.OutboundQuota;
1781     if (lpInputBufferSize) *lpInputBufferSize = fpli.InboundQuota;
1782     if (lpMaxInstances) *lpMaxInstances = fpli.MaximumInstances;
1783
1784     return TRUE;
1785 }
1786
1787 /***********************************************************************
1788  *           GetNamedPipeHandleStateA  (KERNEL32.@)
1789  */
1790 BOOL WINAPI GetNamedPipeHandleStateA(
1791     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1792     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1793     LPSTR lpUsername, DWORD nUsernameMaxSize)
1794 {
1795     FIXME("%p %p %p %p %p %p %d\n",
1796           hNamedPipe, lpState, lpCurInstances,
1797           lpMaxCollectionCount, lpCollectDataTimeout,
1798           lpUsername, nUsernameMaxSize);
1799
1800     return FALSE;
1801 }
1802
1803 /***********************************************************************
1804  *           GetNamedPipeHandleStateW  (KERNEL32.@)
1805  */
1806 BOOL WINAPI GetNamedPipeHandleStateW(
1807     HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1808     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1809     LPWSTR lpUsername, DWORD nUsernameMaxSize)
1810 {
1811     FIXME("%p %p %p %p %p %p %d\n",
1812           hNamedPipe, lpState, lpCurInstances,
1813           lpMaxCollectionCount, lpCollectDataTimeout,
1814           lpUsername, nUsernameMaxSize);
1815
1816     return FALSE;
1817 }
1818
1819 /***********************************************************************
1820  *           SetNamedPipeHandleState  (KERNEL32.@)
1821  */
1822 BOOL WINAPI SetNamedPipeHandleState(
1823     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1824     LPDWORD lpCollectDataTimeout)
1825 {
1826     /* should be a fixme, but this function is called a lot by the RPC
1827      * runtime, and it slows down InstallShield a fair bit. */
1828     WARN("stub: %p %p/%d %p %p\n",
1829           hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
1830     return FALSE;
1831 }
1832
1833 /***********************************************************************
1834  *           CallNamedPipeA  (KERNEL32.@)
1835  */
1836 BOOL WINAPI CallNamedPipeA(
1837     LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1838     LPVOID lpOutput, DWORD dwOutputSize,
1839     LPDWORD lpBytesRead, DWORD nTimeout)
1840 {
1841     DWORD len;
1842     LPWSTR str = NULL;
1843     BOOL ret;
1844
1845     TRACE("%s %p %d %p %d %p %d\n",
1846            debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1847            lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1848
1849     if( lpNamedPipeName )
1850     {
1851         len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1852         str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1853         MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1854     }
1855     ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1856                           dwOutputSize, lpBytesRead, nTimeout );
1857     if( lpNamedPipeName )
1858         HeapFree( GetProcessHeap(), 0, str );
1859
1860     return ret;
1861 }
1862
1863 /***********************************************************************
1864  *           CallNamedPipeW  (KERNEL32.@)
1865  */
1866 BOOL WINAPI CallNamedPipeW(
1867     LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1868     LPVOID lpOutput, DWORD lpOutputSize,
1869     LPDWORD lpBytesRead, DWORD nTimeout)
1870 {
1871     HANDLE pipe;
1872     BOOL ret;
1873     DWORD mode;
1874
1875     TRACE("%s %p %d %p %d %p %d\n",
1876           debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1877           lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1878
1879     pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1880     if (pipe == INVALID_HANDLE_VALUE)
1881     {
1882         ret = WaitNamedPipeW(lpNamedPipeName, nTimeout);
1883         if (!ret)
1884             return FALSE;
1885         pipe = CreateFileW(lpNamedPipeName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
1886         if (pipe == INVALID_HANDLE_VALUE)
1887             return FALSE;
1888     }
1889
1890     mode = PIPE_READMODE_MESSAGE;
1891     ret = SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
1892
1893     /* Currently SetNamedPipeHandleState() is a stub returning FALSE */
1894     if (ret) FIXME("Now that SetNamedPipeHandleState() is more than a stub, please update CallNamedPipeW\n");
1895     /*
1896     if (!ret)
1897     {
1898         CloseHandle(pipe);
1899         return FALSE;
1900     }*/
1901
1902     ret = TransactNamedPipe(pipe, lpInput, lpInputSize, lpOutput, lpOutputSize, lpBytesRead, NULL);
1903     CloseHandle(pipe);
1904     if (!ret)
1905         return FALSE;
1906
1907     return TRUE;
1908 }
1909
1910 /******************************************************************
1911  *              CreatePipe (KERNEL32.@)
1912  *
1913  */
1914 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1915                         LPSECURITY_ATTRIBUTES sa, DWORD size )
1916 {
1917     static unsigned     index /* = 0 */;
1918     WCHAR               name[64];
1919     HANDLE              hr, hw;
1920     unsigned            in_index = index;
1921     UNICODE_STRING      nt_name;
1922     OBJECT_ATTRIBUTES   attr;
1923     NTSTATUS            status;
1924     IO_STATUS_BLOCK     iosb;
1925     LARGE_INTEGER       timeout;
1926
1927     *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1928
1929     attr.Length                   = sizeof(attr);
1930     attr.RootDirectory            = 0;
1931     attr.ObjectName               = &nt_name;
1932     attr.Attributes               = OBJ_CASE_INSENSITIVE |
1933                                     ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1934     attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
1935     attr.SecurityQualityOfService = NULL;
1936
1937     timeout.QuadPart = (ULONGLONG)NMPWAIT_USE_DEFAULT_WAIT * -10000;
1938     /* generate a unique pipe name (system wide) */
1939     do
1940     {
1941         static const WCHAR nameFmt[] = { '\\','?','?','\\','p','i','p','e',
1942          '\\','W','i','n','3','2','.','P','i','p','e','s','.','%','0','8','l',
1943          'u','.','%','0','8','u','\0' };
1944
1945         snprintfW(name, sizeof(name) / sizeof(name[0]), nameFmt,
1946                   GetCurrentProcessId(), ++index);
1947         RtlInitUnicodeString(&nt_name, name);
1948         status = NtCreateNamedPipeFile(&hr, GENERIC_READ | SYNCHRONIZE, &attr, &iosb,
1949                                        0, FILE_OVERWRITE_IF,
1950                                        FILE_SYNCHRONOUS_IO_ALERT | FILE_PIPE_INBOUND,
1951                                        FALSE, FALSE, FALSE, 
1952                                        1, size, size, &timeout);
1953         if (status)
1954         {
1955             SetLastError( RtlNtStatusToDosError(status) );
1956             hr = INVALID_HANDLE_VALUE;
1957         }
1958     } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1959     /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1960     if (hr == INVALID_HANDLE_VALUE) return FALSE;
1961
1962     status = NtOpenFile(&hw, GENERIC_WRITE | SYNCHRONIZE, &attr, &iosb, 0,
1963                         FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE);
1964
1965     if (status) 
1966     {
1967         SetLastError( RtlNtStatusToDosError(status) );
1968         NtClose(hr);
1969         return FALSE;
1970     }
1971
1972     *hReadPipe = hr;
1973     *hWritePipe = hw;
1974     return TRUE;
1975 }
1976
1977
1978 /******************************************************************************
1979  * CreateMailslotA [KERNEL32.@]
1980  *
1981  * See CreateMailslotW.
1982  */
1983 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1984                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1985 {
1986     DWORD len;
1987     HANDLE handle;
1988     LPWSTR name = NULL;
1989
1990     TRACE("%s %d %d %p\n", debugstr_a(lpName),
1991           nMaxMessageSize, lReadTimeout, sa);
1992
1993     if( lpName )
1994     {
1995         len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1996         name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1997         MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1998     }
1999
2000     handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
2001
2002     HeapFree( GetProcessHeap(), 0, name );
2003
2004     return handle;
2005 }
2006
2007
2008 /******************************************************************************
2009  * CreateMailslotW [KERNEL32.@]
2010  *
2011  * Create a mailslot with specified name.
2012  *
2013  * PARAMS
2014  *    lpName          [I] Pointer to string for mailslot name
2015  *    nMaxMessageSize [I] Maximum message size
2016  *    lReadTimeout    [I] Milliseconds before read time-out
2017  *    sa              [I] Pointer to security structure
2018  *
2019  * RETURNS
2020  *    Success: Handle to mailslot
2021  *    Failure: INVALID_HANDLE_VALUE
2022  */
2023 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
2024                                DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
2025 {
2026     HANDLE handle = INVALID_HANDLE_VALUE;
2027     OBJECT_ATTRIBUTES attr;
2028     UNICODE_STRING nameW;
2029     LARGE_INTEGER timeout;
2030     IO_STATUS_BLOCK iosb;
2031     NTSTATUS status;
2032
2033     TRACE("%s %d %d %p\n", debugstr_w(lpName),
2034           nMaxMessageSize, lReadTimeout, sa);
2035
2036     if (!RtlDosPathNameToNtPathName_U( lpName, &nameW, NULL, NULL ))
2037     {
2038         SetLastError( ERROR_PATH_NOT_FOUND );
2039         return INVALID_HANDLE_VALUE;
2040     }
2041
2042     if (nameW.Length >= MAX_PATH * sizeof(WCHAR) )
2043     {
2044         SetLastError( ERROR_FILENAME_EXCED_RANGE );
2045         RtlFreeUnicodeString( &nameW );
2046         return INVALID_HANDLE_VALUE;
2047     }
2048
2049     attr.Length = sizeof(attr);
2050     attr.RootDirectory = 0;
2051     attr.Attributes = OBJ_CASE_INSENSITIVE;
2052     attr.ObjectName = &nameW;
2053     attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
2054     attr.SecurityQualityOfService = NULL;
2055
2056     if (lReadTimeout != MAILSLOT_WAIT_FOREVER)
2057         timeout.QuadPart = (ULONGLONG) lReadTimeout * -10000;
2058     else
2059         timeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
2060
2061     status = NtCreateMailslotFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr,
2062                                    &iosb, 0, 0, nMaxMessageSize, &timeout );
2063     if (status)
2064     {
2065         SetLastError( RtlNtStatusToDosError(status) );
2066         handle = INVALID_HANDLE_VALUE;
2067     }
2068
2069     RtlFreeUnicodeString( &nameW );
2070     return handle;
2071 }
2072
2073
2074 /******************************************************************************
2075  * GetMailslotInfo [KERNEL32.@]
2076  *
2077  * Retrieve information about a mailslot.
2078  *
2079  * PARAMS
2080  *    hMailslot        [I] Mailslot handle
2081  *    lpMaxMessageSize [O] Address of maximum message size
2082  *    lpNextSize       [O] Address of size of next message
2083  *    lpMessageCount   [O] Address of number of messages
2084  *    lpReadTimeout    [O] Address of read time-out
2085  *
2086  * RETURNS
2087  *    Success: TRUE
2088  *    Failure: FALSE
2089  */
2090 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
2091                                LPDWORD lpNextSize, LPDWORD lpMessageCount,
2092                                LPDWORD lpReadTimeout )
2093 {
2094     FILE_MAILSLOT_QUERY_INFORMATION info;
2095     IO_STATUS_BLOCK iosb;
2096     NTSTATUS status;
2097
2098     TRACE("%p %p %p %p %p\n",hMailslot, lpMaxMessageSize,
2099           lpNextSize, lpMessageCount, lpReadTimeout);
2100
2101     status = NtQueryInformationFile( hMailslot, &iosb, &info, sizeof info,
2102                                      FileMailslotQueryInformation );
2103
2104     if( status != STATUS_SUCCESS )
2105     {
2106         SetLastError( RtlNtStatusToDosError(status) );
2107         return FALSE;
2108     }
2109
2110     if( lpMaxMessageSize )
2111         *lpMaxMessageSize = info.MaximumMessageSize;
2112     if( lpNextSize )
2113         *lpNextSize = info.NextMessageSize;
2114     if( lpMessageCount )
2115         *lpMessageCount = info.MessagesAvailable;
2116     if( lpReadTimeout )
2117     {
2118         if (info.ReadTimeout.QuadPart == (((LONGLONG)0x7fffffff << 32) | 0xffffffff))
2119             *lpReadTimeout = MAILSLOT_WAIT_FOREVER;
2120         else
2121             *lpReadTimeout = info.ReadTimeout.QuadPart / -10000;
2122     }
2123     return TRUE;
2124 }
2125
2126
2127 /******************************************************************************
2128  * SetMailslotInfo [KERNEL32.@]
2129  *
2130  * Set the read timeout of a mailslot.
2131  *
2132  * PARAMS
2133  *  hMailslot     [I] Mailslot handle
2134  *  dwReadTimeout [I] Timeout in milliseconds.
2135  *
2136  * RETURNS
2137  *    Success: TRUE
2138  *    Failure: FALSE
2139  */
2140 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
2141 {
2142     FILE_MAILSLOT_SET_INFORMATION info;
2143     IO_STATUS_BLOCK iosb;
2144     NTSTATUS status;
2145
2146     TRACE("%p %d\n", hMailslot, dwReadTimeout);
2147
2148     if (dwReadTimeout != MAILSLOT_WAIT_FOREVER)
2149         info.ReadTimeout.QuadPart = (ULONGLONG)dwReadTimeout * -10000;
2150     else
2151         info.ReadTimeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
2152     status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info,
2153                                    FileMailslotSetInformation );
2154     if( status != STATUS_SUCCESS )
2155     {
2156         SetLastError( RtlNtStatusToDosError(status) );
2157         return FALSE;
2158     }
2159     return TRUE;
2160 }
2161
2162
2163 /******************************************************************************
2164  *              CreateIoCompletionPort (KERNEL32.@)
2165  */
2166 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
2167                                      ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
2168 {
2169     NTSTATUS status;
2170     HANDLE ret = 0;
2171
2172     TRACE("(%p, %p, %08lx, %08x)\n",
2173           hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
2174
2175     if (hExistingCompletionPort && hFileHandle == INVALID_HANDLE_VALUE)
2176     {
2177         SetLastError( ERROR_INVALID_PARAMETER);
2178         return NULL;
2179     }
2180
2181     if (hExistingCompletionPort)
2182         ret = hExistingCompletionPort;
2183     else
2184     {
2185         status = NtCreateIoCompletion( &ret, IO_COMPLETION_ALL_ACCESS, NULL, dwNumberOfConcurrentThreads );
2186         if (status != STATUS_SUCCESS) goto fail;
2187     }
2188
2189     if (hFileHandle != INVALID_HANDLE_VALUE)
2190     {
2191         FILE_COMPLETION_INFORMATION info;
2192         IO_STATUS_BLOCK iosb;
2193
2194         info.CompletionPort = ret;
2195         info.CompletionKey = CompletionKey;
2196         status = NtSetInformationFile( hFileHandle, &iosb, &info, sizeof(info), FileCompletionInformation );
2197         if (status != STATUS_SUCCESS) goto fail;
2198     }
2199
2200     return ret;
2201
2202 fail:
2203     if (ret && !hExistingCompletionPort)
2204         CloseHandle( ret );
2205     SetLastError( RtlNtStatusToDosError(status) );
2206     return 0;
2207 }
2208
2209 /******************************************************************************
2210  *              GetQueuedCompletionStatus (KERNEL32.@)
2211  */
2212 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
2213                                        PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
2214                                        DWORD dwMilliseconds )
2215 {
2216     NTSTATUS status;
2217     IO_STATUS_BLOCK iosb;
2218     LARGE_INTEGER wait_time;
2219
2220     TRACE("(%p,%p,%p,%p,%d)\n",
2221           CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
2222
2223     *lpOverlapped = NULL;
2224
2225     status = NtRemoveIoCompletion( CompletionPort, pCompletionKey, (PULONG_PTR)lpOverlapped,
2226                                    &iosb, get_nt_timeout( &wait_time, dwMilliseconds ) );
2227     if (status == STATUS_SUCCESS)
2228     {
2229         *lpNumberOfBytesTransferred = iosb.Information;
2230         return TRUE;
2231     }
2232
2233     SetLastError( RtlNtStatusToDosError(status) );
2234     return FALSE;
2235 }
2236
2237
2238 /******************************************************************************
2239  *              PostQueuedCompletionStatus (KERNEL32.@)
2240  */
2241 BOOL WINAPI PostQueuedCompletionStatus( HANDLE CompletionPort, DWORD dwNumberOfBytes,
2242                                         ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
2243 {
2244     NTSTATUS status;
2245
2246     TRACE("%p %d %08lx %p\n", CompletionPort, dwNumberOfBytes, dwCompletionKey, lpOverlapped );
2247
2248     status = NtSetIoCompletion( CompletionPort, dwCompletionKey, (ULONG_PTR)lpOverlapped,
2249                                 STATUS_SUCCESS, dwNumberOfBytes );
2250
2251     if (status == STATUS_SUCCESS) return TRUE;
2252     SetLastError( RtlNtStatusToDosError(status) );
2253     return FALSE;
2254 }
2255
2256 /******************************************************************************
2257  *              BindIoCompletionCallback (KERNEL32.@)
2258  */
2259 BOOL WINAPI BindIoCompletionCallback( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags)
2260 {
2261     NTSTATUS status;
2262
2263     TRACE("(%p, %p, %d)\n", FileHandle, Function, Flags);
2264
2265     status = RtlSetIoCompletionCallback( FileHandle, (PRTL_OVERLAPPED_COMPLETION_ROUTINE)Function, Flags );
2266     if (status == STATUS_SUCCESS) return TRUE;
2267     SetLastError( RtlNtStatusToDosError(status) );
2268     return FALSE;
2269 }
2270
2271 #ifdef __i386__
2272
2273 /***********************************************************************
2274  *              InterlockedCompareExchange (KERNEL32.@)
2275  */
2276 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
2277 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
2278                   "movl 12(%esp),%eax\n\t"
2279                   "movl 8(%esp),%ecx\n\t"
2280                   "movl 4(%esp),%edx\n\t"
2281                   "lock; cmpxchgl %ecx,(%edx)\n\t"
2282                   "ret $12")
2283
2284 /***********************************************************************
2285  *              InterlockedExchange (KERNEL32.@)
2286  */
2287 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
2288 __ASM_GLOBAL_FUNC(InterlockedExchange,
2289                   "movl 8(%esp),%eax\n\t"
2290                   "movl 4(%esp),%edx\n\t"
2291                   "lock; xchgl %eax,(%edx)\n\t"
2292                   "ret $8")
2293
2294 /***********************************************************************
2295  *              InterlockedExchangeAdd (KERNEL32.@)
2296  */
2297 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
2298 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
2299                   "movl 8(%esp),%eax\n\t"
2300                   "movl 4(%esp),%edx\n\t"
2301                   "lock; xaddl %eax,(%edx)\n\t"
2302                   "ret $8")
2303
2304 /***********************************************************************
2305  *              InterlockedIncrement (KERNEL32.@)
2306  */
2307 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
2308 __ASM_GLOBAL_FUNC(InterlockedIncrement,
2309                   "movl 4(%esp),%edx\n\t"
2310                   "movl $1,%eax\n\t"
2311                   "lock; xaddl %eax,(%edx)\n\t"
2312                   "incl %eax\n\t"
2313                   "ret $4")
2314
2315 /***********************************************************************
2316  *              InterlockedDecrement (KERNEL32.@)
2317  */
2318 __ASM_GLOBAL_FUNC(InterlockedDecrement,
2319                   "movl 4(%esp),%edx\n\t"
2320                   "movl $-1,%eax\n\t"
2321                   "lock; xaddl %eax,(%edx)\n\t"
2322                   "decl %eax\n\t"
2323                   "ret $4")
2324
2325 #endif  /* __i386__ */