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
26 #ifdef HAVE_SYS_IOCTL_H
27 #include <sys/ioctl.h>
34 #include "wine/server.h"
35 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(win32
);
47 /***********************************************************************
48 * CreateEventA (KERNEL32.@)
50 HANDLE WINAPI
CreateEventA( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
51 BOOL initial_state
, LPCSTR name
)
53 WCHAR buffer
[MAX_PATH
];
55 if (!name
) return CreateEventW( sa
, manual_reset
, initial_state
, NULL
);
57 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
59 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
62 return CreateEventW( sa
, manual_reset
, initial_state
, buffer
);
66 /***********************************************************************
67 * CreateEventW (KERNEL32.@)
69 HANDLE WINAPI
CreateEventW( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
70 BOOL initial_state
, LPCWSTR name
)
73 DWORD len
= name
? strlenW(name
) : 0;
76 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
79 /* one buggy program needs this
80 * ("Van Dale Groot woordenboek der Nederlandse taal")
82 if (sa
&& IsBadReadPtr(sa
,sizeof(SECURITY_ATTRIBUTES
)))
84 ERR("Bad security attributes pointer %p\n",sa
);
85 SetLastError( ERROR_INVALID_PARAMETER
);
88 SERVER_START_REQ( create_event
)
90 req
->manual_reset
= manual_reset
;
91 req
->initial_state
= initial_state
;
92 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
93 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
95 wine_server_call_err( req
);
103 /***********************************************************************
104 * CreateW32Event (KERNEL.457)
106 HANDLE WINAPI
WIN16_CreateEvent( BOOL manual_reset
, BOOL initial_state
)
108 return CreateEventA( NULL
, manual_reset
, initial_state
, NULL
);
112 /***********************************************************************
113 * OpenEventA (KERNEL32.@)
115 HANDLE WINAPI
OpenEventA( DWORD access
, BOOL inherit
, LPCSTR name
)
117 WCHAR buffer
[MAX_PATH
];
119 if (!name
) return OpenEventW( access
, inherit
, NULL
);
121 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
123 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
126 return OpenEventW( access
, inherit
, buffer
);
130 /***********************************************************************
131 * OpenEventW (KERNEL32.@)
133 HANDLE WINAPI
OpenEventW( DWORD access
, BOOL inherit
, LPCWSTR name
)
136 DWORD len
= name
? strlenW(name
) : 0;
139 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
142 SERVER_START_REQ( open_event
)
144 req
->access
= access
;
145 req
->inherit
= inherit
;
146 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
147 wine_server_call_err( req
);
155 /***********************************************************************
158 * Execute an event operation (set,reset,pulse).
160 static BOOL
EVENT_Operation( HANDLE handle
, enum event_op op
)
163 SERVER_START_REQ( event_op
)
165 req
->handle
= handle
;
167 ret
= !wine_server_call_err( req
);
174 /***********************************************************************
175 * PulseEvent (KERNEL32.@)
177 BOOL WINAPI
PulseEvent( HANDLE handle
)
179 return EVENT_Operation( handle
, PULSE_EVENT
);
183 /***********************************************************************
184 * SetW32Event (KERNEL.458)
185 * SetEvent (KERNEL32.@)
187 BOOL WINAPI
SetEvent( HANDLE handle
)
189 return EVENT_Operation( handle
, SET_EVENT
);
193 /***********************************************************************
194 * ResetW32Event (KERNEL.459)
195 * ResetEvent (KERNEL32.@)
197 BOOL WINAPI
ResetEvent( HANDLE handle
)
199 return EVENT_Operation( handle
, RESET_EVENT
);
203 /***********************************************************************
204 * NOTE: The Win95 VWin32_Event routines given below are really low-level
205 * routines implemented directly by VWin32. The user-mode libraries
206 * implement Win32 synchronisation routines on top of these low-level
207 * primitives. We do it the other way around here :-)
210 /***********************************************************************
211 * VWin32_EventCreate (KERNEL.442)
213 HANDLE WINAPI
VWin32_EventCreate(VOID
)
215 HANDLE hEvent
= CreateEventA( NULL
, FALSE
, 0, NULL
);
216 return ConvertToGlobalHandle( hEvent
);
219 /***********************************************************************
220 * VWin32_EventDestroy (KERNEL.443)
222 VOID WINAPI
VWin32_EventDestroy(HANDLE event
)
224 CloseHandle( event
);
227 /***********************************************************************
228 * VWin32_EventWait (KERNEL.450)
230 VOID WINAPI
VWin32_EventWait(HANDLE event
)
234 ReleaseThunkLock( &mutex_count
);
235 WaitForSingleObject( event
, INFINITE
);
236 RestoreThunkLock( mutex_count
);
239 /***********************************************************************
240 * VWin32_EventSet (KERNEL.451)
241 * KERNEL_479 (KERNEL.479)
243 VOID WINAPI
VWin32_EventSet(HANDLE event
)
250 /***********************************************************************
251 * CreateMutexA (KERNEL32.@)
253 HANDLE WINAPI
CreateMutexA( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCSTR name
)
255 WCHAR buffer
[MAX_PATH
];
257 if (!name
) return CreateMutexW( sa
, owner
, NULL
);
259 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
261 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
264 return CreateMutexW( sa
, owner
, buffer
);
268 /***********************************************************************
269 * CreateMutexW (KERNEL32.@)
271 HANDLE WINAPI
CreateMutexW( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCWSTR name
)
274 DWORD len
= name
? strlenW(name
) : 0;
277 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
280 SERVER_START_REQ( create_mutex
)
283 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
284 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
286 wine_server_call_err( req
);
294 /***********************************************************************
295 * OpenMutexA (KERNEL32.@)
297 HANDLE WINAPI
OpenMutexA( DWORD access
, BOOL inherit
, LPCSTR name
)
299 WCHAR buffer
[MAX_PATH
];
301 if (!name
) return OpenMutexW( access
, inherit
, NULL
);
303 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
305 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
308 return OpenMutexW( access
, inherit
, buffer
);
312 /***********************************************************************
313 * OpenMutexW (KERNEL32.@)
315 HANDLE WINAPI
OpenMutexW( DWORD access
, BOOL inherit
, LPCWSTR name
)
318 DWORD len
= name
? strlenW(name
) : 0;
321 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
324 SERVER_START_REQ( open_mutex
)
326 req
->access
= access
;
327 req
->inherit
= inherit
;
328 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
329 wine_server_call_err( req
);
337 /***********************************************************************
338 * ReleaseMutex (KERNEL32.@)
340 BOOL WINAPI
ReleaseMutex( HANDLE handle
)
343 SERVER_START_REQ( release_mutex
)
345 req
->handle
= handle
;
346 ret
= !wine_server_call_err( req
);
358 /***********************************************************************
359 * CreateSemaphoreA (KERNEL32.@)
361 HANDLE WINAPI
CreateSemaphoreA( SECURITY_ATTRIBUTES
*sa
, LONG initial
, LONG max
, LPCSTR name
)
363 WCHAR buffer
[MAX_PATH
];
365 if (!name
) return CreateSemaphoreW( sa
, initial
, max
, NULL
);
367 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
369 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
372 return CreateSemaphoreW( sa
, initial
, max
, buffer
);
376 /***********************************************************************
377 * CreateSemaphoreW (KERNEL32.@)
379 HANDLE WINAPI
CreateSemaphoreW( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
380 LONG max
, LPCWSTR name
)
383 DWORD len
= name
? strlenW(name
) : 0;
385 /* Check parameters */
387 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
389 SetLastError( ERROR_INVALID_PARAMETER
);
394 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
398 SERVER_START_REQ( create_semaphore
)
400 req
->initial
= (unsigned int)initial
;
401 req
->max
= (unsigned int)max
;
402 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
403 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
405 wine_server_call_err( req
);
413 /***********************************************************************
414 * OpenSemaphoreA (KERNEL32.@)
416 HANDLE WINAPI
OpenSemaphoreA( DWORD access
, BOOL inherit
, LPCSTR name
)
418 WCHAR buffer
[MAX_PATH
];
420 if (!name
) return OpenSemaphoreW( access
, inherit
, NULL
);
422 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
424 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
427 return OpenSemaphoreW( access
, inherit
, buffer
);
431 /***********************************************************************
432 * OpenSemaphoreW (KERNEL32.@)
434 HANDLE WINAPI
OpenSemaphoreW( DWORD access
, BOOL inherit
, LPCWSTR name
)
437 DWORD len
= name
? strlenW(name
) : 0;
440 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
443 SERVER_START_REQ( open_semaphore
)
445 req
->access
= access
;
446 req
->inherit
= inherit
;
447 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
448 wine_server_call_err( req
);
456 /***********************************************************************
457 * ReleaseSemaphore (KERNEL32.@)
459 BOOL WINAPI
ReleaseSemaphore( HANDLE handle
, LONG count
, LONG
*previous
)
461 NTSTATUS status
= NtReleaseSemaphore( handle
, count
, previous
);
462 if (status
) SetLastError( RtlNtStatusToDosError(status
) );
472 /***********************************************************************
473 * CreateNamedPipeA (KERNEL32.@)
475 HANDLE WINAPI
CreateNamedPipeA( LPCSTR name
, DWORD dwOpenMode
,
476 DWORD dwPipeMode
, DWORD nMaxInstances
,
477 DWORD nOutBufferSize
, DWORD nInBufferSize
,
478 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
480 WCHAR buffer
[MAX_PATH
];
482 if (!name
) return CreateNamedPipeW( NULL
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
483 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
485 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
487 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
490 return CreateNamedPipeW( buffer
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
491 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
495 /***********************************************************************
496 * CreateNamedPipeW (KERNEL32.@)
498 HANDLE WINAPI
CreateNamedPipeW( LPCWSTR name
, DWORD dwOpenMode
,
499 DWORD dwPipeMode
, DWORD nMaxInstances
,
500 DWORD nOutBufferSize
, DWORD nInBufferSize
,
501 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
504 DWORD len
= name
? strlenW(name
) : 0;
506 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
507 debugstr_w(name
), dwOpenMode
, dwPipeMode
, nMaxInstances
,
508 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
512 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
515 SERVER_START_REQ( create_named_pipe
)
517 req
->openmode
= dwOpenMode
;
518 req
->pipemode
= dwPipeMode
;
519 req
->maxinstances
= nMaxInstances
;
520 req
->outsize
= nOutBufferSize
;
521 req
->insize
= nInBufferSize
;
522 req
->timeout
= nDefaultTimeOut
;
523 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
525 wine_server_call_err( req
);
533 /***********************************************************************
534 * PeekNamedPipe (KERNEL32.@)
536 BOOL WINAPI
PeekNamedPipe( HANDLE hPipe
, LPVOID lpvBuffer
, DWORD cbBuffer
,
537 LPDWORD lpcbRead
, LPDWORD lpcbAvail
, LPDWORD lpcbMessage
)
542 fd
= FILE_GetUnixHandle(hPipe
, GENERIC_READ
);
545 /* On linux fstat on pipes doesn't work */
546 if (ioctl(fd
,FIONREAD
, &avail
) != 0)
548 TRACE("FIONREAD failed reason: %s\n",strerror(errno
));
553 TRACE(" 0x%08x bytes available\n", avail
);
554 if (!lpvBuffer
&& lpcbAvail
)
559 #endif /* defined(FIONREAD) */
561 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
562 FIXME("function not implemented\n");
566 /***********************************************************************
567 * SYNC_CompletePipeOverlapped (Internal)
569 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped
, DWORD result
)
571 TRACE("for %p result %08lx\n",overlapped
,result
);
574 overlapped
->Internal
= result
;
575 SetEvent(overlapped
->hEvent
);
579 /***********************************************************************
580 * WaitNamedPipeA (KERNEL32.@)
582 BOOL WINAPI
WaitNamedPipeA (LPCSTR name
, DWORD nTimeOut
)
584 WCHAR buffer
[MAX_PATH
];
586 if (!name
) return WaitNamedPipeW( NULL
, nTimeOut
);
588 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
590 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
593 return WaitNamedPipeW( buffer
, nTimeOut
);
597 /***********************************************************************
598 * WaitNamedPipeW (KERNEL32.@)
600 BOOL WINAPI
WaitNamedPipeW (LPCWSTR name
, DWORD nTimeOut
)
602 DWORD len
= name
? strlenW(name
) : 0;
608 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
612 TRACE("%s 0x%08lx\n",debugstr_w(name
),nTimeOut
);
614 memset(&ov
,0,sizeof ov
);
615 ov
.hEvent
= CreateEventA( NULL
, 0, 0, NULL
);
619 SERVER_START_REQ( wait_named_pipe
)
621 req
->timeout
= nTimeOut
;
622 req
->overlapped
= &ov
;
623 req
->func
= SYNC_CompletePipeOverlapped
;
624 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
625 ret
= !wine_server_call_err( req
);
631 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
633 SetLastError(ov
.Internal
);
634 ret
= (ov
.Internal
==STATUS_SUCCESS
);
637 CloseHandle(ov
.hEvent
);
642 /***********************************************************************
643 * SYNC_ConnectNamedPipe (Internal)
645 static BOOL
SYNC_ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
652 overlapped
->Internal
= STATUS_PENDING
;
654 SERVER_START_REQ( connect_named_pipe
)
657 req
->overlapped
= overlapped
;
658 req
->func
= SYNC_CompletePipeOverlapped
;
659 ret
= !wine_server_call_err( req
);
666 /***********************************************************************
667 * ConnectNamedPipe (KERNEL32.@)
669 BOOL WINAPI
ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
674 TRACE("(%d,%p)\n",hPipe
, overlapped
);
677 return SYNC_ConnectNamedPipe(hPipe
,overlapped
);
679 memset(&ov
,0,sizeof ov
);
680 ov
.hEvent
= CreateEventA(NULL
,0,0,NULL
);
684 ret
=SYNC_ConnectNamedPipe(hPipe
, &ov
);
687 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
689 SetLastError(ov
.Internal
);
690 ret
= (ov
.Internal
==STATUS_SUCCESS
);
694 CloseHandle(ov
.hEvent
);
699 /***********************************************************************
700 * DisconnectNamedPipe (KERNEL32.@)
702 BOOL WINAPI
DisconnectNamedPipe(HANDLE hPipe
)
706 TRACE("(%d)\n",hPipe
);
708 SERVER_START_REQ( disconnect_named_pipe
)
711 ret
= !wine_server_call_err( req
);
718 /***********************************************************************
719 * TransactNamedPipe (KERNEL32.@)
721 BOOL WINAPI
TransactNamedPipe(
722 HANDLE hPipe
, LPVOID lpInput
, DWORD dwInputSize
, LPVOID lpOutput
,
723 DWORD dwOutputSize
, LPDWORD lpBytesRead
, LPOVERLAPPED lpOverlapped
)
725 FIXME("%d %p %ld %p %ld %p %p\n",
726 hPipe
, lpInput
, dwInputSize
, lpOutput
,
727 dwOutputSize
, lpBytesRead
, lpOverlapped
);
733 /***********************************************************************
734 * GetNamedPipeInfo (KERNEL32.@)
736 BOOL WINAPI
GetNamedPipeInfo(
737 HANDLE hNamedPipe
, LPDWORD lpFlags
, LPDWORD lpOutputBufferSize
,
738 LPDWORD lpInputBufferSize
, LPDWORD lpMaxInstances
)
742 TRACE("%d %p %p %p %p\n", hNamedPipe
, lpFlags
,
743 lpOutputBufferSize
, lpInputBufferSize
, lpMaxInstances
);
745 SERVER_START_REQ( get_named_pipe_info
)
747 req
->handle
= hNamedPipe
;
748 ret
= !wine_server_call_err( req
);
749 if(lpFlags
) *lpFlags
= reply
->flags
;
750 if(lpOutputBufferSize
) *lpOutputBufferSize
= reply
->outsize
;
751 if(lpInputBufferSize
) *lpInputBufferSize
= reply
->outsize
;
752 if(lpMaxInstances
) *lpMaxInstances
= reply
->maxinstances
;
759 /***********************************************************************
760 * GetNamedPipeHandleStateA (KERNEL32.@)
762 BOOL WINAPI
GetNamedPipeHandleStateA(
763 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
764 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
765 LPSTR lpUsername
, DWORD nUsernameMaxSize
)
767 FIXME("%d %p %p %p %p %p %ld\n",
768 hNamedPipe
, lpState
, lpCurInstances
,
769 lpMaxCollectionCount
, lpCollectDataTimeout
,
770 lpUsername
, nUsernameMaxSize
);
775 /***********************************************************************
776 * GetNamedPipeHandleStateW (KERNEL32.@)
778 BOOL WINAPI
GetNamedPipeHandleStateW(
779 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
780 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
781 LPWSTR lpUsername
, DWORD nUsernameMaxSize
)
783 FIXME("%d %p %p %p %p %p %ld\n",
784 hNamedPipe
, lpState
, lpCurInstances
,
785 lpMaxCollectionCount
, lpCollectDataTimeout
,
786 lpUsername
, nUsernameMaxSize
);
791 /***********************************************************************
792 * SetNamedPipeHandleState (KERNEL32.@)
794 BOOL WINAPI
SetNamedPipeHandleState(
795 HANDLE hNamedPipe
, LPDWORD lpMode
, LPDWORD lpMaxCollectionCount
,
796 LPDWORD lpCollectDataTimeout
)
798 FIXME("%d %p %p %p\n",
799 hNamedPipe
, lpMode
, lpMaxCollectionCount
, lpCollectDataTimeout
);
803 /***********************************************************************
804 * CallNamedPipeA (KERNEL32.@)
806 BOOL WINAPI
CallNamedPipeA(
807 LPCSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
808 LPVOID lpOutput
, DWORD lpOutputSize
,
809 LPDWORD lpBytesRead
, DWORD nTimeout
)
811 FIXME("%s %p %ld %p %ld %p %ld\n",
812 debugstr_a(lpNamedPipeName
), lpInput
, lpInputSize
,
813 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
817 /***********************************************************************
818 * CallNamedPipeW (KERNEL32.@)
820 BOOL WINAPI
CallNamedPipeW(
821 LPCWSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
822 LPVOID lpOutput
, DWORD lpOutputSize
,
823 LPDWORD lpBytesRead
, DWORD nTimeout
)
825 FIXME("%s %p %ld %p %ld %p %ld\n",
826 debugstr_w(lpNamedPipeName
), lpInput
, lpInputSize
,
827 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);