--- /dev/null
+/*
+ * 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;
+}