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>
32 #ifdef HAVE_SYS_POLL_H
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
49 #include "wine/server.h"
50 #include "wine/unicode.h"
51 #include "wine/winbase16.h"
52 #include "kernel_private.h"
54 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(sync);
58 /* check if current version is NT or Win95 */
59 inline static int is_version_nt(void)
61 return !(GetVersion() & 0x80000000);
65 /***********************************************************************
68 VOID WINAPI Sleep( DWORD timeout )
70 SleepEx( timeout, FALSE );
73 /******************************************************************************
74 * SleepEx (KERNEL32.@)
76 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
80 if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
85 time.QuadPart = timeout * (ULONGLONG)10000;
86 time.QuadPart = -time.QuadPart;
87 status = NtDelayExecution( alertable, &time );
89 if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
94 /***********************************************************************
95 * WaitForSingleObject (KERNEL32.@)
97 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
99 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
103 /***********************************************************************
104 * WaitForSingleObjectEx (KERNEL32.@)
106 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
109 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
113 /***********************************************************************
114 * WaitForMultipleObjects (KERNEL32.@)
116 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
117 BOOL wait_all, DWORD timeout )
119 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
123 /***********************************************************************
124 * WaitForMultipleObjectsEx (KERNEL32.@)
126 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
127 BOOL wait_all, DWORD timeout,
131 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
134 if (count >= MAXIMUM_WAIT_OBJECTS)
136 SetLastError(ERROR_INVALID_PARAMETER);
139 for (i = 0; i < count; i++)
141 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
142 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
143 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
144 hloc[i] = GetStdHandle( (DWORD)handles[i] );
146 hloc[i] = handles[i];
148 /* yes, even screen buffer console handles are waitable, and are
149 * handled as a handle to the console itself !!
151 if (is_console_handle(hloc[i]))
153 if (!VerifyConsoleIoHandle(hloc[i]))
157 hloc[i] = GetConsoleInputWaitHandle();
161 if (timeout == INFINITE)
163 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
169 time.QuadPart = timeout * (ULONGLONG)10000;
170 time.QuadPart = -time.QuadPart;
171 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
174 if (HIWORD(status)) /* is it an error code? */
176 SetLastError( RtlNtStatusToDosError(status) );
177 status = WAIT_FAILED;
183 /***********************************************************************
184 * WaitForSingleObject (KERNEL.460)
186 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
188 DWORD retval, mutex_count;
190 ReleaseThunkLock( &mutex_count );
191 retval = WaitForSingleObject( handle, timeout );
192 RestoreThunkLock( mutex_count );
196 /***********************************************************************
197 * WaitForMultipleObjects (KERNEL.461)
199 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
200 BOOL wait_all, DWORD timeout )
202 DWORD retval, mutex_count;
204 ReleaseThunkLock( &mutex_count );
205 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
206 RestoreThunkLock( mutex_count );
210 /***********************************************************************
211 * WaitForMultipleObjectsEx (KERNEL.495)
213 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
214 BOOL wait_all, DWORD timeout, BOOL alertable )
216 DWORD retval, mutex_count;
218 ReleaseThunkLock( &mutex_count );
219 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
220 RestoreThunkLock( mutex_count );
224 /***********************************************************************
225 * RegisterWaitForSingleObject (KERNEL32.@)
227 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
228 WAITORTIMERCALLBACK Callback, PVOID Context,
229 ULONG dwMilliseconds, ULONG dwFlags)
231 FIXME("%p %p %p %p %ld %ld\n",
232 phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
236 /***********************************************************************
237 * RegisterWaitForSingleObjectEx (KERNEL32.@)
239 HANDLE WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject,
240 WAITORTIMERCALLBACK Callback, PVOID Context,
241 ULONG dwMilliseconds, ULONG dwFlags )
243 FIXME("%p %p %p %ld %ld\n",
244 hObject,Callback,Context,dwMilliseconds,dwFlags);
248 /***********************************************************************
249 * UnregisterWait (KERNEL32.@)
251 BOOL WINAPI UnregisterWait( HANDLE WaitHandle )
253 FIXME("%p\n",WaitHandle);
257 /***********************************************************************
258 * UnregisterWaitEx (KERNEL32.@)
260 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
262 FIXME("%p %p\n",WaitHandle, CompletionEvent);
266 /***********************************************************************
267 * SignalObjectAndWait (KERNEL32.@)
269 * Allows to atomically signal any of the synchro objects (semaphore,
270 * mutex, event) and wait on another.
272 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
274 FIXME("(%p %p %ld %d): stub\n", hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable);
275 return WAIT_OBJECT_0;
279 /***********************************************************************
280 * InitializeCriticalSection (KERNEL32.@)
282 * Initialise a critical section before use.
285 * crit [O] Critical section to initialise.
288 * Nothing. If the function fails an exception is raised.
290 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
292 NTSTATUS ret = RtlInitializeCriticalSection( crit );
293 if (ret) RtlRaiseStatus( ret );
296 /***********************************************************************
297 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
299 * Initialise a critical section with a spin count.
302 * crit [O] Critical section to initialise.
303 * spincount [I] Number of times to spin upon contention.
307 * Failure: Nothing. If the function fails an exception is raised.
310 * spincount is ignored on uni-processor systems.
312 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
314 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
315 if (ret) RtlRaiseStatus( ret );
319 /***********************************************************************
320 * SetCriticalSectionSpinCount (KERNEL32.@)
322 * Set the spin count for a critical section.
325 * crit [O] Critical section to set the spin count for.
326 * spincount [I] Number of times to spin upon contention.
329 * The previous spin count value of crit.
332 * This function is available on NT4SP3 or later, but not Win98.
334 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
336 ULONG_PTR oldspincount = crit->SpinCount;
337 if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
338 crit->SpinCount = spincount;
342 /***********************************************************************
343 * MakeCriticalSectionGlobal (KERNEL32.@)
345 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
347 /* let's assume that only one thread at a time will try to do this */
348 HANDLE sem = crit->LockSemaphore;
349 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
350 crit->LockSemaphore = ConvertToGlobalHandle( sem );
353 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
354 crit->DebugInfo = NULL;
359 /***********************************************************************
360 * ReinitializeCriticalSection (KERNEL32.@)
362 * Initialise an already used critical section.
365 * crit [O] Critical section to initialise.
370 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
372 if ( !crit->LockSemaphore )
373 RtlInitializeCriticalSection( crit );
377 /***********************************************************************
378 * UninitializeCriticalSection (KERNEL32.@)
380 * UnInitialise a critical section after use.
383 * crit [O] Critical section to uninitialise (destroy).
388 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
390 RtlDeleteCriticalSection( crit );
394 /***********************************************************************
395 * CreateEventA (KERNEL32.@)
397 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
398 BOOL initial_state, LPCSTR name )
400 WCHAR buffer[MAX_PATH];
402 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
404 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
406 SetLastError( ERROR_FILENAME_EXCED_RANGE );
409 return CreateEventW( sa, manual_reset, initial_state, buffer );
413 /***********************************************************************
414 * CreateEventW (KERNEL32.@)
416 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
417 BOOL initial_state, LPCWSTR name )
420 DWORD len = name ? strlenW(name) : 0;
423 SetLastError( ERROR_FILENAME_EXCED_RANGE );
426 /* one buggy program needs this
427 * ("Van Dale Groot woordenboek der Nederlandse taal")
429 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
431 ERR("Bad security attributes pointer %p\n",sa);
432 SetLastError( ERROR_INVALID_PARAMETER);
435 SERVER_START_REQ( create_event )
437 req->manual_reset = manual_reset;
438 req->initial_state = initial_state;
439 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
440 wine_server_add_data( req, name, len * sizeof(WCHAR) );
442 wine_server_call_err( req );
450 /***********************************************************************
451 * CreateW32Event (KERNEL.457)
453 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
455 return CreateEventA( NULL, manual_reset, initial_state, NULL );
459 /***********************************************************************
460 * OpenEventA (KERNEL32.@)
462 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
464 WCHAR buffer[MAX_PATH];
466 if (!name) return OpenEventW( access, inherit, NULL );
468 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
470 SetLastError( ERROR_FILENAME_EXCED_RANGE );
473 return OpenEventW( access, inherit, buffer );
477 /***********************************************************************
478 * OpenEventW (KERNEL32.@)
480 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
483 DWORD len = name ? strlenW(name) : 0;
486 SetLastError( ERROR_FILENAME_EXCED_RANGE );
489 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
491 SERVER_START_REQ( open_event )
493 req->access = access;
494 req->inherit = inherit;
495 wine_server_add_data( req, name, len * sizeof(WCHAR) );
496 wine_server_call_err( req );
503 /***********************************************************************
504 * PulseEvent (KERNEL32.@)
506 BOOL WINAPI PulseEvent( HANDLE handle )
510 if ((status = NtPulseEvent( handle, NULL )))
511 SetLastError( RtlNtStatusToDosError(status) );
516 /***********************************************************************
517 * SetW32Event (KERNEL.458)
518 * SetEvent (KERNEL32.@)
520 BOOL WINAPI SetEvent( HANDLE handle )
524 if ((status = NtSetEvent( handle, NULL )))
525 SetLastError( RtlNtStatusToDosError(status) );
530 /***********************************************************************
531 * ResetW32Event (KERNEL.459)
532 * ResetEvent (KERNEL32.@)
534 BOOL WINAPI ResetEvent( HANDLE handle )
538 if ((status = NtResetEvent( handle, NULL )))
539 SetLastError( RtlNtStatusToDosError(status) );
544 /***********************************************************************
545 * NOTE: The Win95 VWin32_Event routines given below are really low-level
546 * routines implemented directly by VWin32. The user-mode libraries
547 * implement Win32 synchronisation routines on top of these low-level
548 * primitives. We do it the other way around here :-)
551 /***********************************************************************
552 * VWin32_EventCreate (KERNEL.442)
554 HANDLE WINAPI VWin32_EventCreate(VOID)
556 HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
557 return ConvertToGlobalHandle( hEvent );
560 /***********************************************************************
561 * VWin32_EventDestroy (KERNEL.443)
563 VOID WINAPI VWin32_EventDestroy(HANDLE event)
565 CloseHandle( event );
568 /***********************************************************************
569 * VWin32_EventWait (KERNEL.450)
571 VOID WINAPI VWin32_EventWait(HANDLE event)
575 ReleaseThunkLock( &mutex_count );
576 WaitForSingleObject( event, INFINITE );
577 RestoreThunkLock( mutex_count );
580 /***********************************************************************
581 * VWin32_EventSet (KERNEL.451)
582 * KERNEL_479 (KERNEL.479)
584 VOID WINAPI VWin32_EventSet(HANDLE event)
591 /***********************************************************************
592 * CreateMutexA (KERNEL32.@)
594 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
596 WCHAR buffer[MAX_PATH];
598 if (!name) return CreateMutexW( sa, owner, NULL );
600 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
602 SetLastError( ERROR_FILENAME_EXCED_RANGE );
605 return CreateMutexW( sa, owner, buffer );
609 /***********************************************************************
610 * CreateMutexW (KERNEL32.@)
612 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
615 DWORD len = name ? strlenW(name) : 0;
618 SetLastError( ERROR_FILENAME_EXCED_RANGE );
621 SERVER_START_REQ( create_mutex )
624 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
625 wine_server_add_data( req, name, len * sizeof(WCHAR) );
627 wine_server_call_err( req );
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 DWORD len = name ? strlenW(name) : 0;
662 SetLastError( ERROR_FILENAME_EXCED_RANGE );
665 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
667 SERVER_START_REQ( open_mutex )
669 req->access = access;
670 req->inherit = inherit;
671 wine_server_add_data( req, name, len * sizeof(WCHAR) );
672 wine_server_call_err( req );
680 /***********************************************************************
681 * ReleaseMutex (KERNEL32.@)
683 BOOL WINAPI ReleaseMutex( HANDLE handle )
686 SERVER_START_REQ( release_mutex )
688 req->handle = handle;
689 ret = !wine_server_call_err( req );
701 /***********************************************************************
702 * CreateSemaphoreA (KERNEL32.@)
704 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
706 WCHAR buffer[MAX_PATH];
708 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
710 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
712 SetLastError( ERROR_FILENAME_EXCED_RANGE );
715 return CreateSemaphoreW( sa, initial, max, buffer );
719 /***********************************************************************
720 * CreateSemaphoreW (KERNEL32.@)
722 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
723 LONG max, LPCWSTR name )
726 DWORD len = name ? strlenW(name) : 0;
728 /* Check parameters */
730 if ((max <= 0) || (initial < 0) || (initial > max))
732 SetLastError( ERROR_INVALID_PARAMETER );
737 SetLastError( ERROR_FILENAME_EXCED_RANGE );
741 SERVER_START_REQ( create_semaphore )
743 req->initial = (unsigned int)initial;
744 req->max = (unsigned int)max;
745 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
746 wine_server_add_data( req, name, len * sizeof(WCHAR) );
748 wine_server_call_err( req );
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 DWORD len = name ? strlenW(name) : 0;
783 SetLastError( ERROR_FILENAME_EXCED_RANGE );
786 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
788 SERVER_START_REQ( open_semaphore )
790 req->access = access;
791 req->inherit = inherit;
792 wine_server_add_data( req, name, len * sizeof(WCHAR) );
793 wine_server_call_err( req );
801 /***********************************************************************
802 * ReleaseSemaphore (KERNEL32.@)
804 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
806 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
807 if (status) SetLastError( RtlNtStatusToDosError(status) );
817 /***********************************************************************
818 * CreateWaitableTimerA (KERNEL32.@)
820 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
822 WCHAR buffer[MAX_PATH];
824 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
826 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
828 SetLastError( ERROR_FILENAME_EXCED_RANGE );
831 return CreateWaitableTimerW( sa, manual, buffer );
835 /***********************************************************************
836 * CreateWaitableTimerW (KERNEL32.@)
838 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
844 OBJECT_ATTRIBUTES oa;
846 if (name) RtlInitUnicodeString(&us, name);
847 if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
849 InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
850 NULL /* FIXME */, NULL /* FIXME */);
851 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
852 manual ? NotificationTimer : SynchronizationTimer);
854 if (status != STATUS_SUCCESS)
856 SetLastError( RtlNtStatusToDosError(status) );
863 /***********************************************************************
864 * OpenWaitableTimerA (KERNEL32.@)
866 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
868 WCHAR buffer[MAX_PATH];
870 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
872 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
874 SetLastError( ERROR_FILENAME_EXCED_RANGE );
877 return OpenWaitableTimerW( access, inherit, buffer );
881 /***********************************************************************
882 * OpenWaitableTimerW (KERNEL32.@)
884 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
890 OBJECT_ATTRIBUTES oa;
892 if (inherit) attr |= OBJ_INHERIT;
894 if (name) RtlInitUnicodeString(&us, name);
895 InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
896 status = NtOpenTimer(&handle, access, &oa);
897 if (status != STATUS_SUCCESS)
899 SetLastError( RtlNtStatusToDosError(status) );
906 /***********************************************************************
907 * SetWaitableTimer (KERNEL32.@)
909 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
910 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
912 NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
914 if (status != STATUS_SUCCESS)
916 SetLastError( RtlNtStatusToDosError(status) );
917 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
923 /***********************************************************************
924 * CancelWaitableTimer (KERNEL32.@)
926 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
930 status = NtCancelTimer(handle, NULL);
931 if (status != STATUS_SUCCESS)
933 SetLastError( RtlNtStatusToDosError(status) );
940 /***********************************************************************
941 * CreateTimerQueue (KERNEL32.@)
943 HANDLE WINAPI CreateTimerQueue(void)
946 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
951 /***********************************************************************
952 * DeleteTimerQueueEx (KERNEL32.@)
954 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
956 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
957 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
961 /***********************************************************************
962 * CreateTimerQueueTimer (KERNEL32.@)
964 * Creates a timer-queue timer. This timer expires at the specified due
965 * time (in ms), then after every specified period (in ms). When the timer
966 * expires, the callback function is called.
969 * nonzero on success or zero on faillure
974 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
975 WAITORTIMERCALLBACK Callback, PVOID Parameter,
976 DWORD DueTime, DWORD Period, ULONG Flags )
979 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
983 /***********************************************************************
984 * DeleteTimerQueueTimer (KERNEL32.@)
986 * Cancels a timer-queue timer.
989 * nonzero on success or zero on faillure
994 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
995 HANDLE CompletionEvent )
998 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1008 /***********************************************************************
1009 * CreateNamedPipeA (KERNEL32.@)
1011 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
1012 DWORD dwPipeMode, DWORD nMaxInstances,
1013 DWORD nOutBufferSize, DWORD nInBufferSize,
1014 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1016 WCHAR buffer[MAX_PATH];
1018 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1019 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1021 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1023 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1024 return INVALID_HANDLE_VALUE;
1026 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1027 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1031 /***********************************************************************
1032 * CreateNamedPipeW (KERNEL32.@)
1034 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1035 DWORD dwPipeMode, DWORD nMaxInstances,
1036 DWORD nOutBufferSize, DWORD nInBufferSize,
1037 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1040 UNICODE_STRING nt_name;
1041 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1043 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1044 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1045 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1047 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1049 SetLastError( ERROR_PATH_NOT_FOUND );
1050 return INVALID_HANDLE_VALUE;
1052 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1054 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1055 RtlFreeUnicodeString( &nt_name );
1056 return INVALID_HANDLE_VALUE;
1058 if (nt_name.Length < sizeof(leadin) ||
1059 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1061 SetLastError( ERROR_INVALID_NAME );
1062 RtlFreeUnicodeString( &nt_name );
1063 return INVALID_HANDLE_VALUE;
1065 SERVER_START_REQ( create_named_pipe )
1067 req->openmode = dwOpenMode;
1068 req->pipemode = dwPipeMode;
1069 req->maxinstances = nMaxInstances;
1070 req->outsize = nOutBufferSize;
1071 req->insize = nInBufferSize;
1072 req->timeout = nDefaultTimeOut;
1073 req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1074 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1076 if (!wine_server_call_err( req )) ret = reply->handle;
1077 else ret = INVALID_HANDLE_VALUE;
1080 RtlFreeUnicodeString( &nt_name );
1085 /***********************************************************************
1086 * PeekNamedPipe (KERNEL32.@)
1088 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1089 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1092 int avail=0, fd, ret, flags;
1094 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, NULL, &flags );
1097 SetLastError( RtlNtStatusToDosError(ret) );
1100 if (flags & FD_FLAG_RECV_SHUTDOWN)
1102 wine_server_release_fd( hPipe, fd );
1103 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1107 if (ioctl(fd,FIONREAD, &avail ) != 0)
1109 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1110 wine_server_release_fd( hPipe, fd );
1113 if (!avail) /* check for closed pipe */
1115 struct pollfd pollfd;
1117 pollfd.events = POLLIN;
1119 switch (poll( &pollfd, 1, 0 ))
1123 case 1: /* got something */
1124 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1125 TRACE("POLLHUP | POLLERR\n");
1128 wine_server_release_fd( hPipe, fd );
1129 SetLastError(ERROR_BROKEN_PIPE);
1133 TRACE(" 0x%08x bytes available\n", avail );
1139 if (avail && lpvBuffer)
1141 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1142 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1145 WARN("failed to peek socket (%d)\n", errno);
1149 *lpcbRead = readbytes;
1151 wine_server_release_fd( hPipe, fd );
1153 #endif /* defined(FIONREAD) */
1155 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1156 FIXME("function not implemented\n");
1160 /***********************************************************************
1161 * SYNC_CompletePipeOverlapped (Internal)
1163 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1165 TRACE("for %p result %08lx\n",overlapped,result);
1168 overlapped->Internal = result;
1169 SetEvent(overlapped->hEvent);
1173 /***********************************************************************
1174 * WaitNamedPipeA (KERNEL32.@)
1176 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1178 WCHAR buffer[MAX_PATH];
1180 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1182 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1184 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1187 return WaitNamedPipeW( buffer, nTimeOut );
1191 /***********************************************************************
1192 * WaitNamedPipeW (KERNEL32.@)
1194 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1196 DWORD len = name ? strlenW(name) : 0;
1200 if (len >= MAX_PATH)
1202 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1206 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1208 memset(&ov,0,sizeof(ov));
1209 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1213 SERVER_START_REQ( wait_named_pipe )
1215 req->timeout = nTimeOut;
1216 req->overlapped = &ov;
1217 req->func = SYNC_CompletePipeOverlapped;
1218 wine_server_add_data( req, name, len * sizeof(WCHAR) );
1219 ret = !wine_server_call_err( req );
1225 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1227 SetLastError(ov.Internal);
1228 ret = (ov.Internal==STATUS_SUCCESS);
1231 CloseHandle(ov.hEvent);
1236 /***********************************************************************
1237 * SYNC_ConnectNamedPipe (Internal)
1239 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1246 overlapped->Internal = STATUS_PENDING;
1248 SERVER_START_REQ( connect_named_pipe )
1250 req->handle = hPipe;
1251 req->overlapped = overlapped;
1252 req->func = SYNC_CompletePipeOverlapped;
1253 ret = !wine_server_call_err( req );
1260 /***********************************************************************
1261 * ConnectNamedPipe (KERNEL32.@)
1263 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1268 TRACE("(%p,%p)\n",hPipe, overlapped);
1272 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1273 SetLastError( ERROR_IO_PENDING );
1277 memset(&ov,0,sizeof(ov));
1278 ov.hEvent = CreateEventA(NULL,0,0,NULL);
1282 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1285 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1287 SetLastError(ov.Internal);
1288 ret = (ov.Internal==STATUS_SUCCESS);
1292 CloseHandle(ov.hEvent);
1297 /***********************************************************************
1298 * DisconnectNamedPipe (KERNEL32.@)
1300 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1304 TRACE("(%p)\n",hPipe);
1306 SERVER_START_REQ( disconnect_named_pipe )
1308 req->handle = hPipe;
1309 ret = !wine_server_call_err( req );
1310 if (ret && reply->fd != -1) close( reply->fd );
1317 /***********************************************************************
1318 * TransactNamedPipe (KERNEL32.@)
1320 BOOL WINAPI TransactNamedPipe(
1321 HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1322 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1324 FIXME("%p %p %ld %p %ld %p %p\n",
1325 hPipe, lpInput, dwInputSize, lpOutput,
1326 dwOutputSize, lpBytesRead, lpOverlapped);
1332 /***********************************************************************
1333 * GetNamedPipeInfo (KERNEL32.@)
1335 BOOL WINAPI GetNamedPipeInfo(
1336 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1337 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1341 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1342 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1344 SERVER_START_REQ( get_named_pipe_info )
1346 req->handle = hNamedPipe;
1347 ret = !wine_server_call_err( req );
1348 if(lpFlags) *lpFlags = reply->flags;
1349 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1350 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1351 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1358 /***********************************************************************
1359 * GetNamedPipeHandleStateA (KERNEL32.@)
1361 BOOL WINAPI GetNamedPipeHandleStateA(
1362 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1363 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1364 LPSTR lpUsername, DWORD nUsernameMaxSize)
1366 FIXME("%p %p %p %p %p %p %ld\n",
1367 hNamedPipe, lpState, lpCurInstances,
1368 lpMaxCollectionCount, lpCollectDataTimeout,
1369 lpUsername, nUsernameMaxSize);
1374 /***********************************************************************
1375 * GetNamedPipeHandleStateW (KERNEL32.@)
1377 BOOL WINAPI GetNamedPipeHandleStateW(
1378 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1379 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1380 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1382 FIXME("%p %p %p %p %p %p %ld\n",
1383 hNamedPipe, lpState, lpCurInstances,
1384 lpMaxCollectionCount, lpCollectDataTimeout,
1385 lpUsername, nUsernameMaxSize);
1390 /***********************************************************************
1391 * SetNamedPipeHandleState (KERNEL32.@)
1393 BOOL WINAPI SetNamedPipeHandleState(
1394 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1395 LPDWORD lpCollectDataTimeout)
1397 FIXME("%p %p %p %p\n",
1398 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1402 /***********************************************************************
1403 * CallNamedPipeA (KERNEL32.@)
1405 BOOL WINAPI CallNamedPipeA(
1406 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1407 LPVOID lpOutput, DWORD lpOutputSize,
1408 LPDWORD lpBytesRead, DWORD nTimeout)
1410 FIXME("%s %p %ld %p %ld %p %ld\n",
1411 debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1412 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1416 /***********************************************************************
1417 * CallNamedPipeW (KERNEL32.@)
1419 BOOL WINAPI CallNamedPipeW(
1420 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1421 LPVOID lpOutput, DWORD lpOutputSize,
1422 LPDWORD lpBytesRead, DWORD nTimeout)
1424 FIXME("%s %p %ld %p %ld %p %ld\n",
1425 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1426 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1430 /******************************************************************
1431 * CreatePipe (KERNEL32.@)
1434 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1435 LPSECURITY_ATTRIBUTES sa, DWORD size )
1437 static unsigned index = 0;
1440 unsigned in_index = index;
1442 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1443 /* generate a unique pipe name (system wide) */
1446 sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1447 hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND,
1448 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1449 NMPWAIT_USE_DEFAULT_WAIT, sa);
1450 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1451 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1452 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1454 hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1455 if (hw == INVALID_HANDLE_VALUE)
1467 /******************************************************************************
1468 * CreateMailslotA [KERNEL32.@]
1470 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1471 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1477 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1478 nMaxMessageSize, lReadTimeout, sa);
1482 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1483 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1484 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1487 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1490 HeapFree( GetProcessHeap(), 0, name );
1496 /******************************************************************************
1497 * CreateMailslotW [KERNEL32.@]
1499 * Create a mailslot with specified name.
1502 * lpName [I] Pointer to string for mailslot name
1503 * nMaxMessageSize [I] Maximum message size
1504 * lReadTimeout [I] Milliseconds before read time-out
1505 * sa [I] Pointer to security structure
1508 * Success: Handle to mailslot
1509 * Failure: INVALID_HANDLE_VALUE
1511 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1512 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1514 FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1515 nMaxMessageSize, lReadTimeout, sa);
1516 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1517 return INVALID_HANDLE_VALUE;
1521 /******************************************************************************
1522 * GetMailslotInfo [KERNEL32.@]
1524 * Retrieve information about a mailslot.
1527 * hMailslot [I] Mailslot handle
1528 * lpMaxMessageSize [O] Address of maximum message size
1529 * lpNextSize [O] Address of size of next message
1530 * lpMessageCount [O] Address of number of messages
1531 * lpReadTimeout [O] Address of read time-out
1537 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1538 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1539 LPDWORD lpReadTimeout )
1541 FIXME("(%p): stub\n",hMailslot);
1542 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1547 /******************************************************************************
1548 * SetMailslotInfo [KERNEL32.@]
1550 * Set the read timeout of a mailslot.
1553 * hMailslot [I] Mailslot handle
1554 * dwReadTimeout [I] Timeout in milliseconds.
1560 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1562 FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1563 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1568 /******************************************************************************
1569 * CreateIoCompletionPort (KERNEL32.@)
1571 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1572 DWORD dwCompletionKey, DWORD dwNumberOfConcurrentThreads)
1574 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1575 hFileHandle, hExistingCompletionPort, dwCompletionKey, dwNumberOfConcurrentThreads);
1580 /******************************************************************************
1581 * GetQueuedCompletionStatus (KERNEL32.@)
1583 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1584 LPDWORD lpCompletionKey, LPOVERLAPPED *lpOverlapped,
1585 DWORD dwMilliseconds )
1587 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1588 CompletionPort,lpNumberOfBytesTransferred,lpCompletionKey,lpOverlapped,dwMilliseconds);
1589 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1593 /******************************************************************************
1594 * CreateJobObjectW (KERNEL32.@)
1596 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1598 FIXME("%p %s\n", attr, debugstr_w(name) );
1599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1603 /******************************************************************************
1604 * CreateJobObjectA (KERNEL32.@)
1606 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1612 TRACE("%p %s\n", attr, debugstr_a(name) );
1616 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1617 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1620 SetLastError( ERROR_OUTOFMEMORY );
1623 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1626 r = CreateJobObjectW( attr, str );
1629 HeapFree( GetProcessHeap(), 0, str );
1634 /******************************************************************************
1635 * AssignProcessToJobObject (KERNEL32.@)
1637 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1639 FIXME("%p %p\n", hJob, hProcess);
1645 /***********************************************************************
1646 * InterlockedCompareExchange (KERNEL32.@)
1648 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1649 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1650 "movl 12(%esp),%eax\n\t"
1651 "movl 8(%esp),%ecx\n\t"
1652 "movl 4(%esp),%edx\n\t"
1653 "lock; cmpxchgl %ecx,(%edx)\n\t"
1656 /***********************************************************************
1657 * InterlockedExchange (KERNEL32.@)
1659 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1660 __ASM_GLOBAL_FUNC(InterlockedExchange,
1661 "movl 8(%esp),%eax\n\t"
1662 "movl 4(%esp),%edx\n\t"
1663 "lock; xchgl %eax,(%edx)\n\t"
1666 /***********************************************************************
1667 * InterlockedExchangeAdd (KERNEL32.@)
1669 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1670 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1671 "movl 8(%esp),%eax\n\t"
1672 "movl 4(%esp),%edx\n\t"
1673 "lock; xaddl %eax,(%edx)\n\t"
1676 /***********************************************************************
1677 * InterlockedIncrement (KERNEL32.@)
1679 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1680 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1681 "movl 4(%esp),%edx\n\t"
1683 "lock; xaddl %eax,(%edx)\n\t"
1687 /***********************************************************************
1688 * InterlockedDecrement (KERNEL32.@)
1690 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1691 "movl 4(%esp),%edx\n\t"
1693 "lock; xaddl %eax,(%edx)\n\t"
1697 #else /* __i386__ */
1699 /***********************************************************************
1700 * InterlockedCompareExchange (KERNEL32.@)
1702 * Atomically swap one value with another.
1705 * dest [I/O] The value to replace
1706 * xchq [I] The value to be swapped
1707 * compare [I] The value to compare to dest
1710 * The resulting value of dest.
1713 * dest is updated only if it is equal to compare, otherwise no swap is done.
1715 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1717 return interlocked_cmpxchg( dest, xchg, compare );
1720 /***********************************************************************
1721 * InterlockedExchange (KERNEL32.@)
1723 * Atomically swap one value with another.
1726 * dest [I/O] The value to replace
1727 * val [I] The value to be swapped
1730 * The resulting value of dest.
1732 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1734 return interlocked_xchg( dest, val );
1737 /***********************************************************************
1738 * InterlockedExchangeAdd (KERNEL32.@)
1740 * Atomically add one value to another.
1743 * dest [I/O] The value to add to
1744 * incr [I] The value to be added
1747 * The resulting value of dest.
1749 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1751 return interlocked_xchg_add( dest, incr );
1754 /***********************************************************************
1755 * InterlockedIncrement (KERNEL32.@)
1757 * Atomically increment a value.
1760 * dest [I/O] The value to increment
1763 * The resulting value of dest.
1765 LONG WINAPI InterlockedIncrement( PLONG dest )
1767 return interlocked_xchg_add( dest, 1 ) + 1;
1770 /***********************************************************************
1771 * InterlockedDecrement (KERNEL32.@)
1773 * Atomically decrement a value.
1776 * dest [I/O] The value to decrement
1779 * The resulting value of dest.
1781 LONG WINAPI InterlockedDecrement( PLONG dest )
1783 return interlocked_xchg_add( dest, -1 ) - 1;
1786 #endif /* __i386__ */