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>
37 #include "wine/server.h"
38 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(win32);
50 /***********************************************************************
51 * CreateEventA (KERNEL32.@)
53 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
54 BOOL initial_state, LPCSTR name )
56 WCHAR buffer[MAX_PATH];
58 if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
60 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
62 SetLastError( ERROR_FILENAME_EXCED_RANGE );
65 return CreateEventW( sa, manual_reset, initial_state, buffer );
69 /***********************************************************************
70 * CreateEventW (KERNEL32.@)
72 HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
73 BOOL initial_state, LPCWSTR name )
76 DWORD len = name ? strlenW(name) : 0;
79 SetLastError( ERROR_FILENAME_EXCED_RANGE );
82 /* one buggy program needs this
83 * ("Van Dale Groot woordenboek der Nederlandse taal")
85 if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
87 ERR("Bad security attributes pointer %p\n",sa);
88 SetLastError( ERROR_INVALID_PARAMETER);
91 SERVER_START_REQ( create_event )
93 req->manual_reset = manual_reset;
94 req->initial_state = initial_state;
95 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
96 wine_server_add_data( req, name, len * sizeof(WCHAR) );
98 wine_server_call_err( req );
106 /***********************************************************************
107 * CreateW32Event (KERNEL.457)
109 HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
111 return CreateEventA( NULL, manual_reset, initial_state, NULL );
115 /***********************************************************************
116 * OpenEventA (KERNEL32.@)
118 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
120 WCHAR buffer[MAX_PATH];
122 if (!name) return OpenEventW( access, inherit, NULL );
124 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
126 SetLastError( ERROR_FILENAME_EXCED_RANGE );
129 return OpenEventW( access, inherit, buffer );
133 /***********************************************************************
134 * OpenEventW (KERNEL32.@)
136 HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
139 DWORD len = name ? strlenW(name) : 0;
142 SetLastError( ERROR_FILENAME_EXCED_RANGE );
145 SERVER_START_REQ( open_event )
147 req->access = access;
148 req->inherit = inherit;
149 wine_server_add_data( req, name, len * sizeof(WCHAR) );
150 wine_server_call_err( req );
158 /***********************************************************************
161 * Execute an event operation (set,reset,pulse).
163 static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
166 SERVER_START_REQ( event_op )
168 req->handle = handle;
170 ret = !wine_server_call_err( req );
177 /***********************************************************************
178 * PulseEvent (KERNEL32.@)
180 BOOL WINAPI PulseEvent( HANDLE handle )
182 return EVENT_Operation( handle, PULSE_EVENT );
186 /***********************************************************************
187 * SetW32Event (KERNEL.458)
188 * SetEvent (KERNEL32.@)
190 BOOL WINAPI SetEvent( HANDLE handle )
192 return EVENT_Operation( handle, SET_EVENT );
196 /***********************************************************************
197 * ResetW32Event (KERNEL.459)
198 * ResetEvent (KERNEL32.@)
200 BOOL WINAPI ResetEvent( HANDLE handle )
202 return EVENT_Operation( handle, RESET_EVENT );
206 /***********************************************************************
207 * NOTE: The Win95 VWin32_Event routines given below are really low-level
208 * routines implemented directly by VWin32. The user-mode libraries
209 * implement Win32 synchronisation routines on top of these low-level
210 * primitives. We do it the other way around here :-)
213 /***********************************************************************
214 * VWin32_EventCreate (KERNEL.442)
216 HANDLE WINAPI VWin32_EventCreate(VOID)
218 HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
219 return ConvertToGlobalHandle( hEvent );
222 /***********************************************************************
223 * VWin32_EventDestroy (KERNEL.443)
225 VOID WINAPI VWin32_EventDestroy(HANDLE event)
227 CloseHandle( event );
230 /***********************************************************************
231 * VWin32_EventWait (KERNEL.450)
233 VOID WINAPI VWin32_EventWait(HANDLE event)
237 ReleaseThunkLock( &mutex_count );
238 WaitForSingleObject( event, INFINITE );
239 RestoreThunkLock( mutex_count );
242 /***********************************************************************
243 * VWin32_EventSet (KERNEL.451)
244 * KERNEL_479 (KERNEL.479)
246 VOID WINAPI VWin32_EventSet(HANDLE event)
253 /***********************************************************************
254 * CreateMutexA (KERNEL32.@)
256 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
258 WCHAR buffer[MAX_PATH];
260 if (!name) return CreateMutexW( sa, owner, NULL );
262 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
264 SetLastError( ERROR_FILENAME_EXCED_RANGE );
267 return CreateMutexW( sa, owner, buffer );
271 /***********************************************************************
272 * CreateMutexW (KERNEL32.@)
274 HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
277 DWORD len = name ? strlenW(name) : 0;
280 SetLastError( ERROR_FILENAME_EXCED_RANGE );
283 SERVER_START_REQ( create_mutex )
286 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
287 wine_server_add_data( req, name, len * sizeof(WCHAR) );
289 wine_server_call_err( req );
297 /***********************************************************************
298 * OpenMutexA (KERNEL32.@)
300 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
302 WCHAR buffer[MAX_PATH];
304 if (!name) return OpenMutexW( access, inherit, NULL );
306 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
308 SetLastError( ERROR_FILENAME_EXCED_RANGE );
311 return OpenMutexW( access, inherit, buffer );
315 /***********************************************************************
316 * OpenMutexW (KERNEL32.@)
318 HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
321 DWORD len = name ? strlenW(name) : 0;
324 SetLastError( ERROR_FILENAME_EXCED_RANGE );
327 SERVER_START_REQ( open_mutex )
329 req->access = access;
330 req->inherit = inherit;
331 wine_server_add_data( req, name, len * sizeof(WCHAR) );
332 wine_server_call_err( req );
340 /***********************************************************************
341 * ReleaseMutex (KERNEL32.@)
343 BOOL WINAPI ReleaseMutex( HANDLE handle )
346 SERVER_START_REQ( release_mutex )
348 req->handle = handle;
349 ret = !wine_server_call_err( req );
361 /***********************************************************************
362 * CreateSemaphoreA (KERNEL32.@)
364 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
366 WCHAR buffer[MAX_PATH];
368 if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
370 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
372 SetLastError( ERROR_FILENAME_EXCED_RANGE );
375 return CreateSemaphoreW( sa, initial, max, buffer );
379 /***********************************************************************
380 * CreateSemaphoreW (KERNEL32.@)
382 HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
383 LONG max, LPCWSTR name )
386 DWORD len = name ? strlenW(name) : 0;
388 /* Check parameters */
390 if ((max <= 0) || (initial < 0) || (initial > max))
392 SetLastError( ERROR_INVALID_PARAMETER );
397 SetLastError( ERROR_FILENAME_EXCED_RANGE );
401 SERVER_START_REQ( create_semaphore )
403 req->initial = (unsigned int)initial;
404 req->max = (unsigned int)max;
405 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
406 wine_server_add_data( req, name, len * sizeof(WCHAR) );
408 wine_server_call_err( req );
416 /***********************************************************************
417 * OpenSemaphoreA (KERNEL32.@)
419 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
421 WCHAR buffer[MAX_PATH];
423 if (!name) return OpenSemaphoreW( access, inherit, NULL );
425 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
427 SetLastError( ERROR_FILENAME_EXCED_RANGE );
430 return OpenSemaphoreW( access, inherit, buffer );
434 /***********************************************************************
435 * OpenSemaphoreW (KERNEL32.@)
437 HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
440 DWORD len = name ? strlenW(name) : 0;
443 SetLastError( ERROR_FILENAME_EXCED_RANGE );
446 SERVER_START_REQ( open_semaphore )
448 req->access = access;
449 req->inherit = inherit;
450 wine_server_add_data( req, name, len * sizeof(WCHAR) );
451 wine_server_call_err( req );
459 /***********************************************************************
460 * ReleaseSemaphore (KERNEL32.@)
462 BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
464 NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
465 if (status) SetLastError( RtlNtStatusToDosError(status) );
475 /***********************************************************************
476 * CreateNamedPipeA (KERNEL32.@)
478 HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
479 DWORD dwPipeMode, DWORD nMaxInstances,
480 DWORD nOutBufferSize, DWORD nInBufferSize,
481 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
483 WCHAR buffer[MAX_PATH];
485 if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
486 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
488 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
490 SetLastError( ERROR_FILENAME_EXCED_RANGE );
493 return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
494 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
498 /***********************************************************************
499 * CreateNamedPipeW (KERNEL32.@)
501 HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
502 DWORD dwPipeMode, DWORD nMaxInstances,
503 DWORD nOutBufferSize, DWORD nInBufferSize,
504 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
507 DWORD len = name ? strlenW(name) : 0;
509 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
510 debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
511 nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
515 SetLastError( ERROR_FILENAME_EXCED_RANGE );
518 SERVER_START_REQ( create_named_pipe )
520 req->openmode = dwOpenMode;
521 req->pipemode = dwPipeMode;
522 req->maxinstances = nMaxInstances;
523 req->outsize = nOutBufferSize;
524 req->insize = nInBufferSize;
525 req->timeout = nDefaultTimeOut;
526 wine_server_add_data( req, name, len * sizeof(WCHAR) );
528 wine_server_call_err( req );
536 /***********************************************************************
537 * PeekNamedPipe (KERNEL32.@)
539 BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
540 LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
545 fd = FILE_GetUnixHandle(hPipe, GENERIC_READ);
548 /* On linux fstat on pipes doesn't work */
549 if (ioctl(fd,FIONREAD, &avail ) != 0)
551 TRACE("FIONREAD failed reason: %s\n",strerror(errno));
556 TRACE(" 0x%08x bytes available\n", avail );
557 if (!lpvBuffer && lpcbAvail)
562 #endif /* defined(FIONREAD) */
564 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
565 FIXME("function not implemented\n");
569 /***********************************************************************
570 * SYNC_CompletePipeOverlapped (Internal)
572 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
574 TRACE("for %p result %08lx\n",overlapped,result);
577 overlapped->Internal = result;
578 SetEvent(overlapped->hEvent);
582 /***********************************************************************
583 * WaitNamedPipeA (KERNEL32.@)
585 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
587 WCHAR buffer[MAX_PATH];
589 if (!name) return WaitNamedPipeW( NULL, nTimeOut );
591 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
593 SetLastError( ERROR_FILENAME_EXCED_RANGE );
596 return WaitNamedPipeW( buffer, nTimeOut );
600 /***********************************************************************
601 * WaitNamedPipeW (KERNEL32.@)
603 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
605 DWORD len = name ? strlenW(name) : 0;
611 SetLastError( ERROR_FILENAME_EXCED_RANGE );
615 TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
617 memset(&ov,0,sizeof ov);
618 ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
622 SERVER_START_REQ( wait_named_pipe )
624 req->timeout = nTimeOut;
625 req->overlapped = &ov;
626 req->func = SYNC_CompletePipeOverlapped;
627 wine_server_add_data( req, name, len * sizeof(WCHAR) );
628 ret = !wine_server_call_err( req );
634 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
636 SetLastError(ov.Internal);
637 ret = (ov.Internal==STATUS_SUCCESS);
640 CloseHandle(ov.hEvent);
645 /***********************************************************************
646 * SYNC_ConnectNamedPipe (Internal)
648 static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
655 overlapped->Internal = STATUS_PENDING;
657 SERVER_START_REQ( connect_named_pipe )
660 req->overlapped = overlapped;
661 req->func = SYNC_CompletePipeOverlapped;
662 ret = !wine_server_call_err( req );
669 /***********************************************************************
670 * ConnectNamedPipe (KERNEL32.@)
672 BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
677 TRACE("(%d,%p)\n",hPipe, overlapped);
680 return SYNC_ConnectNamedPipe(hPipe,overlapped);
682 memset(&ov,0,sizeof ov);
683 ov.hEvent = CreateEventA(NULL,0,0,NULL);
687 ret=SYNC_ConnectNamedPipe(hPipe, &ov);
690 if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
692 SetLastError(ov.Internal);
693 ret = (ov.Internal==STATUS_SUCCESS);
697 CloseHandle(ov.hEvent);
702 /***********************************************************************
703 * DisconnectNamedPipe (KERNEL32.@)
705 BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
709 TRACE("(%d)\n",hPipe);
711 SERVER_START_REQ( disconnect_named_pipe )
714 ret = !wine_server_call_err( req );
721 /***********************************************************************
722 * TransactNamedPipe (KERNEL32.@)
724 BOOL WINAPI TransactNamedPipe(
725 HANDLE hPipe, LPVOID lpInput, DWORD dwInputSize, LPVOID lpOutput,
726 DWORD dwOutputSize, LPDWORD lpBytesRead, LPOVERLAPPED lpOverlapped)
728 FIXME("%d %p %ld %p %ld %p %p\n",
729 hPipe, lpInput, dwInputSize, lpOutput,
730 dwOutputSize, lpBytesRead, lpOverlapped);
736 /***********************************************************************
737 * GetNamedPipeInfo (KERNEL32.@)
739 BOOL WINAPI GetNamedPipeInfo(
740 HANDLE hNamedPipe, LPDWORD lpFlags, LPDWORD lpOutputBufferSize,
741 LPDWORD lpInputBufferSize, LPDWORD lpMaxInstances)
745 TRACE("%d %p %p %p %p\n", hNamedPipe, lpFlags,
746 lpOutputBufferSize, lpInputBufferSize, lpMaxInstances);
748 SERVER_START_REQ( get_named_pipe_info )
750 req->handle = hNamedPipe;
751 ret = !wine_server_call_err( req );
752 if(lpFlags) *lpFlags = reply->flags;
753 if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
754 if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
755 if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
762 /***********************************************************************
763 * GetNamedPipeHandleStateA (KERNEL32.@)
765 BOOL WINAPI GetNamedPipeHandleStateA(
766 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
767 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
768 LPSTR lpUsername, DWORD nUsernameMaxSize)
770 FIXME("%d %p %p %p %p %p %ld\n",
771 hNamedPipe, lpState, lpCurInstances,
772 lpMaxCollectionCount, lpCollectDataTimeout,
773 lpUsername, nUsernameMaxSize);
778 /***********************************************************************
779 * GetNamedPipeHandleStateW (KERNEL32.@)
781 BOOL WINAPI GetNamedPipeHandleStateW(
782 HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances,
783 LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
784 LPWSTR lpUsername, DWORD nUsernameMaxSize)
786 FIXME("%d %p %p %p %p %p %ld\n",
787 hNamedPipe, lpState, lpCurInstances,
788 lpMaxCollectionCount, lpCollectDataTimeout,
789 lpUsername, nUsernameMaxSize);
794 /***********************************************************************
795 * SetNamedPipeHandleState (KERNEL32.@)
797 BOOL WINAPI SetNamedPipeHandleState(
798 HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
799 LPDWORD lpCollectDataTimeout)
801 FIXME("%d %p %p %p\n",
802 hNamedPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
806 /***********************************************************************
807 * CallNamedPipeA (KERNEL32.@)
809 BOOL WINAPI CallNamedPipeA(
810 LPCSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
811 LPVOID lpOutput, DWORD lpOutputSize,
812 LPDWORD lpBytesRead, DWORD nTimeout)
814 FIXME("%s %p %ld %p %ld %p %ld\n",
815 debugstr_a(lpNamedPipeName), lpInput, lpInputSize,
816 lpOutput, lpOutputSize, lpBytesRead, nTimeout);
820 /***********************************************************************
821 * CallNamedPipeW (KERNEL32.@)
823 BOOL WINAPI CallNamedPipeW(
824 LPCWSTR lpNamedPipeName, LPVOID lpInput, DWORD lpInputSize,
825 LPVOID lpOutput, DWORD lpOutputSize,
826 LPDWORD lpBytesRead, DWORD nTimeout)
828 FIXME("%s %p %ld %p %ld %p %ld\n",
829 debugstr_w(lpNamedPipeName), lpInput, lpInputSize,
830 lpOutput, lpOutputSize, lpBytesRead, nTimeout);