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
40 #include "wine/server.h"
41 #include "wine/unicode.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(win32
);
53 /***********************************************************************
54 * CreateEventA (KERNEL32.@)
56 HANDLE WINAPI
CreateEventA( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
57 BOOL initial_state
, LPCSTR name
)
59 WCHAR buffer
[MAX_PATH
];
61 if (!name
) return CreateEventW( sa
, manual_reset
, initial_state
, NULL
);
63 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
65 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
68 return CreateEventW( sa
, manual_reset
, initial_state
, buffer
);
72 /***********************************************************************
73 * CreateEventW (KERNEL32.@)
75 HANDLE WINAPI
CreateEventW( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
76 BOOL initial_state
, LPCWSTR name
)
79 DWORD len
= name
? strlenW(name
) : 0;
82 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
85 /* one buggy program needs this
86 * ("Van Dale Groot woordenboek der Nederlandse taal")
88 if (sa
&& IsBadReadPtr(sa
,sizeof(SECURITY_ATTRIBUTES
)))
90 ERR("Bad security attributes pointer %p\n",sa
);
91 SetLastError( ERROR_INVALID_PARAMETER
);
94 SERVER_START_REQ( create_event
)
96 req
->manual_reset
= manual_reset
;
97 req
->initial_state
= initial_state
;
98 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
99 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
101 wine_server_call_err( req
);
109 /***********************************************************************
110 * CreateW32Event (KERNEL.457)
112 HANDLE WINAPI
WIN16_CreateEvent( BOOL manual_reset
, BOOL initial_state
)
114 return CreateEventA( NULL
, manual_reset
, initial_state
, NULL
);
118 /***********************************************************************
119 * OpenEventA (KERNEL32.@)
121 HANDLE WINAPI
OpenEventA( DWORD access
, BOOL inherit
, LPCSTR name
)
123 WCHAR buffer
[MAX_PATH
];
125 if (!name
) return OpenEventW( access
, inherit
, NULL
);
127 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
129 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
132 return OpenEventW( access
, inherit
, buffer
);
136 /***********************************************************************
137 * OpenEventW (KERNEL32.@)
139 HANDLE WINAPI
OpenEventW( DWORD access
, BOOL inherit
, LPCWSTR name
)
142 DWORD len
= name
? strlenW(name
) : 0;
145 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
148 SERVER_START_REQ( open_event
)
150 req
->access
= access
;
151 req
->inherit
= inherit
;
152 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
153 wine_server_call_err( req
);
161 /***********************************************************************
164 * Execute an event operation (set,reset,pulse).
166 static BOOL
EVENT_Operation( HANDLE handle
, enum event_op op
)
169 SERVER_START_REQ( event_op
)
171 req
->handle
= handle
;
173 ret
= !wine_server_call_err( req
);
180 /***********************************************************************
181 * PulseEvent (KERNEL32.@)
183 BOOL WINAPI
PulseEvent( HANDLE handle
)
185 return EVENT_Operation( handle
, PULSE_EVENT
);
189 /***********************************************************************
190 * SetW32Event (KERNEL.458)
191 * SetEvent (KERNEL32.@)
193 BOOL WINAPI
SetEvent( HANDLE handle
)
195 return EVENT_Operation( handle
, SET_EVENT
);
199 /***********************************************************************
200 * ResetW32Event (KERNEL.459)
201 * ResetEvent (KERNEL32.@)
203 BOOL WINAPI
ResetEvent( HANDLE handle
)
205 return EVENT_Operation( handle
, RESET_EVENT
);
209 /***********************************************************************
210 * NOTE: The Win95 VWin32_Event routines given below are really low-level
211 * routines implemented directly by VWin32. The user-mode libraries
212 * implement Win32 synchronisation routines on top of these low-level
213 * primitives. We do it the other way around here :-)
216 /***********************************************************************
217 * VWin32_EventCreate (KERNEL.442)
219 HANDLE WINAPI
VWin32_EventCreate(VOID
)
221 HANDLE hEvent
= CreateEventA( NULL
, FALSE
, 0, NULL
);
222 return ConvertToGlobalHandle( hEvent
);
225 /***********************************************************************
226 * VWin32_EventDestroy (KERNEL.443)
228 VOID WINAPI
VWin32_EventDestroy(HANDLE event
)
230 CloseHandle( event
);
233 /***********************************************************************
234 * VWin32_EventWait (KERNEL.450)
236 VOID WINAPI
VWin32_EventWait(HANDLE event
)
240 ReleaseThunkLock( &mutex_count
);
241 WaitForSingleObject( event
, INFINITE
);
242 RestoreThunkLock( mutex_count
);
245 /***********************************************************************
246 * VWin32_EventSet (KERNEL.451)
247 * KERNEL_479 (KERNEL.479)
249 VOID WINAPI
VWin32_EventSet(HANDLE event
)
256 /***********************************************************************
257 * CreateMutexA (KERNEL32.@)
259 HANDLE WINAPI
CreateMutexA( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCSTR name
)
261 WCHAR buffer
[MAX_PATH
];
263 if (!name
) return CreateMutexW( sa
, owner
, NULL
);
265 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
267 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
270 return CreateMutexW( sa
, owner
, buffer
);
274 /***********************************************************************
275 * CreateMutexW (KERNEL32.@)
277 HANDLE WINAPI
CreateMutexW( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCWSTR name
)
280 DWORD len
= name
? strlenW(name
) : 0;
283 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
286 SERVER_START_REQ( create_mutex
)
289 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
290 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
292 wine_server_call_err( req
);
300 /***********************************************************************
301 * OpenMutexA (KERNEL32.@)
303 HANDLE WINAPI
OpenMutexA( DWORD access
, BOOL inherit
, LPCSTR name
)
305 WCHAR buffer
[MAX_PATH
];
307 if (!name
) return OpenMutexW( access
, inherit
, NULL
);
309 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
311 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
314 return OpenMutexW( access
, inherit
, buffer
);
318 /***********************************************************************
319 * OpenMutexW (KERNEL32.@)
321 HANDLE WINAPI
OpenMutexW( DWORD access
, BOOL inherit
, LPCWSTR name
)
324 DWORD len
= name
? strlenW(name
) : 0;
327 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
330 SERVER_START_REQ( open_mutex
)
332 req
->access
= access
;
333 req
->inherit
= inherit
;
334 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
335 wine_server_call_err( req
);
343 /***********************************************************************
344 * ReleaseMutex (KERNEL32.@)
346 BOOL WINAPI
ReleaseMutex( HANDLE handle
)
349 SERVER_START_REQ( release_mutex
)
351 req
->handle
= handle
;
352 ret
= !wine_server_call_err( req
);
364 /***********************************************************************
365 * CreateSemaphoreA (KERNEL32.@)
367 HANDLE WINAPI
CreateSemaphoreA( SECURITY_ATTRIBUTES
*sa
, LONG initial
, LONG max
, LPCSTR name
)
369 WCHAR buffer
[MAX_PATH
];
371 if (!name
) return CreateSemaphoreW( sa
, initial
, max
, NULL
);
373 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
375 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
378 return CreateSemaphoreW( sa
, initial
, max
, buffer
);
382 /***********************************************************************
383 * CreateSemaphoreW (KERNEL32.@)
385 HANDLE WINAPI
CreateSemaphoreW( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
386 LONG max
, LPCWSTR name
)
389 DWORD len
= name
? strlenW(name
) : 0;
391 /* Check parameters */
393 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
395 SetLastError( ERROR_INVALID_PARAMETER
);
400 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
404 SERVER_START_REQ( create_semaphore
)
406 req
->initial
= (unsigned int)initial
;
407 req
->max
= (unsigned int)max
;
408 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
409 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
411 wine_server_call_err( req
);
419 /***********************************************************************
420 * OpenSemaphoreA (KERNEL32.@)
422 HANDLE WINAPI
OpenSemaphoreA( DWORD access
, BOOL inherit
, LPCSTR name
)
424 WCHAR buffer
[MAX_PATH
];
426 if (!name
) return OpenSemaphoreW( access
, inherit
, NULL
);
428 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
430 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
433 return OpenSemaphoreW( access
, inherit
, buffer
);
437 /***********************************************************************
438 * OpenSemaphoreW (KERNEL32.@)
440 HANDLE WINAPI
OpenSemaphoreW( DWORD access
, BOOL inherit
, LPCWSTR name
)
443 DWORD len
= name
? strlenW(name
) : 0;
446 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
449 SERVER_START_REQ( open_semaphore
)
451 req
->access
= access
;
452 req
->inherit
= inherit
;
453 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
454 wine_server_call_err( req
);
462 /***********************************************************************
463 * ReleaseSemaphore (KERNEL32.@)
465 BOOL WINAPI
ReleaseSemaphore( HANDLE handle
, LONG count
, LONG
*previous
)
467 NTSTATUS status
= NtReleaseSemaphore( handle
, count
, previous
);
468 if (status
) SetLastError( RtlNtStatusToDosError(status
) );
478 /***********************************************************************
479 * CreateNamedPipeA (KERNEL32.@)
481 HANDLE WINAPI
CreateNamedPipeA( LPCSTR name
, DWORD dwOpenMode
,
482 DWORD dwPipeMode
, DWORD nMaxInstances
,
483 DWORD nOutBufferSize
, DWORD nInBufferSize
,
484 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
486 WCHAR buffer
[MAX_PATH
];
488 if (!name
) return CreateNamedPipeW( NULL
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
489 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
491 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
493 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
496 return CreateNamedPipeW( buffer
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
497 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
501 /***********************************************************************
502 * CreateNamedPipeW (KERNEL32.@)
504 HANDLE WINAPI
CreateNamedPipeW( LPCWSTR name
, DWORD dwOpenMode
,
505 DWORD dwPipeMode
, DWORD nMaxInstances
,
506 DWORD nOutBufferSize
, DWORD nInBufferSize
,
507 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
510 DWORD len
= name
? strlenW(name
) : 0;
512 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
513 debugstr_w(name
), dwOpenMode
, dwPipeMode
, nMaxInstances
,
514 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
518 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
521 SERVER_START_REQ( create_named_pipe
)
523 req
->openmode
= dwOpenMode
;
524 req
->pipemode
= dwPipeMode
;
525 req
->maxinstances
= nMaxInstances
;
526 req
->outsize
= nOutBufferSize
;
527 req
->insize
= nInBufferSize
;
528 req
->timeout
= nDefaultTimeOut
;
529 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
531 wine_server_call_err( req
);
539 /***********************************************************************
540 * PeekNamedPipe (KERNEL32.@)
542 BOOL WINAPI
PeekNamedPipe( HANDLE hPipe
, LPVOID lpvBuffer
, DWORD cbBuffer
,
543 LPDWORD lpcbRead
, LPDWORD lpcbAvail
, LPDWORD lpcbMessage
)
548 fd
= FILE_GetUnixHandle(hPipe
, GENERIC_READ
);
549 if (fd
== -1) return FALSE
;
551 if (ioctl(fd
,FIONREAD
, &avail
) != 0)
553 TRACE("FIONREAD failed reason: %s\n",strerror(errno
));
557 if (!avail
) /* check for closed pipe */
559 struct pollfd pollfd
;
561 pollfd
.events
= POLLIN
;
563 switch (poll( &pollfd
, 1, 0 ))
567 case 1: /* got something */
568 if (!(pollfd
.revents
& (POLLHUP
| POLLERR
))) break;
569 TRACE("POLLHUP | POLLERR\n");
573 SetLastError(ERROR_BROKEN_PIPE
);
578 TRACE(" 0x%08x bytes available\n", avail
);
579 if (!lpvBuffer
&& lpcbAvail
)
584 #endif /* defined(FIONREAD) */
586 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
587 FIXME("function not implemented\n");
591 /***********************************************************************
592 * SYNC_CompletePipeOverlapped (Internal)
594 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped
, DWORD result
)
596 TRACE("for %p result %08lx\n",overlapped
,result
);
599 overlapped
->Internal
= result
;
600 SetEvent(overlapped
->hEvent
);
604 /***********************************************************************
605 * WaitNamedPipeA (KERNEL32.@)
607 BOOL WINAPI
WaitNamedPipeA (LPCSTR name
, DWORD nTimeOut
)
609 WCHAR buffer
[MAX_PATH
];
611 if (!name
) return WaitNamedPipeW( NULL
, nTimeOut
);
613 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
615 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
618 return WaitNamedPipeW( buffer
, nTimeOut
);
622 /***********************************************************************
623 * WaitNamedPipeW (KERNEL32.@)
625 BOOL WINAPI
WaitNamedPipeW (LPCWSTR name
, DWORD nTimeOut
)
627 DWORD len
= name
? strlenW(name
) : 0;
633 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
637 TRACE("%s 0x%08lx\n",debugstr_w(name
),nTimeOut
);
639 memset(&ov
,0,sizeof ov
);
640 ov
.hEvent
= CreateEventA( NULL
, 0, 0, NULL
);
644 SERVER_START_REQ( wait_named_pipe
)
646 req
->timeout
= nTimeOut
;
647 req
->overlapped
= &ov
;
648 req
->func
= SYNC_CompletePipeOverlapped
;
649 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
650 ret
= !wine_server_call_err( req
);
656 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
658 SetLastError(ov
.Internal
);
659 ret
= (ov
.Internal
==STATUS_SUCCESS
);
662 CloseHandle(ov
.hEvent
);
667 /***********************************************************************
668 * SYNC_ConnectNamedPipe (Internal)
670 static BOOL
SYNC_ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
677 overlapped
->Internal
= STATUS_PENDING
;
679 SERVER_START_REQ( connect_named_pipe
)
682 req
->overlapped
= overlapped
;
683 req
->func
= SYNC_CompletePipeOverlapped
;
684 ret
= !wine_server_call_err( req
);
691 /***********************************************************************
692 * ConnectNamedPipe (KERNEL32.@)
694 BOOL WINAPI
ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
699 TRACE("(%p,%p)\n",hPipe
, overlapped
);
702 return SYNC_ConnectNamedPipe(hPipe
,overlapped
);
704 memset(&ov
,0,sizeof ov
);
705 ov
.hEvent
= CreateEventA(NULL
,0,0,NULL
);
709 ret
=SYNC_ConnectNamedPipe(hPipe
, &ov
);
712 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
714 SetLastError(ov
.Internal
);
715 ret
= (ov
.Internal
==STATUS_SUCCESS
);
719 CloseHandle(ov
.hEvent
);
724 /***********************************************************************
725 * DisconnectNamedPipe (KERNEL32.@)
727 BOOL WINAPI
DisconnectNamedPipe(HANDLE hPipe
)
731 TRACE("(%p)\n",hPipe
);
733 SERVER_START_REQ( disconnect_named_pipe
)
736 ret
= !wine_server_call_err( req
);
743 /***********************************************************************
744 * TransactNamedPipe (KERNEL32.@)
746 BOOL WINAPI
TransactNamedPipe(
747 HANDLE hPipe
, LPVOID lpInput
, DWORD dwInputSize
, LPVOID lpOutput
,
748 DWORD dwOutputSize
, LPDWORD lpBytesRead
, LPOVERLAPPED lpOverlapped
)
750 FIXME("%p %p %ld %p %ld %p %p\n",
751 hPipe
, lpInput
, dwInputSize
, lpOutput
,
752 dwOutputSize
, lpBytesRead
, lpOverlapped
);
758 /***********************************************************************
759 * GetNamedPipeInfo (KERNEL32.@)
761 BOOL WINAPI
GetNamedPipeInfo(
762 HANDLE hNamedPipe
, LPDWORD lpFlags
, LPDWORD lpOutputBufferSize
,
763 LPDWORD lpInputBufferSize
, LPDWORD lpMaxInstances
)
767 TRACE("%p %p %p %p %p\n", hNamedPipe
, lpFlags
,
768 lpOutputBufferSize
, lpInputBufferSize
, lpMaxInstances
);
770 SERVER_START_REQ( get_named_pipe_info
)
772 req
->handle
= hNamedPipe
;
773 ret
= !wine_server_call_err( req
);
774 if(lpFlags
) *lpFlags
= reply
->flags
;
775 if(lpOutputBufferSize
) *lpOutputBufferSize
= reply
->outsize
;
776 if(lpInputBufferSize
) *lpInputBufferSize
= reply
->outsize
;
777 if(lpMaxInstances
) *lpMaxInstances
= reply
->maxinstances
;
784 /***********************************************************************
785 * GetNamedPipeHandleStateA (KERNEL32.@)
787 BOOL WINAPI
GetNamedPipeHandleStateA(
788 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
789 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
790 LPSTR lpUsername
, DWORD nUsernameMaxSize
)
792 FIXME("%p %p %p %p %p %p %ld\n",
793 hNamedPipe
, lpState
, lpCurInstances
,
794 lpMaxCollectionCount
, lpCollectDataTimeout
,
795 lpUsername
, nUsernameMaxSize
);
800 /***********************************************************************
801 * GetNamedPipeHandleStateW (KERNEL32.@)
803 BOOL WINAPI
GetNamedPipeHandleStateW(
804 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
805 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
806 LPWSTR lpUsername
, DWORD nUsernameMaxSize
)
808 FIXME("%p %p %p %p %p %p %ld\n",
809 hNamedPipe
, lpState
, lpCurInstances
,
810 lpMaxCollectionCount
, lpCollectDataTimeout
,
811 lpUsername
, nUsernameMaxSize
);
816 /***********************************************************************
817 * SetNamedPipeHandleState (KERNEL32.@)
819 BOOL WINAPI
SetNamedPipeHandleState(
820 HANDLE hNamedPipe
, LPDWORD lpMode
, LPDWORD lpMaxCollectionCount
,
821 LPDWORD lpCollectDataTimeout
)
823 FIXME("%p %p %p %p\n",
824 hNamedPipe
, lpMode
, lpMaxCollectionCount
, lpCollectDataTimeout
);
828 /***********************************************************************
829 * CallNamedPipeA (KERNEL32.@)
831 BOOL WINAPI
CallNamedPipeA(
832 LPCSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
833 LPVOID lpOutput
, DWORD lpOutputSize
,
834 LPDWORD lpBytesRead
, DWORD nTimeout
)
836 FIXME("%s %p %ld %p %ld %p %ld\n",
837 debugstr_a(lpNamedPipeName
), lpInput
, lpInputSize
,
838 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
842 /***********************************************************************
843 * CallNamedPipeW (KERNEL32.@)
845 BOOL WINAPI
CallNamedPipeW(
846 LPCWSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
847 LPVOID lpOutput
, DWORD lpOutputSize
,
848 LPDWORD lpBytesRead
, DWORD nTimeout
)
850 FIXME("%s %p %ld %p %ld %p %ld\n",
851 debugstr_w(lpNamedPipeName
), lpInput
, lpInputSize
,
852 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);