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