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
29 #include "wine/server.h"
30 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(win32
);
41 /***********************************************************************
42 * CreateEventA (KERNEL32.@)
44 HANDLE WINAPI
CreateEventA( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
45 BOOL initial_state
, LPCSTR name
)
47 WCHAR buffer
[MAX_PATH
];
49 if (!name
) return CreateEventW( sa
, manual_reset
, initial_state
, NULL
);
51 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
53 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
56 return CreateEventW( sa
, manual_reset
, initial_state
, buffer
);
60 /***********************************************************************
61 * CreateEventW (KERNEL32.@)
63 HANDLE WINAPI
CreateEventW( SECURITY_ATTRIBUTES
*sa
, BOOL manual_reset
,
64 BOOL initial_state
, LPCWSTR name
)
67 DWORD len
= name
? strlenW(name
) : 0;
70 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
73 /* one buggy program needs this
74 * ("Van Dale Groot woordenboek der Nederlandse taal")
76 if (sa
&& IsBadReadPtr(sa
,sizeof(SECURITY_ATTRIBUTES
)))
78 ERR("Bad security attributes pointer %p\n",sa
);
79 SetLastError( ERROR_INVALID_PARAMETER
);
82 SERVER_START_REQ( create_event
)
84 req
->manual_reset
= manual_reset
;
85 req
->initial_state
= initial_state
;
86 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
87 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
89 wine_server_call_err( req
);
97 /***********************************************************************
98 * CreateW32Event (KERNEL.457)
100 HANDLE WINAPI
WIN16_CreateEvent( BOOL manual_reset
, BOOL initial_state
)
102 return CreateEventA( NULL
, manual_reset
, initial_state
, NULL
);
106 /***********************************************************************
107 * OpenEventA (KERNEL32.@)
109 HANDLE WINAPI
OpenEventA( DWORD access
, BOOL inherit
, LPCSTR name
)
111 WCHAR buffer
[MAX_PATH
];
113 if (!name
) return OpenEventW( access
, inherit
, NULL
);
115 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
117 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
120 return OpenEventW( access
, inherit
, buffer
);
124 /***********************************************************************
125 * OpenEventW (KERNEL32.@)
127 HANDLE WINAPI
OpenEventW( DWORD access
, BOOL inherit
, LPCWSTR name
)
130 DWORD len
= name
? strlenW(name
) : 0;
133 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
136 SERVER_START_REQ( open_event
)
138 req
->access
= access
;
139 req
->inherit
= inherit
;
140 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
141 wine_server_call_err( req
);
149 /***********************************************************************
152 * Execute an event operation (set,reset,pulse).
154 static BOOL
EVENT_Operation( HANDLE handle
, enum event_op op
)
157 SERVER_START_REQ( event_op
)
159 req
->handle
= handle
;
161 ret
= !wine_server_call_err( req
);
168 /***********************************************************************
169 * PulseEvent (KERNEL32.@)
171 BOOL WINAPI
PulseEvent( HANDLE handle
)
173 return EVENT_Operation( handle
, PULSE_EVENT
);
177 /***********************************************************************
178 * SetW32Event (KERNEL.458)
179 * SetEvent (KERNEL32.@)
181 BOOL WINAPI
SetEvent( HANDLE handle
)
183 return EVENT_Operation( handle
, SET_EVENT
);
187 /***********************************************************************
188 * ResetW32Event (KERNEL.459)
189 * ResetEvent (KERNEL32.@)
191 BOOL WINAPI
ResetEvent( HANDLE handle
)
193 return EVENT_Operation( handle
, RESET_EVENT
);
197 /***********************************************************************
198 * NOTE: The Win95 VWin32_Event routines given below are really low-level
199 * routines implemented directly by VWin32. The user-mode libraries
200 * implement Win32 synchronisation routines on top of these low-level
201 * primitives. We do it the other way around here :-)
204 /***********************************************************************
205 * VWin32_EventCreate (KERNEL.442)
207 HANDLE WINAPI
VWin32_EventCreate(VOID
)
209 HANDLE hEvent
= CreateEventA( NULL
, FALSE
, 0, NULL
);
210 return ConvertToGlobalHandle( hEvent
);
213 /***********************************************************************
214 * VWin32_EventDestroy (KERNEL.443)
216 VOID WINAPI
VWin32_EventDestroy(HANDLE event
)
218 CloseHandle( event
);
221 /***********************************************************************
222 * VWin32_EventWait (KERNEL.450)
224 VOID WINAPI
VWin32_EventWait(HANDLE event
)
228 ReleaseThunkLock( &mutex_count
);
229 WaitForSingleObject( event
, INFINITE
);
230 RestoreThunkLock( mutex_count
);
233 /***********************************************************************
234 * VWin32_EventSet (KERNEL.451)
235 * KERNEL_479 (KERNEL.479)
237 VOID WINAPI
VWin32_EventSet(HANDLE event
)
244 /***********************************************************************
245 * CreateMutexA (KERNEL32.@)
247 HANDLE WINAPI
CreateMutexA( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCSTR name
)
249 WCHAR buffer
[MAX_PATH
];
251 if (!name
) return CreateMutexW( sa
, owner
, NULL
);
253 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
255 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
258 return CreateMutexW( sa
, owner
, buffer
);
262 /***********************************************************************
263 * CreateMutexW (KERNEL32.@)
265 HANDLE WINAPI
CreateMutexW( SECURITY_ATTRIBUTES
*sa
, BOOL owner
, LPCWSTR name
)
268 DWORD len
= name
? strlenW(name
) : 0;
271 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
274 SERVER_START_REQ( create_mutex
)
277 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
278 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
280 wine_server_call_err( req
);
288 /***********************************************************************
289 * OpenMutexA (KERNEL32.@)
291 HANDLE WINAPI
OpenMutexA( DWORD access
, BOOL inherit
, LPCSTR name
)
293 WCHAR buffer
[MAX_PATH
];
295 if (!name
) return OpenMutexW( access
, inherit
, NULL
);
297 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
299 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
302 return OpenMutexW( access
, inherit
, buffer
);
306 /***********************************************************************
307 * OpenMutexW (KERNEL32.@)
309 HANDLE WINAPI
OpenMutexW( DWORD access
, BOOL inherit
, LPCWSTR name
)
312 DWORD len
= name
? strlenW(name
) : 0;
315 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
318 SERVER_START_REQ( open_mutex
)
320 req
->access
= access
;
321 req
->inherit
= inherit
;
322 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
323 wine_server_call_err( req
);
331 /***********************************************************************
332 * ReleaseMutex (KERNEL32.@)
334 BOOL WINAPI
ReleaseMutex( HANDLE handle
)
337 SERVER_START_REQ( release_mutex
)
339 req
->handle
= handle
;
340 ret
= !wine_server_call_err( req
);
352 /***********************************************************************
353 * CreateSemaphoreA (KERNEL32.@)
355 HANDLE WINAPI
CreateSemaphoreA( SECURITY_ATTRIBUTES
*sa
, LONG initial
, LONG max
, LPCSTR name
)
357 WCHAR buffer
[MAX_PATH
];
359 if (!name
) return CreateSemaphoreW( sa
, initial
, max
, NULL
);
361 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
363 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
366 return CreateSemaphoreW( sa
, initial
, max
, buffer
);
370 /***********************************************************************
371 * CreateSemaphoreW (KERNEL32.@)
373 HANDLE WINAPI
CreateSemaphoreW( SECURITY_ATTRIBUTES
*sa
, LONG initial
,
374 LONG max
, LPCWSTR name
)
377 DWORD len
= name
? strlenW(name
) : 0;
379 /* Check parameters */
381 if ((max
<= 0) || (initial
< 0) || (initial
> max
))
383 SetLastError( ERROR_INVALID_PARAMETER
);
388 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
392 SERVER_START_REQ( create_semaphore
)
394 req
->initial
= (unsigned int)initial
;
395 req
->max
= (unsigned int)max
;
396 req
->inherit
= (sa
&& (sa
->nLength
>=sizeof(*sa
)) && sa
->bInheritHandle
);
397 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
399 wine_server_call_err( req
);
407 /***********************************************************************
408 * OpenSemaphoreA (KERNEL32.@)
410 HANDLE WINAPI
OpenSemaphoreA( DWORD access
, BOOL inherit
, LPCSTR name
)
412 WCHAR buffer
[MAX_PATH
];
414 if (!name
) return OpenSemaphoreW( access
, inherit
, NULL
);
416 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
418 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
421 return OpenSemaphoreW( access
, inherit
, buffer
);
425 /***********************************************************************
426 * OpenSemaphoreW (KERNEL32.@)
428 HANDLE WINAPI
OpenSemaphoreW( DWORD access
, BOOL inherit
, LPCWSTR name
)
431 DWORD len
= name
? strlenW(name
) : 0;
434 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
437 SERVER_START_REQ( open_semaphore
)
439 req
->access
= access
;
440 req
->inherit
= inherit
;
441 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
442 wine_server_call_err( req
);
450 /***********************************************************************
451 * ReleaseSemaphore (KERNEL32.@)
453 BOOL WINAPI
ReleaseSemaphore( HANDLE handle
, LONG count
, LONG
*previous
)
455 NTSTATUS status
= NtReleaseSemaphore( handle
, count
, previous
);
456 if (status
) SetLastError( RtlNtStatusToDosError(status
) );
466 /***********************************************************************
467 * CreateNamedPipeA (KERNEL32.@)
469 HANDLE WINAPI
CreateNamedPipeA( LPCSTR name
, DWORD dwOpenMode
,
470 DWORD dwPipeMode
, DWORD nMaxInstances
,
471 DWORD nOutBufferSize
, DWORD nInBufferSize
,
472 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
474 WCHAR buffer
[MAX_PATH
];
476 if (!name
) return CreateNamedPipeW( NULL
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
477 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
479 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
481 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
484 return CreateNamedPipeW( buffer
, dwOpenMode
, dwPipeMode
, nMaxInstances
,
485 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
489 /***********************************************************************
490 * CreateNamedPipeW (KERNEL32.@)
492 HANDLE WINAPI
CreateNamedPipeW( LPCWSTR name
, DWORD dwOpenMode
,
493 DWORD dwPipeMode
, DWORD nMaxInstances
,
494 DWORD nOutBufferSize
, DWORD nInBufferSize
,
495 DWORD nDefaultTimeOut
, LPSECURITY_ATTRIBUTES attr
)
498 DWORD len
= name
? strlenW(name
) : 0;
500 TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
501 debugstr_w(name
), dwOpenMode
, dwPipeMode
, nMaxInstances
,
502 nOutBufferSize
, nInBufferSize
, nDefaultTimeOut
, attr
);
506 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
509 SERVER_START_REQ( create_named_pipe
)
511 req
->openmode
= dwOpenMode
;
512 req
->pipemode
= dwPipeMode
;
513 req
->maxinstances
= nMaxInstances
;
514 req
->outsize
= nOutBufferSize
;
515 req
->insize
= nInBufferSize
;
516 req
->timeout
= nDefaultTimeOut
;
517 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
519 wine_server_call_err( req
);
527 /***********************************************************************
528 * PeekNamedPipe (KERNEL32.@)
530 BOOL WINAPI
PeekNamedPipe( HANDLE hPipe
, LPVOID lpvBuffer
, DWORD cbBuffer
,
531 LPDWORD lpcbRead
, LPDWORD lpcbAvail
, LPDWORD lpcbMessage
)
533 FIXME("(%08x, %p, %08lx, %p, %p, %p): stub\n",
534 hPipe
, lpvBuffer
, cbBuffer
, lpcbRead
, lpcbAvail
, lpcbMessage
);
535 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
539 /***********************************************************************
540 * SYNC_CompletePipeOverlapped (Internal)
542 static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped
, DWORD result
)
544 TRACE("for %p result %08lx\n",overlapped
,result
);
547 overlapped
->Internal
= result
;
548 SetEvent(overlapped
->hEvent
);
552 /***********************************************************************
553 * WaitNamedPipeA (KERNEL32.@)
555 BOOL WINAPI
WaitNamedPipeA (LPCSTR name
, DWORD nTimeOut
)
557 WCHAR buffer
[MAX_PATH
];
559 if (!name
) return WaitNamedPipeW( NULL
, nTimeOut
);
561 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
563 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
566 return WaitNamedPipeW( buffer
, nTimeOut
);
570 /***********************************************************************
571 * WaitNamedPipeW (KERNEL32.@)
573 BOOL WINAPI
WaitNamedPipeW (LPCWSTR name
, DWORD nTimeOut
)
575 DWORD len
= name
? strlenW(name
) : 0;
581 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
585 TRACE("%s 0x%08lx\n",debugstr_w(name
),nTimeOut
);
587 memset(&ov
,0,sizeof ov
);
588 ov
.hEvent
= CreateEventA( NULL
, 0, 0, NULL
);
592 SERVER_START_REQ( wait_named_pipe
)
594 req
->timeout
= nTimeOut
;
595 req
->overlapped
= &ov
;
596 req
->func
= SYNC_CompletePipeOverlapped
;
597 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
598 ret
= !wine_server_call_err( req
);
604 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
606 SetLastError(ov
.Internal
);
607 ret
= (ov
.Internal
==STATUS_SUCCESS
);
610 CloseHandle(ov
.hEvent
);
615 /***********************************************************************
616 * SYNC_ConnectNamedPipe (Internal)
618 static BOOL
SYNC_ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
625 overlapped
->Internal
= STATUS_PENDING
;
627 SERVER_START_REQ( connect_named_pipe
)
630 req
->overlapped
= overlapped
;
631 req
->func
= SYNC_CompletePipeOverlapped
;
632 ret
= !wine_server_call_err( req
);
639 /***********************************************************************
640 * ConnectNamedPipe (KERNEL32.@)
642 BOOL WINAPI
ConnectNamedPipe(HANDLE hPipe
, LPOVERLAPPED overlapped
)
647 TRACE("(%d,%p)\n",hPipe
, overlapped
);
650 return SYNC_ConnectNamedPipe(hPipe
,overlapped
);
652 memset(&ov
,0,sizeof ov
);
653 ov
.hEvent
= CreateEventA(NULL
,0,0,NULL
);
657 ret
=SYNC_ConnectNamedPipe(hPipe
, &ov
);
660 if (WAIT_OBJECT_0
==WaitForSingleObject(ov
.hEvent
,INFINITE
))
662 SetLastError(ov
.Internal
);
663 ret
= (ov
.Internal
==STATUS_SUCCESS
);
667 CloseHandle(ov
.hEvent
);
672 /***********************************************************************
673 * DisconnectNamedPipe (KERNEL32.@)
675 BOOL WINAPI
DisconnectNamedPipe(HANDLE hPipe
)
679 TRACE("(%d)\n",hPipe
);
681 SERVER_START_REQ( disconnect_named_pipe
)
684 ret
= !wine_server_call_err( req
);
691 /***********************************************************************
692 * TransactNamedPipe (KERNEL32.@)
694 BOOL WINAPI
TransactNamedPipe(
695 HANDLE hPipe
, LPVOID lpInput
, DWORD dwInputSize
, LPVOID lpOutput
,
696 DWORD dwOutputSize
, LPDWORD lpBytesRead
, LPOVERLAPPED lpOverlapped
)
698 FIXME("%d %p %ld %p %ld %p %p\n",
699 hPipe
, lpInput
, dwInputSize
, lpOutput
,
700 dwOutputSize
, lpBytesRead
, lpOverlapped
);
706 /***********************************************************************
707 * GetNamedPipeInfo (KERNEL32.@)
709 BOOL WINAPI
GetNamedPipeInfo(
710 HANDLE hNamedPipe
, LPDWORD lpFlags
, LPDWORD lpOutputBufferSize
,
711 LPDWORD lpInputBufferSize
, LPDWORD lpMaxInstances
)
715 TRACE("%d %p %p %p %p\n", hNamedPipe
, lpFlags
,
716 lpOutputBufferSize
, lpInputBufferSize
, lpMaxInstances
);
718 SERVER_START_REQ( get_named_pipe_info
)
720 req
->handle
= hNamedPipe
;
721 ret
= !wine_server_call_err( req
);
722 if(lpFlags
) *lpFlags
= reply
->flags
;
723 if(lpOutputBufferSize
) *lpOutputBufferSize
= reply
->outsize
;
724 if(lpInputBufferSize
) *lpInputBufferSize
= reply
->outsize
;
725 if(lpMaxInstances
) *lpMaxInstances
= reply
->maxinstances
;
732 /***********************************************************************
733 * GetNamedPipeHandleStateA (KERNEL32.@)
735 BOOL WINAPI
GetNamedPipeHandleStateA(
736 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
737 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
738 LPSTR lpUsername
, DWORD nUsernameMaxSize
)
740 FIXME("%d %p %p %p %p %p %ld\n",
741 hNamedPipe
, lpState
, lpCurInstances
,
742 lpMaxCollectionCount
, lpCollectDataTimeout
,
743 lpUsername
, nUsernameMaxSize
);
748 /***********************************************************************
749 * GetNamedPipeHandleStateW (KERNEL32.@)
751 BOOL WINAPI
GetNamedPipeHandleStateW(
752 HANDLE hNamedPipe
, LPDWORD lpState
, LPDWORD lpCurInstances
,
753 LPDWORD lpMaxCollectionCount
, LPDWORD lpCollectDataTimeout
,
754 LPWSTR lpUsername
, DWORD nUsernameMaxSize
)
756 FIXME("%d %p %p %p %p %p %ld\n",
757 hNamedPipe
, lpState
, lpCurInstances
,
758 lpMaxCollectionCount
, lpCollectDataTimeout
,
759 lpUsername
, nUsernameMaxSize
);
764 /***********************************************************************
765 * SetNamedPipeHandleState (KERNEL32.@)
767 BOOL WINAPI
SetNamedPipeHandleState(
768 HANDLE hNamedPipe
, LPDWORD lpMode
, LPDWORD lpMaxCollectionCount
,
769 LPDWORD lpCollectDataTimeout
)
771 FIXME("%d %p %p %p\n",
772 hNamedPipe
, lpMode
, lpMaxCollectionCount
, lpCollectDataTimeout
);
776 /***********************************************************************
777 * CallNamedPipeA (KERNEL32.@)
779 BOOL WINAPI
CallNamedPipeA(
780 LPCSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
781 LPVOID lpOutput
, DWORD lpOutputSize
,
782 LPDWORD lpBytesRead
, DWORD nTimeout
)
784 FIXME("%s %p %ld %p %ld %p %ld\n",
785 debugstr_a(lpNamedPipeName
), lpInput
, lpInputSize
,
786 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);
790 /***********************************************************************
791 * CallNamedPipeW (KERNEL32.@)
793 BOOL WINAPI
CallNamedPipeW(
794 LPCWSTR lpNamedPipeName
, LPVOID lpInput
, DWORD lpInputSize
,
795 LPVOID lpOutput
, DWORD lpOutputSize
,
796 LPDWORD lpBytesRead
, DWORD nTimeout
)
798 FIXME("%s %p %ld %p %ld %p %ld\n",
799 debugstr_w(lpNamedPipeName
), lpInput
, lpInputSize
,
800 lpOutput
, lpOutputSize
, lpBytesRead
, nTimeout
);