2 * Kernel synchronization objects
4 * Copyright 1998 Alexandre Julliard
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
35 #ifdef HAVE_SYS_POLL_H
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
44 #define NONAMELESSUNION
45 #define NONAMELESSSTRUCT
48 #define WIN32_NO_STATUS
56 #include "wine/server.h"
57 #include "wine/unicode.h"
58 #include "wine/winbase16.h"
59 #include "kernel_private.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(sync);
65 /* check if current version is NT or Win95 */
66 inline static int is_version_nt(void)
68 return !(GetVersion() & 0x80000000);
72 /***********************************************************************
75 VOID WINAPI Sleep( DWORD timeout )
77 SleepEx( timeout, FALSE );
80 /******************************************************************************
81 * SleepEx (KERNEL32.@)
83 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
87 if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
92 time.QuadPart = timeout * (ULONGLONG)10000;
93 time.QuadPart = -time.QuadPart;
94 status = NtDelayExecution( alertable, &time );
96 if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
101 /***********************************************************************
102 * SwitchToThread (KERNEL32.@)
104 BOOL WINAPI SwitchToThread(void)
106 return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
110 /***********************************************************************
111 * WaitForSingleObject (KERNEL32.@)
113 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
115 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
119 /***********************************************************************
120 * WaitForSingleObjectEx (KERNEL32.@)
122 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
125 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
129 /***********************************************************************
130 * WaitForMultipleObjects (KERNEL32.@)
132 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
133 BOOL wait_all, DWORD timeout )
135 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
139 /***********************************************************************
140 * WaitForMultipleObjectsEx (KERNEL32.@)
142 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
143 BOOL wait_all, DWORD timeout,
147 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
150 if (count >= MAXIMUM_WAIT_OBJECTS)
152 SetLastError(ERROR_INVALID_PARAMETER);
155 for (i = 0; i < count; i++)
157 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
158 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
159 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
160 hloc[i] = GetStdHandle( (DWORD)handles[i] );
162 hloc[i] = handles[i];
164 /* yes, even screen buffer console handles are waitable, and are
165 * handled as a handle to the console itself !!
167 if (is_console_handle(hloc[i]))
169 if (!VerifyConsoleIoHandle(hloc[i]))
173 hloc[i] = GetConsoleInputWaitHandle();
177 if (timeout == INFINITE)
179 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
185 time.QuadPart = timeout * (ULONGLONG)10000;
186 time.QuadPart = -time.QuadPart;
187 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
190 if (HIWORD(status)) /* is it an error code? */
192 SetLastError( RtlNtStatusToDosError(status) );
193 status = WAIT_FAILED;
199 /***********************************************************************
200 * WaitForSingleObject (KERNEL.460)
202 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
204 DWORD retval, mutex_count;
206 ReleaseThunkLock( &mutex_count );
207 retval = WaitForSingleObject( handle, timeout );
208 RestoreThunkLock( mutex_count );
212 /***********************************************************************
213 * WaitForMultipleObjects (KERNEL.461)
215 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
216 BOOL wait_all, DWORD timeout )
218 DWORD retval, mutex_count;
220 ReleaseThunkLock( &mutex_count );
221 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
222 RestoreThunkLock( mutex_count );
226 /***********************************************************************
227 * WaitForMultipleObjectsEx (KERNEL.495)
229 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
230 BOOL wait_all, DWORD timeout, BOOL alertable )
232 DWORD retval, mutex_count;
234 ReleaseThunkLock( &mutex_count );
235 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
236 RestoreThunkLock( mutex_count );
240 /***********************************************************************
241 * RegisterWaitForSingleObject (KERNEL32.@)
243 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
244 WAITORTIMERCALLBACK Callback, PVOID Context,
245 ULONG dwMilliseconds, ULONG dwFlags)
247 FIXME("%p %p %p %p %ld %ld\n",
248 phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
252 /***********************************************************************
253 * RegisterWaitForSingleObjectEx (KERNEL32.@)
255 HANDLE WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject,
256 WAITORTIMERCALLBACK Callback, PVOID Context,
257 ULONG dwMilliseconds, ULONG dwFlags )
259 FIXME("%p %p %p %ld %ld\n",
260 hObject,Callback,Context,dwMilliseconds,dwFlags);
264 /***********************************************************************
265 * UnregisterWait (KERNEL32.@)
267 BOOL WINAPI UnregisterWait( HANDLE WaitHandle )
269 FIXME("%p\n",WaitHandle);
273 /***********************************************************************
274 * UnregisterWaitEx (KERNEL32.@)
276 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
278 FIXME("%p %p\n",WaitHandle, CompletionEvent);
282 /***********************************************************************
283 * SignalObjectAndWait (KERNEL32.@)
285 * Allows to atomically signal any of the synchro objects (semaphore,
286 * mutex, event) and wait on another.
288 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn,
289 DWORD dwMilliseconds, BOOL bAlertable )
292 LARGE_INTEGER timeout, *ptimeout = NULL;
294 TRACE("%p %p %ld %d\n", hObjectToSignal,
295 hObjectToWaitOn, dwMilliseconds, bAlertable);
297 if (dwMilliseconds != INFINITE)
299 timeout.QuadPart = dwMilliseconds * (ULONGLONG)10000;
300 timeout.QuadPart = -timeout.QuadPart;
304 status = NtSignalAndWaitForSingleObject( hObjectToSignal, hObjectToWaitOn,
305 bAlertable, ptimeout );
308 SetLastError( RtlNtStatusToDosError(status) );
309 status = WAIT_FAILED;
314 /***********************************************************************
315 * InitializeCriticalSection (KERNEL32.@)
317 * Initialise a critical section before use.
320 * crit [O] Critical section to initialise.
323 * Nothing. If the function fails an exception is raised.
325 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
327 NTSTATUS ret = RtlInitializeCriticalSection( crit );
328 if (ret) RtlRaiseStatus( ret );
331 /***********************************************************************
332 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
334 * Initialise a critical section with a spin count.
337 * crit [O] Critical section to initialise.
338 * spincount [I] Number of times to spin upon contention.
342 * Failure: Nothing. If the function fails an exception is raised.
345 * spincount is ignored on uni-processor systems.
347 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
349 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
350 if (ret) RtlRaiseStatus( ret );
354 /***********************************************************************
355 * MakeCriticalSectionGlobal (KERNEL32.@)
357 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
359 /* let's assume that only one thread at a time will try to do this */
360 HANDLE sem = crit->LockSemaphore;
361 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
362 crit->LockSemaphore = ConvertToGlobalHandle( sem );
365 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
366 crit->DebugInfo = NULL;
371 /***********************************************************************
372 * ReinitializeCriticalSection (KERNEL32.@)
374 * Initialise an already used critical section.
377 * crit [O] Critical section to initialise.
382 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
384 if ( !crit->LockSemaphore )
385 RtlInitializeCriticalSection( crit );
389 /***********************************************************************
390 * UninitializeCriticalSection (KERNEL32.@)
392 * UnInitialise a critical section after use.
395 * crit [O] Critical section to uninitialise (destroy).
400 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
402 RtlDeleteCriticalSection( crit );
406 /***********************************************************************
407 * CreateEventA (KERNEL32.@)
409 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
410 BOOL initial_state, LPCSTR name )
412 WCHAR buffer[MAX_PATH];
414 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
416 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
418 SetLastError( ERROR_FILENAME_EXCED_RANGE );
421 return CreateEventW( sa, manual_reset, initial_state, buffer );
425 /***********************************************************************
426 * CreateEventW (KERNEL32.@)
428 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
429 BOOL initial_state, LPCWSTR name )
432 UNICODE_STRING nameW;
433 OBJECT_ATTRIBUTES attr;
436 /* one buggy program needs this
437 * ("Van Dale Groot woordenboek der Nederlandse taal")
439 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
441 ERR("Bad security attributes pointer %p\n",sa);
442 SetLastError( ERROR_INVALID_PARAMETER);
446 attr.Length = sizeof(attr);
447 attr.RootDirectory = 0;
448 attr.ObjectName = NULL;
449 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
450 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
451 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
452 attr.SecurityQualityOfService = NULL;
455 RtlInitUnicodeString( &nameW, name );
456 attr.ObjectName = &nameW;
459 status = NtCreateEvent( &ret, EVENT_ALL_ACCESS, &attr, manual_reset, initial_state );
460 if (status == STATUS_OBJECT_NAME_EXISTS)
461 SetLastError( ERROR_ALREADY_EXISTS );
463 SetLastError( RtlNtStatusToDosError(status) );
468 /***********************************************************************
469 * CreateW32Event (KERNEL.457)
471 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
473 return CreateEventW( NULL, manual_reset, initial_state, NULL );
477 /***********************************************************************
478 * OpenEventA (KERNEL32.@)
480 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
482 WCHAR buffer[MAX_PATH];
484 if (!name) return OpenEventW( access, inherit, NULL );
486 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
488 SetLastError( ERROR_FILENAME_EXCED_RANGE );
491 return OpenEventW( access, inherit, buffer );
495 /***********************************************************************
496 * OpenEventW (KERNEL32.@)
498 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
501 UNICODE_STRING nameW;
502 OBJECT_ATTRIBUTES attr;
505 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
507 attr.Length = sizeof(attr);
508 attr.RootDirectory = 0;
509 attr.ObjectName = NULL;
510 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
511 attr.SecurityDescriptor = NULL;
512 attr.SecurityQualityOfService = NULL;
515 RtlInitUnicodeString( &nameW, name );
516 attr.ObjectName = &nameW;
519 status = NtOpenEvent( &ret, access, &attr );
520 if (status != STATUS_SUCCESS)
522 SetLastError( RtlNtStatusToDosError(status) );
528 /***********************************************************************
529 * PulseEvent (KERNEL32.@)
531 BOOL WINAPI PulseEvent( HANDLE handle )
535 if ((status = NtPulseEvent( handle, NULL )))
536 SetLastError( RtlNtStatusToDosError(status) );
541 /***********************************************************************
542 * SetW32Event (KERNEL.458)
543 * SetEvent (KERNEL32.@)
545 BOOL WINAPI SetEvent( HANDLE handle )
549 if ((status = NtSetEvent( handle, NULL )))
550 SetLastError( RtlNtStatusToDosError(status) );
555 /***********************************************************************
556 * ResetW32Event (KERNEL.459)
557 * ResetEvent (KERNEL32.@)
559 BOOL WINAPI ResetEvent( HANDLE handle )
563 if ((status = NtResetEvent( handle, NULL )))
564 SetLastError( RtlNtStatusToDosError(status) );
569 /***********************************************************************
570 * NOTE: The Win95 VWin32_Event routines given below are really low-level
571 * routines implemented directly by VWin32. The user-mode libraries
572 * implement Win32 synchronisation routines on top of these low-level
573 * primitives. We do it the other way around here :-)
576 /***********************************************************************
577 * VWin32_EventCreate (KERNEL.442)
579 HANDLE WINAPI VWin32_EventCreate(VOID)
581 HANDLE hEvent = CreateEventW( NULL, FALSE, 0, NULL );
582 return ConvertToGlobalHandle( hEvent );
585 /***********************************************************************
586 * VWin32_EventDestroy (KERNEL.443)
588 VOID WINAPI VWin32_EventDestroy(HANDLE event)
590 CloseHandle( event );
593 /***********************************************************************
594 * VWin32_EventWait (KERNEL.450)
596 VOID WINAPI VWin32_EventWait(HANDLE event)
600 ReleaseThunkLock( &mutex_count );
601 WaitForSingleObject( event, INFINITE );
602 RestoreThunkLock( mutex_count );
605 /***********************************************************************
606 * VWin32_EventSet (KERNEL.451)
607 * KERNEL_479 (KERNEL.479)
609 VOID WINAPI VWin32_EventSet(HANDLE event)
616 /***********************************************************************
617 * CreateMutexA (KERNEL32.@)
619 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
621 WCHAR buffer[MAX_PATH];
623 if (!name) return CreateMutexW( sa, owner, NULL );
625 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
627 SetLastError( ERROR_FILENAME_EXCED_RANGE );
630 return CreateMutexW( sa, owner, buffer );
634 /***********************************************************************
635 * CreateMutexW (KERNEL32.@)
637 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
640 UNICODE_STRING nameW;
641 OBJECT_ATTRIBUTES attr;
644 attr.Length = sizeof(attr);
645 attr.RootDirectory = 0;
646 attr.ObjectName = NULL;
647 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
648 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
649 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
650 attr.SecurityQualityOfService = NULL;
653 RtlInitUnicodeString( &nameW, name );
654 attr.ObjectName = &nameW;
657 status = NtCreateMutant( &ret, MUTEX_ALL_ACCESS, &attr, owner );
658 if (status == STATUS_OBJECT_NAME_EXISTS)
659 SetLastError( ERROR_ALREADY_EXISTS );
661 SetLastError( RtlNtStatusToDosError(status) );
666 /***********************************************************************
667 * OpenMutexA (KERNEL32.@)
669 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
671 WCHAR buffer[MAX_PATH];
673 if (!name) return OpenMutexW( access, inherit, NULL );
675 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
677 SetLastError( ERROR_FILENAME_EXCED_RANGE );
680 return OpenMutexW( access, inherit, buffer );
684 /***********************************************************************
685 * OpenMutexW (KERNEL32.@)
687 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
690 UNICODE_STRING nameW;
691 OBJECT_ATTRIBUTES attr;
694 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
696 attr.Length = sizeof(attr);
697 attr.RootDirectory = 0;
698 attr.ObjectName = NULL;
699 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
700 attr.SecurityDescriptor = NULL;
701 attr.SecurityQualityOfService = NULL;
704 RtlInitUnicodeString( &nameW, name );
705 attr.ObjectName = &nameW;
708 status = NtOpenMutant( &ret, access, &attr );
709 if (status != STATUS_SUCCESS)
711 SetLastError( RtlNtStatusToDosError(status) );
718 /***********************************************************************
719 * ReleaseMutex (KERNEL32.@)
721 BOOL WINAPI ReleaseMutex( HANDLE handle )
725 status = NtReleaseMutant(handle, NULL);
726 if (status != STATUS_SUCCESS)
728 SetLastError( RtlNtStatusToDosError(status) );
740 /***********************************************************************
741 * CreateSemaphoreA (KERNEL32.@)
743 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
745 WCHAR buffer[MAX_PATH];
747 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
749 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
751 SetLastError( ERROR_FILENAME_EXCED_RANGE );
754 return CreateSemaphoreW( sa, initial, max, buffer );
758 /***********************************************************************
759 * CreateSemaphoreW (KERNEL32.@)
761 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
762 LONG max, LPCWSTR name )
765 UNICODE_STRING nameW;
766 OBJECT_ATTRIBUTES attr;
769 attr.Length = sizeof(attr);
770 attr.RootDirectory = 0;
771 attr.ObjectName = NULL;
772 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
773 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
774 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
775 attr.SecurityQualityOfService = NULL;
778 RtlInitUnicodeString( &nameW, name );
779 attr.ObjectName = &nameW;
782 status = NtCreateSemaphore( &ret, SEMAPHORE_ALL_ACCESS, &attr, initial, max );
783 if (status == STATUS_OBJECT_NAME_EXISTS)
784 SetLastError( ERROR_ALREADY_EXISTS );
786 SetLastError( RtlNtStatusToDosError(status) );
791 /***********************************************************************
792 * OpenSemaphoreA (KERNEL32.@)
794 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
796 WCHAR buffer[MAX_PATH];
798 if (!name) return OpenSemaphoreW( access, inherit, NULL );
800 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
802 SetLastError( ERROR_FILENAME_EXCED_RANGE );
805 return OpenSemaphoreW( access, inherit, buffer );
809 /***********************************************************************
810 * OpenSemaphoreW (KERNEL32.@)
812 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
815 UNICODE_STRING nameW;
816 OBJECT_ATTRIBUTES attr;
819 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
821 attr.Length = sizeof(attr);
822 attr.RootDirectory = 0;
823 attr.ObjectName = NULL;
824 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
825 attr.SecurityDescriptor = NULL;
826 attr.SecurityQualityOfService = NULL;
829 RtlInitUnicodeString( &nameW, name );
830 attr.ObjectName = &nameW;
833 status = NtOpenSemaphore( &ret, access, &attr );
834 if (status != STATUS_SUCCESS)
836 SetLastError( RtlNtStatusToDosError(status) );
843 /***********************************************************************
844 * ReleaseSemaphore (KERNEL32.@)
846 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
848 NTSTATUS status = NtReleaseSemaphore( handle, count, (PULONG)previous );
849 if (status) SetLastError( RtlNtStatusToDosError(status) );
859 /***********************************************************************
860 * CreateWaitableTimerA (KERNEL32.@)
862 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
864 WCHAR buffer[MAX_PATH];
866 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
868 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
870 SetLastError( ERROR_FILENAME_EXCED_RANGE );
873 return CreateWaitableTimerW( sa, manual, buffer );
877 /***********************************************************************
878 * CreateWaitableTimerW (KERNEL32.@)
880 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
884 UNICODE_STRING nameW;
885 OBJECT_ATTRIBUTES attr;
887 attr.Length = sizeof(attr);
888 attr.RootDirectory = 0;
889 attr.ObjectName = NULL;
890 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
891 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
892 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
893 attr.SecurityQualityOfService = NULL;
896 RtlInitUnicodeString( &nameW, name );
897 attr.ObjectName = &nameW;
900 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &attr,
901 manual ? NotificationTimer : SynchronizationTimer);
902 if (status == STATUS_OBJECT_NAME_EXISTS)
903 SetLastError( ERROR_ALREADY_EXISTS );
905 SetLastError( RtlNtStatusToDosError(status) );
910 /***********************************************************************
911 * OpenWaitableTimerA (KERNEL32.@)
913 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
915 WCHAR buffer[MAX_PATH];
917 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
919 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
921 SetLastError( ERROR_FILENAME_EXCED_RANGE );
924 return OpenWaitableTimerW( access, inherit, buffer );
928 /***********************************************************************
929 * OpenWaitableTimerW (KERNEL32.@)
931 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
934 UNICODE_STRING nameW;
935 OBJECT_ATTRIBUTES attr;
938 if (!is_version_nt()) access = TIMER_ALL_ACCESS;
940 attr.Length = sizeof(attr);
941 attr.RootDirectory = 0;
942 attr.ObjectName = NULL;
943 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
944 attr.SecurityDescriptor = NULL;
945 attr.SecurityQualityOfService = NULL;
948 RtlInitUnicodeString( &nameW, name );
949 attr.ObjectName = &nameW;
952 status = NtOpenTimer(&handle, access, &attr);
953 if (status != STATUS_SUCCESS)
955 SetLastError( RtlNtStatusToDosError(status) );
962 /***********************************************************************
963 * SetWaitableTimer (KERNEL32.@)
965 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
966 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
968 NTSTATUS status = NtSetTimer(handle, when, (PTIMER_APC_ROUTINE)callback,
969 arg, resume, period, NULL);
971 if (status != STATUS_SUCCESS)
973 SetLastError( RtlNtStatusToDosError(status) );
974 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
980 /***********************************************************************
981 * CancelWaitableTimer (KERNEL32.@)
983 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
987 status = NtCancelTimer(handle, NULL);
988 if (status != STATUS_SUCCESS)
990 SetLastError( RtlNtStatusToDosError(status) );
997 /***********************************************************************
998 * CreateTimerQueue (KERNEL32.@)
1000 HANDLE WINAPI CreateTimerQueue(void)
1003 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1008 /***********************************************************************
1009 * DeleteTimerQueueEx (KERNEL32.@)
1011 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
1013 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
1014 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1018 /***********************************************************************
1019 * CreateTimerQueueTimer (KERNEL32.@)
1021 * Creates a timer-queue timer. This timer expires at the specified due
1022 * time (in ms), then after every specified period (in ms). When the timer
1023 * expires, the callback function is called.
1026 * nonzero on success or zero on faillure
1031 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
1032 WAITORTIMERCALLBACK Callback, PVOID Parameter,
1033 DWORD DueTime, DWORD Period, ULONG Flags )
1036 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1040 /***********************************************************************
1041 * DeleteTimerQueueTimer (KERNEL32.@)
1043 * Cancels a timer-queue timer.
1046 * nonzero on success or zero on faillure
1051 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1052 HANDLE CompletionEvent )
1055 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1065 /***********************************************************************
1066 * CreateNamedPipeA (KERNEL32.@)
1068 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1069 DWORD dwPipeMode, DWORD nMaxInstances,
1070 DWORD nOutBufferSize, DWORD nInBufferSize,
1071 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1073 WCHAR buffer[MAX_PATH];
1075 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1076 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1078 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1080 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1081 return INVALID_HANDLE_VALUE;
1083 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1084 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1088 /***********************************************************************
1089 * CreateNamedPipeW (KERNEL32.@)
1091 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1092 DWORD dwPipeMode, DWORD nMaxInstances,
1093 DWORD nOutBufferSize, DWORD nInBufferSize,
1094 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES sa )
1097 UNICODE_STRING nt_name;
1098 OBJECT_ATTRIBUTES attr;
1100 BOOLEAN pipe_type, read_mode, non_block;
1102 IO_STATUS_BLOCK iosb;
1103 LARGE_INTEGER timeout;
1105 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1106 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1107 nOutBufferSize, nInBufferSize, nDefaultTimeOut, sa );
1109 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1111 SetLastError( ERROR_PATH_NOT_FOUND );
1112 return INVALID_HANDLE_VALUE;
1114 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1116 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1117 RtlFreeUnicodeString( &nt_name );
1118 return INVALID_HANDLE_VALUE;
1121 attr.Length = sizeof(attr);
1122 attr.RootDirectory = 0;
1123 attr.ObjectName = &nt_name;
1124 attr.Attributes = OBJ_CASE_INSENSITIVE |
1125 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1126 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
1127 attr.SecurityQualityOfService = NULL;
1130 if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) options |= FILE_WRITE_THROUGH;
1131 if (!(dwOpenMode & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_ALERT;
1132 if ((dwOpenMode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
1133 options |= FILE_PIPE_FULL_DUPLEX;
1134 else if (dwOpenMode & PIPE_ACCESS_INBOUND) options |= FILE_PIPE_INBOUND;
1135 else if (dwOpenMode & PIPE_ACCESS_OUTBOUND) options |= FILE_PIPE_OUTBOUND;
1136 pipe_type = (dwPipeMode & PIPE_TYPE_MESSAGE) ? TRUE : FALSE;
1137 read_mode = (dwPipeMode & PIPE_READMODE_MESSAGE) ? TRUE : FALSE;
1138 non_block = (dwPipeMode & PIPE_NOWAIT) ? TRUE : FALSE;
1139 if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) nMaxInstances = ~0UL;
1141 timeout.QuadPart = (ULONGLONG)nDefaultTimeOut * -10000;
1145 status = NtCreateNamedPipeFile(&handle, GENERIC_READ|GENERIC_WRITE, &attr, &iosb,
1146 0, FILE_OVERWRITE_IF, options, pipe_type,
1147 read_mode, non_block, nMaxInstances,
1148 nInBufferSize, nOutBufferSize, &timeout);
1150 RtlFreeUnicodeString( &nt_name );
1153 handle = INVALID_HANDLE_VALUE;
1154 SetLastError( RtlNtStatusToDosError(status) );
1160 /***********************************************************************
1161 * PeekNamedPipe (KERNEL32.@)
1163 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1164 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1167 int avail=0, fd, ret, flags;
1169 TRACE("(%p,%p,%lu,%p,%p,%p)\n", hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage);
1171 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, &flags );
1174 SetLastError( RtlNtStatusToDosError(ret) );
1177 if (flags & FD_FLAG_RECV_SHUTDOWN)
1179 wine_server_release_fd( hPipe, fd );
1180 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1184 if (ioctl(fd,FIONREAD, &avail ) != 0)
1186 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1187 wine_server_release_fd( hPipe, fd );
1190 if (!avail) /* check for closed pipe */
1192 struct pollfd pollfd;
1194 pollfd.events = POLLIN;
1196 switch (poll( &pollfd, 1, 0 ))
1200 case 1: /* got something */
1201 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1202 TRACE("POLLHUP | POLLERR\n");
1205 wine_server_release_fd( hPipe, fd );
1206 SetLastError(ERROR_BROKEN_PIPE);
1210 TRACE(" 0x%08x bytes available\n", avail );
1216 if (avail && lpvBuffer && cbBuffer)
1218 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1219 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1222 WARN("failed to peek socket (%d)\n", errno);
1226 *lpcbRead = readbytes;
1228 wine_server_release_fd( hPipe, fd );
1230 #endif /* defined(FIONREAD) */
1232 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1233 FIXME("function not implemented\n");
1237 /***********************************************************************
1238 * PIPE_CompletionWait (Internal)
1240 static void CALLBACK PIPE_CompletionWait(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
1242 LPOVERLAPPED ovlp = (LPOVERLAPPED)user;
1244 TRACE("for %p/%p, status=%08lx\n", ovlp, iosb, status);
1248 ovlp->Internal = status;
1249 SetEvent(ovlp->hEvent);
1254 /***********************************************************************
1255 * WaitNamedPipeA (KERNEL32.@)
1257 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1259 WCHAR buffer[MAX_PATH];
1261 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1263 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1265 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1268 return WaitNamedPipeW( buffer, nTimeOut );
1272 /***********************************************************************
1273 * WaitNamedPipeW (KERNEL32.@)
1275 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1279 UNICODE_STRING nt_name;
1280 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1282 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1284 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1287 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1289 RtlFreeUnicodeString( &nt_name );
1292 if (nt_name.Length < sizeof(leadin) ||
1293 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1295 RtlFreeUnicodeString( &nt_name );
1299 memset(&ov,0,sizeof(ov));
1300 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1304 SERVER_START_REQ( wait_named_pipe )
1306 req->timeout = nTimeOut;
1307 req->overlapped = &ov;
1308 req->func = PIPE_CompletionWait;
1309 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1310 ret = !wine_server_call_err( req );
1314 RtlFreeUnicodeString( &nt_name );
1318 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1320 SetLastError(RtlNtStatusToDosError(ov.Internal));
1321 ret = (ov.Internal==STATUS_SUCCESS);
1324 CloseHandle(ov.hEvent);
1329 /***********************************************************************
1330 * ConnectNamedPipe (KERNEL32.@)
1332 * Connects to a named pipe
1335 * hPipe: A handle to a named pipe returned by CreateNamedPipe
1336 * overlapped: Optional OVERLAPPED struct
1340 * FALSE: Failure, GetLastError can be called for further details
1342 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1345 IO_STATUS_BLOCK status_block;
1347 TRACE("(%p,%p)\n", hPipe, overlapped);
1350 overlapped->Internal = STATUS_PENDING;
1352 status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, NULL,
1353 overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block,
1354 FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0);
1356 if (status == STATUS_SUCCESS) return TRUE;
1357 SetLastError( RtlNtStatusToDosError(status) );
1361 /***********************************************************************
1362 * DisconnectNamedPipe (KERNEL32.@)
1364 * Disconnects from a named pipe
1367 * hPipe: A handle to a named pipe returned by CreateNamedPipe
1371 * FALSE: Failure, GetLastError can be called for further details
1373 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1376 IO_STATUS_BLOCK io_block;
1378 TRACE("(%p)\n",hPipe);
1380 status = NtFsControlFile(hPipe, 0, NULL, NULL, &io_block, FSCTL_PIPE_DISCONNECT,
1382 if (status == STATUS_SUCCESS) return TRUE;
1383 SetLastError( RtlNtStatusToDosError(status) );
1387 /***********************************************************************
1388 * TransactNamedPipe (KERNEL32.@)
1391 * should be done as a single operation in the wineserver or kernel
1393 BOOL WINAPI TransactNamedPipe(
1394 HANDLE handle, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1395 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1400 TRACE("%p %p %ld %p %ld %p %p\n",
1401 handle, lpInput, dwInputSize, lpOutput,
1402 dwOutputSize, lpBytesRead, lpOverlapped);
1406 FIXME("Doesn't support overlapped operation as yet\n");
1410 r = WriteFile(handle, lpOutput, dwOutputSize, &count, NULL);
1412 r = ReadFile(handle, lpInput, dwInputSize, lpBytesRead, NULL);
1417 /***********************************************************************
1418 * GetNamedPipeInfo (KERNEL32.@)
1420 BOOL WINAPI GetNamedPipeInfo(
1421 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1422 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1426 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1427 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1429 SERVER_START_REQ( get_named_pipe_info )
1431 req->handle = hNamedPipe;
1432 ret = !wine_server_call_err( req );
1436 if (reply->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
1437 *lpFlags |= PIPE_TYPE_MESSAGE;
1438 if (reply->flags & NAMED_PIPE_MESSAGE_STREAM_READ)
1439 *lpFlags |= PIPE_READMODE_MESSAGE;
1440 if (reply->flags & NAMED_PIPE_NONBLOCKING_MODE)
1441 *lpFlags |= PIPE_NOWAIT;
1443 if (lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1444 if (lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1445 if (lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1452 /***********************************************************************
1453 * GetNamedPipeHandleStateA (KERNEL32.@)
1455 BOOL WINAPI GetNamedPipeHandleStateA(
1456 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1457 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1458 LPSTR lpUsername, DWORD nUsernameMaxSize)
1460 FIXME("%p %p %p %p %p %p %ld\n",
1461 hNamedPipe, lpState, lpCurInstances,
1462 lpMaxCollectionCount, lpCollectDataTimeout,
1463 lpUsername, nUsernameMaxSize);
1468 /***********************************************************************
1469 * GetNamedPipeHandleStateW (KERNEL32.@)
1471 BOOL WINAPI GetNamedPipeHandleStateW(
1472 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1473 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1474 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1476 FIXME("%p %p %p %p %p %p %ld\n",
1477 hNamedPipe, lpState, lpCurInstances,
1478 lpMaxCollectionCount, lpCollectDataTimeout,
1479 lpUsername, nUsernameMaxSize);
1484 /***********************************************************************
1485 * SetNamedPipeHandleState (KERNEL32.@)
1487 BOOL WINAPI SetNamedPipeHandleState(
1488 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1489 LPDWORD lpCollectDataTimeout)
1491 /* should be a fixme, but this function is called a lot by the RPC
1492 * runtime, and it slows down InstallShield a fair bit. */
1493 WARN("stub: %p %p/%ld %p %p\n",
1494 hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
1498 /***********************************************************************
1499 * CallNamedPipeA (KERNEL32.@)
1501 BOOL WINAPI CallNamedPipeA(
1502 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1503 LPVOID lpOutput, DWORD dwOutputSize,
1504 LPDWORD lpBytesRead, DWORD nTimeout)
1510 TRACE("%s %p %ld %p %ld %p %ld\n",
1511 debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1512 lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1514 if( lpNamedPipeName )
1516 len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1517 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1518 MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1520 ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1521 dwOutputSize, lpBytesRead, nTimeout );
1522 if( lpNamedPipeName )
1523 HeapFree( GetProcessHeap(), 0, str );
1528 /***********************************************************************
1529 * CallNamedPipeW (KERNEL32.@)
1531 BOOL WINAPI CallNamedPipeW(
1532 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1533 LPVOID lpOutput, DWORD lpOutputSize,
1534 LPDWORD lpBytesRead, DWORD nTimeout)
1536 FIXME("%s %p %ld %p %ld %p %ld\n",
1537 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1538 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1542 /******************************************************************
1543 * CreatePipe (KERNEL32.@)
1546 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1547 LPSECURITY_ATTRIBUTES sa, DWORD size )
1549 static unsigned index /* = 0 */;
1552 unsigned in_index = index;
1553 UNICODE_STRING nt_name;
1554 OBJECT_ATTRIBUTES attr;
1556 IO_STATUS_BLOCK iosb;
1557 LARGE_INTEGER timeout;
1559 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1561 attr.Length = sizeof(attr);
1562 attr.RootDirectory = 0;
1563 attr.ObjectName = &nt_name;
1564 attr.Attributes = OBJ_CASE_INSENSITIVE |
1565 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
1566 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
1567 attr.SecurityQualityOfService = NULL;
1569 timeout.QuadPart = (ULONGLONG)NMPWAIT_USE_DEFAULT_WAIT * -10000;
1570 /* generate a unique pipe name (system wide) */
1573 static const WCHAR nameFmt[] = { '\\','?','?','\\','p','i','p','e',
1574 '\\','W','i','n','3','2','.','P','i','p','e','s','.','%','0','8','l',
1575 'u','.','%','0','8','u','\0' };
1577 snprintfW(name, sizeof(name) / sizeof(name[0]), nameFmt,
1578 GetCurrentProcessId(), ++index);
1579 RtlInitUnicodeString(&nt_name, name);
1580 status = NtCreateNamedPipeFile(&hr, GENERIC_READ | SYNCHRONIZE, &attr, &iosb,
1581 0, FILE_OVERWRITE_IF,
1582 FILE_SYNCHRONOUS_IO_ALERT | FILE_PIPE_INBOUND,
1583 FALSE, FALSE, FALSE,
1584 1, size, size, &timeout);
1587 SetLastError( RtlNtStatusToDosError(status) );
1588 hr = INVALID_HANDLE_VALUE;
1590 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1591 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1592 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1594 status = NtOpenFile(&hw, GENERIC_WRITE | SYNCHRONIZE, &attr, &iosb, 0,
1595 FILE_SYNCHRONOUS_IO_ALERT | FILE_NON_DIRECTORY_FILE);
1599 SetLastError( RtlNtStatusToDosError(status) );
1610 /******************************************************************************
1611 * CreateMailslotA [KERNEL32.@]
1613 * See CreatMailslotW.
1615 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1616 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1622 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1623 nMaxMessageSize, lReadTimeout, sa);
1627 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1628 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1629 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1632 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1634 HeapFree( GetProcessHeap(), 0, name );
1640 /******************************************************************************
1641 * CreateMailslotW [KERNEL32.@]
1643 * Create a mailslot with specified name.
1646 * lpName [I] Pointer to string for mailslot name
1647 * nMaxMessageSize [I] Maximum message size
1648 * lReadTimeout [I] Milliseconds before read time-out
1649 * sa [I] Pointer to security structure
1652 * Success: Handle to mailslot
1653 * Failure: INVALID_HANDLE_VALUE
1655 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1656 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1658 HANDLE handle = INVALID_HANDLE_VALUE;
1659 OBJECT_ATTRIBUTES attr;
1660 UNICODE_STRING nameW;
1661 LARGE_INTEGER timeout;
1662 IO_STATUS_BLOCK iosb;
1665 TRACE("%s %ld %ld %p\n", debugstr_w(lpName),
1666 nMaxMessageSize, lReadTimeout, sa);
1668 if (!RtlDosPathNameToNtPathName_U( lpName, &nameW, NULL, NULL ))
1670 SetLastError( ERROR_PATH_NOT_FOUND );
1671 return INVALID_HANDLE_VALUE;
1674 if (nameW.Length >= MAX_PATH * sizeof(WCHAR) )
1676 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1677 RtlFreeUnicodeString( &nameW );
1678 return INVALID_HANDLE_VALUE;
1681 attr.Length = sizeof(attr);
1682 attr.RootDirectory = 0;
1683 attr.Attributes = OBJ_CASE_INSENSITIVE;
1684 attr.ObjectName = &nameW;
1685 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
1686 attr.SecurityQualityOfService = NULL;
1688 if (lReadTimeout != MAILSLOT_WAIT_FOREVER)
1689 timeout.QuadPart = (ULONGLONG) lReadTimeout * -10000;
1691 timeout.QuadPart = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
1693 status = NtCreateMailslotFile( &handle, GENERIC_READ | GENERIC_WRITE, &attr,
1694 &iosb, 0, 0, nMaxMessageSize, &timeout );
1697 SetLastError( RtlNtStatusToDosError(status) );
1698 handle = INVALID_HANDLE_VALUE;
1701 RtlFreeUnicodeString( &nameW );
1706 /******************************************************************************
1707 * GetMailslotInfo [KERNEL32.@]
1709 * Retrieve information about a mailslot.
1712 * hMailslot [I] Mailslot handle
1713 * lpMaxMessageSize [O] Address of maximum message size
1714 * lpNextSize [O] Address of size of next message
1715 * lpMessageCount [O] Address of number of messages
1716 * lpReadTimeout [O] Address of read time-out
1722 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1723 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1724 LPDWORD lpReadTimeout )
1726 FILE_MAILSLOT_QUERY_INFORMATION info;
1727 IO_STATUS_BLOCK iosb;
1730 TRACE("%p %p %p %p %p\n",hMailslot, lpMaxMessageSize,
1731 lpNextSize, lpMessageCount, lpReadTimeout);
1733 status = NtQueryInformationFile( hMailslot, &iosb, &info, sizeof info,
1734 FileMailslotQueryInformation );
1736 if( status != STATUS_SUCCESS )
1738 SetLastError( RtlNtStatusToDosError(status) );
1742 if( lpMaxMessageSize )
1743 *lpMaxMessageSize = info.MaximumMessageSize;
1745 *lpNextSize = info.NextMessageSize;
1746 if( lpMessageCount )
1747 *lpMessageCount = info.MessagesAvailable;
1749 *lpReadTimeout = info.ReadTimeout.QuadPart / -10000;
1755 /******************************************************************************
1756 * SetMailslotInfo [KERNEL32.@]
1758 * Set the read timeout of a mailslot.
1761 * hMailslot [I] Mailslot handle
1762 * dwReadTimeout [I] Timeout in milliseconds.
1768 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1770 FILE_MAILSLOT_SET_INFORMATION info;
1771 IO_STATUS_BLOCK iosb;
1774 TRACE("%p %ld\n", hMailslot, dwReadTimeout);
1776 info.ReadTimeout.QuadPart = dwReadTimeout * -10000;
1777 status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info,
1778 FileMailslotSetInformation );
1779 if( status != STATUS_SUCCESS )
1781 SetLastError( RtlNtStatusToDosError(status) );
1788 /******************************************************************************
1789 * CreateIoCompletionPort (KERNEL32.@)
1791 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1792 ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
1794 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1795 hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
1800 /******************************************************************************
1801 * GetQueuedCompletionStatus (KERNEL32.@)
1803 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1804 PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
1805 DWORD dwMilliseconds )
1807 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1808 CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
1809 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1813 /******************************************************************************
1814 * CreateJobObjectW (KERNEL32.@)
1816 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1818 FIXME("%p %s\n", attr, debugstr_w(name) );
1819 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1823 /******************************************************************************
1824 * CreateJobObjectA (KERNEL32.@)
1826 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1832 TRACE("%p %s\n", attr, debugstr_a(name) );
1836 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1837 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1840 SetLastError( ERROR_OUTOFMEMORY );
1843 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1846 r = CreateJobObjectW( attr, str );
1848 HeapFree( GetProcessHeap(), 0, str );
1853 /******************************************************************************
1854 * AssignProcessToJobObject (KERNEL32.@)
1856 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1858 FIXME("%p %p\n", hJob, hProcess);
1864 /***********************************************************************
1865 * InterlockedCompareExchange (KERNEL32.@)
1867 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1868 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1869 "movl 12(%esp),%eax\n\t"
1870 "movl 8(%esp),%ecx\n\t"
1871 "movl 4(%esp),%edx\n\t"
1872 "lock; cmpxchgl %ecx,(%edx)\n\t"
1875 /***********************************************************************
1876 * InterlockedExchange (KERNEL32.@)
1878 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1879 __ASM_GLOBAL_FUNC(InterlockedExchange,
1880 "movl 8(%esp),%eax\n\t"
1881 "movl 4(%esp),%edx\n\t"
1882 "lock; xchgl %eax,(%edx)\n\t"
1885 /***********************************************************************
1886 * InterlockedExchangeAdd (KERNEL32.@)
1888 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1889 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1890 "movl 8(%esp),%eax\n\t"
1891 "movl 4(%esp),%edx\n\t"
1892 "lock; xaddl %eax,(%edx)\n\t"
1895 /***********************************************************************
1896 * InterlockedIncrement (KERNEL32.@)
1898 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1899 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1900 "movl 4(%esp),%edx\n\t"
1902 "lock; xaddl %eax,(%edx)\n\t"
1906 /***********************************************************************
1907 * InterlockedDecrement (KERNEL32.@)
1909 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1910 "movl 4(%esp),%edx\n\t"
1912 "lock; xaddl %eax,(%edx)\n\t"
1916 #else /* __i386__ */
1918 /***********************************************************************
1919 * InterlockedCompareExchange (KERNEL32.@)
1921 * Atomically swap one value with another.
1924 * dest [I/O] The value to replace
1925 * xchq [I] The value to be swapped
1926 * compare [I] The value to compare to dest
1929 * The resulting value of dest.
1932 * dest is updated only if it is equal to compare, otherwise no swap is done.
1934 LONG WINAPI InterlockedCompareExchange( LONG volatile *dest, LONG xchg, LONG compare )
1936 return interlocked_cmpxchg( (int *)dest, xchg, compare );
1939 /***********************************************************************
1940 * InterlockedExchange (KERNEL32.@)
1942 * Atomically swap one value with another.
1945 * dest [I/O] The value to replace
1946 * val [I] The value to be swapped
1949 * The resulting value of dest.
1951 LONG WINAPI InterlockedExchange( LONG volatile *dest, LONG val )
1953 return interlocked_xchg( (int *)dest, val );
1956 /***********************************************************************
1957 * InterlockedExchangeAdd (KERNEL32.@)
1959 * Atomically add one value to another.
1962 * dest [I/O] The value to add to
1963 * incr [I] The value to be added
1966 * The resulting value of dest.
1968 LONG WINAPI InterlockedExchangeAdd( LONG volatile *dest, LONG incr )
1970 return interlocked_xchg_add( (int *)dest, incr );
1973 /***********************************************************************
1974 * InterlockedIncrement (KERNEL32.@)
1976 * Atomically increment a value.
1979 * dest [I/O] The value to increment
1982 * The resulting value of dest.
1984 LONG WINAPI InterlockedIncrement( LONG volatile *dest )
1986 return interlocked_xchg_add( (int *)dest, 1 ) + 1;
1989 /***********************************************************************
1990 * InterlockedDecrement (KERNEL32.@)
1992 * Atomically decrement a value.
1995 * dest [I/O] The value to decrement
1998 * The resulting value of dest.
2000 LONG WINAPI InterlockedDecrement( LONG volatile *dest )
2002 return interlocked_xchg_add( (int *)dest, -1 ) - 1;
2005 #endif /* __i386__ */