wine/dlls/kernel/sync.c

672 lines
18 KiB
C
Raw Normal View History

/*
* Kernel synchronization objects
*
* Copyright 1998 Alexandre Julliard
*/
#include <string.h>
#include "winerror.h"
#include "winnls.h"
#include "wine/unicode.h"
2001-07-19 00:39:09 +00:00
#include "wine/server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(win32);
/*
* Events
*/
/***********************************************************************
* CreateEventA (KERNEL32.@)
*/
HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
BOOL initial_state, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
{
req->manual_reset = manual_reset;
req->initial_state = initial_state;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* CreateEventW (KERNEL32.@)
*/
HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
BOOL initial_state, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
/* one buggy program needs this
* ("Van Dale Groot woordenboek der Nederlandse taal")
*/
if (sa && IsBadReadPtr(sa,sizeof(SECURITY_ATTRIBUTES)))
{
ERR("Bad security attributes pointer %p\n",sa);
SetLastError( ERROR_INVALID_PARAMETER);
return 0;
}
SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
{
req->manual_reset = manual_reset;
req->initial_state = initial_state;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
2001-07-02 19:59:40 +00:00
* CreateW32Event (KERNEL.457)
*/
HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state )
{
return CreateEventA( NULL, manual_reset, initial_state, NULL );
}
/***********************************************************************
* OpenEventA (KERNEL32.@)
*/
HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* OpenEventW (KERNEL32.@)
*/
HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* EVENT_Operation
*
* Execute an event operation (set,reset,pulse).
*/
static BOOL EVENT_Operation( HANDLE handle, enum event_op op )
{
BOOL ret;
SERVER_START_REQ( event_op )
{
req->handle = handle;
req->op = op;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* PulseEvent (KERNEL32.@)
*/
BOOL WINAPI PulseEvent( HANDLE handle )
{
return EVENT_Operation( handle, PULSE_EVENT );
}
/***********************************************************************
2001-07-11 18:56:41 +00:00
* SetW32Event (KERNEL.458)
* SetEvent (KERNEL32.@)
*/
BOOL WINAPI SetEvent( HANDLE handle )
{
return EVENT_Operation( handle, SET_EVENT );
}
/***********************************************************************
2001-07-11 18:56:41 +00:00
* ResetW32Event (KERNEL.459)
* ResetEvent (KERNEL32.@)
*/
BOOL WINAPI ResetEvent( HANDLE handle )
{
return EVENT_Operation( handle, RESET_EVENT );
}
/***********************************************************************
* NOTE: The Win95 VWin32_Event routines given below are really low-level
* routines implemented directly by VWin32. The user-mode libraries
* implement Win32 synchronisation routines on top of these low-level
* primitives. We do it the other way around here :-)
*/
/***********************************************************************
* VWin32_EventCreate (KERNEL.442)
*/
HANDLE WINAPI VWin32_EventCreate(VOID)
{
HANDLE hEvent = CreateEventA( NULL, FALSE, 0, NULL );
return ConvertToGlobalHandle( hEvent );
}
/***********************************************************************
* VWin32_EventDestroy (KERNEL.443)
*/
VOID WINAPI VWin32_EventDestroy(HANDLE event)
{
CloseHandle( event );
}
/***********************************************************************
* VWin32_EventWait (KERNEL.450)
*/
VOID WINAPI VWin32_EventWait(HANDLE event)
{
DWORD mutex_count;
ReleaseThunkLock( &mutex_count );
WaitForSingleObject( event, INFINITE );
RestoreThunkLock( mutex_count );
}
/***********************************************************************
2001-06-19 18:20:47 +00:00
* VWin32_EventSet (KERNEL.451)
2001-07-02 19:59:40 +00:00
* KERNEL_479 (KERNEL.479)
*/
VOID WINAPI VWin32_EventSet(HANDLE event)
{
SetEvent( event );
}
/***********************************************************************
* CreateMutexA (KERNEL32.@)
*/
HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
{
req->owned = owner;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* CreateMutexW (KERNEL32.@)
*/
HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
{
req->owned = owner;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/*
* Mutexes
*/
/***********************************************************************
* OpenMutexA (KERNEL32.@)
*/
HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* OpenMutexW (KERNEL32.@)
*/
HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* ReleaseMutex (KERNEL32.@)
*/
BOOL WINAPI ReleaseMutex( HANDLE handle )
{
BOOL ret;
SERVER_START_REQ( release_mutex )
{
req->handle = handle;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
return ret;
}
/*
* Semaphores
*/
/***********************************************************************
* CreateSemaphoreA (KERNEL32.@)
*/
HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
/* Check parameters */
if ((max <= 0) || (initial < 0) || (initial > max))
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
{
req->initial = (unsigned int)initial;
req->max = (unsigned int)max;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* CreateSemaphoreW (KERNEL32.@)
*/
HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial,
LONG max, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
/* Check parameters */
if ((max <= 0) || (initial < 0) || (initial > max))
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
{
req->initial = (unsigned int)initial;
req->max = (unsigned int)max;
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* OpenSemaphoreA (KERNEL32.@)
*/
HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
{
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* OpenSemaphoreW (KERNEL32.@)
*/
HANDLE WINAPI OpenSemaphoreW( DWORD access, BOOL inherit, LPCWSTR name )
{
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
{
req->access = access;
req->inherit = inherit;
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* ReleaseSemaphore (KERNEL32.@)
*/
BOOL WINAPI ReleaseSemaphore( HANDLE handle, LONG count, LONG *previous )
{
NTSTATUS status = NtReleaseSemaphore( handle, count, previous );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
/*
* Pipes
*/
/***********************************************************************
* CreateNamedPipeA (KERNEL32.@)
*/
HANDLE WINAPI CreateNamedPipeA( LPCSTR name, DWORD dwOpenMode,
DWORD dwPipeMode, DWORD nMaxInstances,
DWORD nOutBufferSize, DWORD nInBufferSize,
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
{
2001-07-10 19:16:49 +00:00
HANDLE ret;
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p): stub\n",
debugstr_a(name), dwOpenMode, dwPipeMode, nMaxInstances,
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
2001-07-10 19:16:49 +00:00
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
{
req->openmode = dwOpenMode;
req->pipemode = dwPipeMode;
req->maxinstances = nMaxInstances;
req->outsize = nOutBufferSize;
req->insize = nInBufferSize;
req->timeout = nDefaultTimeOut;
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
TRACE("Returned %d\n",ret);
return ret;
}
/***********************************************************************
* CreateNamedPipeW (KERNEL32.@)
*/
HANDLE WINAPI CreateNamedPipeW( LPCWSTR name, DWORD dwOpenMode,
DWORD dwPipeMode, DWORD nMaxInstances,
DWORD nOutBufferSize, DWORD nInBufferSize,
DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
{
2001-07-10 19:16:49 +00:00
HANDLE ret;
DWORD len = name ? strlenW(name) : 0;
TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances,
nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
2001-07-10 19:16:49 +00:00
if (len >= MAX_PATH)
{
SetLastError( ERROR_FILENAME_EXCED_RANGE );
return 0;
}
SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
{
req->openmode = dwOpenMode;
req->pipemode = dwPipeMode;
req->maxinstances = nMaxInstances;
req->outsize = nOutBufferSize;
req->insize = nInBufferSize;
req->timeout = nDefaultTimeOut;
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
SetLastError(0);
SERVER_CALL_ERR();
ret = req->handle;
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* PeekNamedPipe (KERNEL32.@)
*/
BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage )
{
FIXME("(%08x, %p, %08lx, %p, %p, %p): stub\n",
hPipe, lpvBuffer, cbBuffer, lpcbRead, lpcbAvail, lpcbMessage);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/***********************************************************************
* WaitNamedPipeA (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeA (LPCSTR lpNamedPipeName, DWORD nTimeOut)
{
FIXME("%s 0x%08lx\n",lpNamedPipeName,nTimeOut);
SetLastError(ERROR_PIPE_NOT_CONNECTED);
return FALSE;
}
/***********************************************************************
* WaitNamedPipeW (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeW (LPCWSTR lpNamedPipeName, DWORD nTimeOut)
{
FIXME("%s 0x%08lx\n",debugstr_w(lpNamedPipeName),nTimeOut);
SetLastError(ERROR_PIPE_NOT_CONNECTED);
return FALSE;
}
2001-07-10 19:16:49 +00:00
/***********************************************************************
* ConnectNamedPipe (KERNEL32.@)
*/
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
{
BOOL ret;
HANDLE event;
TRACE("(%d,%p):stub\n",hPipe, overlapped);
if(overlapped)
{
FIXME("overlapped operation not supported\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
event = CreateEventA(NULL,0,0,NULL);
if(event==INVALID_HANDLE_VALUE)
{
ERR("create event failed!\n");
return FALSE;
}
SERVER_START_REQ( connect_named_pipe )
{
req->handle = hPipe;
req->event = event;
ret = SERVER_CALL_ERR();
}
SERVER_END_REQ;
if(ret) {
ERR("server returned status %08lx\n",GetLastError());
return FALSE;
}
WaitForSingleObject(event,INFINITE);
return TRUE;
}
/***********************************************************************
* DisconnectNamedPipe (KERNEL32.@)
*/
BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
{
FIXME("(%d):stub\n",hPipe);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}