reactos/sdk/lib/drivers/sound/mmebuddy/kernel.c

133 lines
3.8 KiB
C

/*
* PROJECT: ReactOS Sound System "MME Buddy" Library
* LICENSE: GPL - See COPYING in the top level directory
* FILE: lib/drivers/sound/mmebuddy/kernel.c
*
* PURPOSE: Routines assisting with device I/O between user-mode and
* kernel-mode.
*
* PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
*/
#include "precomp.h"
/*
Wraps around CreateFile in order to provide a simpler interface tailored
towards sound driver support code. This simply takes a device path and
opens the device in either read-only mode, or read/write mode (depending on
the ReadOnly parameter).
If the device is opened in read/write mode, it is opened for overlapped I/O.
*/
MMRESULT
OpenKernelSoundDeviceByName(
IN PWSTR DevicePath,
IN BOOLEAN ReadOnly,
OUT PHANDLE Handle)
{
DWORD AccessRights;
VALIDATE_MMSYS_PARAMETER( DevicePath );
VALIDATE_MMSYS_PARAMETER( Handle );
AccessRights = ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
SND_TRACE(L"OpenKernelSoundDeviceByName: %wS\n", DevicePath);
*Handle = CreateFile(DevicePath,
AccessRights,
FILE_SHARE_WRITE, /* FIXME? Should be read also? */
NULL,
OPEN_EXISTING,
ReadOnly ? 0 : FILE_FLAG_OVERLAPPED,
NULL);
if ( *Handle == INVALID_HANDLE_VALUE )
{
SND_ERR(L"CreateFile filed - winerror %d\n", GetLastError());
return Win32ErrorToMmResult(GetLastError());
}
return MMSYSERR_NOERROR;
}
/*
Just a wrapped around CloseHandle.
*/
MMRESULT
CloseKernelSoundDevice(
IN HANDLE Handle)
{
VALIDATE_MMSYS_PARAMETER( Handle );
CloseHandle(Handle);
return MMSYSERR_NOERROR;
}
/*
This is a wrapper around DeviceIoControl which provides control over
instantiated sound devices. It waits for I/O to complete (since an
instantiated sound device is opened in overlapped mode, this is necessary).
*/
MMRESULT
SyncOverlappedDeviceIoControl(
IN HANDLE Handle,
IN DWORD IoControlCode,
IN LPVOID InBuffer,
IN DWORD InBufferSize,
OUT LPVOID OutBuffer,
IN DWORD OutBufferSize,
OUT LPDWORD BytesTransferred OPTIONAL)
{
OVERLAPPED Overlapped;
BOOLEAN IoResult;
DWORD Transferred;
/* Overlapped I/O is done here - this is used for waiting for completion */
ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if ( ! Overlapped.hEvent )
return Win32ErrorToMmResult(GetLastError());
/* Talk to the device */
IoResult = DeviceIoControl(Handle,
IoControlCode,
InBuffer,
InBufferSize,
OutBuffer,
OutBufferSize,
NULL,
&Overlapped);
/* If failure occurs, make sure it's not just due to the overlapped I/O */
if ( ! IoResult )
{
if ( GetLastError() != ERROR_IO_PENDING )
{
CloseHandle(Overlapped.hEvent);
return Win32ErrorToMmResult(GetLastError());
}
}
/* Wait for the I/O to complete */
IoResult = GetOverlappedResult(Handle,
&Overlapped,
&Transferred,
TRUE);
/* Don't need this any more */
CloseHandle(Overlapped.hEvent);
if ( ! IoResult )
return Win32ErrorToMmResult(GetLastError());
SND_TRACE(L"Transferred %d bytes in Sync overlapped I/O\n", Transferred);
if ( BytesTransferred )
*BytesTransferred = Transferred;
return MMSYSERR_NOERROR;
}