Hackfix wdmaud.drv for now (Johannes Anderwald)
[reactos.git] / reactos / dll / win32 / wdmaud.drv / wdmaud.c
index bb3f386..2db6c0e 100644 (file)
  *
  */
 
-#include <windows.h>
-#include <ntddsnd.h>
-#include <sndtypes.h>
-#include <mmddk.h>
-#include <mmebuddy.h>
+#include "wdmaud.h"
 
-#include <ks.h>
-#include <ksmedia.h>
-#include "interface.h"
 
 #define KERNEL_DEVICE_NAME      L"\\\\.\\wdmaud"
 
@@ -29,9 +22,19 @@ PWSTR UnknownWaveOut = L"Wave Output";
 PWSTR UnknownMidiIn = L"Midi Input";
 PWSTR UnknownMidiOut = L"Midi Output";
 
+
 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
 DWORD OpenCount = 0;
 
+MMRESULT
+WriteFileEx_Remixer(
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    IN  PVOID OffsetPtr,
+    IN  DWORD Length,
+    IN  PSOUND_OVERLAPPED Overlap,
+    IN  LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
+
+
 
 MMRESULT
 GetNumWdmDevs(
@@ -39,6 +42,25 @@ GetNumWdmDevs(
     IN  MMDEVICE_TYPE DeviceType,
     OUT DWORD* DeviceCount)
 {
+#ifdef USE_MMIXER_LIB
+
+    switch(DeviceType)
+    {
+        case MIXER_DEVICE_TYPE:
+            *DeviceCount = WdmAudGetMixerCount();
+            break;
+        case WAVE_OUT_DEVICE_TYPE:
+            *DeviceCount = WdmAudGetWaveOutCount();
+            break;
+        case WAVE_IN_DEVICE_TYPE:
+            *DeviceCount = WdmAudGetWaveInCount();
+            break;
+        default:
+            *DeviceCount = 0;
+    }
+    return MMSYSERR_NOERROR;
+#else
+
     MMRESULT Result;
     WDMAUD_DEVICE_INFO DeviceInfo;
 
@@ -67,11 +89,13 @@ GetNumWdmDevs(
     *DeviceCount = DeviceInfo.DeviceCount;
 
     return MMSYSERR_NOERROR;
+#endif
 }
 
 MMRESULT
 GetWdmDeviceCapabilities(
     IN  PSOUND_DEVICE SoundDevice,
+    IN  DWORD DeviceId,
     OUT PVOID Capabilities,
     IN  DWORD CapabilitiesSize)
 {
@@ -84,18 +108,34 @@ GetWdmDeviceCapabilities(
     SND_ASSERT( SoundDevice );
     SND_ASSERT( Capabilities );
 
-    SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities\n");
-
     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
     SND_ASSERT( Result == MMSYSERR_NOERROR );
 
     if ( ! MMSUCCESS(Result) )
         return Result;
 
+    SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
+
+#ifdef USE_MMIXER_LIB
+    if (DeviceType == MIXER_DEVICE_TYPE)
+    {
+        return WdmAudGetMixerCapabilities(DeviceId, (LPMIXERCAPSW)Capabilities);
+    }
+    else if (DeviceType == WAVE_OUT_DEVICE_TYPE)
+    {
+        return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities);
+    }
+    else if (DeviceType == WAVE_IN_DEVICE_TYPE)
+    {
+        return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities);
+    }
+
+#endif
+
 
     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
     DeviceInfo.DeviceType = DeviceType;
-    DeviceInfo.DeviceIndex = 0; //FIXME
+    DeviceInfo.DeviceIndex = DeviceId;
 
     Result = SyncOverlappedDeviceIoControl(KernelHandle,
                                            IOCTL_GETCAPABILITIES,
@@ -110,18 +150,33 @@ GetWdmDeviceCapabilities(
         return TranslateInternalMmResult(Result);
     }
 
-
     /* This is pretty much a big hack right now */
     switch ( DeviceType )
     {
+        case MIXER_DEVICE_TYPE:
+        {
+            LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities;
+
+            DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
+            CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
+
+            MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
+            MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
+            MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion;
+            MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid;
+            MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid;
+            break;
+        }
         case WAVE_OUT_DEVICE_TYPE :
         {
             LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
+
+            DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
             WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
             WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
 
             WaveOutCaps->vDriverVersion = 0x0001;
-            CopyWideString(WaveOutCaps->szPname, UnknownWaveOut);
+            CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
 
             WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
             WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
@@ -130,9 +185,19 @@ GetWdmDeviceCapabilities(
         }
         case WAVE_IN_DEVICE_TYPE :
         {
-            LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities;
-            CopyWideString(WaveInCaps->szPname, UnknownWaveIn);
-            /* TODO... other fields */
+            LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
+
+            DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
+
+            WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
+            WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
+
+            WaveInCaps->vDriverVersion = 0x0001;
+            CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
+
+            WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
+            WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
+            WaveInCaps->wReserved1 = 0;
             break;
         }
     }
@@ -175,6 +240,18 @@ CloseWdmSoundDevice(
     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
     IN  PVOID Handle)
 {
+    WDMAUD_DEVICE_INFO DeviceInfo;
+    MMRESULT Result;
+    MMDEVICE_TYPE DeviceType;
+    PSOUND_DEVICE SoundDevice;
+
+    Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        return TranslateInternalMmResult(Result);
+    }
+
     if ( OpenCount == 0 )
     {
         return MMSYSERR_NOERROR;
@@ -182,9 +259,49 @@ CloseWdmSoundDevice(
 
     SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
 
+    Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
+
     if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
     {
-        CloseHandle((HANDLE)SoundDeviceInstance->Handle);
+        ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+
+        DeviceInfo.DeviceType = DeviceType;
+        DeviceInfo.hDevice = SoundDeviceInstance->Handle;
+
+         /* First stop the stream */
+         if (DeviceType != MIXER_DEVICE_TYPE)
+         {
+             DeviceInfo.u.State = KSSTATE_STOP;
+             SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_SETDEVICE_STATE,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                            sizeof(WDMAUD_DEVICE_INFO),
+                                            NULL);
+        }
+#ifdef USE_MMIXER_LIB
+    if (DeviceType == MIXER_DEVICE_TYPE)
+    {
+        return WdmAudCloseMixer(SoundDeviceInstance->Handle, SoundDeviceInstance->hNotifyEvent);
+    }
+#endif
+
+        SyncOverlappedDeviceIoControl(KernelHandle,
+                                      IOCTL_CLOSE_WDMAUD,
+                                      (LPVOID) &DeviceInfo,
+                                      sizeof(WDMAUD_DEVICE_INFO),
+                                      (LPVOID) &DeviceInfo,
+                                      sizeof(WDMAUD_DEVICE_INFO),
+                                      NULL);
+    }
+
+    if (DeviceType == MIXER_DEVICE_TYPE)
+    {
+        SetEvent(SoundDeviceInstance->hStopEvent);
+        CloseHandle(SoundDeviceInstance->hStopEvent);
+        CloseHandle(SoundDeviceInstance->hNotifyEvent);
     }
 
     --OpenCount;
@@ -209,9 +326,76 @@ QueryWdmWaveDeviceFormatSupport(
     return MMSYSERR_NOERROR;
 }
 
+
+
+
+
+MMRESULT
+SetWdmMixerDeviceFormat(
+    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  DWORD DeviceId,
+    IN  PWAVEFORMATEX WaveFormat,
+    IN  DWORD WaveFormatSize)
+{
+    MMRESULT Result;
+    WDMAUD_DEVICE_INFO DeviceInfo;
+    HANDLE hThread;
+
+
+    Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if ( ! Instance->hNotifyEvent )
+        return MMSYSERR_NOMEM;
+
+#ifdef USE_MMIXER_LIB
+    return WdmAudOpenMixer(&Instance->Handle, DeviceId, Instance->hNotifyEvent);
+#endif
+
+    if (Instance->Handle != KernelHandle)
+    {
+        /* device is already open */
+        return MMSYSERR_NOERROR;
+    }
+
+    Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if ( ! Instance->hStopEvent )
+        return MMSYSERR_NOMEM;
+
+    ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+    DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
+    DeviceInfo.DeviceIndex = DeviceId;
+    DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent;
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_OPEN_WDMAUD,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        CloseHandle(Instance->hNotifyEvent);
+        CloseHandle(Instance->hStopEvent);
+        return TranslateInternalMmResult(Result);
+    }
+
+    hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL);
+    if (  hThread )
+    {
+        CloseHandle(hThread);
+    }
+
+    /* Store sound device handle instance handle */
+    Instance->Handle = (PVOID)DeviceInfo.hDevice;
+
+    return MMSYSERR_NOERROR;
+}
+
 MMRESULT
 SetWdmWaveDeviceFormat(
     IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  DWORD DeviceId,
     IN  PWAVEFORMATEX WaveFormat,
     IN  DWORD WaveFormatSize)
 {
@@ -241,20 +425,33 @@ SetWdmWaveDeviceFormat(
         return MMSYSERR_NOERROR;
     }
 
-
     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+
+#ifdef USE_MMIXER_LIB
+    return WdmAudOpenWavePin(Instance, DeviceId, WaveFormat, DeviceType);
+#endif
+
+
     SND_ASSERT( Result == MMSYSERR_NOERROR );
 
     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
     DeviceInfo.DeviceType = DeviceType;
-    DeviceInfo.DeviceIndex = 0; //FIXME
-    DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
+    DeviceInfo.DeviceIndex = DeviceId;
+    DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize;
     DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
+#ifdef USERMODE_MIXER
+    DeviceInfo.u.WaveFormatEx.nChannels = 2;
+    DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
+    DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
+    DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
+    DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
+#else
     DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
     DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
     DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
     DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
     DeviceInfo.u.WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
+#endif
 
     Result = SyncOverlappedDeviceIoControl(KernelHandle,
                                            IOCTL_OPEN_WDMAUD,
@@ -269,53 +466,340 @@ SetWdmWaveDeviceFormat(
         return TranslateInternalMmResult(Result);
     }
 
+    /* Store format */
+    Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
+    Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
+    Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
+    Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
+    Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
+    Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
+    Instance->WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
+
+    /* Store sound device handle instance handle */
     Instance->Handle = (PVOID)DeviceInfo.hDevice;
 
+    /* Now determine framing requirements */
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_GETFRAMESIZE,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    if ( MMSUCCESS(Result) )
+    {
+        if (DeviceInfo.u.FrameSize)
+        {
+            Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
+            Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
+            SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
+        }
+    }
+    else
+    {
+        // use a default of 100 buffers
+        Instance->BufferCount = 100;
+    }
+
+    if (DeviceType == WAVE_OUT_DEVICE_TYPE)
+    {
+        /* Now start the stream */
+        DeviceInfo.u.State = KSSTATE_RUN;
+        SyncOverlappedDeviceIoControl(KernelHandle,
+                                      IOCTL_SETDEVICE_STATE,
+                                      (LPVOID) &DeviceInfo,
+                                      sizeof(WDMAUD_DEVICE_INFO),
+                                      (LPVOID) &DeviceInfo,
+                                      sizeof(WDMAUD_DEVICE_INFO),
+                                      NULL);
+    }
+
     return MMSYSERR_NOERROR;
 }
 
+
 MMRESULT
-WriteFileEx_Committer2(
-    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
-    IN  PVOID OffsetPtr,
-    IN  DWORD Length,
-    IN  PSOUND_OVERLAPPED Overlap,
-    IN  LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
+SetWdmWaveState(
+    IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+    IN BOOL bStart)
 {
-    HANDLE Handle;
+    MMRESULT Result;
+    PSOUND_DEVICE SoundDevice;
     WDMAUD_DEVICE_INFO DeviceInfo;
+    MMDEVICE_TYPE DeviceType;
+    HANDLE Handle;
 
+    Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
 
-    VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
-    VALIDATE_MMSYS_PARAMETER( OffsetPtr );
-    VALIDATE_MMSYS_PARAMETER( Overlap );
-    VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
+    if ( ! MMSUCCESS(Result) )
+    {
+        return TranslateInternalMmResult(Result);
+    }
 
-    GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+    Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
 
-    SND_ASSERT(Handle);
+    Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
 
     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
     DeviceInfo.hDevice = Handle;
-    DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE; //FIXME
-    DeviceInfo.Buffer = OffsetPtr;
-    DeviceInfo.BufferSize = Length;
+    DeviceInfo.DeviceType = DeviceType;
+
+    if (bStart)
+        DeviceInfo.u.State = KSSTATE_RUN;
+    else
+        DeviceInfo.u.State = KSSTATE_PAUSE;
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_SETDEVICE_STATE,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    return Result;
+}
+
+MMRESULT
+GetDeviceInterfaceString(
+    IN  MMDEVICE_TYPE DeviceType,
+    IN  DWORD DeviceId,
+    IN  LPWSTR Interface,
+    IN  DWORD  InterfaceLength,
+    OUT  DWORD * InterfaceSize)
+{
+    WDMAUD_DEVICE_INFO DeviceInfo;
+    MMRESULT Result;
+
+    ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+    DeviceInfo.DeviceType = DeviceType;
+    DeviceInfo.DeviceIndex = DeviceId;
+
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_QUERYDEVICEINTERFACESTRING,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        return TranslateInternalMmResult(Result);
+    }
 
-    Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
 
-    if ( ! WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine))
+    if (!Interface)
     {
-        SND_TRACE(L"WriteFileEx failed with %x\n", GetLastError());
+        SND_ASSERT(InterfaceSize);
+
+        *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
+        return MMSYSERR_NOERROR;
     }
-    else
+
+    if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
     {
-        WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
+        /* buffer is too small */
+        return MMSYSERR_MOREDATA;
+    }
 
+    DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
+    DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_QUERYDEVICEINTERFACESTRING,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    if (  MMSUCCESS(Result) && InterfaceLength > 2)
+    {
+        Interface[1] = L'\\';
+        Interface[InterfaceLength-1] = L'\0';
     }
 
+    return Result;
+}
+
+MMRESULT
+GetWdmPosition(
+    IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+    IN  MMTIME* Time)
+{
+    MMRESULT Result;
+    PSOUND_DEVICE SoundDevice;
+    WDMAUD_DEVICE_INFO DeviceInfo;
+    MMDEVICE_TYPE DeviceType;
+    HANDLE Handle;
+
+    Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        return TranslateInternalMmResult(Result);
+    }
+
+    Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+    DeviceInfo.hDevice = Handle;
+    DeviceInfo.DeviceType = DeviceType;
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_OPEN_WDMAUD,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        return TranslateInternalMmResult(Result);
+    }
+
+    Time->wType = TIME_BYTES;
+    Time->u.cb = (DWORD)DeviceInfo.u.Position;
+
     return MMSYSERR_NOERROR;
 }
 
+MMRESULT
+ResetStream(
+    IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+    IN  MMDEVICE_TYPE DeviceType,
+    IN  BOOLEAN bStartReset)
+{
+    MMRESULT Result;
+    HANDLE Handle;
+    WDMAUD_DEVICE_INFO DeviceInfo;
+
+    Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+    DeviceInfo.hDevice = Handle;
+    DeviceInfo.DeviceType = DeviceType;
+    DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END);
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IOCTL_RESET_STREAM,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+    return Result;
+}
+
+
+MMRESULT
+QueryMixerInfo(
+    IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+    IN UINT uMsg,
+    IN LPVOID Parameter,
+    IN DWORD Flags)
+{
+    MMRESULT Result;
+    WDMAUD_DEVICE_INFO DeviceInfo;
+    HANDLE Handle;
+    DWORD IoControlCode;
+    LPMIXERLINEW MixLine;
+    LPMIXERLINECONTROLSW MixControls;
+    LPMIXERCONTROLDETAILS MixDetails;
+
+    SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
+
+    Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+    SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+    DeviceInfo.hDevice = Handle;
+    DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
+    DeviceInfo.Flags = Flags;
+
+    MixLine = (LPMIXERLINEW)Parameter;
+    MixControls = (LPMIXERLINECONTROLSW)Parameter;
+    MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
+
+#ifdef USE_MMIXER_LIB
+    switch(uMsg)
+    {
+        case MXDM_GETLINEINFO:
+            return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags);
+        case MXDM_GETLINECONTROLS:
+            return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags);
+       case MXDM_SETCONTROLDETAILS:
+            return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
+            break;
+       case MXDM_GETCONTROLDETAILS:
+            return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
+            break;
+       default:
+           SND_ASSERT(0);
+           return MMSYSERR_NOTSUPPORTED;
+    }
+#endif
+
+
+    switch(uMsg)
+    {
+        case MXDM_GETLINEINFO:
+            RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
+            IoControlCode = IOCTL_GETLINEINFO;
+            break;
+        case MXDM_GETLINECONTROLS:
+            RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
+            IoControlCode = IOCTL_GETLINECONTROLS;
+            break;
+       case MXDM_SETCONTROLDETAILS:
+            RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
+            IoControlCode = IOCTL_SETCONTROLDETAILS;
+            break;
+       case MXDM_GETCONTROLDETAILS:
+            RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
+            IoControlCode = IOCTL_GETCONTROLDETAILS;
+            break;
+       default:
+           SND_ASSERT(0);
+           return MMSYSERR_NOTSUPPORTED;
+    }
+
+    Result = SyncOverlappedDeviceIoControl(KernelHandle,
+                                           IoControlCode,
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           (LPVOID) &DeviceInfo,
+                                           sizeof(WDMAUD_DEVICE_INFO),
+                                           NULL);
+
+    if ( ! MMSUCCESS(Result) )
+    {
+        return Result;
+    }
+
+    switch(uMsg)
+    {
+        case MXDM_GETLINEINFO:
+        {
+            RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
+            break;
+        }
+    }
+
+    return Result;
+}
+
 
 MMRESULT
 PopulateWdmDeviceList(
@@ -344,7 +828,7 @@ PopulateWdmDeviceList(
 
     for ( i = 0; i < DeviceCount; ++ i )
     {
-        Result = ListSoundDevice(DeviceType, (PVOID) i, &SoundDevice);
+        Result = ListSoundDevice(DeviceType, UlongToPtr(i), &SoundDevice);
 
         if ( ! MMSUCCESS(Result) )
         {
@@ -356,10 +840,31 @@ PopulateWdmDeviceList(
         ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE));
         FuncTable.GetCapabilities = GetWdmDeviceCapabilities;
         FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport;
-        FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
+        if (DeviceType == MIXER_DEVICE_TYPE)
+        {
+            FuncTable.SetWaveFormat = SetWdmMixerDeviceFormat;
+            FuncTable.QueryMixerInfo = QueryMixerInfo;
+        }
+        else
+        {
+            FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
+        }
+
+        if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
+        {
+            FuncTable.SetState = SetWdmWaveState;
+            FuncTable.ResetStream = ResetStream;
+        }
+
         FuncTable.Open = OpenWdmSoundDevice;
         FuncTable.Close = CloseWdmSoundDevice;
+        FuncTable.GetDeviceInterfaceString = GetDeviceInterfaceString;
+#ifndef USERMODE_MIXER
         FuncTable.CommitWaveBuffer = WriteFileEx_Committer2;
+#else
+        FuncTable.CommitWaveBuffer = WriteFileEx_Remixer;
+#endif
+        FuncTable.GetPos = GetWdmPosition;
 
         SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
     }
@@ -369,7 +874,8 @@ PopulateWdmDeviceList(
 
 
 
-APIENTRY LONG
+LONG
+APIENTRY
 DriverProc(
     DWORD DriverId,
     HANDLE DriverHandle,
@@ -395,7 +901,7 @@ DriverProc(
 
             if ( Handle == INVALID_HANDLE_VALUE )
             {
-                SND_ERR(L"Failed to open %s\n", KERNEL_DEVICE_NAME);
+                SND_ERR(L"Failed to open \\\\.\\wdmaud\n");
                 CleanupEntrypointMutexes();
 
                 //UnlistAllSoundDevices();
@@ -479,6 +985,9 @@ BOOL WINAPI DllMain(
     switch ( fdwReason )
     {
         case DLL_PROCESS_ATTACH :
+#ifdef USE_MMIXER_LIB
+            WdmAudInitUserModeMixer();
+#endif
             SND_TRACE(L"WDMAUD.DRV - Process attached\n");
             break;
         case DLL_PROCESS_DETACH :