Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / sdk / lib / drivers / sound / mmebuddy / kernel.c
diff --git a/sdk/lib/drivers/sound/mmebuddy/kernel.c b/sdk/lib/drivers/sound/mmebuddy/kernel.c
new file mode 100644 (file)
index 0000000..63b57a4
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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;
+}