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 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, &flags );
1114 SetLastError( RtlNtStatusToDosError(ret) );
1117 if (flags & FD_FLAG_RECV_SHUTDOWN)
1119 wine_server_release_fd( hPipe, fd );
1120 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1124 if (ioctl(fd,FIONREAD, &avail ) != 0)
1126 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1127 wine_server_release_fd( hPipe, fd );
1130 if (!avail) /* check for closed pipe */
1132 struct pollfd pollfd;
1134 pollfd.events = POLLIN;
1136 switch (poll( &pollfd, 1, 0 ))
1140 case 1: /* got something */
1141 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1142 TRACE("POLLHUP | POLLERR\n");
1145 wine_server_release_fd( hPipe, fd );
1146 SetLastError(ERROR_BROKEN_PIPE);
1150 TRACE(" 0x%08x bytes available\n", avail );
1156 if (avail && lpvBuffer)
1158 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1159 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1162 WARN("failed to peek socket (%d)\n", errno);
1166 *lpcbRead = readbytes;
1168 wine_server_release_fd( hPipe, fd );
1170 #endif /* defined(FIONREAD) */
1172 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1173 FIXME("function not implemented\n");
1177 /***********************************************************************
1178 * SYNC_CompletePipeOverlapped (Internal)
1180 static void CALLBACK SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1182 TRACE("for %p result %08lx\n",overlapped,result);
1185 overlapped->Internal = result;
1186 SetEvent(overlapped->hEvent);
1190 /***********************************************************************
1191 * WaitNamedPipeA (KERNEL32.@)
1193 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1195 WCHAR buffer[MAX_PATH];
1197 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1199 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1201 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1204 return WaitNamedPipeW( buffer, nTimeOut );
1208 /***********************************************************************
1209 * WaitNamedPipeW (KERNEL32.@)
1211 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1215 UNICODE_STRING nt_name;
1216 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1218 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1220 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1223 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1225 RtlFreeUnicodeString( &nt_name );
1228 if (nt_name.Length < sizeof(leadin) ||
1229 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1231 RtlFreeUnicodeString( &nt_name );
1235 memset(&ov,0,sizeof(ov));
1236 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1240 SERVER_START_REQ( wait_named_pipe )
1242 req->timeout = nTimeOut;
1243 req->overlapped = &ov;
1244 req->func = SYNC_CompletePipeOverlapped;
1245 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1246 ret = !wine_server_call_err( req );
1250 RtlFreeUnicodeString( &nt_name );
1254 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1256 SetLastError(RtlNtStatusToDosError(ov.Internal));
1257 ret = (ov.Internal==STATUS_SUCCESS);
1260 CloseHandle(ov.hEvent);
1265 /***********************************************************************
1266 * SYNC_ConnectNamedPipe (Internal)
1268 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1275 overlapped->Internal = STATUS_PENDING;
1277 SERVER_START_REQ( connect_named_pipe )
1279 req->handle = hPipe;
1280 req->overlapped = overlapped;
1281 req->func = SYNC_CompletePipeOverlapped;
1282 ret = !wine_server_call_err( req );
1289 /***********************************************************************
1290 * ConnectNamedPipe (KERNEL32.@)
1292 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1297 TRACE("(%p,%p)\n",hPipe, overlapped);
1301 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1302 SetLastError( ERROR_IO_PENDING );
1306 memset(&ov,0,sizeof(ov));
1307 ov.hEvent = CreateEventW(NULL,0,0,NULL);
1311 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1314 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1316 SetLastError(RtlNtStatusToDosError(ov.Internal));
1317 ret = (ov.Internal==STATUS_SUCCESS);
1321 CloseHandle(ov.hEvent);
1326 /***********************************************************************
1327 * DisconnectNamedPipe (KERNEL32.@)
1329 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1333 TRACE("(%p)\n",hPipe);
1335 SERVER_START_REQ( disconnect_named_pipe )
1337 req->handle = hPipe;
1338 ret = !wine_server_call_err( req );
1339 if (ret && reply->fd != -1) close( reply->fd );
1346 /***********************************************************************
1347 * TransactNamedPipe (KERNEL32.@)
1350 * should be done as a single operation in the wineserver or kernel
1352 BOOL WINAPI TransactNamedPipe(
1353 HANDLE handle, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1354 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1359 TRACE("%p %p %ld %p %ld %p %p\n",
1360 handle, lpInput, dwInputSize, lpOutput,
1361 dwOutputSize, lpBytesRead, lpOverlapped);
1365 FIXME("Doesn't support overlapped operation as yet\n");
1369 r = WriteFile(handle, lpOutput, dwOutputSize, &count, NULL);
1371 r = ReadFile(handle, lpInput, dwInputSize, lpBytesRead, NULL);
1376 /***********************************************************************
1377 * GetNamedPipeInfo (KERNEL32.@)
1379 BOOL WINAPI GetNamedPipeInfo(
1380 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1381 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1385 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1386 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1388 SERVER_START_REQ( get_named_pipe_info )
1390 req->handle = hNamedPipe;
1391 ret = !wine_server_call_err( req );
1392 if(lpFlags) *lpFlags = reply->flags;
1393 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1394 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1395 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1402 /***********************************************************************
1403 * GetNamedPipeHandleStateA (KERNEL32.@)
1405 BOOL WINAPI GetNamedPipeHandleStateA(
1406 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1407 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1408 LPSTR lpUsername, DWORD nUsernameMaxSize)
1410 FIXME("%p %p %p %p %p %p %ld\n",
1411 hNamedPipe, lpState, lpCurInstances,
1412 lpMaxCollectionCount, lpCollectDataTimeout,
1413 lpUsername, nUsernameMaxSize);
1418 /***********************************************************************
1419 * GetNamedPipeHandleStateW (KERNEL32.@)
1421 BOOL WINAPI GetNamedPipeHandleStateW(
1422 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1423 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1424 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1426 FIXME("%p %p %p %p %p %p %ld\n",
1427 hNamedPipe, lpState, lpCurInstances,
1428 lpMaxCollectionCount, lpCollectDataTimeout,
1429 lpUsername, nUsernameMaxSize);
1434 /***********************************************************************
1435 * SetNamedPipeHandleState (KERNEL32.@)
1437 BOOL WINAPI SetNamedPipeHandleState(
1438 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1439 LPDWORD lpCollectDataTimeout)
1441 FIXME("%p %p %p %p\n",
1442 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1446 /***********************************************************************
1447 * CallNamedPipeA (KERNEL32.@)
1449 BOOL WINAPI CallNamedPipeA(
1450 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1451 LPVOID lpOutput, DWORD dwOutputSize,
1452 LPDWORD lpBytesRead, DWORD nTimeout)
1458 TRACE("%s %p %ld %p %ld %p %ld\n",
1459 debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1460 lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1462 if( lpNamedPipeName )
1464 len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1465 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1466 MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1468 ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1469 dwOutputSize, lpBytesRead, nTimeout );
1470 if( lpNamedPipeName )
1471 HeapFree( GetProcessHeap(), 0, str );
1476 /***********************************************************************
1477 * CallNamedPipeW (KERNEL32.@)
1479 BOOL WINAPI CallNamedPipeW(
1480 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1481 LPVOID lpOutput, DWORD lpOutputSize,
1482 LPDWORD lpBytesRead, DWORD nTimeout)
1484 FIXME("%s %p %ld %p %ld %p %ld\n",
1485 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1486 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1490 /******************************************************************
1491 * CreatePipe (KERNEL32.@)
1494 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1495 LPSECURITY_ATTRIBUTES sa, DWORD size )
1497 static unsigned index = 0;
1500 unsigned in_index = index;
1502 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1503 /* generate a unique pipe name (system wide) */
1506 static const WCHAR nameFmt[] = { '\\','\\','.','\\','p','i','p','e',
1507 '\\','W','i','n','3','2','.','P','i','p','e','s','.','%','0','8','l',
1508 'u','.','%','0','8','u','\0' };
1509 snprintfW(name, sizeof(name) / sizeof(name[0]), nameFmt,
1510 GetCurrentProcessId(), ++index);
1511 hr = CreateNamedPipeW(name, PIPE_ACCESS_INBOUND,
1512 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1513 NMPWAIT_USE_DEFAULT_WAIT, sa);
1514 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1515 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1516 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1518 hw = CreateFileW(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1519 if (hw == INVALID_HANDLE_VALUE)
1531 /******************************************************************************
1532 * CreateMailslotA [KERNEL32.@]
1534 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1535 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1541 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1542 nMaxMessageSize, lReadTimeout, sa);
1546 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1547 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1548 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1551 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1553 HeapFree( GetProcessHeap(), 0, name );
1559 /******************************************************************************
1560 * CreateMailslotW [KERNEL32.@]
1562 * Create a mailslot with specified name.
1565 * lpName [I] Pointer to string for mailslot name
1566 * nMaxMessageSize [I] Maximum message size
1567 * lReadTimeout [I] Milliseconds before read time-out
1568 * sa [I] Pointer to security structure
1571 * Success: Handle to mailslot
1572 * Failure: INVALID_HANDLE_VALUE
1574 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1575 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1577 FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1578 nMaxMessageSize, lReadTimeout, sa);
1579 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1580 return INVALID_HANDLE_VALUE;
1584 /******************************************************************************
1585 * GetMailslotInfo [KERNEL32.@]
1587 * Retrieve information about a mailslot.
1590 * hMailslot [I] Mailslot handle
1591 * lpMaxMessageSize [O] Address of maximum message size
1592 * lpNextSize [O] Address of size of next message
1593 * lpMessageCount [O] Address of number of messages
1594 * lpReadTimeout [O] Address of read time-out
1600 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1601 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1602 LPDWORD lpReadTimeout )
1604 FIXME("(%p): stub\n",hMailslot);
1605 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1610 /******************************************************************************
1611 * SetMailslotInfo [KERNEL32.@]
1613 * Set the read timeout of a mailslot.
1616 * hMailslot [I] Mailslot handle
1617 * dwReadTimeout [I] Timeout in milliseconds.
1623 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1625 FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1626 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1631 /******************************************************************************
1632 * CreateIoCompletionPort (KERNEL32.@)
1634 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1635 ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
1637 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1638 hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
1643 /******************************************************************************
1644 * GetQueuedCompletionStatus (KERNEL32.@)
1646 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1647 PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
1648 DWORD dwMilliseconds )
1650 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1651 CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
1652 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1656 /******************************************************************************
1657 * CreateJobObjectW (KERNEL32.@)
1659 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1661 FIXME("%p %s\n", attr, debugstr_w(name) );
1662 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1666 /******************************************************************************
1667 * CreateJobObjectA (KERNEL32.@)
1669 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1675 TRACE("%p %s\n", attr, debugstr_a(name) );
1679 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1680 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1683 SetLastError( ERROR_OUTOFMEMORY );
1686 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1689 r = CreateJobObjectW( attr, str );
1691 HeapFree( GetProcessHeap(), 0, str );
1696 /******************************************************************************
1697 * AssignProcessToJobObject (KERNEL32.@)
1699 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1701 FIXME("%p %p\n", hJob, hProcess);
1707 /***********************************************************************
1708 * InterlockedCompareExchange (KERNEL32.@)
1710 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1711 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1712 "movl 12(%esp),%eax\n\t"
1713 "movl 8(%esp),%ecx\n\t"
1714 "movl 4(%esp),%edx\n\t"
1715 "lock; cmpxchgl %ecx,(%edx)\n\t"
1718 /***********************************************************************
1719 * InterlockedExchange (KERNEL32.@)
1721 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1722 __ASM_GLOBAL_FUNC(InterlockedExchange,
1723 "movl 8(%esp),%eax\n\t"
1724 "movl 4(%esp),%edx\n\t"
1725 "lock; xchgl %eax,(%edx)\n\t"
1728 /***********************************************************************
1729 * InterlockedExchangeAdd (KERNEL32.@)
1731 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1732 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1733 "movl 8(%esp),%eax\n\t"
1734 "movl 4(%esp),%edx\n\t"
1735 "lock; xaddl %eax,(%edx)\n\t"
1738 /***********************************************************************
1739 * InterlockedIncrement (KERNEL32.@)
1741 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1742 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1743 "movl 4(%esp),%edx\n\t"
1745 "lock; xaddl %eax,(%edx)\n\t"
1749 /***********************************************************************
1750 * InterlockedDecrement (KERNEL32.@)
1752 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1753 "movl 4(%esp),%edx\n\t"
1755 "lock; xaddl %eax,(%edx)\n\t"
1759 #else /* __i386__ */
1761 /***********************************************************************
1762 * InterlockedCompareExchange (KERNEL32.@)
1764 * Atomically swap one value with another.
1767 * dest [I/O] The value to replace
1768 * xchq [I] The value to be swapped
1769 * compare [I] The value to compare to dest
1772 * The resulting value of dest.
1775 * dest is updated only if it is equal to compare, otherwise no swap is done.
1777 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1779 return interlocked_cmpxchg( dest, xchg, compare );
1782 /***********************************************************************
1783 * InterlockedExchange (KERNEL32.@)
1785 * Atomically swap one value with another.
1788 * dest [I/O] The value to replace
1789 * val [I] The value to be swapped
1792 * The resulting value of dest.
1794 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1796 return interlocked_xchg( dest, val );
1799 /***********************************************************************
1800 * InterlockedExchangeAdd (KERNEL32.@)
1802 * Atomically add one value to another.
1805 * dest [I/O] The value to add to
1806 * incr [I] The value to be added
1809 * The resulting value of dest.
1811 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1813 return interlocked_xchg_add( dest, incr );
1816 /***********************************************************************
1817 * InterlockedIncrement (KERNEL32.@)
1819 * Atomically increment a value.
1822 * dest [I/O] The value to increment
1825 * The resulting value of dest.
1827 LONG WINAPI InterlockedIncrement( PLONG dest )
1829 return interlocked_xchg_add( dest, 1 ) + 1;
1832 /***********************************************************************
1833 * InterlockedDecrement (KERNEL32.@)
1835 * Atomically decrement a value.
1838 * dest [I/O] The value to decrement
1841 * The resulting value of dest.
1843 LONG WINAPI InterlockedDecrement( PLONG dest )
1845 return interlocked_xchg_add( dest, -1 ) - 1;
1848 #endif /* __i386__ */