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>
52 #include "wine/server.h"
53 #include "wine/unicode.h"
54 #include "wine/winbase16.h"
55 #include "kernel_private.h"
57 #include "wine/debug.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(sync);
61 /* check if current version is NT or Win95 */
62 inline static int is_version_nt(void)
64 return !(GetVersion() & 0x80000000);
68 /***********************************************************************
71 VOID WINAPI Sleep( DWORD timeout )
73 SleepEx( timeout, FALSE );
76 /******************************************************************************
77 * SleepEx (KERNEL32.@)
79 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
83 if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
88 time.QuadPart = timeout * (ULONGLONG)10000;
89 time.QuadPart = -time.QuadPart;
90 status = NtDelayExecution( alertable, &time );
92 if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
97 /***********************************************************************
98 * SwitchToThread (KERNEL32.@)
100 BOOL WINAPI SwitchToThread(void)
102 return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
106 /***********************************************************************
107 * WaitForSingleObject (KERNEL32.@)
109 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
111 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
115 /***********************************************************************
116 * WaitForSingleObjectEx (KERNEL32.@)
118 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
121 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
125 /***********************************************************************
126 * WaitForMultipleObjects (KERNEL32.@)
128 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
129 BOOL wait_all, DWORD timeout )
131 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
135 /***********************************************************************
136 * WaitForMultipleObjectsEx (KERNEL32.@)
138 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
139 BOOL wait_all, DWORD timeout,
143 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
146 if (count >= MAXIMUM_WAIT_OBJECTS)
148 SetLastError(ERROR_INVALID_PARAMETER);
151 for (i = 0; i < count; i++)
153 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
154 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
155 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
156 hloc[i] = GetStdHandle( (DWORD)handles[i] );
158 hloc[i] = handles[i];
160 /* yes, even screen buffer console handles are waitable, and are
161 * handled as a handle to the console itself !!
163 if (is_console_handle(hloc[i]))
165 if (!VerifyConsoleIoHandle(hloc[i]))
169 hloc[i] = GetConsoleInputWaitHandle();
173 if (timeout == INFINITE)
175 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
181 time.QuadPart = timeout * (ULONGLONG)10000;
182 time.QuadPart = -time.QuadPart;
183 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
186 if (HIWORD(status)) /* is it an error code? */
188 SetLastError( RtlNtStatusToDosError(status) );
189 status = WAIT_FAILED;
195 /***********************************************************************
196 * WaitForSingleObject (KERNEL.460)
198 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
200 DWORD retval, mutex_count;
202 ReleaseThunkLock( &mutex_count );
203 retval = WaitForSingleObject( handle, timeout );
204 RestoreThunkLock( mutex_count );
208 /***********************************************************************
209 * WaitForMultipleObjects (KERNEL.461)
211 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
212 BOOL wait_all, DWORD timeout )
214 DWORD retval, mutex_count;
216 ReleaseThunkLock( &mutex_count );
217 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
218 RestoreThunkLock( mutex_count );
222 /***********************************************************************
223 * WaitForMultipleObjectsEx (KERNEL.495)
225 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
226 BOOL wait_all, DWORD timeout, BOOL alertable )
228 DWORD retval, mutex_count;
230 ReleaseThunkLock( &mutex_count );
231 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
232 RestoreThunkLock( mutex_count );
236 /***********************************************************************
237 * RegisterWaitForSingleObject (KERNEL32.@)
239 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
240 WAITORTIMERCALLBACK Callback, PVOID Context,
241 ULONG dwMilliseconds, ULONG dwFlags)
243 FIXME("%p %p %p %p %ld %ld\n",
244 phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
248 /***********************************************************************
249 * RegisterWaitForSingleObjectEx (KERNEL32.@)
251 HANDLE WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject,
252 WAITORTIMERCALLBACK Callback, PVOID Context,
253 ULONG dwMilliseconds, ULONG dwFlags )
255 FIXME("%p %p %p %ld %ld\n",
256 hObject,Callback,Context,dwMilliseconds,dwFlags);
260 /***********************************************************************
261 * UnregisterWait (KERNEL32.@)
263 BOOL WINAPI UnregisterWait( HANDLE WaitHandle )
265 FIXME("%p\n",WaitHandle);
269 /***********************************************************************
270 * UnregisterWaitEx (KERNEL32.@)
272 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
274 FIXME("%p %p\n",WaitHandle, CompletionEvent);
278 /***********************************************************************
279 * SignalObjectAndWait (KERNEL32.@)
281 * Allows to atomically signal any of the synchro objects (semaphore,
282 * mutex, event) and wait on another.
284 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
286 FIXME("(%p %p %ld %d): stub\n", hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable);
287 return WAIT_OBJECT_0;
291 /***********************************************************************
292 * InitializeCriticalSection (KERNEL32.@)
294 * Initialise a critical section before use.
297 * crit [O] Critical section to initialise.
300 * Nothing. If the function fails an exception is raised.
302 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
304 NTSTATUS ret = RtlInitializeCriticalSection( crit );
305 if (ret) RtlRaiseStatus( ret );
308 /***********************************************************************
309 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
311 * Initialise a critical section with a spin count.
314 * crit [O] Critical section to initialise.
315 * spincount [I] Number of times to spin upon contention.
319 * Failure: Nothing. If the function fails an exception is raised.
322 * spincount is ignored on uni-processor systems.
324 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
326 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
327 if (ret) RtlRaiseStatus( ret );
331 /***********************************************************************
332 * MakeCriticalSectionGlobal (KERNEL32.@)
334 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
336 /* let's assume that only one thread at a time will try to do this */
337 HANDLE sem = crit->LockSemaphore;
338 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
339 crit->LockSemaphore = ConvertToGlobalHandle( sem );
342 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
343 crit->DebugInfo = NULL;
348 /***********************************************************************
349 * ReinitializeCriticalSection (KERNEL32.@)
351 * Initialise an already used critical section.
354 * crit [O] Critical section to initialise.
359 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
361 if ( !crit->LockSemaphore )
362 RtlInitializeCriticalSection( crit );
366 /***********************************************************************
367 * UninitializeCriticalSection (KERNEL32.@)
369 * UnInitialise a critical section after use.
372 * crit [O] Critical section to uninitialise (destroy).
377 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
379 RtlDeleteCriticalSection( crit );
383 /***********************************************************************
384 * CreateEventA (KERNEL32.@)
386 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
387 BOOL initial_state, LPCSTR name )
389 WCHAR buffer[MAX_PATH];
391 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
393 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
395 SetLastError( ERROR_FILENAME_EXCED_RANGE );
398 return CreateEventW( sa, manual_reset, initial_state, buffer );
402 /***********************************************************************
403 * CreateEventW (KERNEL32.@)
405 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
406 BOOL initial_state, LPCWSTR name )
409 UNICODE_STRING nameW;
410 OBJECT_ATTRIBUTES attr;
413 /* one buggy program needs this
414 * ("Van Dale Groot woordenboek der Nederlandse taal")
416 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
418 ERR("Bad security attributes pointer %p\n",sa);
419 SetLastError( ERROR_INVALID_PARAMETER);
423 attr.Length = sizeof(attr);
424 attr.RootDirectory = 0;
425 attr.ObjectName = NULL;
426 attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
427 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
428 attr.SecurityQualityOfService = NULL;
431 RtlInitUnicodeString( &nameW, name );
432 attr.ObjectName = &nameW;
435 status = NtCreateEvent( &ret, EVENT_ALL_ACCESS, &attr, manual_reset, initial_state );
436 SetLastError( RtlNtStatusToDosError(status) );
441 /***********************************************************************
442 * CreateW32Event (KERNEL.457)
444 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
446 return CreateEventW( NULL, manual_reset, initial_state, NULL );
450 /***********************************************************************
451 * OpenEventA (KERNEL32.@)
453 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
455 WCHAR buffer[MAX_PATH];
457 if (!name) return OpenEventW( access, inherit, NULL );
459 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
461 SetLastError( ERROR_FILENAME_EXCED_RANGE );
464 return OpenEventW( access, inherit, buffer );
468 /***********************************************************************
469 * OpenEventW (KERNEL32.@)
471 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
474 UNICODE_STRING nameW;
475 OBJECT_ATTRIBUTES attr;
478 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
480 attr.Length = sizeof(attr);
481 attr.RootDirectory = 0;
482 attr.ObjectName = NULL;
483 attr.Attributes = inherit ? OBJ_INHERIT : 0;
484 attr.SecurityDescriptor = NULL;
485 attr.SecurityQualityOfService = NULL;
488 RtlInitUnicodeString( &nameW, name );
489 attr.ObjectName = &nameW;
492 status = NtOpenEvent( &ret, access, &attr );
493 if (status != STATUS_SUCCESS)
495 SetLastError( RtlNtStatusToDosError(status) );
501 /***********************************************************************
502 * PulseEvent (KERNEL32.@)
504 BOOL WINAPI PulseEvent( HANDLE handle )
508 if ((status = NtPulseEvent( handle, NULL )))
509 SetLastError( RtlNtStatusToDosError(status) );
514 /***********************************************************************
515 * SetW32Event (KERNEL.458)
516 * SetEvent (KERNEL32.@)
518 BOOL WINAPI SetEvent( HANDLE handle )
522 if ((status = NtSetEvent( handle, NULL )))
523 SetLastError( RtlNtStatusToDosError(status) );
528 /***********************************************************************
529 * ResetW32Event (KERNEL.459)
530 * ResetEvent (KERNEL32.@)
532 BOOL WINAPI ResetEvent( HANDLE handle )
536 if ((status = NtResetEvent( handle, NULL )))
537 SetLastError( RtlNtStatusToDosError(status) );
542 /***********************************************************************
543 * NOTE: The Win95 VWin32_Event routines given below are really low-level
544 * routines implemented directly by VWin32. The user-mode libraries
545 * implement Win32 synchronisation routines on top of these low-level
546 * primitives. We do it the other way around here :-)
549 /***********************************************************************
550 * VWin32_EventCreate (KERNEL.442)
552 HANDLE WINAPI VWin32_EventCreate(VOID)
554 HANDLE hEvent = CreateEventW( NULL, FALSE, 0, NULL );
555 return ConvertToGlobalHandle( hEvent );
558 /***********************************************************************
559 * VWin32_EventDestroy (KERNEL.443)
561 VOID WINAPI VWin32_EventDestroy(HANDLE event)
563 CloseHandle( event );
566 /***********************************************************************
567 * VWin32_EventWait (KERNEL.450)
569 VOID WINAPI VWin32_EventWait(HANDLE event)
573 ReleaseThunkLock( &mutex_count );
574 WaitForSingleObject( event, INFINITE );
575 RestoreThunkLock( mutex_count );
578 /***********************************************************************
579 * VWin32_EventSet (KERNEL.451)
580 * KERNEL_479 (KERNEL.479)
582 VOID WINAPI VWin32_EventSet(HANDLE event)
589 /***********************************************************************
590 * CreateMutexA (KERNEL32.@)
592 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
594 WCHAR buffer[MAX_PATH];
596 if (!name) return CreateMutexW( sa, owner, NULL );
598 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
600 SetLastError( ERROR_FILENAME_EXCED_RANGE );
603 return CreateMutexW( sa, owner, buffer );
607 /***********************************************************************
608 * CreateMutexW (KERNEL32.@)
610 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
613 UNICODE_STRING nameW;
614 OBJECT_ATTRIBUTES attr;
617 attr.Length = sizeof(attr);
618 attr.RootDirectory = 0;
619 attr.ObjectName = NULL;
620 attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
621 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
622 attr.SecurityQualityOfService = NULL;
625 RtlInitUnicodeString( &nameW, name );
626 attr.ObjectName = &nameW;
629 status = NtCreateMutant( &ret, MUTEX_ALL_ACCESS, &attr, owner );
630 SetLastError( RtlNtStatusToDosError(status) );
635 /***********************************************************************
636 * OpenMutexA (KERNEL32.@)
638 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
640 WCHAR buffer[MAX_PATH];
642 if (!name) return OpenMutexW( access, inherit, NULL );
644 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
646 SetLastError( ERROR_FILENAME_EXCED_RANGE );
649 return OpenMutexW( access, inherit, buffer );
653 /***********************************************************************
654 * OpenMutexW (KERNEL32.@)
656 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
659 UNICODE_STRING nameW;
660 OBJECT_ATTRIBUTES attr;
663 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
665 attr.Length = sizeof(attr);
666 attr.RootDirectory = 0;
667 attr.ObjectName = NULL;
668 attr.Attributes = inherit ? OBJ_INHERIT : 0;
669 attr.SecurityDescriptor = NULL;
670 attr.SecurityQualityOfService = NULL;
673 RtlInitUnicodeString( &nameW, name );
674 attr.ObjectName = &nameW;
677 status = NtOpenMutant( &ret, access, &attr );
678 if (status != STATUS_SUCCESS)
680 SetLastError( RtlNtStatusToDosError(status) );
687 /***********************************************************************
688 * ReleaseMutex (KERNEL32.@)
690 BOOL WINAPI ReleaseMutex( HANDLE handle )
694 status = NtReleaseMutant(handle, NULL);
695 if (status != STATUS_SUCCESS)
697 SetLastError( RtlNtStatusToDosError(status) );
709 /***********************************************************************
710 * CreateSemaphoreA (KERNEL32.@)
712 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
714 WCHAR buffer[MAX_PATH];
716 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
718 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
720 SetLastError( ERROR_FILENAME_EXCED_RANGE );
723 return CreateSemaphoreW( sa, initial, max, buffer );
727 /***********************************************************************
728 * CreateSemaphoreW (KERNEL32.@)
730 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
731 LONG max, LPCWSTR name )
734 UNICODE_STRING nameW;
735 OBJECT_ATTRIBUTES attr;
738 attr.Length = sizeof(attr);
739 attr.RootDirectory = 0;
740 attr.ObjectName = NULL;
741 attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
742 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
743 attr.SecurityQualityOfService = NULL;
746 RtlInitUnicodeString( &nameW, name );
747 attr.ObjectName = &nameW;
750 status = NtCreateSemaphore( &ret, SEMAPHORE_ALL_ACCESS, &attr, initial, max );
751 SetLastError( RtlNtStatusToDosError(status) );
756 /***********************************************************************
757 * OpenSemaphoreA (KERNEL32.@)
759 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
761 WCHAR buffer[MAX_PATH];
763 if (!name) return OpenSemaphoreW( access, inherit, NULL );
765 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
767 SetLastError( ERROR_FILENAME_EXCED_RANGE );
770 return OpenSemaphoreW( access, inherit, buffer );
774 /***********************************************************************
775 * OpenSemaphoreW (KERNEL32.@)
777 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
780 UNICODE_STRING nameW;
781 OBJECT_ATTRIBUTES attr;
784 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
786 attr.Length = sizeof(attr);
787 attr.RootDirectory = 0;
788 attr.ObjectName = NULL;
789 attr.Attributes = inherit ? OBJ_INHERIT : 0;
790 attr.SecurityDescriptor = NULL;
791 attr.SecurityQualityOfService = NULL;
794 RtlInitUnicodeString( &nameW, name );
795 attr.ObjectName = &nameW;
798 status = NtOpenSemaphore( &ret, access, &attr );
799 if (status != STATUS_SUCCESS)
801 SetLastError( RtlNtStatusToDosError(status) );
808 /***********************************************************************
809 * ReleaseSemaphore (KERNEL32.@)
811 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
813 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
814 if (status) SetLastError( RtlNtStatusToDosError(status) );
824 /***********************************************************************
825 * CreateWaitableTimerA (KERNEL32.@)
827 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
829 WCHAR buffer[MAX_PATH];
831 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
833 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
835 SetLastError( ERROR_FILENAME_EXCED_RANGE );
838 return CreateWaitableTimerW( sa, manual, buffer );
842 /***********************************************************************
843 * CreateWaitableTimerW (KERNEL32.@)
845 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
849 UNICODE_STRING nameW;
850 OBJECT_ATTRIBUTES attr;
852 attr.Length = sizeof(attr);
853 attr.RootDirectory = 0;
854 attr.ObjectName = NULL;
855 attr.Attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
856 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
857 attr.SecurityQualityOfService = NULL;
860 RtlInitUnicodeString( &nameW, name );
861 attr.ObjectName = &nameW;
864 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &attr,
865 manual ? NotificationTimer : SynchronizationTimer);
866 SetLastError( RtlNtStatusToDosError(status) );
871 /***********************************************************************
872 * OpenWaitableTimerA (KERNEL32.@)
874 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
876 WCHAR buffer[MAX_PATH];
878 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
880 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
882 SetLastError( ERROR_FILENAME_EXCED_RANGE );
885 return OpenWaitableTimerW( access, inherit, buffer );
889 /***********************************************************************
890 * OpenWaitableTimerW (KERNEL32.@)
892 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
895 UNICODE_STRING nameW;
896 OBJECT_ATTRIBUTES attr;
899 if (!is_version_nt()) access = TIMER_ALL_ACCESS;
901 attr.Length = sizeof(attr);
902 attr.RootDirectory = 0;
903 attr.ObjectName = NULL;
904 attr.Attributes = inherit ? OBJ_INHERIT : 0;
905 attr.SecurityDescriptor = NULL;
906 attr.SecurityQualityOfService = NULL;
909 RtlInitUnicodeString( &nameW, name );
910 attr.ObjectName = &nameW;
913 status = NtOpenTimer(&handle, access, &attr);
914 if (status != STATUS_SUCCESS)
916 SetLastError( RtlNtStatusToDosError(status) );
923 /***********************************************************************
924 * SetWaitableTimer (KERNEL32.@)
926 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
927 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
929 NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
931 if (status != STATUS_SUCCESS)
933 SetLastError( RtlNtStatusToDosError(status) );
934 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
940 /***********************************************************************
941 * CancelWaitableTimer (KERNEL32.@)
943 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
947 status = NtCancelTimer(handle, NULL);
948 if (status != STATUS_SUCCESS)
950 SetLastError( RtlNtStatusToDosError(status) );
957 /***********************************************************************
958 * CreateTimerQueue (KERNEL32.@)
960 HANDLE WINAPI CreateTimerQueue(void)
963 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
968 /***********************************************************************
969 * DeleteTimerQueueEx (KERNEL32.@)
971 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
973 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
974 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
978 /***********************************************************************
979 * CreateTimerQueueTimer (KERNEL32.@)
981 * Creates a timer-queue timer. This timer expires at the specified due
982 * time (in ms), then after every specified period (in ms). When the timer
983 * expires, the callback function is called.
986 * nonzero on success or zero on faillure
991 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
992 WAITORTIMERCALLBACK Callback, PVOID Parameter,
993 DWORD DueTime, DWORD Period, ULONG Flags )
996 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1000 /***********************************************************************
1001 * DeleteTimerQueueTimer (KERNEL32.@)
1003 * Cancels a timer-queue timer.
1006 * nonzero on success or zero on faillure
1011 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
1012 HANDLE CompletionEvent )
1015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1025 /***********************************************************************
1026 * CreateNamedPipeA (KERNEL32.@)
1028 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1029 DWORD dwPipeMode, DWORD nMaxInstances,
1030 DWORD nOutBufferSize, DWORD nInBufferSize,
1031 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1033 WCHAR buffer[MAX_PATH];
1035 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1036 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1038 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1040 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1041 return INVALID_HANDLE_VALUE;
1043 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1044 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1048 /***********************************************************************
1049 * CreateNamedPipeW (KERNEL32.@)
1051 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1052 DWORD dwPipeMode, DWORD nMaxInstances,
1053 DWORD nOutBufferSize, DWORD nInBufferSize,
1054 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1057 UNICODE_STRING nt_name;
1058 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1060 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1061 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1062 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1064 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1066 SetLastError( ERROR_PATH_NOT_FOUND );
1067 return INVALID_HANDLE_VALUE;
1069 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1071 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1072 RtlFreeUnicodeString( &nt_name );
1073 return INVALID_HANDLE_VALUE;
1075 if (nt_name.Length < sizeof(leadin) ||
1076 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1078 SetLastError( ERROR_INVALID_NAME );
1079 RtlFreeUnicodeString( &nt_name );
1080 return INVALID_HANDLE_VALUE;
1082 SERVER_START_REQ( create_named_pipe )
1084 req->openmode = dwOpenMode;
1085 req->pipemode = dwPipeMode;
1086 req->maxinstances = nMaxInstances;
1087 req->outsize = nOutBufferSize;
1088 req->insize = nInBufferSize;
1089 req->timeout = nDefaultTimeOut;
1090 req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1091 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1093 if (!wine_server_call_err( req )) ret = reply->handle;
1094 else ret = INVALID_HANDLE_VALUE;
1097 RtlFreeUnicodeString( &nt_name );
1102 /***********************************************************************
1103 * PeekNamedPipe (KERNEL32.@)
1105 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1106 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1109 int avail=0, fd, ret, flags;
1111 TRACE("(%p,%p,%lu,%p,%p,%p)\n", hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage);
1113 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, &flags );
1116 SetLastError( RtlNtStatusToDosError(ret) );
1119 if (flags & FD_FLAG_RECV_SHUTDOWN)
1121 wine_server_release_fd( hPipe, fd );
1122 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1126 if (ioctl(fd,FIONREAD, &avail ) != 0)
1128 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1129 wine_server_release_fd( hPipe, fd );
1132 if (!avail) /* check for closed pipe */
1134 struct pollfd pollfd;
1136 pollfd.events = POLLIN;
1138 switch (poll( &pollfd, 1, 0 ))
1142 case 1: /* got something */
1143 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1144 TRACE("POLLHUP | POLLERR\n");
1147 wine_server_release_fd( hPipe, fd );
1148 SetLastError(ERROR_BROKEN_PIPE);
1152 TRACE(" 0x%08x bytes available\n", avail );
1158 if (avail && lpvBuffer && cbBuffer)
1160 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1161 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1164 WARN("failed to peek socket (%d)\n", errno);
1168 *lpcbRead = readbytes;
1170 wine_server_release_fd( hPipe, fd );
1172 #endif /* defined(FIONREAD) */
1174 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1175 FIXME("function not implemented\n");
1179 /***********************************************************************
1180 * SYNC_CompletePipeOverlapped (Internal)
1182 static void CALLBACK SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1184 TRACE("for %p result %08lx\n",overlapped,result);
1187 overlapped->Internal = result;
1188 SetEvent(overlapped->hEvent);
1192 /***********************************************************************
1193 * WaitNamedPipeA (KERNEL32.@)
1195 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1197 WCHAR buffer[MAX_PATH];
1199 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1201 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1203 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1206 return WaitNamedPipeW( buffer, nTimeOut );
1210 /***********************************************************************
1211 * WaitNamedPipeW (KERNEL32.@)
1213 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1217 UNICODE_STRING nt_name;
1218 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1220 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1222 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1225 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1227 RtlFreeUnicodeString( &nt_name );
1230 if (nt_name.Length < sizeof(leadin) ||
1231 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1233 RtlFreeUnicodeString( &nt_name );
1237 memset(&ov,0,sizeof(ov));
1238 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1242 SERVER_START_REQ( wait_named_pipe )
1244 req->timeout = nTimeOut;
1245 req->overlapped = &ov;
1246 req->func = SYNC_CompletePipeOverlapped;
1247 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1248 ret = !wine_server_call_err( req );
1252 RtlFreeUnicodeString( &nt_name );
1256 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1258 SetLastError(RtlNtStatusToDosError(ov.Internal));
1259 ret = (ov.Internal==STATUS_SUCCESS);
1262 CloseHandle(ov.hEvent);
1267 /***********************************************************************
1268 * SYNC_ConnectNamedPipe (Internal)
1270 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1277 overlapped->Internal = STATUS_PENDING;
1279 SERVER_START_REQ( connect_named_pipe )
1281 req->handle = hPipe;
1282 req->overlapped = overlapped;
1283 req->func = SYNC_CompletePipeOverlapped;
1284 ret = !wine_server_call_err( req );
1291 /***********************************************************************
1292 * ConnectNamedPipe (KERNEL32.@)
1294 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1299 TRACE("(%p,%p)\n",hPipe, overlapped);
1303 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1304 SetLastError( ERROR_IO_PENDING );
1308 memset(&ov,0,sizeof(ov));
1309 ov.hEvent = CreateEventW(NULL,0,0,NULL);
1313 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1316 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1318 SetLastError(RtlNtStatusToDosError(ov.Internal));
1319 ret = (ov.Internal==STATUS_SUCCESS);
1323 CloseHandle(ov.hEvent);
1328 /***********************************************************************
1329 * DisconnectNamedPipe (KERNEL32.@)
1331 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1335 TRACE("(%p)\n",hPipe);
1337 SERVER_START_REQ( disconnect_named_pipe )
1339 req->handle = hPipe;
1340 ret = !wine_server_call_err( req );
1341 if (ret && reply->fd != -1) close( reply->fd );
1348 /***********************************************************************
1349 * TransactNamedPipe (KERNEL32.@)
1352 * should be done as a single operation in the wineserver or kernel
1354 BOOL WINAPI TransactNamedPipe(
1355 HANDLE handle, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1356 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1361 TRACE("%p %p %ld %p %ld %p %p\n",
1362 handle, lpInput, dwInputSize, lpOutput,
1363 dwOutputSize, lpBytesRead, lpOverlapped);
1367 FIXME("Doesn't support overlapped operation as yet\n");
1371 r = WriteFile(handle, lpOutput, dwOutputSize, &count, NULL);
1373 r = ReadFile(handle, lpInput, dwInputSize, lpBytesRead, NULL);
1378 /***********************************************************************
1379 * GetNamedPipeInfo (KERNEL32.@)
1381 BOOL WINAPI GetNamedPipeInfo(
1382 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1383 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1387 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1388 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1390 SERVER_START_REQ( get_named_pipe_info )
1392 req->handle = hNamedPipe;
1393 ret = !wine_server_call_err( req );
1394 if(lpFlags) *lpFlags = reply->flags;
1395 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1396 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1397 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1404 /***********************************************************************
1405 * GetNamedPipeHandleStateA (KERNEL32.@)
1407 BOOL WINAPI GetNamedPipeHandleStateA(
1408 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1409 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1410 LPSTR lpUsername, DWORD nUsernameMaxSize)
1412 FIXME("%p %p %p %p %p %p %ld\n",
1413 hNamedPipe, lpState, lpCurInstances,
1414 lpMaxCollectionCount, lpCollectDataTimeout,
1415 lpUsername, nUsernameMaxSize);
1420 /***********************************************************************
1421 * GetNamedPipeHandleStateW (KERNEL32.@)
1423 BOOL WINAPI GetNamedPipeHandleStateW(
1424 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1425 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1426 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1428 FIXME("%p %p %p %p %p %p %ld\n",
1429 hNamedPipe, lpState, lpCurInstances,
1430 lpMaxCollectionCount, lpCollectDataTimeout,
1431 lpUsername, nUsernameMaxSize);
1436 /***********************************************************************
1437 * SetNamedPipeHandleState (KERNEL32.@)
1439 BOOL WINAPI SetNamedPipeHandleState(
1440 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1441 LPDWORD lpCollectDataTimeout)
1443 FIXME("%p %p %p %p\n",
1444 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1448 /***********************************************************************
1449 * CallNamedPipeA (KERNEL32.@)
1451 BOOL WINAPI CallNamedPipeA(
1452 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1453 LPVOID lpOutput, DWORD dwOutputSize,
1454 LPDWORD lpBytesRead, DWORD nTimeout)
1460 TRACE("%s %p %ld %p %ld %p %ld\n",
1461 debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1462 lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1464 if( lpNamedPipeName )
1466 len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1467 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1468 MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1470 ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1471 dwOutputSize, lpBytesRead, nTimeout );
1472 if( lpNamedPipeName )
1473 HeapFree( GetProcessHeap(), 0, str );
1478 /***********************************************************************
1479 * CallNamedPipeW (KERNEL32.@)
1481 BOOL WINAPI CallNamedPipeW(
1482 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1483 LPVOID lpOutput, DWORD lpOutputSize,
1484 LPDWORD lpBytesRead, DWORD nTimeout)
1486 FIXME("%s %p %ld %p %ld %p %ld\n",
1487 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1488 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1492 /******************************************************************
1493 * CreatePipe (KERNEL32.@)
1496 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1497 LPSECURITY_ATTRIBUTES sa, DWORD size )
1499 static unsigned index = 0;
1502 unsigned in_index = index;
1504 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1505 /* generate a unique pipe name (system wide) */
1508 static const WCHAR nameFmt[] = { '\\','\\','.','\\','p','i','p','e',
1509 '\\','W','i','n','3','2','.','P','i','p','e','s','.','%','0','8','l',
1510 'u','.','%','0','8','u','\0' };
1511 snprintfW(name, sizeof(name) / sizeof(name[0]), nameFmt,
1512 GetCurrentProcessId(), ++index);
1513 hr = CreateNamedPipeW(name, PIPE_ACCESS_INBOUND,
1514 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1515 NMPWAIT_USE_DEFAULT_WAIT, sa);
1516 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1517 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1518 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1520 hw = CreateFileW(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1521 if (hw == INVALID_HANDLE_VALUE)
1533 /******************************************************************************
1534 * CreateMailslotA [KERNEL32.@]
1536 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1537 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1543 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1544 nMaxMessageSize, lReadTimeout, sa);
1548 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1549 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1550 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1553 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1555 HeapFree( GetProcessHeap(), 0, name );
1561 /******************************************************************************
1562 * CreateMailslotW [KERNEL32.@]
1564 * Create a mailslot with specified name.
1567 * lpName [I] Pointer to string for mailslot name
1568 * nMaxMessageSize [I] Maximum message size
1569 * lReadTimeout [I] Milliseconds before read time-out
1570 * sa [I] Pointer to security structure
1573 * Success: Handle to mailslot
1574 * Failure: INVALID_HANDLE_VALUE
1576 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1577 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1579 HANDLE handle = INVALID_HANDLE_VALUE;
1580 OBJECT_ATTRIBUTES attr;
1581 UNICODE_STRING nameW;
1582 LARGE_INTEGER timeout;
1583 IO_STATUS_BLOCK iosb;
1586 TRACE("%s %ld %ld %p\n", debugstr_w(lpName),
1587 nMaxMessageSize, lReadTimeout, sa);
1589 if (!RtlDosPathNameToNtPathName_U( lpName, &nameW, NULL, NULL ))
1591 SetLastError( ERROR_PATH_NOT_FOUND );
1592 return INVALID_HANDLE_VALUE;
1595 if (nameW.Length >= MAX_PATH * sizeof(WCHAR) )
1597 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1598 RtlFreeUnicodeString( &nameW );
1599 return INVALID_HANDLE_VALUE;
1602 attr.Length = sizeof(attr);
1603 attr.RootDirectory = 0;
1604 attr.Attributes = OBJ_CASE_INSENSITIVE;
1605 attr.ObjectName = &nameW;
1606 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
1607 attr.SecurityQualityOfService = NULL;
1609 timeout.QuadPart = (ULONGLONG) lReadTimeout * -10000;
1611 status = NtCreateMailslotFile( &handle, GENERIC_READ | GENERIC_WRITE, &attr,
1612 &iosb, 0, 0, nMaxMessageSize, &timeout );
1615 SetLastError( RtlNtStatusToDosError(status) );
1616 handle = INVALID_HANDLE_VALUE;
1619 RtlFreeUnicodeString( &nameW );
1624 /******************************************************************************
1625 * GetMailslotInfo [KERNEL32.@]
1627 * Retrieve information about a mailslot.
1630 * hMailslot [I] Mailslot handle
1631 * lpMaxMessageSize [O] Address of maximum message size
1632 * lpNextSize [O] Address of size of next message
1633 * lpMessageCount [O] Address of number of messages
1634 * lpReadTimeout [O] Address of read time-out
1640 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1641 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1642 LPDWORD lpReadTimeout )
1644 FILE_MAILSLOT_QUERY_INFORMATION info;
1645 IO_STATUS_BLOCK iosb;
1648 TRACE("%p %p %p %p %p\n",hMailslot, lpMaxMessageSize,
1649 lpNextSize, lpMessageCount, lpReadTimeout);
1651 status = NtQueryInformationFile( hMailslot, &iosb, &info, sizeof info,
1652 FileMailslotQueryInformation );
1654 if( status != STATUS_SUCCESS )
1656 SetLastError( RtlNtStatusToDosError(status) );
1660 if( lpMaxMessageSize )
1661 *lpMaxMessageSize = info.MaximumMessageSize;
1663 *lpNextSize = info.NextMessageSize;
1664 if( lpMessageCount )
1665 *lpMessageCount = info.MessagesAvailable;
1667 *lpReadTimeout = info.ReadTimeout.QuadPart / -10000;
1673 /******************************************************************************
1674 * SetMailslotInfo [KERNEL32.@]
1676 * Set the read timeout of a mailslot.
1679 * hMailslot [I] Mailslot handle
1680 * dwReadTimeout [I] Timeout in milliseconds.
1686 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1688 FILE_MAILSLOT_SET_INFORMATION info;
1689 IO_STATUS_BLOCK iosb;
1692 TRACE("%p %ld\n", hMailslot, dwReadTimeout);
1694 info.ReadTimeout.QuadPart = dwReadTimeout * -10000;
1695 status = NtSetInformationFile( hMailslot, &iosb, &info, sizeof info,
1696 FileMailslotSetInformation );
1697 if( status != STATUS_SUCCESS )
1699 SetLastError( RtlNtStatusToDosError(status) );
1706 /******************************************************************************
1707 * CreateIoCompletionPort (KERNEL32.@)
1709 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1710 ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
1712 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1713 hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
1718 /******************************************************************************
1719 * GetQueuedCompletionStatus (KERNEL32.@)
1721 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1722 PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
1723 DWORD dwMilliseconds )
1725 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1726 CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
1727 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1731 /******************************************************************************
1732 * CreateJobObjectW (KERNEL32.@)
1734 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1736 FIXME("%p %s\n", attr, debugstr_w(name) );
1737 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1741 /******************************************************************************
1742 * CreateJobObjectA (KERNEL32.@)
1744 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1750 TRACE("%p %s\n", attr, debugstr_a(name) );
1754 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1755 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1758 SetLastError( ERROR_OUTOFMEMORY );
1761 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1764 r = CreateJobObjectW( attr, str );
1766 HeapFree( GetProcessHeap(), 0, str );
1771 /******************************************************************************
1772 * AssignProcessToJobObject (KERNEL32.@)
1774 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1776 FIXME("%p %p\n", hJob, hProcess);
1782 /***********************************************************************
1783 * InterlockedCompareExchange (KERNEL32.@)
1785 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1786 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1787 "movl 12(%esp),%eax\n\t"
1788 "movl 8(%esp),%ecx\n\t"
1789 "movl 4(%esp),%edx\n\t"
1790 "lock; cmpxchgl %ecx,(%edx)\n\t"
1793 /***********************************************************************
1794 * InterlockedExchange (KERNEL32.@)
1796 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1797 __ASM_GLOBAL_FUNC(InterlockedExchange,
1798 "movl 8(%esp),%eax\n\t"
1799 "movl 4(%esp),%edx\n\t"
1800 "lock; xchgl %eax,(%edx)\n\t"
1803 /***********************************************************************
1804 * InterlockedExchangeAdd (KERNEL32.@)
1806 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1807 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1808 "movl 8(%esp),%eax\n\t"
1809 "movl 4(%esp),%edx\n\t"
1810 "lock; xaddl %eax,(%edx)\n\t"
1813 /***********************************************************************
1814 * InterlockedIncrement (KERNEL32.@)
1816 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1817 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1818 "movl 4(%esp),%edx\n\t"
1820 "lock; xaddl %eax,(%edx)\n\t"
1824 /***********************************************************************
1825 * InterlockedDecrement (KERNEL32.@)
1827 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1828 "movl 4(%esp),%edx\n\t"
1830 "lock; xaddl %eax,(%edx)\n\t"
1834 #else /* __i386__ */
1836 /***********************************************************************
1837 * InterlockedCompareExchange (KERNEL32.@)
1839 * Atomically swap one value with another.
1842 * dest [I/O] The value to replace
1843 * xchq [I] The value to be swapped
1844 * compare [I] The value to compare to dest
1847 * The resulting value of dest.
1850 * dest is updated only if it is equal to compare, otherwise no swap is done.
1852 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1854 return interlocked_cmpxchg( dest, xchg, compare );
1857 /***********************************************************************
1858 * InterlockedExchange (KERNEL32.@)
1860 * Atomically swap one value with another.
1863 * dest [I/O] The value to replace
1864 * val [I] The value to be swapped
1867 * The resulting value of dest.
1869 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1871 return interlocked_xchg( dest, val );
1874 /***********************************************************************
1875 * InterlockedExchangeAdd (KERNEL32.@)
1877 * Atomically add one value to another.
1880 * dest [I/O] The value to add to
1881 * incr [I] The value to be added
1884 * The resulting value of dest.
1886 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1888 return interlocked_xchg_add( dest, incr );
1891 /***********************************************************************
1892 * InterlockedIncrement (KERNEL32.@)
1894 * Atomically increment a value.
1897 * dest [I/O] The value to increment
1900 * The resulting value of dest.
1902 LONG WINAPI InterlockedIncrement( PLONG dest )
1904 return interlocked_xchg_add( dest, 1 ) + 1;
1907 /***********************************************************************
1908 * InterlockedDecrement (KERNEL32.@)
1910 * Atomically decrement a value.
1913 * dest [I/O] The value to decrement
1916 * The resulting value of dest.
1918 LONG WINAPI InterlockedDecrement( PLONG dest )
1920 return interlocked_xchg_add( dest, -1 ) - 1;
1923 #endif /* __i386__ */