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 * SwitchToThread (KERNEL32.@)
97 BOOL WINAPI SwitchToThread(void)
99 return (NtYieldExecution() != STATUS_NO_YIELD_PERFORMED);
103 /***********************************************************************
104 * WaitForSingleObject (KERNEL32.@)
106 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
108 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
112 /***********************************************************************
113 * WaitForSingleObjectEx (KERNEL32.@)
115 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
118 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
122 /***********************************************************************
123 * WaitForMultipleObjects (KERNEL32.@)
125 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
126 BOOL wait_all, DWORD timeout )
128 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
132 /***********************************************************************
133 * WaitForMultipleObjectsEx (KERNEL32.@)
135 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
136 BOOL wait_all, DWORD timeout,
140 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
143 if (count >= MAXIMUM_WAIT_OBJECTS)
145 SetLastError(ERROR_INVALID_PARAMETER);
148 for (i = 0; i < count; i++)
150 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
151 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
152 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
153 hloc[i] = GetStdHandle( (DWORD)handles[i] );
155 hloc[i] = handles[i];
157 /* yes, even screen buffer console handles are waitable, and are
158 * handled as a handle to the console itself !!
160 if (is_console_handle(hloc[i]))
162 if (!VerifyConsoleIoHandle(hloc[i]))
166 hloc[i] = GetConsoleInputWaitHandle();
170 if (timeout == INFINITE)
172 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
178 time.QuadPart = timeout * (ULONGLONG)10000;
179 time.QuadPart = -time.QuadPart;
180 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
183 if (HIWORD(status)) /* is it an error code? */
185 SetLastError( RtlNtStatusToDosError(status) );
186 status = WAIT_FAILED;
192 /***********************************************************************
193 * WaitForSingleObject (KERNEL.460)
195 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
197 DWORD retval, mutex_count;
199 ReleaseThunkLock( &mutex_count );
200 retval = WaitForSingleObject( handle, timeout );
201 RestoreThunkLock( mutex_count );
205 /***********************************************************************
206 * WaitForMultipleObjects (KERNEL.461)
208 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
209 BOOL wait_all, DWORD timeout )
211 DWORD retval, mutex_count;
213 ReleaseThunkLock( &mutex_count );
214 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
215 RestoreThunkLock( mutex_count );
219 /***********************************************************************
220 * WaitForMultipleObjectsEx (KERNEL.495)
222 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
223 BOOL wait_all, DWORD timeout, BOOL alertable )
225 DWORD retval, mutex_count;
227 ReleaseThunkLock( &mutex_count );
228 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
229 RestoreThunkLock( mutex_count );
233 /***********************************************************************
234 * RegisterWaitForSingleObject (KERNEL32.@)
236 BOOL WINAPI RegisterWaitForSingleObject(PHANDLE phNewWaitObject, HANDLE hObject,
237 WAITORTIMERCALLBACK Callback, PVOID Context,
238 ULONG dwMilliseconds, ULONG dwFlags)
240 FIXME("%p %p %p %p %ld %ld\n",
241 phNewWaitObject,hObject,Callback,Context,dwMilliseconds,dwFlags);
245 /***********************************************************************
246 * RegisterWaitForSingleObjectEx (KERNEL32.@)
248 HANDLE WINAPI RegisterWaitForSingleObjectEx( HANDLE hObject,
249 WAITORTIMERCALLBACK Callback, PVOID Context,
250 ULONG dwMilliseconds, ULONG dwFlags )
252 FIXME("%p %p %p %ld %ld\n",
253 hObject,Callback,Context,dwMilliseconds,dwFlags);
257 /***********************************************************************
258 * UnregisterWait (KERNEL32.@)
260 BOOL WINAPI UnregisterWait( HANDLE WaitHandle )
262 FIXME("%p\n",WaitHandle);
266 /***********************************************************************
267 * UnregisterWaitEx (KERNEL32.@)
269 BOOL WINAPI UnregisterWaitEx( HANDLE WaitHandle, HANDLE CompletionEvent )
271 FIXME("%p %p\n",WaitHandle, CompletionEvent);
275 /***********************************************************************
276 * SignalObjectAndWait (KERNEL32.@)
278 * Allows to atomically signal any of the synchro objects (semaphore,
279 * mutex, event) and wait on another.
281 DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable )
283 FIXME("(%p %p %ld %d): stub\n", hObjectToSignal, hObjectToWaitOn, dwMilliseconds, bAlertable);
284 return WAIT_OBJECT_0;
288 /***********************************************************************
289 * InitializeCriticalSection (KERNEL32.@)
291 * Initialise a critical section before use.
294 * crit [O] Critical section to initialise.
297 * Nothing. If the function fails an exception is raised.
299 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
301 NTSTATUS ret = RtlInitializeCriticalSection( crit );
302 if (ret) RtlRaiseStatus( ret );
305 /***********************************************************************
306 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
308 * Initialise a critical section with a spin count.
311 * crit [O] Critical section to initialise.
312 * spincount [I] Number of times to spin upon contention.
316 * Failure: Nothing. If the function fails an exception is raised.
319 * spincount is ignored on uni-processor systems.
321 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
323 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
324 if (ret) RtlRaiseStatus( ret );
328 /***********************************************************************
329 * MakeCriticalSectionGlobal (KERNEL32.@)
331 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
333 /* let's assume that only one thread at a time will try to do this */
334 HANDLE sem = crit->LockSemaphore;
335 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
336 crit->LockSemaphore = ConvertToGlobalHandle( sem );
339 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
340 crit->DebugInfo = NULL;
345 /***********************************************************************
346 * ReinitializeCriticalSection (KERNEL32.@)
348 * Initialise an already used critical section.
351 * crit [O] Critical section to initialise.
356 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
358 if ( !crit->LockSemaphore )
359 RtlInitializeCriticalSection( crit );
363 /***********************************************************************
364 * UninitializeCriticalSection (KERNEL32.@)
366 * UnInitialise a critical section after use.
369 * crit [O] Critical section to uninitialise (destroy).
374 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
376 RtlDeleteCriticalSection( crit );
380 /***********************************************************************
381 * CreateEventA (KERNEL32.@)
383 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
384 BOOL initial_state, LPCSTR name )
386 WCHAR buffer[MAX_PATH];
388 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
390 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
392 SetLastError( ERROR_FILENAME_EXCED_RANGE );
395 return CreateEventW( sa, manual_reset, initial_state, buffer );
399 /***********************************************************************
400 * CreateEventW (KERNEL32.@)
402 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
403 BOOL initial_state, LPCWSTR name )
406 DWORD len = name ? strlenW(name) : 0;
409 SetLastError( ERROR_FILENAME_EXCED_RANGE );
412 /* one buggy program needs this
413 * ("Van Dale Groot woordenboek der Nederlandse taal")
415 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
417 ERR("Bad security attributes pointer %p\n",sa);
418 SetLastError( ERROR_INVALID_PARAMETER);
421 SERVER_START_REQ( create_event )
423 req->manual_reset = manual_reset;
424 req->initial_state = initial_state;
425 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
426 wine_server_add_data( req, name, len * sizeof(WCHAR) );
428 wine_server_call_err( req );
436 /***********************************************************************
437 * CreateW32Event (KERNEL.457)
439 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
441 return CreateEventA( NULL, manual_reset, initial_state, NULL );
445 /***********************************************************************
446 * OpenEventA (KERNEL32.@)
448 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
450 WCHAR buffer[MAX_PATH];
452 if (!name) return OpenEventW( access, inherit, NULL );
454 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
456 SetLastError( ERROR_FILENAME_EXCED_RANGE );
459 return OpenEventW( access, inherit, buffer );
463 /***********************************************************************
464 * OpenEventW (KERNEL32.@)
466 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
469 DWORD len = name ? strlenW(name) : 0;
472 SetLastError( ERROR_FILENAME_EXCED_RANGE );
475 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
477 SERVER_START_REQ( open_event )
479 req->access = access;
480 req->inherit = inherit;
481 wine_server_add_data( req, name, len * sizeof(WCHAR) );
482 wine_server_call_err( req );
489 /***********************************************************************
490 * PulseEvent (KERNEL32.@)
492 BOOL WINAPI PulseEvent( HANDLE handle )
496 if ((status = NtPulseEvent( handle, NULL )))
497 SetLastError( RtlNtStatusToDosError(status) );
502 /***********************************************************************
503 * SetW32Event (KERNEL.458)
504 * SetEvent (KERNEL32.@)
506 BOOL WINAPI SetEvent( HANDLE handle )
510 if ((status = NtSetEvent( handle, NULL )))
511 SetLastError( RtlNtStatusToDosError(status) );
516 /***********************************************************************
517 * ResetW32Event (KERNEL.459)
518 * ResetEvent (KERNEL32.@)
520 BOOL WINAPI ResetEvent( HANDLE handle )
524 if ((status = NtResetEvent( handle, NULL )))
525 SetLastError( RtlNtStatusToDosError(status) );
530 /***********************************************************************
531 * NOTE: The Win95 VWin32_Event routines given below are really low-level
532 * routines implemented directly by VWin32. The user-mode libraries
533 * implement Win32 synchronisation routines on top of these low-level
534 * primitives. We do it the other way around here :-)
537 /***********************************************************************
538 * VWin32_EventCreate (KERNEL.442)
540 HANDLE WINAPI VWin32_EventCreate(VOID)
542 HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
543 return ConvertToGlobalHandle( hEvent );
546 /***********************************************************************
547 * VWin32_EventDestroy (KERNEL.443)
549 VOID WINAPI VWin32_EventDestroy(HANDLE event)
551 CloseHandle( event );
554 /***********************************************************************
555 * VWin32_EventWait (KERNEL.450)
557 VOID WINAPI VWin32_EventWait(HANDLE event)
561 ReleaseThunkLock( &mutex_count );
562 WaitForSingleObject( event, INFINITE );
563 RestoreThunkLock( mutex_count );
566 /***********************************************************************
567 * VWin32_EventSet (KERNEL.451)
568 * KERNEL_479 (KERNEL.479)
570 VOID WINAPI VWin32_EventSet(HANDLE event)
577 /***********************************************************************
578 * CreateMutexA (KERNEL32.@)
580 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
582 WCHAR buffer[MAX_PATH];
584 if (!name) return CreateMutexW( sa, owner, NULL );
586 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
588 SetLastError( ERROR_FILENAME_EXCED_RANGE );
591 return CreateMutexW( sa, owner, buffer );
595 /***********************************************************************
596 * CreateMutexW (KERNEL32.@)
598 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
601 DWORD len = name ? strlenW(name) : 0;
604 SetLastError( ERROR_FILENAME_EXCED_RANGE );
607 SERVER_START_REQ( create_mutex )
610 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
611 wine_server_add_data( req, name, len * sizeof(WCHAR) );
613 wine_server_call_err( req );
621 /***********************************************************************
622 * OpenMutexA (KERNEL32.@)
624 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
626 WCHAR buffer[MAX_PATH];
628 if (!name) return OpenMutexW( access, inherit, NULL );
630 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
632 SetLastError( ERROR_FILENAME_EXCED_RANGE );
635 return OpenMutexW( access, inherit, buffer );
639 /***********************************************************************
640 * OpenMutexW (KERNEL32.@)
642 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
645 DWORD len = name ? strlenW(name) : 0;
648 SetLastError( ERROR_FILENAME_EXCED_RANGE );
651 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
653 SERVER_START_REQ( open_mutex )
655 req->access = access;
656 req->inherit = inherit;
657 wine_server_add_data( req, name, len * sizeof(WCHAR) );
658 wine_server_call_err( req );
666 /***********************************************************************
667 * ReleaseMutex (KERNEL32.@)
669 BOOL WINAPI ReleaseMutex( HANDLE handle )
672 SERVER_START_REQ( release_mutex )
674 req->handle = handle;
675 ret = !wine_server_call_err( req );
687 /***********************************************************************
688 * CreateSemaphoreA (KERNEL32.@)
690 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
692 WCHAR buffer[MAX_PATH];
694 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
696 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
698 SetLastError( ERROR_FILENAME_EXCED_RANGE );
701 return CreateSemaphoreW( sa, initial, max, buffer );
705 /***********************************************************************
706 * CreateSemaphoreW (KERNEL32.@)
708 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
709 LONG max, LPCWSTR name )
712 DWORD len = name ? strlenW(name) : 0;
714 /* Check parameters */
716 if ((max <= 0) || (initial < 0) || (initial > max))
718 SetLastError( ERROR_INVALID_PARAMETER );
723 SetLastError( ERROR_FILENAME_EXCED_RANGE );
727 SERVER_START_REQ( create_semaphore )
729 req->initial = (unsigned int)initial;
730 req->max = (unsigned int)max;
731 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
732 wine_server_add_data( req, name, len * sizeof(WCHAR) );
734 wine_server_call_err( req );
742 /***********************************************************************
743 * OpenSemaphoreA (KERNEL32.@)
745 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
747 WCHAR buffer[MAX_PATH];
749 if (!name) return OpenSemaphoreW( access, inherit, NULL );
751 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
753 SetLastError( ERROR_FILENAME_EXCED_RANGE );
756 return OpenSemaphoreW( access, inherit, buffer );
760 /***********************************************************************
761 * OpenSemaphoreW (KERNEL32.@)
763 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
766 DWORD len = name ? strlenW(name) : 0;
769 SetLastError( ERROR_FILENAME_EXCED_RANGE );
772 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
774 SERVER_START_REQ( open_semaphore )
776 req->access = access;
777 req->inherit = inherit;
778 wine_server_add_data( req, name, len * sizeof(WCHAR) );
779 wine_server_call_err( req );
787 /***********************************************************************
788 * ReleaseSemaphore (KERNEL32.@)
790 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
792 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
793 if (status) SetLastError( RtlNtStatusToDosError(status) );
803 /***********************************************************************
804 * CreateWaitableTimerA (KERNEL32.@)
806 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
808 WCHAR buffer[MAX_PATH];
810 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
812 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
814 SetLastError( ERROR_FILENAME_EXCED_RANGE );
817 return CreateWaitableTimerW( sa, manual, buffer );
821 /***********************************************************************
822 * CreateWaitableTimerW (KERNEL32.@)
824 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
830 OBJECT_ATTRIBUTES oa;
832 if (name) RtlInitUnicodeString(&us, name);
833 if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
835 InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
836 NULL /* FIXME */, NULL /* FIXME */);
837 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
838 manual ? NotificationTimer : SynchronizationTimer);
840 if (status != STATUS_SUCCESS)
842 SetLastError( RtlNtStatusToDosError(status) );
849 /***********************************************************************
850 * OpenWaitableTimerA (KERNEL32.@)
852 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
854 WCHAR buffer[MAX_PATH];
856 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
858 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
860 SetLastError( ERROR_FILENAME_EXCED_RANGE );
863 return OpenWaitableTimerW( access, inherit, buffer );
867 /***********************************************************************
868 * OpenWaitableTimerW (KERNEL32.@)
870 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
876 OBJECT_ATTRIBUTES oa;
878 if (inherit) attr |= OBJ_INHERIT;
880 if (name) RtlInitUnicodeString(&us, name);
881 InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
882 status = NtOpenTimer(&handle, access, &oa);
883 if (status != STATUS_SUCCESS)
885 SetLastError( RtlNtStatusToDosError(status) );
892 /***********************************************************************
893 * SetWaitableTimer (KERNEL32.@)
895 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
896 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
898 NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
900 if (status != STATUS_SUCCESS)
902 SetLastError( RtlNtStatusToDosError(status) );
903 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
909 /***********************************************************************
910 * CancelWaitableTimer (KERNEL32.@)
912 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
916 status = NtCancelTimer(handle, NULL);
917 if (status != STATUS_SUCCESS)
919 SetLastError( RtlNtStatusToDosError(status) );
926 /***********************************************************************
927 * CreateTimerQueue (KERNEL32.@)
929 HANDLE WINAPI CreateTimerQueue(void)
932 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
937 /***********************************************************************
938 * DeleteTimerQueueEx (KERNEL32.@)
940 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
942 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
943 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
947 /***********************************************************************
948 * CreateTimerQueueTimer (KERNEL32.@)
950 * Creates a timer-queue timer. This timer expires at the specified due
951 * time (in ms), then after every specified period (in ms). When the timer
952 * expires, the callback function is called.
955 * nonzero on success or zero on faillure
960 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
961 WAITORTIMERCALLBACK Callback, PVOID Parameter,
962 DWORD DueTime, DWORD Period, ULONG Flags )
965 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
969 /***********************************************************************
970 * DeleteTimerQueueTimer (KERNEL32.@)
972 * Cancels a timer-queue timer.
975 * nonzero on success or zero on faillure
980 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
981 HANDLE CompletionEvent )
984 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
994 /***********************************************************************
995 * CreateNamedPipeA (KERNEL32.@)
997 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
998 DWORD dwPipeMode, DWORD nMaxInstances,
999 DWORD nOutBufferSize, DWORD nInBufferSize,
1000 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1002 WCHAR buffer[MAX_PATH];
1004 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
1005 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1007 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1009 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1010 return INVALID_HANDLE_VALUE;
1012 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
1013 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1017 /***********************************************************************
1018 * CreateNamedPipeW (KERNEL32.@)
1020 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
1021 DWORD dwPipeMode, DWORD nMaxInstances,
1022 DWORD nOutBufferSize, DWORD nInBufferSize,
1023 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
1026 UNICODE_STRING nt_name;
1027 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1029 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
1030 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
1031 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
1033 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1035 SetLastError( ERROR_PATH_NOT_FOUND );
1036 return INVALID_HANDLE_VALUE;
1038 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1040 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1041 RtlFreeUnicodeString( &nt_name );
1042 return INVALID_HANDLE_VALUE;
1044 if (nt_name.Length < sizeof(leadin) ||
1045 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1047 SetLastError( ERROR_INVALID_NAME );
1048 RtlFreeUnicodeString( &nt_name );
1049 return INVALID_HANDLE_VALUE;
1051 SERVER_START_REQ( create_named_pipe )
1053 req->openmode = dwOpenMode;
1054 req->pipemode = dwPipeMode;
1055 req->maxinstances = nMaxInstances;
1056 req->outsize = nOutBufferSize;
1057 req->insize = nInBufferSize;
1058 req->timeout = nDefaultTimeOut;
1059 req->inherit = (attr && (attr->nLength>=sizeof(*attr)) && attr->bInheritHandle);
1060 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1062 if (!wine_server_call_err( req )) ret = reply->handle;
1063 else ret = INVALID_HANDLE_VALUE;
1066 RtlFreeUnicodeString( &nt_name );
1071 /***********************************************************************
1072 * PeekNamedPipe (KERNEL32.@)
1074 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1075 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1078 int avail=0, fd, ret, flags;
1080 ret = wine_server_handle_to_fd( hPipe, GENERIC_READ, &fd, &flags );
1083 SetLastError( RtlNtStatusToDosError(ret) );
1086 if (flags & FD_FLAG_RECV_SHUTDOWN)
1088 wine_server_release_fd( hPipe, fd );
1089 SetLastError ( ERROR_PIPE_NOT_CONNECTED );
1093 if (ioctl(fd,FIONREAD, &avail ) != 0)
1095 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1096 wine_server_release_fd( hPipe, fd );
1099 if (!avail) /* check for closed pipe */
1101 struct pollfd pollfd;
1103 pollfd.events = POLLIN;
1105 switch (poll( &pollfd, 1, 0 ))
1109 case 1: /* got something */
1110 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1111 TRACE("POLLHUP | POLLERR\n");
1114 wine_server_release_fd( hPipe, fd );
1115 SetLastError(ERROR_BROKEN_PIPE);
1119 TRACE(" 0x%08x bytes available\n", avail );
1125 if (avail && lpvBuffer)
1127 int readbytes = (avail < cbBuffer) ? avail : cbBuffer;
1128 readbytes = recv(fd, lpvBuffer, readbytes, MSG_PEEK);
1131 WARN("failed to peek socket (%d)\n", errno);
1135 *lpcbRead = readbytes;
1137 wine_server_release_fd( hPipe, fd );
1139 #endif /* defined(FIONREAD) */
1141 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1142 FIXME("function not implemented\n");
1146 /***********************************************************************
1147 * SYNC_CompletePipeOverlapped (Internal)
1149 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1151 TRACE("for %p result %08lx\n",overlapped,result);
1154 overlapped->Internal = result;
1155 SetEvent(overlapped->hEvent);
1159 /***********************************************************************
1160 * WaitNamedPipeA (KERNEL32.@)
1162 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1164 WCHAR buffer[MAX_PATH];
1166 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1168 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1170 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1173 return WaitNamedPipeW( buffer, nTimeOut );
1177 /***********************************************************************
1178 * WaitNamedPipeW (KERNEL32.@)
1180 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1184 UNICODE_STRING nt_name;
1185 static const WCHAR leadin[] = {'\\','?','?','\\','P','I','P','E','\\'};
1187 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1189 if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
1192 if (nt_name.Length >= MAX_PATH * sizeof(WCHAR) )
1194 RtlFreeUnicodeString( &nt_name );
1197 if (nt_name.Length < sizeof(leadin) ||
1198 strncmpiW( nt_name.Buffer, leadin, sizeof(leadin)/sizeof(leadin[0])))
1200 RtlFreeUnicodeString( &nt_name );
1204 memset(&ov,0,sizeof(ov));
1205 ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
1209 SERVER_START_REQ( wait_named_pipe )
1211 req->timeout = nTimeOut;
1212 req->overlapped = &ov;
1213 req->func = SYNC_CompletePipeOverlapped;
1214 wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
1215 ret = !wine_server_call_err( req );
1219 RtlFreeUnicodeString( &nt_name );
1223 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1225 SetLastError(ov.Internal);
1226 ret = (ov.Internal==STATUS_SUCCESS);
1229 CloseHandle(ov.hEvent);
1234 /***********************************************************************
1235 * SYNC_ConnectNamedPipe (Internal)
1237 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1244 overlapped->Internal = STATUS_PENDING;
1246 SERVER_START_REQ( connect_named_pipe )
1248 req->handle = hPipe;
1249 req->overlapped = overlapped;
1250 req->func = SYNC_CompletePipeOverlapped;
1251 ret = !wine_server_call_err( req );
1258 /***********************************************************************
1259 * ConnectNamedPipe (KERNEL32.@)
1261 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1266 TRACE("(%p,%p)\n",hPipe, overlapped);
1270 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1271 SetLastError( ERROR_IO_PENDING );
1275 memset(&ov,0,sizeof(ov));
1276 ov.hEvent = CreateEventA(NULL,0,0,NULL);
1280 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1283 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1285 SetLastError(ov.Internal);
1286 ret = (ov.Internal==STATUS_SUCCESS);
1290 CloseHandle(ov.hEvent);
1295 /***********************************************************************
1296 * DisconnectNamedPipe (KERNEL32.@)
1298 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1302 TRACE("(%p)\n",hPipe);
1304 SERVER_START_REQ( disconnect_named_pipe )
1306 req->handle = hPipe;
1307 ret = !wine_server_call_err( req );
1308 if (ret && reply->fd != -1) close( reply->fd );
1315 /***********************************************************************
1316 * TransactNamedPipe (KERNEL32.@)
1318 BOOL WINAPI TransactNamedPipe(
1319 HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1320 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1322 FIXME("%p %p %ld %p %ld %p %p\n",
1323 hPipe, lpInput, dwInputSize, lpOutput,
1324 dwOutputSize, lpBytesRead, lpOverlapped);
1330 /***********************************************************************
1331 * GetNamedPipeInfo (KERNEL32.@)
1333 BOOL WINAPI GetNamedPipeInfo(
1334 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1335 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1339 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1340 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1342 SERVER_START_REQ( get_named_pipe_info )
1344 req->handle = hNamedPipe;
1345 ret = !wine_server_call_err( req );
1346 if(lpFlags) *lpFlags = reply->flags;
1347 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1348 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1349 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1356 /***********************************************************************
1357 * GetNamedPipeHandleStateA (KERNEL32.@)
1359 BOOL WINAPI GetNamedPipeHandleStateA(
1360 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1361 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1362 LPSTR lpUsername, DWORD nUsernameMaxSize)
1364 FIXME("%p %p %p %p %p %p %ld\n",
1365 hNamedPipe, lpState, lpCurInstances,
1366 lpMaxCollectionCount, lpCollectDataTimeout,
1367 lpUsername, nUsernameMaxSize);
1372 /***********************************************************************
1373 * GetNamedPipeHandleStateW (KERNEL32.@)
1375 BOOL WINAPI GetNamedPipeHandleStateW(
1376 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1377 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1378 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1380 FIXME("%p %p %p %p %p %p %ld\n",
1381 hNamedPipe, lpState, lpCurInstances,
1382 lpMaxCollectionCount, lpCollectDataTimeout,
1383 lpUsername, nUsernameMaxSize);
1388 /***********************************************************************
1389 * SetNamedPipeHandleState (KERNEL32.@)
1391 BOOL WINAPI SetNamedPipeHandleState(
1392 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1393 LPDWORD lpCollectDataTimeout)
1395 FIXME("%p %p %p %p\n",
1396 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1400 /***********************************************************************
1401 * CallNamedPipeA (KERNEL32.@)
1403 BOOL WINAPI CallNamedPipeA(
1404 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD dwInputSize,
1405 LPVOID lpOutput, DWORD dwOutputSize,
1406 LPDWORD lpBytesRead, DWORD nTimeout)
1412 TRACE("%s %p %ld %p %ld %p %ld\n",
1413 debugstr_a(lpNamedPipeName), lpInput, dwInputSize,
1414 lpOutput, dwOutputSize, lpBytesRead, nTimeout);
1416 if( lpNamedPipeName )
1418 len = MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, NULL, 0 );
1419 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1420 MultiByteToWideChar( CP_ACP, 0, lpNamedPipeName, -1, str, len );
1422 ret = CallNamedPipeW( str, lpInput, dwInputSize, lpOutput,
1423 dwOutputSize, lpBytesRead, nTimeout );
1424 if( lpNamedPipeName )
1425 HeapFree( GetProcessHeap(), 0, str );
1430 /***********************************************************************
1431 * CallNamedPipeW (KERNEL32.@)
1433 BOOL WINAPI CallNamedPipeW(
1434 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1435 LPVOID lpOutput, DWORD lpOutputSize,
1436 LPDWORD lpBytesRead, DWORD nTimeout)
1438 FIXME("%s %p %ld %p %ld %p %ld\n",
1439 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1440 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1444 /******************************************************************
1445 * CreatePipe (KERNEL32.@)
1448 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1449 LPSECURITY_ATTRIBUTES sa, DWORD size )
1451 static unsigned index = 0;
1454 unsigned in_index = index;
1456 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1457 /* generate a unique pipe name (system wide) */
1460 sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1461 hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND,
1462 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1463 NMPWAIT_USE_DEFAULT_WAIT, sa);
1464 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1465 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1466 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1468 hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1469 if (hw == INVALID_HANDLE_VALUE)
1481 /******************************************************************************
1482 * CreateMailslotA [KERNEL32.@]
1484 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1485 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1491 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1492 nMaxMessageSize, lReadTimeout, sa);
1496 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1497 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1498 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1501 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1504 HeapFree( GetProcessHeap(), 0, name );
1510 /******************************************************************************
1511 * CreateMailslotW [KERNEL32.@]
1513 * Create a mailslot with specified name.
1516 * lpName [I] Pointer to string for mailslot name
1517 * nMaxMessageSize [I] Maximum message size
1518 * lReadTimeout [I] Milliseconds before read time-out
1519 * sa [I] Pointer to security structure
1522 * Success: Handle to mailslot
1523 * Failure: INVALID_HANDLE_VALUE
1525 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1526 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1528 FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1529 nMaxMessageSize, lReadTimeout, sa);
1530 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1531 return INVALID_HANDLE_VALUE;
1535 /******************************************************************************
1536 * GetMailslotInfo [KERNEL32.@]
1538 * Retrieve information about a mailslot.
1541 * hMailslot [I] Mailslot handle
1542 * lpMaxMessageSize [O] Address of maximum message size
1543 * lpNextSize [O] Address of size of next message
1544 * lpMessageCount [O] Address of number of messages
1545 * lpReadTimeout [O] Address of read time-out
1551 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1552 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1553 LPDWORD lpReadTimeout )
1555 FIXME("(%p): stub\n",hMailslot);
1556 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1561 /******************************************************************************
1562 * SetMailslotInfo [KERNEL32.@]
1564 * Set the read timeout of a mailslot.
1567 * hMailslot [I] Mailslot handle
1568 * dwReadTimeout [I] Timeout in milliseconds.
1574 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1576 FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1582 /******************************************************************************
1583 * CreateIoCompletionPort (KERNEL32.@)
1585 HANDLE WINAPI CreateIoCompletionPort(HANDLE hFileHandle, HANDLE hExistingCompletionPort,
1586 ULONG_PTR CompletionKey, DWORD dwNumberOfConcurrentThreads)
1588 FIXME("(%p, %p, %08lx, %08lx): stub.\n",
1589 hFileHandle, hExistingCompletionPort, CompletionKey, dwNumberOfConcurrentThreads);
1594 /******************************************************************************
1595 * GetQueuedCompletionStatus (KERNEL32.@)
1597 BOOL WINAPI GetQueuedCompletionStatus( HANDLE CompletionPort, LPDWORD lpNumberOfBytesTransferred,
1598 PULONG_PTR pCompletionKey, LPOVERLAPPED *lpOverlapped,
1599 DWORD dwMilliseconds )
1601 FIXME("(%p,%p,%p,%p,%ld), stub!\n",
1602 CompletionPort,lpNumberOfBytesTransferred,pCompletionKey,lpOverlapped,dwMilliseconds);
1603 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1607 /******************************************************************************
1608 * CreateJobObjectW (KERNEL32.@)
1610 HANDLE WINAPI CreateJobObjectW( LPSECURITY_ATTRIBUTES attr, LPCWSTR name )
1612 FIXME("%p %s\n", attr, debugstr_w(name) );
1613 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1617 /******************************************************************************
1618 * CreateJobObjectA (KERNEL32.@)
1620 HANDLE WINAPI CreateJobObjectA( LPSECURITY_ATTRIBUTES attr, LPCSTR name )
1626 TRACE("%p %s\n", attr, debugstr_a(name) );
1630 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
1631 str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1634 SetLastError( ERROR_OUTOFMEMORY );
1637 len = MultiByteToWideChar( CP_ACP, 0, name, -1, str, len );
1640 r = CreateJobObjectW( attr, str );
1643 HeapFree( GetProcessHeap(), 0, str );
1648 /******************************************************************************
1649 * AssignProcessToJobObject (KERNEL32.@)
1651 BOOL WINAPI AssignProcessToJobObject( HANDLE hJob, HANDLE hProcess )
1653 FIXME("%p %p\n", hJob, hProcess);
1659 /***********************************************************************
1660 * InterlockedCompareExchange (KERNEL32.@)
1662 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1663 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1664 "movl 12(%esp),%eax\n\t"
1665 "movl 8(%esp),%ecx\n\t"
1666 "movl 4(%esp),%edx\n\t"
1667 "lock; cmpxchgl %ecx,(%edx)\n\t"
1670 /***********************************************************************
1671 * InterlockedExchange (KERNEL32.@)
1673 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1674 __ASM_GLOBAL_FUNC(InterlockedExchange,
1675 "movl 8(%esp),%eax\n\t"
1676 "movl 4(%esp),%edx\n\t"
1677 "lock; xchgl %eax,(%edx)\n\t"
1680 /***********************************************************************
1681 * InterlockedExchangeAdd (KERNEL32.@)
1683 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1684 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1685 "movl 8(%esp),%eax\n\t"
1686 "movl 4(%esp),%edx\n\t"
1687 "lock; xaddl %eax,(%edx)\n\t"
1690 /***********************************************************************
1691 * InterlockedIncrement (KERNEL32.@)
1693 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1694 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1695 "movl 4(%esp),%edx\n\t"
1697 "lock; xaddl %eax,(%edx)\n\t"
1701 /***********************************************************************
1702 * InterlockedDecrement (KERNEL32.@)
1704 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1705 "movl 4(%esp),%edx\n\t"
1707 "lock; xaddl %eax,(%edx)\n\t"
1711 #else /* __i386__ */
1713 /***********************************************************************
1714 * InterlockedCompareExchange (KERNEL32.@)
1716 * Atomically swap one value with another.
1719 * dest [I/O] The value to replace
1720 * xchq [I] The value to be swapped
1721 * compare [I] The value to compare to dest
1724 * The resulting value of dest.
1727 * dest is updated only if it is equal to compare, otherwise no swap is done.
1729 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1731 return interlocked_cmpxchg( dest, xchg, compare );
1734 /***********************************************************************
1735 * InterlockedExchange (KERNEL32.@)
1737 * Atomically swap one value with another.
1740 * dest [I/O] The value to replace
1741 * val [I] The value to be swapped
1744 * The resulting value of dest.
1746 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1748 return interlocked_xchg( dest, val );
1751 /***********************************************************************
1752 * InterlockedExchangeAdd (KERNEL32.@)
1754 * Atomically add one value to another.
1757 * dest [I/O] The value to add to
1758 * incr [I] The value to be added
1761 * The resulting value of dest.
1763 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1765 return interlocked_xchg_add( dest, incr );
1768 /***********************************************************************
1769 * InterlockedIncrement (KERNEL32.@)
1771 * Atomically increment a value.
1774 * dest [I/O] The value to increment
1777 * The resulting value of dest.
1779 LONG WINAPI InterlockedIncrement( PLONG dest )
1781 return interlocked_xchg_add( dest, 1 ) + 1;
1784 /***********************************************************************
1785 * InterlockedDecrement (KERNEL32.@)
1787 * Atomically decrement a value.
1790 * dest [I/O] The value to decrement
1793 * The resulting value of dest.
1795 LONG WINAPI InterlockedDecrement( PLONG dest )
1797 return interlocked_xchg_add( dest, -1 ) - 1;
1800 #endif /* __i386__ */