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
28 #ifdef HAVE_SYS_IOCTL_H
29 #include <sys/ioctl.h>
36 #include "wine/server.h"
37 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(win32
);
49 /***********************************************************************
50 * CreateEventA (KERNEL32.@)
52 HANDLE WINAPI
CreateEventA( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
53 BOOL initial_state
, LPCSTR name
)
55 WCHAR buffer
[MAX_PATH
];
57 if (!name
) return CreateEventW( sa
, manual_reset
, initial_state
, NULL
);
59 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
61 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
64 return CreateEventW( sa
, manual_reset
, initial_state
, buffer
);
68 /***********************************************************************
69 * CreateEventW (KERNEL32.@)
71 HANDLE WINAPI
CreateEventW( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
72 BOOL initial_state
, LPCWSTR name
)
75 DWORD len
= name
? strlenW(name
) : 0;
78 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
81 /* one buggy program needs this
82 * ("Van Dale Groot woordenboek der Nederlandse taal")
84 if (sa
&& IsBadReadPtr(sa
,sizeof(SECURITY_ATTRIBUTES
)))
86 ERR("Bad security attributes pointer %p\n",sa
);
87 SetLastError( ERROR_INVALID_PARAMETER
);
90 SERVER_START_REQ( create_event
)
92 req
->manual_reset
= manual_reset
;
93 req
->initial_state
= initial_state
;
94 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
95 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
97 wine_server_call_err( req
);
105 /***********************************************************************
106 * CreateW32Event (KERNEL.457)
108 HANDLE WINAPI
WIN16_CreateEvent( BOOL manual_reset
, BOOL initial_state
)
110 return CreateEventA( NULL
, manual_reset
, initial_state
, NULL
);
114 /***********************************************************************
115 * OpenEventA (KERNEL32.@)
117 HANDLE WINAPI
OpenEventA( DWORD access
, BOOL inherit
, LPCSTR name
)
119 WCHAR buffer
[MAX_PATH
];
121 if (!name
) return OpenEventW( access
, inherit
, NULL
);
123 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
125 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
128 return OpenEventW( access
, inherit
, buffer
);
132 /***********************************************************************
133 * OpenEventW (KERNEL32.@)
135 HANDLE WINAPI
OpenEventW( DWORD access
, BOOL inherit
, LPCWSTR name
)
138 DWORD len
= name
? strlenW(name
) : 0;
141 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
144 SERVER_START_REQ( open_event
)
146 req
->access
= access
;
147 req
->inherit
= inherit
;
148 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
149 wine_server_call_err( req
);
157 /***********************************************************************
160 * Execute an event operation (set,reset,pulse).
162 static BOOL
EVENT_Operation( HANDLE handle
, enum event_op op
)
165 SERVER_START_REQ( event_op
)
167 req
->handle
= handle
;
169 ret
= !wine_server_call_err( req
);
176 /***********************************************************************
177 * PulseEvent (KERNEL32.@)
179 BOOL WINAPI
PulseEvent( HANDLE handle
)
181 return EVENT_Operation( handle
, PULSE_EVENT
);
185 /***********************************************************************
186 * SetW32Event (KERNEL.458)
187 * SetEvent (KERNEL32.@)
189 BOOL WINAPI
SetEvent( HANDLE handle
)
191 return EVENT_Operation( handle
, SET_EVENT
);
195 /***********************************************************************
196 * ResetW32Event (KERNEL.459)
197 * ResetEvent (KERNEL32.@)
199 BOOL WINAPI
ResetEvent( HANDLE handle
)
201 return EVENT_Operation( handle
, RESET_EVENT
);
205 /***********************************************************************
206 * NOTE: The Win95 VWin32_Event routines given below are really low-level
207 * routines implemented directly by VWin32. The user-mode libraries
208 * implement Win32 synchronisation routines on top of these low-level
209 * primitives. We do it the other way around here :-)
212 /***********************************************************************
213 * VWin32_EventCreate (KERNEL.442)
215 HANDLE WINAPI
VWin32_EventCreate(VOID
)
217 HANDLE hEvent
= CreateEventA( NULL
, FALSE
, 0, NULL
);
218 return ConvertToGlobalHandle( hEvent
);
221 /***********************************************************************
222 * VWin32_EventDestroy (KERNEL.443)
224 VOID WINAPI
VWin32_EventDestroy(HANDLE event
)
226 CloseHandle( event
);
229 /***********************************************************************
230 * VWin32_EventWait (KERNEL.450)
232 VOID WINAPI
VWin32_EventWait(HANDLE event
)
236 ReleaseThunkLock( &mutex_count
);
237 WaitForSingleObject( event
, INFINITE
);
238 RestoreThunkLock( mutex_count
);
241 /***********************************************************************
242 * VWin32_EventSet (KERNEL.451)
243 * KERNEL_479 (KERNEL.479)
245 VOID WINAPI
VWin32_EventSet(HANDLE event
)
252 /***********************************************************************
253 * CreateMutexA (KERNEL32.@)
255 HANDLE WINAPI
CreateMutexA( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCSTR name
)
257 WCHAR buffer
[MAX_PATH
];
259 if (!name
) return CreateMutexW( sa
, owner
, NULL
);
261 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
263 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
266 return CreateMutexW( sa
, owner
, buffer
);
270 /***********************************************************************
271 * CreateMutexW (KERNEL32.@)
273 HANDLE WINAPI
CreateMutexW( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCWSTR name
)
276 DWORD len
= name
? strlenW(name
) : 0;
279 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
282 SERVER_START_REQ( create_mutex
)
285 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
286 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
288 wine_server_call_err( req
);
296 /***********************************************************************
297 * OpenMutexA (KERNEL32.@)
299 HANDLE WINAPI
OpenMutexA( DWORD access
, BOOL inherit
, LPCSTR name
)
301 WCHAR buffer
[MAX_PATH
];
303 if (!name
) return OpenMutexW( access
, inherit
, NULL
);
305 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
307 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
310 return OpenMutexW( access
, inherit
, buffer
);
314 /***********************************************************************
315 * OpenMutexW (KERNEL32.@)
317 HANDLE WINAPI
OpenMutexW( DWORD access
, BOOL inherit
, LPCWSTR name
)
320 DWORD len
= name
? strlenW(name
) : 0;
323 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
326 SERVER_START_REQ( open_mutex
)
328 req
->access
= access
;
329 req
->inherit
= inherit
;
330 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
331 wine_server_call_err( req
);
339 /***********************************************************************
340 * ReleaseMutex (KERNEL32.@)
342 BOOL WINAPI
ReleaseMutex( HANDLE handle
)
345 SERVER_START_REQ( release_mutex
)
347 req
->handle
= handle
;
348 ret
= !wine_server_call_err( req
);
360 /***********************************************************************
361 * CreateSemaphoreA (KERNEL32.@)
363 HANDLE WINAPI
CreateSemaphoreA( SECURITY_ATTRIBUTES
*sa
, LONG initial
, LONG max
, LPCSTR name
)
365 WCHAR buffer
[MAX_PATH
];
367 if (!name
) return CreateSemaphoreW( sa
, initial
, max
, NULL
);
369 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
371 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
374 return CreateSemaphoreW( sa
, initial
, max
, buffer
);
378 /***********************************************************************
379 * CreateSemaphoreW (KERNEL32.@)
381 HANDLE WINAPI
CreateSemaphoreW( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
382 LONG max
, LPCWSTR name
)
385 DWORD len
= name
? strlenW(name
) : 0;
387 /* Check parameters */
389 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
391 SetLastError( ERROR_INVALID_PARAMETER
);
396 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
400 SERVER_START_REQ( create_semaphore
)
402 req
->initial
= (unsigned int)initial
;
403 req
->max
= (unsigned int)max
;
404 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
405 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
407 wine_server_call_err( req
);
415 /***********************************************************************
416 * OpenSemaphoreA (KERNEL32.@)
418 HANDLE WINAPI
OpenSemaphoreA( DWORD access
, BOOL inherit
, LPCSTR name
)
420 WCHAR buffer
[MAX_PATH
];
422 if (!name
) return OpenSemaphoreW( access
, inherit
, NULL
);
424 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
426 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
429 return OpenSemaphoreW( access
, inherit
, buffer
);
433 /***********************************************************************
434 * OpenSemaphoreW (KERNEL32.@)
436 HANDLE WINAPI
OpenSemaphoreW( DWORD access
, BOOL inherit
, LPCWSTR name
)
439 DWORD len
= name
? strlenW(name
) : 0;
442 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
445 SERVER_START_REQ( open_semaphore
)
447 req
->access
= access
;
448 req
->inherit
= inherit
;
449 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
450 wine_server_call_err( req
);
458 /***********************************************************************
459 * ReleaseSemaphore (KERNEL32.@)
461 BOOL WINAPI
ReleaseSemaphore( HANDLE handle
, LONG count
, LONG
*previous
)
463 NTSTATUS status
= NtReleaseSemaphore( handle
, count
, previous
);
464 if (status
) SetLastError( RtlNtStatusToDosError(status
) );
474 /***********************************************************************
475 * CreateNamedPipeA (KERNEL32.@)
477 HANDLE WINAPI
CreateNamedPipeA( LPCSTR name
, DWORD dwOpenMode
,
478 DWORD dwPipeMode
, DWORD nMaxInstances
,
479 DWORD nOutBufferSize
, DWORD nInBufferSize
,
480 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
482 WCHAR buffer
[MAX_PATH
];
484 if (!name
) return CreateNamedPipeW( NULL
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
485 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
487 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
489 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
492 return CreateNamedPipeW( buffer
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
493 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
497 /***********************************************************************
498 * CreateNamedPipeW (KERNEL32.@)
500 HANDLE WINAPI
CreateNamedPipeW( LPCWSTR name
, DWORD dwOpenMode
,
501 DWORD dwPipeMode
, DWORD nMaxInstances
,
502 DWORD nOutBufferSize
, DWORD nInBufferSize
,
503 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
506 DWORD len
= name
? strlenW(name
) : 0;
508 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
509 debugstr_w(name
), dwOpenMode
, dwPipeMode
, nMaxInstances
,
510 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
514 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
517 SERVER_START_REQ( create_named_pipe
)
519 req
->openmode
= dwOpenMode
;
520 req
->pipemode
= dwPipeMode
;
521 req
->maxinstances
= nMaxInstances
;
522 req
->outsize
= nOutBufferSize
;
523 req
->insize
= nInBufferSize
;
524 req
->timeout
= nDefaultTimeOut
;
525 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
527 wine_server_call_err( req
);
535 /***********************************************************************
536 * PeekNamedPipe (KERNEL32.@)
538 BOOL WINAPI
PeekNamedPipe( HANDLE hPipe
, LPVOID lpvBuffer
, DWORD cbBuffer
,
539 LPDWORD lpcbRead
, LPDWORD lpcbAvail
, LPDWORD lpcbMessage
)
544 fd
= FILE_GetUnixHandle(hPipe
, GENERIC_READ
);
547 /* On linux fstat on pipes doesn't work */
548 if (ioctl(fd
,FIONREAD
, &avail
) != 0)
550 TRACE("FIONREAD failed reason: %s\n",strerror(errno
));
555 TRACE(" 0x%08x bytes available\n", avail
);
556 if (!lpvBuffer
&& lpcbAvail
)
561 #endif /* defined(FIONREAD) */
563 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
564 FIXME("function not implemented\n");
568 /***********************************************************************
569 * SYNC_CompletePipeOverlapped (Internal)
571 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped
, DWORD result
)
573 TRACE("for %p result %08lx\n",overlapped
,result
);
576 overlapped
->Internal
= result
;
577 SetEvent(overlapped
->hEvent
);
581 /***********************************************************************
582 * WaitNamedPipeA (KERNEL32.@)
584 BOOL WINAPI
WaitNamedPipeA (LPCSTR name
, DWORD nTimeOut
)
586 WCHAR buffer
[MAX_PATH
];
588 if (!name
) return WaitNamedPipeW( NULL
, nTimeOut
);
590 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
592 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
595 return WaitNamedPipeW( buffer
, nTimeOut
);
599 /***********************************************************************
600 * WaitNamedPipeW (KERNEL32.@)
602 BOOL WINAPI
WaitNamedPipeW (LPCWSTR name
, DWORD nTimeOut
)
604 DWORD len
= name
? strlenW(name
) : 0;
610 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
614 TRACE("%s 0x%08lx\n",debugstr_w(name
),nTimeOut
);
616 memset(&ov
,0,sizeof ov
);
617 ov
.hEvent
= CreateEventA( NULL
, 0, 0, NULL
);
621 SERVER_START_REQ( wait_named_pipe
)
623 req
->timeout
= nTimeOut
;
624 req
->overlapped
= &ov
;
625 req
->func
= SYNC_CompletePipeOverlapped
;
626 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
627 ret
= !wine_server_call_err( req
);
633 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
635 SetLastError(ov
.Internal
);
636 ret
= (ov
.Internal
==STATUS_SUCCESS
);
639 CloseHandle(ov
.hEvent
);
644 /***********************************************************************
645 * SYNC_ConnectNamedPipe (Internal)
647 static BOOL
SYNC_ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
654 overlapped
->Internal
= STATUS_PENDING
;
656 SERVER_START_REQ( connect_named_pipe
)
659 req
->overlapped
= overlapped
;
660 req
->func
= SYNC_CompletePipeOverlapped
;
661 ret
= !wine_server_call_err( req
);
668 /***********************************************************************
669 * ConnectNamedPipe (KERNEL32.@)
671 BOOL WINAPI
ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
676 TRACE("(%d,%p)\n",hPipe
, overlapped
);
679 return SYNC_ConnectNamedPipe(hPipe
,overlapped
);
681 memset(&ov
,0,sizeof ov
);
682 ov
.hEvent
= CreateEventA(NULL
,0,0,NULL
);
686 ret
=SYNC_ConnectNamedPipe(hPipe
, &ov
);
689 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
691 SetLastError(ov
.Internal
);
692 ret
= (ov
.Internal
==STATUS_SUCCESS
);
696 CloseHandle(ov
.hEvent
);
701 /***********************************************************************
702 * DisconnectNamedPipe (KERNEL32.@)
704 BOOL WINAPI
DisconnectNamedPipe(HANDLE hPipe
)
708 TRACE("(%d)\n",hPipe
);
710 SERVER_START_REQ( disconnect_named_pipe
)
713 ret
= !wine_server_call_err( req
);
720 /***********************************************************************
721 * TransactNamedPipe (KERNEL32.@)
723 BOOL WINAPI
TransactNamedPipe(
724 HANDLE hPipe
, LPVOID lpInput
, DWORD dwInputSize
, LPVOID lpOutput
,
725 DWORD dwOutputSize
, LPDWORD lpBytesRead
, LPOVERLAPPED lpOverlapped
)
727 FIXME("%d %p %ld %p %ld %p %p\n",
728 hPipe
, lpInput
, dwInputSize
, lpOutput
,
729 dwOutputSize
, lpBytesRead
, lpOverlapped
);
735 /***********************************************************************
736 * GetNamedPipeInfo (KERNEL32.@)
738 BOOL WINAPI
GetNamedPipeInfo(
739 HANDLE hNamedPipe
, LPDWORD lpFlags
, LPDWORD lpOutputBufferSize
,
740 LPDWORD lpInputBufferSize
, LPDWORD lpMaxInstances
)
744 TRACE("%d %p %p %p %p\n", hNamedPipe
, lpFlags
,
745 lpOutputBufferSize
, lpInputBufferSize
, lpMaxInstances
);
747 SERVER_START_REQ( get_named_pipe_info
)
749 req
->handle
= hNamedPipe
;
750 ret
= !wine_server_call_err( req
);
751 if(lpFlags
) *lpFlags
= reply
->flags
;
752 if(lpOutputBufferSize
) *lpOutputBufferSize
= reply
->outsize
;
753 if(lpInputBufferSize
) *lpInputBufferSize
= reply
->outsize
;
754 if(lpMaxInstances
) *lpMaxInstances
= reply
->maxinstances
;
761 /***********************************************************************
762 * GetNamedPipeHandleStateA (KERNEL32.@)
764 BOOL WINAPI
GetNamedPipeHandleStateA(
765 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
766 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
767 LPSTR lpUsername
, DWORD nUsernameMaxSize
)
769 FIXME("%d %p %p %p %p %p %ld\n",
770 hNamedPipe
, lpState
, lpCurInstances
,
771 lpMaxCollectionCount
, lpCollectDataTimeout
,
772 lpUsername
, nUsernameMaxSize
);
777 /***********************************************************************
778 * GetNamedPipeHandleStateW (KERNEL32.@)
780 BOOL WINAPI
GetNamedPipeHandleStateW(
781 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
782 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
783 LPWSTR lpUsername
, DWORD nUsernameMaxSize
)
785 FIXME("%d %p %p %p %p %p %ld\n",
786 hNamedPipe
, lpState
, lpCurInstances
,
787 lpMaxCollectionCount
, lpCollectDataTimeout
,
788 lpUsername
, nUsernameMaxSize
);
793 /***********************************************************************
794 * SetNamedPipeHandleState (KERNEL32.@)
796 BOOL WINAPI
SetNamedPipeHandleState(
797 HANDLE hNamedPipe
, LPDWORD lpMode
, LPDWORD lpMaxCollectionCount
,
798 LPDWORD lpCollectDataTimeout
)
800 FIXME("%d %p %p %p\n",
801 hNamedPipe
, lpMode
, lpMaxCollectionCount
, lpCollectDataTimeout
);
805 /***********************************************************************
806 * CallNamedPipeA (KERNEL32.@)
808 BOOL WINAPI
CallNamedPipeA(
809 LPCSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
810 LPVOID lpOutput
, DWORD lpOutputSize
,
811 LPDWORD lpBytesRead
, DWORD nTimeout
)
813 FIXME("%s %p %ld %p %ld %p %ld\n",
814 debugstr_a(lpNamedPipeName
), lpInput
, lpInputSize
,
815 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
819 /***********************************************************************
820 * CallNamedPipeW (KERNEL32.@)
822 BOOL WINAPI
CallNamedPipeW(
823 LPCWSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
824 LPVOID lpOutput
, DWORD lpOutputSize
,
825 LPDWORD lpBytesRead
, DWORD nTimeout
)
827 FIXME("%s %p %ld %p %ld %p %ld\n",
828 debugstr_w(lpNamedPipeName
), lpInput
, lpInputSize
,
829 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);