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
44 #include "wine/server.h"
45 #include "wine/unicode.h"
46 #include "kernel_private.h"
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(win32);
53 /* check if current version is NT or Win95 */
54 inline static int is_version_nt(void)
56 return !(GetVersion() & 0x80000000);
60 /***********************************************************************
63 VOID WINAPI Sleep( DWORD timeout )
65 SleepEx( timeout, FALSE );
68 /******************************************************************************
69 * SleepEx (KERNEL32.@)
71 DWORD WINAPI SleepEx( DWORD timeout, BOOL alertable )
75 if (timeout == INFINITE) status = NtDelayExecution( alertable, NULL );
80 time.QuadPart = timeout * (ULONGLONG)10000;
81 time.QuadPart = -time.QuadPart;
82 status = NtDelayExecution( alertable, &time );
84 if (status != STATUS_USER_APC) status = STATUS_SUCCESS;
89 /***********************************************************************
90 * WaitForSingleObject (KERNEL32.@)
92 DWORD WINAPI WaitForSingleObject( HANDLE handle, DWORD timeout )
94 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
98 /***********************************************************************
99 * WaitForSingleObjectEx (KERNEL32.@)
101 DWORD WINAPI WaitForSingleObjectEx( HANDLE handle, DWORD timeout,
104 return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
108 /***********************************************************************
109 * WaitForMultipleObjects (KERNEL32.@)
111 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles,
112 BOOL wait_all, DWORD timeout )
114 return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
118 /***********************************************************************
119 * WaitForMultipleObjectsEx (KERNEL32.@)
121 DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
122 BOOL wait_all, DWORD timeout,
126 HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
129 if (count >= MAXIMUM_WAIT_OBJECTS)
131 SetLastError(ERROR_INVALID_PARAMETER);
134 for (i = 0; i < count; i++)
136 if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
137 (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
138 (handles[i] == (HANDLE)STD_ERROR_HANDLE))
139 hloc[i] = GetStdHandle( (DWORD)handles[i] );
141 hloc[i] = handles[i];
143 /* yes, even screen buffer console handles are waitable, and are
144 * handled as a handle to the console itself !!
146 if (is_console_handle(hloc[i]))
148 if (!VerifyConsoleIoHandle(hloc[i]))
152 hloc[i] = GetConsoleInputWaitHandle();
156 if (timeout == INFINITE)
158 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
164 time.QuadPart = timeout * (ULONGLONG)10000;
165 time.QuadPart = -time.QuadPart;
166 status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
169 if (HIWORD(status)) /* is it an error code? */
171 SetLastError( RtlNtStatusToDosError(status) );
172 status = WAIT_FAILED;
178 /***********************************************************************
179 * WaitForSingleObject (KERNEL.460)
181 DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout )
183 DWORD retval, mutex_count;
185 ReleaseThunkLock( &mutex_count );
186 retval = WaitForSingleObject( handle, timeout );
187 RestoreThunkLock( mutex_count );
191 /***********************************************************************
192 * WaitForMultipleObjects (KERNEL.461)
194 DWORD WINAPI WaitForMultipleObjects16( DWORD count, const HANDLE *handles,
195 BOOL wait_all, DWORD timeout )
197 DWORD retval, mutex_count;
199 ReleaseThunkLock( &mutex_count );
200 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
201 RestoreThunkLock( mutex_count );
205 /***********************************************************************
206 * WaitForMultipleObjectsEx (KERNEL.495)
208 DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles,
209 BOOL wait_all, DWORD timeout, BOOL alertable )
211 DWORD retval, mutex_count;
213 ReleaseThunkLock( &mutex_count );
214 retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable );
215 RestoreThunkLock( mutex_count );
219 /***********************************************************************
220 * InitializeCriticalSection (KERNEL32.@)
222 * Initialise a critical section before use.
225 * crit [O] Critical section to initialise.
228 * Nothing. If the function fails an exception is raised.
230 void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit )
232 NTSTATUS ret = RtlInitializeCriticalSection( crit );
233 if (ret) RtlRaiseStatus( ret );
236 /***********************************************************************
237 * InitializeCriticalSectionAndSpinCount (KERNEL32.@)
239 * Initialise a critical section with a spin count.
242 * crit [O] Critical section to initialise.
243 * spincount [I] Number of times to spin upon contention.
247 * Failure: Nothing. If the function fails an exception is raised.
250 * spincount is ignored on uni-processor systems.
252 BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
254 NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount );
255 if (ret) RtlRaiseStatus( ret );
259 /***********************************************************************
260 * SetCriticalSectionSpinCount (KERNEL32.@)
262 * Set the spin count for a critical section.
265 * crit [O] Critical section to set the spin count for.
266 * spincount [I] Number of times to spin upon contention.
269 * The previous spin count value of crit.
272 * This function is available on NT4SP3 or later, but not Win98.
274 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
276 ULONG_PTR oldspincount = crit->SpinCount;
277 if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
278 crit->SpinCount = spincount;
282 /***********************************************************************
283 * MakeCriticalSectionGlobal (KERNEL32.@)
285 void WINAPI MakeCriticalSectionGlobal( CRITICAL_SECTION *crit )
287 /* let's assume that only one thread at a time will try to do this */
288 HANDLE sem = crit->LockSemaphore;
289 if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
290 crit->LockSemaphore = ConvertToGlobalHandle( sem );
293 RtlFreeHeap( GetProcessHeap(), 0, crit->DebugInfo );
294 crit->DebugInfo = NULL;
299 /***********************************************************************
300 * ReinitializeCriticalSection (KERNEL32.@)
302 * Initialise an already used critical section.
305 * crit [O] Critical section to initialise.
310 void WINAPI ReinitializeCriticalSection( CRITICAL_SECTION *crit )
312 if ( !crit->LockSemaphore )
313 RtlInitializeCriticalSection( crit );
317 /***********************************************************************
318 * UninitializeCriticalSection (KERNEL32.@)
320 * UnInitialise a critical section after use.
323 * crit [O] Critical section to uninitialise (destroy).
328 void WINAPI UninitializeCriticalSection( CRITICAL_SECTION *crit )
330 RtlDeleteCriticalSection( crit );
334 /***********************************************************************
335 * CreateEventA (KERNEL32.@)
337 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
338 BOOL initial_state, LPCSTR name )
340 WCHAR buffer[MAX_PATH];
342 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
344 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
346 SetLastError( ERROR_FILENAME_EXCED_RANGE );
349 return CreateEventW( sa, manual_reset, initial_state, buffer );
353 /***********************************************************************
354 * CreateEventW (KERNEL32.@)
356 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
357 BOOL initial_state, LPCWSTR name )
360 DWORD len = name ? strlenW(name) : 0;
363 SetLastError( ERROR_FILENAME_EXCED_RANGE );
366 /* one buggy program needs this
367 * ("Van Dale Groot woordenboek der Nederlandse taal")
369 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
371 ERR("Bad security attributes pointer %p\n",sa);
372 SetLastError( ERROR_INVALID_PARAMETER);
375 SERVER_START_REQ( create_event )
377 req->manual_reset = manual_reset;
378 req->initial_state = initial_state;
379 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
380 wine_server_add_data( req, name, len * sizeof(WCHAR) );
382 wine_server_call_err( req );
390 /***********************************************************************
391 * CreateW32Event (KERNEL.457)
393 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
395 return CreateEventA( NULL, manual_reset, initial_state, NULL );
399 /***********************************************************************
400 * OpenEventA (KERNEL32.@)
402 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
404 WCHAR buffer[MAX_PATH];
406 if (!name) return OpenEventW( access, inherit, NULL );
408 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
410 SetLastError( ERROR_FILENAME_EXCED_RANGE );
413 return OpenEventW( access, inherit, buffer );
417 /***********************************************************************
418 * OpenEventW (KERNEL32.@)
420 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
423 DWORD len = name ? strlenW(name) : 0;
426 SetLastError( ERROR_FILENAME_EXCED_RANGE );
429 if (!is_version_nt()) access = EVENT_ALL_ACCESS;
431 SERVER_START_REQ( open_event )
433 req->access = access;
434 req->inherit = inherit;
435 wine_server_add_data( req, name, len * sizeof(WCHAR) );
436 wine_server_call_err( req );
444 /***********************************************************************
447 * Execute an event operation (set,reset,pulse).
449 static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
452 SERVER_START_REQ( event_op )
454 req->handle = handle;
456 ret = !wine_server_call_err( req );
463 /***********************************************************************
464 * PulseEvent (KERNEL32.@)
466 BOOL WINAPI PulseEvent( HANDLE handle )
468 return EVENT_Operation( handle, PULSE_EVENT );
472 /***********************************************************************
473 * SetW32Event (KERNEL.458)
474 * SetEvent (KERNEL32.@)
476 BOOL WINAPI SetEvent( HANDLE handle )
478 return EVENT_Operation( handle, SET_EVENT );
482 /***********************************************************************
483 * ResetW32Event (KERNEL.459)
484 * ResetEvent (KERNEL32.@)
486 BOOL WINAPI ResetEvent( HANDLE handle )
488 return EVENT_Operation( handle, RESET_EVENT );
492 /***********************************************************************
493 * NOTE: The Win95 VWin32_Event routines given below are really low-level
494 * routines implemented directly by VWin32. The user-mode libraries
495 * implement Win32 synchronisation routines on top of these low-level
496 * primitives. We do it the other way around here :-)
499 /***********************************************************************
500 * VWin32_EventCreate (KERNEL.442)
502 HANDLE WINAPI VWin32_EventCreate(VOID)
504 HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
505 return ConvertToGlobalHandle( hEvent );
508 /***********************************************************************
509 * VWin32_EventDestroy (KERNEL.443)
511 VOID WINAPI VWin32_EventDestroy(HANDLE event)
513 CloseHandle( event );
516 /***********************************************************************
517 * VWin32_EventWait (KERNEL.450)
519 VOID WINAPI VWin32_EventWait(HANDLE event)
523 ReleaseThunkLock( &mutex_count );
524 WaitForSingleObject( event, INFINITE );
525 RestoreThunkLock( mutex_count );
528 /***********************************************************************
529 * VWin32_EventSet (KERNEL.451)
530 * KERNEL_479 (KERNEL.479)
532 VOID WINAPI VWin32_EventSet(HANDLE event)
539 /***********************************************************************
540 * CreateMutexA (KERNEL32.@)
542 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
544 WCHAR buffer[MAX_PATH];
546 if (!name) return CreateMutexW( sa, owner, NULL );
548 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
550 SetLastError( ERROR_FILENAME_EXCED_RANGE );
553 return CreateMutexW( sa, owner, buffer );
557 /***********************************************************************
558 * CreateMutexW (KERNEL32.@)
560 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
563 DWORD len = name ? strlenW(name) : 0;
566 SetLastError( ERROR_FILENAME_EXCED_RANGE );
569 SERVER_START_REQ( create_mutex )
572 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
573 wine_server_add_data( req, name, len * sizeof(WCHAR) );
575 wine_server_call_err( req );
583 /***********************************************************************
584 * OpenMutexA (KERNEL32.@)
586 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
588 WCHAR buffer[MAX_PATH];
590 if (!name) return OpenMutexW( access, inherit, NULL );
592 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
594 SetLastError( ERROR_FILENAME_EXCED_RANGE );
597 return OpenMutexW( access, inherit, buffer );
601 /***********************************************************************
602 * OpenMutexW (KERNEL32.@)
604 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
607 DWORD len = name ? strlenW(name) : 0;
610 SetLastError( ERROR_FILENAME_EXCED_RANGE );
613 if (!is_version_nt()) access = MUTEX_ALL_ACCESS;
615 SERVER_START_REQ( open_mutex )
617 req->access = access;
618 req->inherit = inherit;
619 wine_server_add_data( req, name, len * sizeof(WCHAR) );
620 wine_server_call_err( req );
628 /***********************************************************************
629 * ReleaseMutex (KERNEL32.@)
631 BOOL WINAPI ReleaseMutex( HANDLE handle )
634 SERVER_START_REQ( release_mutex )
636 req->handle = handle;
637 ret = !wine_server_call_err( req );
649 /***********************************************************************
650 * CreateSemaphoreA (KERNEL32.@)
652 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
654 WCHAR buffer[MAX_PATH];
656 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
658 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
660 SetLastError( ERROR_FILENAME_EXCED_RANGE );
663 return CreateSemaphoreW( sa, initial, max, buffer );
667 /***********************************************************************
668 * CreateSemaphoreW (KERNEL32.@)
670 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
671 LONG max, LPCWSTR name )
674 DWORD len = name ? strlenW(name) : 0;
676 /* Check parameters */
678 if ((max <= 0) || (initial < 0) || (initial > max))
680 SetLastError( ERROR_INVALID_PARAMETER );
685 SetLastError( ERROR_FILENAME_EXCED_RANGE );
689 SERVER_START_REQ( create_semaphore )
691 req->initial = (unsigned int)initial;
692 req->max = (unsigned int)max;
693 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
694 wine_server_add_data( req, name, len * sizeof(WCHAR) );
696 wine_server_call_err( req );
704 /***********************************************************************
705 * OpenSemaphoreA (KERNEL32.@)
707 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
709 WCHAR buffer[MAX_PATH];
711 if (!name) return OpenSemaphoreW( access, inherit, NULL );
713 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
715 SetLastError( ERROR_FILENAME_EXCED_RANGE );
718 return OpenSemaphoreW( access, inherit, buffer );
722 /***********************************************************************
723 * OpenSemaphoreW (KERNEL32.@)
725 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
728 DWORD len = name ? strlenW(name) : 0;
731 SetLastError( ERROR_FILENAME_EXCED_RANGE );
734 if (!is_version_nt()) access = SEMAPHORE_ALL_ACCESS;
736 SERVER_START_REQ( open_semaphore )
738 req->access = access;
739 req->inherit = inherit;
740 wine_server_add_data( req, name, len * sizeof(WCHAR) );
741 wine_server_call_err( req );
749 /***********************************************************************
750 * ReleaseSemaphore (KERNEL32.@)
752 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
754 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
755 if (status) SetLastError( RtlNtStatusToDosError(status) );
765 /***********************************************************************
766 * CreateWaitableTimerA (KERNEL32.@)
768 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
770 WCHAR buffer[MAX_PATH];
772 if (!name) return CreateWaitableTimerW( sa, manual, NULL );
774 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
776 SetLastError( ERROR_FILENAME_EXCED_RANGE );
779 return CreateWaitableTimerW( sa, manual, buffer );
783 /***********************************************************************
784 * CreateWaitableTimerW (KERNEL32.@)
786 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
792 OBJECT_ATTRIBUTES oa;
794 if (name) RtlInitUnicodeString(&us, name);
795 if (sa && (sa->nLength >= sizeof(*sa)) && sa->bInheritHandle)
797 InitializeObjectAttributes(&oa, name ? &us : NULL, attr,
798 NULL /* FIXME */, NULL /* FIXME */);
799 status = NtCreateTimer(&handle, TIMER_ALL_ACCESS, &oa,
800 manual ? NotificationTimer : SynchronizationTimer);
802 if (status != STATUS_SUCCESS)
804 SetLastError( RtlNtStatusToDosError(status) );
811 /***********************************************************************
812 * OpenWaitableTimerA (KERNEL32.@)
814 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
816 WCHAR buffer[MAX_PATH];
818 if (!name) return OpenWaitableTimerW( access, inherit, NULL );
820 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
822 SetLastError( ERROR_FILENAME_EXCED_RANGE );
825 return OpenWaitableTimerW( access, inherit, buffer );
829 /***********************************************************************
830 * OpenWaitableTimerW (KERNEL32.@)
832 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
838 OBJECT_ATTRIBUTES oa;
840 if (inherit) attr |= OBJ_INHERIT;
842 if (name) RtlInitUnicodeString(&us, name);
843 InitializeObjectAttributes(&oa, name ? &us : NULL, attr, NULL /* FIXME */, NULL /* FIXME */);
844 status = NtOpenTimer(&handle, access, &oa);
845 if (status != STATUS_SUCCESS)
847 SetLastError( RtlNtStatusToDosError(status) );
854 /***********************************************************************
855 * SetWaitableTimer (KERNEL32.@)
857 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
858 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
860 NTSTATUS status = NtSetTimer(handle, when, callback, arg, resume, period, NULL);
862 if (status != STATUS_SUCCESS)
864 SetLastError( RtlNtStatusToDosError(status) );
865 if (status != STATUS_TIMER_RESUME_IGNORED) return FALSE;
871 /***********************************************************************
872 * CancelWaitableTimer (KERNEL32.@)
874 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
878 status = NtCancelTimer(handle, NULL);
879 if (status != STATUS_SUCCESS)
881 SetLastError( RtlNtStatusToDosError(status) );
888 /***********************************************************************
889 * CreateTimerQueue (KERNEL32.@)
891 HANDLE WINAPI CreateTimerQueue(void)
894 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
899 /***********************************************************************
900 * DeleteTimerQueueEx (KERNEL32.@)
902 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
904 FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
905 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
909 /***********************************************************************
910 * CreateTimerQueueTimer (KERNEL32.@)
912 * Creates a timer-queue timer. This timer expires at the specified due
913 * time (in ms), then after every specified period (in ms). When the timer
914 * expires, the callback function is called.
917 * nonzero on success or zero on faillure
922 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
923 WAITORTIMERCALLBACK Callback, PVOID Parameter,
924 DWORD DueTime, DWORD Period, ULONG Flags )
927 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
931 /***********************************************************************
932 * DeleteTimerQueueTimer (KERNEL32.@)
934 * Cancels a timer-queue timer.
937 * nonzero on success or zero on faillure
942 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
943 HANDLE CompletionEvent )
946 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
956 /***********************************************************************
957 * CreateNamedPipeA (KERNEL32.@)
959 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
960 DWORD dwPipeMode, DWORD nMaxInstances,
961 DWORD nOutBufferSize, DWORD nInBufferSize,
962 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
964 WCHAR buffer[MAX_PATH];
966 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
967 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
969 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
971 SetLastError( ERROR_FILENAME_EXCED_RANGE );
972 return INVALID_HANDLE_VALUE;
974 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
975 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
979 /***********************************************************************
980 * CreateNamedPipeW (KERNEL32.@)
982 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
983 DWORD dwPipeMode, DWORD nMaxInstances,
984 DWORD nOutBufferSize, DWORD nInBufferSize,
985 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
989 static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
991 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
992 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
993 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
997 SetLastError( ERROR_PATH_NOT_FOUND );
998 return INVALID_HANDLE_VALUE;
1000 len = strlenW(name);
1001 if (len >= MAX_PATH)
1003 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1004 return INVALID_HANDLE_VALUE;
1006 if (strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0])))
1008 SetLastError( ERROR_INVALID_NAME );
1009 return INVALID_HANDLE_VALUE;
1011 SERVER_START_REQ( create_named_pipe )
1013 req->openmode = dwOpenMode;
1014 req->pipemode = dwPipeMode;
1015 req->maxinstances = nMaxInstances;
1016 req->outsize = nOutBufferSize;
1017 req->insize = nInBufferSize;
1018 req->timeout = nDefaultTimeOut;
1019 wine_server_add_data( req, name, len * sizeof(WCHAR) );
1021 if (!wine_server_call_err( req )) ret = reply->handle;
1022 else ret = INVALID_HANDLE_VALUE;
1029 /***********************************************************************
1030 * PeekNamedPipe (KERNEL32.@)
1032 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
1033 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
1038 fd = FILE_GetUnixHandle(hPipe, GENERIC_READ);
1039 if (fd == -1) return FALSE;
1041 if (ioctl(fd,FIONREAD, &avail ) != 0)
1043 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
1047 if (!avail) /* check for closed pipe */
1049 struct pollfd pollfd;
1051 pollfd.events = POLLIN;
1053 switch (poll( &pollfd, 1, 0 ))
1057 case 1: /* got something */
1058 if (!(pollfd.revents & (POLLHUP | POLLERR))) break;
1059 TRACE("POLLHUP | POLLERR\n");
1063 SetLastError(ERROR_BROKEN_PIPE);
1068 TRACE(" 0x%08x bytes available\n", avail );
1069 if (!lpvBuffer && lpcbAvail)
1074 #endif /* defined(FIONREAD) */
1076 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1077 FIXME("function not implemented\n");
1081 /***********************************************************************
1082 * SYNC_CompletePipeOverlapped (Internal)
1084 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
1086 TRACE("for %p result %08lx\n",overlapped,result);
1089 overlapped->Internal = result;
1090 SetEvent(overlapped->hEvent);
1094 /***********************************************************************
1095 * WaitNamedPipeA (KERNEL32.@)
1097 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
1099 WCHAR buffer[MAX_PATH];
1101 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
1103 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
1105 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1108 return WaitNamedPipeW( buffer, nTimeOut );
1112 /***********************************************************************
1113 * WaitNamedPipeW (KERNEL32.@)
1115 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
1117 DWORD len = name ? strlenW(name) : 0;
1121 if (len >= MAX_PATH)
1123 SetLastError( ERROR_FILENAME_EXCED_RANGE );
1127 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
1129 memset(&ov,0,sizeof(ov));
1130 ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
1134 SERVER_START_REQ( wait_named_pipe )
1136 req->timeout = nTimeOut;
1137 req->overlapped = &ov;
1138 req->func = SYNC_CompletePipeOverlapped;
1139 wine_server_add_data( req, name, len * sizeof(WCHAR) );
1140 ret = !wine_server_call_err( req );
1146 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1148 SetLastError(ov.Internal);
1149 ret = (ov.Internal==STATUS_SUCCESS);
1152 CloseHandle(ov.hEvent);
1157 /***********************************************************************
1158 * SYNC_ConnectNamedPipe (Internal)
1160 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1167 overlapped->Internal = STATUS_PENDING;
1169 SERVER_START_REQ( connect_named_pipe )
1171 req->handle = hPipe;
1172 req->overlapped = overlapped;
1173 req->func = SYNC_CompletePipeOverlapped;
1174 ret = !wine_server_call_err( req );
1181 /***********************************************************************
1182 * ConnectNamedPipe (KERNEL32.@)
1184 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
1189 TRACE("(%p,%p)\n",hPipe, overlapped);
1193 if(SYNC_ConnectNamedPipe(hPipe,overlapped))
1194 SetLastError( ERROR_IO_PENDING );
1198 memset(&ov,0,sizeof(ov));
1199 ov.hEvent = CreateEventA(NULL,0,0,NULL);
1203 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
1206 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
1208 SetLastError(ov.Internal);
1209 ret = (ov.Internal==STATUS_SUCCESS);
1213 CloseHandle(ov.hEvent);
1218 /***********************************************************************
1219 * DisconnectNamedPipe (KERNEL32.@)
1221 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
1225 TRACE("(%p)\n",hPipe);
1227 SERVER_START_REQ( disconnect_named_pipe )
1229 req->handle = hPipe;
1230 ret = !wine_server_call_err( req );
1231 if (ret && reply->fd != -1) close( reply->fd );
1238 /***********************************************************************
1239 * TransactNamedPipe (KERNEL32.@)
1241 BOOL WINAPI TransactNamedPipe(
1242 HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
1243 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
1245 FIXME("%p %p %ld %p %ld %p %p\n",
1246 hPipe, lpInput, dwInputSize, lpOutput,
1247 dwOutputSize, lpBytesRead, lpOverlapped);
1253 /***********************************************************************
1254 * GetNamedPipeInfo (KERNEL32.@)
1256 BOOL WINAPI GetNamedPipeInfo(
1257 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
1258 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
1262 TRACE("%p %p %p %p %p\n", hNamedPipe, lpFlags,
1263 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
1265 SERVER_START_REQ( get_named_pipe_info )
1267 req->handle = hNamedPipe;
1268 ret = !wine_server_call_err( req );
1269 if(lpFlags) *lpFlags = reply->flags;
1270 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
1271 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
1272 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
1279 /***********************************************************************
1280 * GetNamedPipeHandleStateA (KERNEL32.@)
1282 BOOL WINAPI GetNamedPipeHandleStateA(
1283 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1284 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1285 LPSTR lpUsername, DWORD nUsernameMaxSize)
1287 FIXME("%p %p %p %p %p %p %ld\n",
1288 hNamedPipe, lpState, lpCurInstances,
1289 lpMaxCollectionCount, lpCollectDataTimeout,
1290 lpUsername, nUsernameMaxSize);
1295 /***********************************************************************
1296 * GetNamedPipeHandleStateW (KERNEL32.@)
1298 BOOL WINAPI GetNamedPipeHandleStateW(
1299 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
1300 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
1301 LPWSTR lpUsername, DWORD nUsernameMaxSize)
1303 FIXME("%p %p %p %p %p %p %ld\n",
1304 hNamedPipe, lpState, lpCurInstances,
1305 lpMaxCollectionCount, lpCollectDataTimeout,
1306 lpUsername, nUsernameMaxSize);
1311 /***********************************************************************
1312 * SetNamedPipeHandleState (KERNEL32.@)
1314 BOOL WINAPI SetNamedPipeHandleState(
1315 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
1316 LPDWORD lpCollectDataTimeout)
1318 FIXME("%p %p %p %p\n",
1319 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
1323 /***********************************************************************
1324 * CallNamedPipeA (KERNEL32.@)
1326 BOOL WINAPI CallNamedPipeA(
1327 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1328 LPVOID lpOutput, DWORD lpOutputSize,
1329 LPDWORD lpBytesRead, DWORD nTimeout)
1331 FIXME("%s %p %ld %p %ld %p %ld\n",
1332 debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
1333 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1337 /***********************************************************************
1338 * CallNamedPipeW (KERNEL32.@)
1340 BOOL WINAPI CallNamedPipeW(
1341 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
1342 LPVOID lpOutput, DWORD lpOutputSize,
1343 LPDWORD lpBytesRead, DWORD nTimeout)
1345 FIXME("%s %p %ld %p %ld %p %ld\n",
1346 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
1347 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
1351 /******************************************************************
1352 * CreatePipe (KERNEL32.@)
1355 BOOL WINAPI CreatePipe( PHANDLE hReadPipe, PHANDLE hWritePipe,
1356 LPSECURITY_ATTRIBUTES sa, DWORD size )
1358 static unsigned index = 0;
1361 unsigned in_index = index;
1363 *hReadPipe = *hWritePipe = INVALID_HANDLE_VALUE;
1364 /* generate a unique pipe name (system wide) */
1367 sprintf(name, "\\\\.\\pipe\\Win32.Pipes.%08lu.%08u", GetCurrentProcessId(), ++index);
1368 hr = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND,
1369 PIPE_TYPE_BYTE | PIPE_WAIT, 1, size, size,
1370 NMPWAIT_USE_DEFAULT_WAIT, sa);
1371 } while (hr == INVALID_HANDLE_VALUE && index != in_index);
1372 /* from completion sakeness, I think system resources might be exhausted before this happens !! */
1373 if (hr == INVALID_HANDLE_VALUE) return FALSE;
1375 hw = CreateFileA(name, GENERIC_WRITE, 0, sa, OPEN_EXISTING, 0, 0);
1376 if (hw == INVALID_HANDLE_VALUE)
1388 /******************************************************************************
1389 * CreateMailslotA [KERNEL32.@]
1391 HANDLE WINAPI CreateMailslotA( LPCSTR lpName, DWORD nMaxMessageSize,
1392 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1398 TRACE("%s %ld %ld %p\n", debugstr_a(lpName),
1399 nMaxMessageSize, lReadTimeout, sa);
1403 len = MultiByteToWideChar( CP_ACP, 0, lpName, -1, NULL, 0 );
1404 name = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1405 MultiByteToWideChar( CP_ACP, 0, lpName, -1, name, len );
1408 handle = CreateMailslotW( name, nMaxMessageSize, lReadTimeout, sa );
1411 HeapFree( GetProcessHeap(), 0, name );
1417 /******************************************************************************
1418 * CreateMailslotW [KERNEL32.@]
1420 * Create a mailslot with specified name.
1423 * lpName [I] Pointer to string for mailslot name
1424 * nMaxMessageSize [I] Maximum message size
1425 * lReadTimeout [I] Milliseconds before read time-out
1426 * sa [I] Pointer to security structure
1429 * Success: Handle to mailslot
1430 * Failure: INVALID_HANDLE_VALUE
1432 HANDLE WINAPI CreateMailslotW( LPCWSTR lpName, DWORD nMaxMessageSize,
1433 DWORD lReadTimeout, LPSECURITY_ATTRIBUTES sa )
1435 FIXME("(%s,%ld,%ld,%p): stub\n", debugstr_w(lpName),
1436 nMaxMessageSize, lReadTimeout, sa);
1441 /******************************************************************************
1442 * GetMailslotInfo [KERNEL32.@]
1444 * Retrieve information about a mailslot.
1447 * hMailslot [I] Mailslot handle
1448 * lpMaxMessageSize [O] Address of maximum message size
1449 * lpNextSize [O] Address of size of next message
1450 * lpMessageCount [O] Address of number of messages
1451 * lpReadTimeout [O] Address of read time-out
1457 BOOL WINAPI GetMailslotInfo( HANDLE hMailslot, LPDWORD lpMaxMessageSize,
1458 LPDWORD lpNextSize, LPDWORD lpMessageCount,
1459 LPDWORD lpReadTimeout )
1461 FIXME("(%p): stub\n",hMailslot);
1462 if (lpMaxMessageSize) *lpMaxMessageSize = (DWORD)NULL;
1463 if (lpNextSize) *lpNextSize = (DWORD)NULL;
1464 if (lpMessageCount) *lpMessageCount = (DWORD)NULL;
1465 if (lpReadTimeout) *lpReadTimeout = (DWORD)NULL;
1470 /******************************************************************************
1471 * SetMailslotInfo [KERNEL32.@]
1473 * Set the read timeout of a mailslot.
1476 * hMailslot [I] Mailslot handle
1477 * dwReadTimeout [I] Timeout in milliseconds.
1483 BOOL WINAPI SetMailslotInfo( HANDLE hMailslot, DWORD dwReadTimeout)
1485 FIXME("%p %ld: stub\n", hMailslot, dwReadTimeout);
1492 /***********************************************************************
1493 * InterlockedCompareExchange (KERNEL32.@)
1495 /* LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare ); */
1496 __ASM_GLOBAL_FUNC(InterlockedCompareExchange,
1497 "movl 12(%esp),%eax\n\t"
1498 "movl 8(%esp),%ecx\n\t"
1499 "movl 4(%esp),%edx\n\t"
1500 "lock; cmpxchgl %ecx,(%edx)\n\t"
1503 /***********************************************************************
1504 * InterlockedExchange (KERNEL32.@)
1506 /* LONG WINAPI InterlockedExchange( PLONG dest, LONG val ); */
1507 __ASM_GLOBAL_FUNC(InterlockedExchange,
1508 "movl 8(%esp),%eax\n\t"
1509 "movl 4(%esp),%edx\n\t"
1510 "lock; xchgl %eax,(%edx)\n\t"
1513 /***********************************************************************
1514 * InterlockedExchangeAdd (KERNEL32.@)
1516 /* LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ); */
1517 __ASM_GLOBAL_FUNC(InterlockedExchangeAdd,
1518 "movl 8(%esp),%eax\n\t"
1519 "movl 4(%esp),%edx\n\t"
1520 "lock; xaddl %eax,(%edx)\n\t"
1523 /***********************************************************************
1524 * InterlockedIncrement (KERNEL32.@)
1526 /* LONG WINAPI InterlockedIncrement( PLONG dest ); */
1527 __ASM_GLOBAL_FUNC(InterlockedIncrement,
1528 "movl 4(%esp),%edx\n\t"
1530 "lock; xaddl %eax,(%edx)\n\t"
1534 /***********************************************************************
1535 * InterlockedDecrement (KERNEL32.@)
1537 __ASM_GLOBAL_FUNC(InterlockedDecrement,
1538 "movl 4(%esp),%edx\n\t"
1540 "lock; xaddl %eax,(%edx)\n\t"
1544 #else /* __i386__ */
1546 /***********************************************************************
1547 * InterlockedCompareExchange (KERNEL32.@)
1549 * Atomically swap one value with another.
1552 * dest [I/O] The value to replace
1553 * xchq [I] The value to be swapped
1554 * compare [I] The value to compare to dest
1557 * The resulting value of dest.
1560 * dest is updated only if it is equal to compare, otherwise no swap is done.
1562 LONG WINAPI InterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare )
1564 return interlocked_cmpxchg( dest, xchg, compare );
1567 /***********************************************************************
1568 * InterlockedExchange (KERNEL32.@)
1570 * Atomically swap one value with another.
1573 * dest [I/O] The value to replace
1574 * val [I] The value to be swapped
1577 * The resulting value of dest.
1579 LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
1581 return interlocked_xchg( dest, val );
1584 /***********************************************************************
1585 * InterlockedExchangeAdd (KERNEL32.@)
1587 * Atomically add one value to another.
1590 * dest [I/O] The value to add to
1591 * incr [I] The value to be added
1594 * The resulting value of dest.
1596 LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
1598 return interlocked_xchg_add( dest, incr );
1601 /***********************************************************************
1602 * InterlockedIncrement (KERNEL32.@)
1604 * Atomically increment a value.
1607 * dest [I/O] The value to increment
1610 * The resulting value of dest.
1612 LONG WINAPI InterlockedIncrement( PLONG dest )
1614 return interlocked_xchg_add( dest, 1 ) + 1;
1617 /***********************************************************************
1618 * InterlockedDecrement (KERNEL32.@)
1620 * Atomically decrement a value.
1623 * dest [I/O] The value to decrement
1626 * The resulting value of dest.
1628 LONG WINAPI InterlockedDecrement( PLONG dest )
1630 return interlocked_xchg_add( dest, -1 ) - 1;
1633 #endif /* __i386__ */