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