[WDMAUD_KERNEL]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 11 Feb 2010 21:04:57 +0000 (21:04 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 11 Feb 2010 21:04:57 +0000 (21:04 +0000)
- Replace mixer / wave support code by mmixer library
[MMIXER]
- Compare device name from 2 character onwards as there are difference in paths in user mode / kernel mode
- Invoke create pin callback if the caller provides it
[WDMAUD.DRV]
- Apply changes from mmixer library

-- Tested in Vbox with Winamp / ReactOS mplay32

svn path=/trunk/; revision=45579

13 files changed:
reactos/boot/bootdata/packages/reactos.dff
reactos/dll/win32/wdmaud.drv/mmixer.c
reactos/drivers/wdm/audio/legacy/wdmaud/control.c
reactos/drivers/wdm/audio/legacy/wdmaud/entry.c
reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [deleted file]
reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c [new file with mode: 0644]
reactos/drivers/wdm/audio/legacy/wdmaud/sup.c
reactos/drivers/wdm/audio/legacy/wdmaud/wave.c [deleted file]
reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild
reactos/lib/drivers/sound/mmixer/mmixer.h
reactos/lib/drivers/sound/mmixer/sup.c
reactos/lib/drivers/sound/mmixer/wave.c

index df124e9..733aba3 100644 (file)
@@ -156,7 +156,7 @@ dll\directx\dinput8\dinput8.dll                     1
 dll\directx\dmusic\dmusic.dll                       1
 dll\directx\dplay\dplay.dll                         1
 dll\directx\dplayx\dplayx.dll                       1
-dll\directx\dsound\dsound.dll                       1
+dll\directx\dsound_new\dsound.dll                   1
 dll\directx\dxdiagn\dxdiagn.dll                     1
 dll\directx\wine\ddraw\ddraw.dll                    1
 dll\directx\d3d8thk\d3d8thk.dll                     1
@@ -515,7 +515,7 @@ drivers\storage\ide\pciidex\pciidex.sys             2
 ;drivers\usb\miniport\usbuhci\usbuhci.sys           2
 ;drivers\usb\usbhub\usbhub.sys                      2
 ;drivers\usb\usbport\usbport.sys                    2
-drivers\usb\nt4compat\usbdriver\usbdriver.sys       2
+;drivers\usb\nt4compat\usbdriver\usbdriver.sys       2
 
 drivers\video\displays\vga\vgaddi.dll               1
 drivers\video\displays\framebuf\framebuf.dll        1
@@ -528,6 +528,7 @@ drivers\wdm\audio\filters\kmixer\kmixer.sys         2
 drivers\wdm\audio\sysaudio\sysaudio.sys             2
 drivers\wdm\audio\legacy\wdmaud\wdmaud.sys          2
 drivers\wdm\audio\backpln\portcls\portcls.sys       2
+drivers\wdm\audio\backpln\audio_test\audio_test.exe 1
 drivers\wdm\audio\drm\drmk\drmk.sys                 2
 drivers\wmi\wmilib.sys                              2
 
@@ -798,4 +799,21 @@ modules\rostests\winetests\wintrust\wintrust_winetest.exe                  7   o
 modules\rostests\winetests\wlanapi\wlanapi_winetest.exe                    7   optional
 modules\rostests\winetests\ws2_32\ws2_32_winetest.exe                      7   optional
 
+
 modules\wallpaper\Angelus_02_ROSWP.bmp                                     4   optional
+modules\windows\alcxwdm.sys                                                2   optional
+modules\windows\dlkfet5b.sys                                               2   optional
+modules\windows\cmaudio.sys                                                2   optional
+modules\windows\cmaudio.inf                                                6   optional
+;modules\windows\es1370mp.sys                                               2   optional
+;modules\windows\es1371mp.sys                                               2   optional
+modules\windows\alcxwdm.inf                                                6   optional
+modules\windows\netdlfet.inf                                               6   optional
+modules\windows\ks.inf                                                     6   optional
+;modules\windows\wdma_ens.inf                                               6   optional
+modules\windows\b.mp3                                                      7   optional
+modules\windows\winamp.exe                                                 7   optional
+modules\windows\windows.wav                                                7   optional
+modules\windows\D530.exe                                                   7   optional
+modules\windows\vmaudio.sys                                                2   optional
+modules\windows\vmaudio.inf                                                6   optional
index 6ef1515..0b7cac1 100644 (file)
@@ -467,7 +467,7 @@ WdmAudSetWdmWaveDeviceFormatByMMixer(
 
     bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE);
 
-    if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, &Instance->Handle) == MM_STATUS_SUCCESS)
+    if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS)
     {
         if (DeviceType == WAVE_OUT_DEVICE_TYPE)
         {
index b5f1c53..07e9ef8 100644 (file)
@@ -8,17 +8,7 @@
  */
 #include "wdmaud.h"
 
-const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
-const GUID KSPROPSETID_Connection               = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 const GUID KSPROPSETID_Sysaudio                 = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
-const GUID KSPROPSETID_General                  = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
-const GUID KSINTERFACESETID_Standard            = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-const GUID KSMEDIUMSETID_Standard               = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-const GUID KSDATAFORMAT_TYPE_AUDIO              = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
-const GUID KSDATAFORMAT_SUBTYPE_PCM             = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
-const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX  = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
-const GUID KSPROPSETID_Topology                 = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
-
 
 NTSTATUS
 WdmAudControlOpen(
@@ -55,15 +45,15 @@ WdmAudControlDeviceType(
 
     if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
     {
-        Result = DeviceExtension->MixerInfoCount;
+        Result = WdmAudGetMixerDeviceCount();
     }
     else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
     {
-        Result = DeviceExtension->WaveOutDeviceCount;
+        Result = WdmAudGetWaveInDeviceCount();
     }
     else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
     {
-        Result = DeviceExtension->WaveInDeviceCount;
+        Result = WdmAudGetWaveOutDeviceCount();
     }
 
     /* store result count */
@@ -221,7 +211,6 @@ WdmAudGetDeviceInterface(
     PWDMAUD_DEVICE_EXTENSION DeviceExtension;
     NTSTATUS Status;
     LPWSTR Device;
-    LPWAVE_INFO WaveInfo;
     ULONG Size, Length;
 
     /* get device extension */
@@ -233,16 +222,8 @@ WdmAudGetDeviceInterface(
     if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
     {
         /* get wave info */
-        Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
-
-        /* check for success */
-        if (!NT_SUCCESS(Status))
-        {
-            /* invalid device id */
-            return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
-        }
+        Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
 
-        Status = GetSysAudioDevicePnpName(DeviceObject, WaveInfo->FilterId, &Device);
         /* check for success */
         if (!NT_SUCCESS(Status))
         {
@@ -275,13 +256,13 @@ WdmAudGetDeviceInterface(
     }
     else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
     {
-        if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
+        if (DeviceInfo->DeviceIndex >= WdmAudGetMixerDeviceCount())
         {
             /* invalid device id */
             return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
         }
 
-        Status = GetSysAudioDevicePnpName(DeviceObject, DeviceExtension->MixerInfo[DeviceInfo->DeviceIndex].DeviceIndex, &Device);
+        Status = WdmAudGetMixerPnpNameByIndex(DeviceInfo->DeviceIndex, &Device);
         /* check for success */
         if (!NT_SUCCESS(Status))
         {
@@ -308,8 +289,6 @@ WdmAudGetDeviceInterface(
             //FIXME SEH
             RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
         }
-
-        ExFreePool(Device);
         return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
     }
 
index 013be6a..20421ea 100644 (file)
@@ -80,9 +80,7 @@ WdmAudInstallDevice(
     }
 
     Status = WdmAudMixerInitialize(DeviceObject);
-    DPRINT("WdmAudMixerInitialize Status %x\n", Status);
-    Status = WdmAudWaveInitialize(DeviceObject);
-    DPRINT("WdmAudWaveInitialize Status %x\n", Status);
+    DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
 
     DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
     DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c b/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c
deleted file mode 100644 (file)
index 5de3872..0000000
+++ /dev/null
@@ -1,2438 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS Kernel Streaming
- * FILE:            drivers/wdm/audio/legacy/wdmaud/mixer.c
- * PURPOSE:         System Audio graph builder
- * PROGRAMMER:      Andrew Greenwood
- *                  Johannes Anderwald
- */
-#include "wdmaud.h"
-
-const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_AGC = {0xE88C9BA0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_LOUDNESS = {0x41887440L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_MUTE =     {0x02B223C0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_TONE =     {0x7607E580L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_VOLUME =   {0x3A5ACC00L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_PEAKMETER = {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}};
-const GUID KSNODETYPE_MUX =       {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_CHORUS =      {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_REVERB =      {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_SUPERMIX =    {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
-const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
-
-#define DESTINATION_LINE 0xFFFF0000
-
-LPMIXERLINE_EXT
-GetSourceMixerLine(
-    LPMIXER_INFO MixerInfo,
-    DWORD dwSource)
-{
-    PLIST_ENTRY Entry;
-    LPMIXERLINE_EXT MixerLineSrc;
-
-    /* get first entry */
-    Entry = MixerInfo->LineList.Flink;
-
-    while(Entry != &MixerInfo->LineList)
-    {
-        MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
-        DPRINT("dwSource %x dwSource %x\n", MixerLineSrc->Line.dwSource, dwSource);
-        if (MixerLineSrc->Line.dwSource == dwSource)
-            return MixerLineSrc;
-
-        Entry = Entry->Flink;
-    }
-
-    return NULL;
-}
-
-LPMIXERCONTROL_DATA
-GetMixerControlDataById(
-    PLIST_ENTRY ListHead,
-    DWORD dwControlId)
-{
-    PLIST_ENTRY Entry;
-    LPMIXERCONTROL_DATA Control;
-
-    /* get first entry */
-    Entry = ListHead->Flink;
-
-    while(Entry != ListHead)
-    {
-        Control = (LPMIXERCONTROL_DATA)CONTAINING_RECORD(Entry, MIXERCONTROL_DATA, Entry);
-        DPRINT("dwSource %x dwSource %x\n", Control->dwControlID, dwControlId);
-        if (Control->dwControlID == dwControlId)
-            return Control;
-
-        Entry = Entry->Flink;
-    }
-    return NULL;
-}
-
-NTSTATUS
-GetMixerControlById(
-    LPMIXER_INFO MixerInfo,
-    DWORD dwControlID,
-    LPMIXERLINE_EXT *MixerLine,
-    LPMIXERCONTROLW *MixerControl,
-    PULONG NodeId)
-{
-    PLIST_ENTRY Entry;
-    LPMIXERLINE_EXT MixerLineSrc;
-    ULONG Index;
-
-    /* get first entry */
-    Entry = MixerInfo->LineList.Flink;
-
-    while(Entry != &MixerInfo->LineList)
-    {
-        MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
-
-        for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
-        {
-            if (MixerLineSrc->LineControls[Index].dwControlID == dwControlID)
-            {
-                if (MixerLine)
-                    *MixerLine = MixerLineSrc;
-                if (MixerControl)
-                    *MixerControl = &MixerLineSrc->LineControls[Index];
-                if (NodeId)
-                    *NodeId = MixerLineSrc->NodeIds[Index];
-                return STATUS_SUCCESS;
-            }
-        }
-        Entry = Entry->Flink;
-    }
-
-    return STATUS_NOT_FOUND;
-}
-
-LPMIXERLINE_EXT
-GetSourceMixerLineByComponentType(
-    LPMIXER_INFO MixerInfo,
-    DWORD dwComponentType)
-{
-    PLIST_ENTRY Entry;
-    LPMIXERLINE_EXT MixerLineSrc;
-
-    /* get first entry */
-    Entry = MixerInfo->LineList.Flink;
-
-    while(Entry != &MixerInfo->LineList)
-    {
-        MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
-        if (MixerLineSrc->Line.dwComponentType == dwComponentType)
-            return MixerLineSrc;
-
-        Entry = Entry->Flink;
-    }
-
-    return NULL;
-}
-
-LPMIXERLINE_EXT
-GetSourceMixerLineByLineId(
-    LPMIXER_INFO MixerInfo,
-    DWORD dwLineID)
-{
-    PLIST_ENTRY Entry;
-    LPMIXERLINE_EXT MixerLineSrc;
-
-    /* get first entry */
-    Entry = MixerInfo->LineList.Flink;
-
-    while(Entry != &MixerInfo->LineList)
-    {
-        MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
-        DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID);
-        if (MixerLineSrc->Line.dwLineID == dwLineID)
-            return MixerLineSrc;
-
-        Entry = Entry->Flink;
-    }
-
-    return NULL;
-}
-
-
-
-ULONG
-GetPinCount(
-    IN PFILE_OBJECT FileObject)
-{
-    KSPROPERTY Pin;
-    NTSTATUS Status;
-    ULONG NumPins, BytesReturned;
-
-    Pin.Flags = KSPROPERTY_TYPE_GET;
-    Pin.Set = KSPROPSETID_Pin;
-    Pin.Id = KSPROPERTY_PIN_CTYPES;
-
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
-    if (!NT_SUCCESS(Status))
-        return 0;
-
-    return NumPins;
-}
-
-
-ULONG
-GetSysAudioDeviceCount(
-    IN  PDEVICE_OBJECT DeviceObject)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    KSPROPERTY Pin;
-    ULONG Count, BytesReturned;
-    NTSTATUS Status;
-
-    /* setup the query request */
-    Pin.Set = KSPROPSETID_Sysaudio;
-    Pin.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
-    Pin.Flags = KSPROPERTY_TYPE_GET;
-
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* query sysaudio for the device count */
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
-    if (!NT_SUCCESS(Status))
-        return 0;
-
-    return Count;
-}
-
-NTSTATUS
-GetSysAudioDevicePnpName(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  ULONG DeviceIndex,
-    OUT LPWSTR * Device)
-{
-    ULONG BytesReturned;
-    KSP_PIN Pin;
-    NTSTATUS Status;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-
-   /* first check if the device index is within bounds */
-   if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject))
-       return STATUS_INVALID_PARAMETER;
-
-    /* setup the query request */
-    Pin.Property.Set = KSPROPSETID_Sysaudio;
-    Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME;
-    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-    Pin.PinId = DeviceIndex;
-
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* query sysaudio for the device path */
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned);
-
-    /* check if the request failed */
-    if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0)
-        return STATUS_UNSUCCESSFUL;
-
-    /* allocate buffer for the device */
-    *Device = ExAllocatePool(NonPagedPool, BytesReturned);
-    if (!Device)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* query sysaudio again for the device path */
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), (PVOID)*Device, BytesReturned, &BytesReturned);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        ExFreePool(*Device);
-        return Status;
-    }
-
-    return Status;
-}
-
-ULONG
-GetDeviceIndexFromPnpName(
-    IN PDEVICE_OBJECT DeviceObject,
-    LPWSTR Device)
-{
-    ULONG Count, Index;
-    LPWSTR DeviceName;
-    NTSTATUS Status;
-
-    /* get device count */
-    Count = GetSysAudioDeviceCount(DeviceObject);
-
-    if (!Count)
-        return MAXULONG;
-
-    for(Index = 0; Index < Count; Index++)
-    {
-        /* get device name */
-        Status = GetSysAudioDevicePnpName(DeviceObject, Index, &DeviceName);
-        if (NT_SUCCESS(Status))
-        {
-            if (!wcsicmp(Device, DeviceName))
-            {
-                /* found device index */
-                ExFreePool(DeviceName);
-                return Index;
-            }
-            ExFreePool(DeviceName);
-        }
-    }
-
-    return MAXULONG;
-}
-
-
-NTSTATUS
-OpenDevice(
-    IN LPWSTR Device,
-    OUT PHANDLE DeviceHandle,
-    OUT PFILE_OBJECT * FileObject)
-{
-    NTSTATUS Status;
-    HANDLE hDevice;
-
-    /* now open the device */
-    Status = WdmAudOpenSysAudioDevice(Device, &hDevice);
-
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
-
-    *DeviceHandle = hDevice;
-
-    if (FileObject)
-    {
-        Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL);
-
-        if (!NT_SUCCESS(Status))
-        {
-            ZwClose(hDevice);
-        }
-    }
-
-    return Status;
-
-}
-
-
-NTSTATUS
-OpenSysAudioDeviceByIndex(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  ULONG DeviceIndex,
-    IN  PHANDLE DeviceHandle,
-    IN  PFILE_OBJECT * FileObject)
-{
-    LPWSTR Device = NULL;
-    NTSTATUS Status;
-
-    Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, &Device);
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    Status = OpenDevice(Device, DeviceHandle, FileObject);
-
-    /* free device buffer */
-    ExFreePool(Device);
-
-    return Status;
-}
-
-NTSTATUS
-GetFilterNodeProperty(
-    IN PFILE_OBJECT FileObject,
-    IN ULONG PropertyId,
-    PKSMULTIPLE_ITEM * Item)
-{
-    NTSTATUS Status;
-    ULONG BytesReturned;
-    PKSMULTIPLE_ITEM MultipleItem;
-    KSPROPERTY Property;
-
-    /* setup query request */
-    Property.Id = PropertyId;
-    Property.Flags = KSPROPERTY_TYPE_GET;
-    Property.Set = KSPROPSETID_Topology;
-
-    /* query for required size */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
-
-    /* check for success */
-    if (Status != STATUS_MORE_ENTRIES)
-        return Status;
-
-    /* allocate buffer */
-    MultipleItem = (PKSMULTIPLE_ITEM)ExAllocatePool(NonPagedPool, BytesReturned);
-    if (!MultipleItem)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* query for required size */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        ExFreePool(MultipleItem);
-        return Status;
-    }
-
-    *Item = MultipleItem;
-    return Status;
-}
-
-ULONG
-CountNodeType(
-    PKSMULTIPLE_ITEM MultipleItem,
-    LPGUID NodeType)
-{
-    ULONG Count;
-    ULONG Index;
-    LPGUID Guid;
-
-    Count = 0;
-    Guid = (LPGUID)(MultipleItem+1);
-
-    /* iterate through node type array */
-    for(Index = 0; Index < MultipleItem->Count; Index++)
-    {
-        if (IsEqualGUIDAligned(NodeType, Guid))
-        {
-            /* found matching guid */
-            Count++;
-        }
-        Guid++;
-    }
-    return Count;
-}
-
-ULONG
-GetNodeTypeIndex(
-    PKSMULTIPLE_ITEM MultipleItem,
-    LPGUID NodeType)
-{
-    ULONG Index;
-    LPGUID Guid;
-
-    Guid = (LPGUID)(MultipleItem+1);
-
-    /* iterate through node type array */
-    for(Index = 0; Index < MultipleItem->Count; Index++)
-    {
-        if (IsEqualGUIDAligned(NodeType, Guid))
-        {
-            /* found matching guid */
-            return Index;
-        }
-        Guid++;
-    }
-    return MAXULONG;
-}
-
-ULONG
-GetControlTypeFromTopologyNode(
-    IN LPGUID NodeType)
-{
-    if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_AGC))
-    {
-        // automatic gain control
-        return MIXERCONTROL_CONTROLTYPE_ONOFF;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_LOUDNESS))
-    {
-        // loudness control
-        return MIXERCONTROL_CONTROLTYPE_LOUDNESS;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE ))
-    {
-        // mute control
-        return MIXERCONTROL_CONTROLTYPE_MUTE;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_TONE))
-    {
-        // tpne control
-        //FIXME
-        // MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported
-        // MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported
-        // MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported
-        UNIMPLEMENTED;
-        return MIXERCONTROL_CONTROLTYPE_ONOFF;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_VOLUME))
-    {
-        // volume control
-        return MIXERCONTROL_CONTROLTYPE_VOLUME;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_PEAKMETER))
-    {
-        // peakmeter control
-        return MIXERCONTROL_CONTROLTYPE_PEAKMETER;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
-    {
-        // mux control
-        return MIXERCONTROL_CONTROLTYPE_MUX;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX))
-    {
-        // mux control
-        return MIXERCONTROL_CONTROLTYPE_MUX;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE))
-    {
-        // stero wide control
-        return MIXERCONTROL_CONTROLTYPE_FADER;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_CHORUS))
-    {
-        // chorus control
-        return MIXERCONTROL_CONTROLTYPE_FADER;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_REVERB))
-    {
-        // reverb control
-        return MIXERCONTROL_CONTROLTYPE_FADER;
-    }
-    else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_SUPERMIX))
-    {
-        // supermix control
-        // MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported 
-        UNIMPLEMENTED;
-        return MIXERCONTROL_CONTROLTYPE_VOLUME;
-    }
-    UNIMPLEMENTED
-    return 0;
-}
-
-NTSTATUS
-GetPhysicalConnection(
-    IN PFILE_OBJECT FileObject,
-    IN ULONG PinId,
-    OUT PKSPIN_PHYSICALCONNECTION *OutConnection)
-{
-    KSP_PIN Pin;
-    NTSTATUS Status;
-    ULONG BytesReturned;
-    PKSPIN_PHYSICALCONNECTION Connection;
-
-    /* setup the request */
-    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-    Pin.Property.Id = KSPROPERTY_PIN_PHYSICALCONNECTION;
-    Pin.Property.Set = KSPROPSETID_Pin;
-    Pin.PinId = PinId;
-
-    /* query the pin for the physical connection */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
-
-    if (Status == STATUS_NOT_FOUND)
-    {
-        /* pin does not have a physical connection */
-        return Status;
-    }
-
-    Connection = ExAllocatePool(NonPagedPool, BytesReturned);
-    if (!Connection)
-    {
-        /* not enough memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* query the pin for the physical connection */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned);
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed to query the physical connection */
-        ExFreePool(Connection);
-        return Status;
-    }
-
-    /* store connection */
-    *OutConnection = Connection;
-    return Status;
-}
-
-NTSTATUS
-GetNodeIndexes(
-    IN PKSMULTIPLE_ITEM MultipleItem,
-    IN ULONG NodeIndex,
-    IN ULONG bNode,
-    IN ULONG bFrom,
-    OUT PULONG NodeReferenceCount,
-    OUT PULONG *NodeReference)
-{
-    ULONG Index, Count = 0;
-    PKSTOPOLOGY_CONNECTION Connection;
-    PULONG Refs;
-
-    /* KSMULTIPLE_ITEM is followed by several KSTOPOLOGY_CONNECTION */
-    Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
-
-    /* first count all referenced nodes */
-    for(Index = 0; Index < MultipleItem->Count; Index++)
-    {
-        //DbgPrint("FromPin %u FromNode %u ToPin %u ToNode %u\n", Connection->FromNodePin, Connection->FromNode, Connection->ToNodePin, Connection->ToNode);
-        if (bNode)
-        {
-            if (bFrom)
-            {
-                if (Connection->FromNode == NodeIndex)
-                {
-                    /* node id has a connection */
-                    Count++;
-                }
-            }
-            else
-            {
-                if (Connection->ToNode == NodeIndex)
-                {
-                    /* node id has a connection */
-                    Count++;
-                }
-            }
-        }
-        else
-        {
-            if (bFrom)
-            {
-                if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
-                {
-                    /* node id has a connection */
-                    Count++;
-                }
-            }
-            else
-            {
-                if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
-                {
-                    /* node id has a connection */
-                    Count++;
-                }
-            }
-        }
-
-
-        /* move to next connection */
-        Connection++;
-    }
-
-    ASSERT(Count != 0);
-
-    /* now allocate node index array */
-    Refs = ExAllocatePool(NonPagedPool, sizeof(ULONG) * Count);
-    if (!Refs)
-    {
-        /* not enough memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* clear node index array */
-    RtlZeroMemory(Refs, Count * sizeof(ULONG));
-
-    Count = 0;
-    Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
-    for(Index = 0; Index < MultipleItem->Count; Index++)
-    {
-        if (bNode)
-        {
-            if (bFrom)
-            {
-                if (Connection->FromNode == NodeIndex)
-                {
-                    /* node id has a connection */
-                    Refs[Count] = Index;
-                    Count++;
-                }
-            }
-            else
-            {
-                if (Connection->ToNode == NodeIndex)
-                {
-                    /* node id has a connection */
-                    Refs[Count] = Index;
-                    Count++;
-                }
-            }
-        }
-        else
-        {
-            if (bFrom)
-            {
-                if (Connection->FromNodePin == NodeIndex && Connection->FromNode == KSFILTER_NODE)
-                {
-                    /* node id has a connection */
-                    Refs[Count] = Index;
-                    Count++;
-                }
-            }
-            else
-            {
-                if (Connection->ToNodePin == NodeIndex && Connection->ToNode == KSFILTER_NODE)
-                {
-                    /* node id has a connection */
-                    Refs[Count] = Index;
-                    Count++;
-                }
-            }
-        }
-
-        /* move to next connection */
-        Connection++;
-    }
-
-    /* store result */
-    *NodeReference = Refs;
-    *NodeReferenceCount = Count;
-
-    return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-GetTargetPinsByNodeConnectionIndex(
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG bUpDirection,
-    IN ULONG NodeConnectionIndex,
-    OUT PULONG Pins)
-{
-    PKSTOPOLOGY_CONNECTION Connection;
-    ULONG PinId, NodeConnectionCount, Index;
-    PULONG NodeConnection;
-    NTSTATUS Status;
-
-
-    /* sanity check */
-    ASSERT(NodeConnectionIndex < NodeConnections->Count);
-
-    Connection = (PKSTOPOLOGY_CONNECTION)(NodeConnections + 1);
-
-    DPRINT("FromNode %u FromNodePin %u -> ToNode %u ToNodePin %u\n", Connection[NodeConnectionIndex].FromNode, Connection[NodeConnectionIndex].FromNodePin, Connection[NodeConnectionIndex].ToNode, Connection[NodeConnectionIndex].ToNodePin );
-
-    if ((Connection[NodeConnectionIndex].ToNode == KSFILTER_NODE && bUpDirection == FALSE) ||
-        (Connection[NodeConnectionIndex].FromNode == KSFILTER_NODE && bUpDirection == TRUE))
-    {
-        /* iteration stops here */
-       if (bUpDirection)
-           PinId = Connection[NodeConnectionIndex].FromNodePin;
-       else
-           PinId = Connection[NodeConnectionIndex].ToNodePin;
-
-       DPRINT("GetTargetPinsByNodeIndex FOUND Target Pin %u Parsed %u\n", PinId, Pins[PinId]);
-
-       /* mark pin index as a target pin */
-       Pins[PinId] = TRUE;
-       return STATUS_SUCCESS;
-    }
-
-    /* get all node indexes referenced by that node */
-    if (bUpDirection)
-    {
-        Status = GetNodeIndexes(NodeConnections, Connection[NodeConnectionIndex].FromNode, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
-    }
-    else
-    {
-        Status = GetNodeIndexes(NodeConnections, Connection[NodeConnectionIndex].ToNode, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
-    }
-
-    if (NT_SUCCESS(Status))
-    {
-        for(Index = 0; Index < NodeConnectionCount; Index++)
-        {
-            /* iterate recursively into the nodes */
-            Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins);
-            ASSERT(Status == STATUS_SUCCESS);
-        }
-        /* free node connection indexes */
-        ExFreePool(NodeConnection);
-    }
-
-    return Status;
-}
-
-
-
-NTSTATUS
-GetTargetPins(
-    PKSMULTIPLE_ITEM NodeTypes,
-    PKSMULTIPLE_ITEM NodeConnections,
-    IN ULONG NodeIndex,
-    IN ULONG bUpDirection,
-    PULONG Pins,
-    ULONG PinCount)
-{
-    ULONG NodeConnectionCount, Index;
-    NTSTATUS Status;
-    PULONG NodeConnection;
-
-    /* sanity check */
-    ASSERT(NodeIndex != (ULONG)-1);
-
-    /* get all node indexes referenced by that pin */
-    if (bUpDirection)
-        Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
-    else
-        Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
-
-    DPRINT("NodeIndex %u Status %x Count %u\n", NodeIndex, Status, NodeConnectionCount);
-
-    if (NT_SUCCESS(Status))
-    {
-        for(Index = 0; Index < NodeConnectionCount; Index++)
-        {
-            Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins);
-            ASSERT(Status == STATUS_SUCCESS);
-        }
-        ExFreePool(NodeConnection);
-    }
-
-    return Status;
-}
-
-PULONG
-AllocatePinArray(
-    ULONG PinCount)
-{
-    PULONG Pins = ExAllocatePool(NonPagedPool, PinCount * sizeof(ULONG));
-    if (!Pins)
-        return NULL;
-
-    RtlZeroMemory(Pins, sizeof(ULONG) * PinCount);
-
-    return Pins;
-}
-
-PKSTOPOLOGY_CONNECTION
-GetConnectionByIndex(
-    IN PKSMULTIPLE_ITEM MultipleItem,
-    IN ULONG Index)
-{
-    PKSTOPOLOGY_CONNECTION Descriptor;
-
-    ASSERT(Index < MultipleItem->Count);
-
-    Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
-    return &Descriptor[Index];
-}
-
-LPGUID
-GetNodeType(
-    IN PKSMULTIPLE_ITEM MultipleItem,
-    IN ULONG Index)
-{
-    LPGUID NodeType;
-
-    ASSERT(Index < MultipleItem->Count);
-
-    NodeType = (LPGUID)(MultipleItem + 1);
-    return &NodeType[Index];
-}
-
-NTSTATUS
-GetControlsFromPinByConnectionIndex(
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG bUpDirection,
-    IN ULONG NodeConnectionIndex,
-    OUT PULONG Nodes)
-{
-    PKSTOPOLOGY_CONNECTION CurConnection;
-    LPGUID NodeType;
-    ULONG NodeIndex;
-    NTSTATUS Status;
-    ULONG NodeConnectionCount, Index;
-    PULONG NodeConnection;
-
-
-    /* get current connection */
-    CurConnection = GetConnectionByIndex(NodeConnections, NodeConnectionIndex);
-
-    if (bUpDirection)
-        NodeIndex = CurConnection->FromNode;
-    else
-        NodeIndex = CurConnection->ToNode;
-
-    /* get target node type of current connection */
-    NodeType = GetNodeType(NodeTypes, NodeIndex);
-
-    if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_SUM) || IsEqualGUIDAligned(NodeType, &KSNODETYPE_MUX))
-    {
-        if (bUpDirection)
-        {
-            /* add the sum / mux node to destination line */
-            Nodes[NodeIndex] = TRUE;
-        }
-
-        return STATUS_SUCCESS;
-    }
-
-    /* now add the node */
-    Nodes[NodeIndex] = TRUE;
-
-
-    /* get all node indexes referenced by that node */
-    if (bUpDirection)
-    {
-        Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
-    }
-    else
-    {
-        Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
-    }
-
-    if (NT_SUCCESS(Status))
-    {
-        for(Index = 0; Index < NodeConnectionCount; Index++)
-        {
-            /* iterate recursively into the nodes */
-            Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
-            ASSERT(Status == STATUS_SUCCESS);
-        }
-        /* free node connection indexes */
-        ExFreePool(NodeConnection);
-    }
-
-    return Status;
-}
-
-NTSTATUS
-GetControlsFromPin(
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG PinId,
-    IN ULONG bUpDirection,
-    OUT PULONG Nodes)
-{
-    ULONG NodeConnectionCount, Index;
-    NTSTATUS Status;
-    PULONG NodeConnection;
-
-    /* sanity check */
-    ASSERT(PinId != (ULONG)-1);
-
-    /* get all node indexes referenced by that pin */
-    if (bUpDirection)
-        Status = GetNodeIndexes(NodeConnections, PinId, FALSE, FALSE, &NodeConnectionCount, &NodeConnection);
-    else
-        Status = GetNodeIndexes(NodeConnections, PinId, FALSE, TRUE, &NodeConnectionCount, &NodeConnection);
-
-    for(Index = 0; Index < NodeConnectionCount; Index++)
-    {
-        /* get all associated controls */
-        Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
-    }
-
-    ExFreePool(NodeConnection);
-
-    return Status;
-}
-
-NTSTATUS
-AddMixerControl(
-    IN LPMIXER_INFO MixerInfo,
-    IN PFILE_OBJECT FileObject,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG NodeIndex,
-    IN LPMIXERLINE_EXT MixerLine,
-    OUT LPMIXERCONTROLW MixerControl)
-{
-    LPGUID NodeType;
-    KSP_NODE Node;
-    ULONG BytesReturned;
-    NTSTATUS Status;
-    LPWSTR Name;
-
-    /* initialize mixer control */
-    MixerControl->cbStruct = sizeof(MIXERCONTROLW);
-    MixerControl->dwControlID = MixerInfo->ControlId;
-
-    /* get node type */
-    NodeType = GetNodeType(NodeTypes, NodeIndex);
-    /* store control type */
-    MixerControl->dwControlType = GetControlTypeFromTopologyNode(NodeType);
-
-    MixerControl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; //FIXME
-    MixerControl->cMultipleItems = 0; //FIXME
-
-    if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
-    {
-        MixerControl->Bounds.dwMinimum = 0;
-        MixerControl->Bounds.dwMaximum = 1;
-    }
-    else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
-    {
-        MixerControl->Bounds.dwMinimum = 0;
-        MixerControl->Bounds.dwMaximum = 0xFFFF;
-        MixerControl->Metrics.cSteps = 0xC0; //FIXME
-    }
-
-    /* setup request to retrieve name */
-    Node.NodeId = NodeIndex;
-    Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME;
-    Node.Property.Flags = KSPROPERTY_TYPE_GET;
-    Node.Property.Set = KSPROPSETID_Topology;
-    Node.Reserved = 0;
-
-    /* get node name size */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned);
-
-    if (Status == STATUS_BUFFER_TOO_SMALL)
-    {
-        ASSERT(BytesReturned != 0);
-        Name = ExAllocatePool(NonPagedPool, BytesReturned);
-        if (!Name)
-        {
-            /* not enough memory */
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        /* get node name */
-        Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned);
-        if (NT_SUCCESS(Status))
-        {
-            RtlMoveMemory(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
-            MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
-
-            RtlMoveMemory(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
-            MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
-        }
-
-        /* free name buffer */
-        ExFreePool(Name);
-    }
-
-    MixerInfo->ControlId++;
-#if 0
-    if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
-    {
-        KSNODEPROPERTY Property;
-        ULONG PinId = 2;
-
-        /* setup the request */
-        RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY));
-
-        Property.NodeId = NodeIndex;
-        Property.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
-        Property.Property.Flags = KSPROPERTY_TYPE_SET;
-        Property.Property.Set = KSPROPSETID_Audio;
-
-        /* get node volume level info */
-        Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY), (PVOID)&PinId, sizeof(ULONG), &BytesReturned);
-
-        DPRINT1("Status %x NodeIndex %u PinId %u\n", Status, NodeIndex, PinId);
-        //DbgBreakPoint();
-    }else
-#endif
-    if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
-    {
-        KSNODEPROPERTY_AUDIO_CHANNEL Property;
-        ULONG Length;
-        PKSPROPERTY_DESCRIPTION Desc;
-        PKSPROPERTY_MEMBERSHEADER Members;
-        PKSPROPERTY_STEPPING_LONG Range;
-
-        Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG);
-        Desc = ExAllocatePool(NonPagedPool, Length);
-        ASSERT(Desc);
-        RtlZeroMemory(Desc, Length);
-
-        /* setup the request */
-        RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL));
-
-        Property.NodeProperty.NodeId = NodeIndex;
-        Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
-        Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT;
-        Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
-
-        /* get node volume level info */
-        Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned);
-
-        if (NT_SUCCESS(Status))
-        {
-            LPMIXERVOLUME_DATA VolumeData;
-            ULONG Steps, MaxRange, Index;
-            LONG Value;
-
-            Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1);
-            Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1); //98304
-
-            DPRINT("NodeIndex %u Range Min %d Max %d Steps %x UMin %x UMax %x\n", NodeIndex, Range->Bounds.SignedMinimum, Range->Bounds.SignedMaximum, Range->SteppingDelta, Range->Bounds.UnsignedMinimum, Range->Bounds.UnsignedMaximum);
-
-            MaxRange = Range->Bounds.UnsignedMaximum  - Range->Bounds.UnsignedMinimum;
-
-            if (MaxRange)
-            {
-                ASSERT(MaxRange);
-                VolumeData = ExAllocatePool(NonPagedPool, sizeof(MIXERVOLUME_DATA));
-                if (!VolumeData)
-                    return STATUS_INSUFFICIENT_RESOURCES;
-
-                Steps = MaxRange / Range->SteppingDelta + 1;
-
-                /* store mixer control info there */
-                VolumeData->Header.dwControlID = MixerControl->dwControlID;
-                VolumeData->SignedMaximum = Range->Bounds.SignedMaximum;
-                VolumeData->SignedMinimum = Range->Bounds.SignedMinimum;
-                VolumeData->SteppingDelta = Range->SteppingDelta;
-                VolumeData->ValuesCount = Steps;
-                VolumeData->InputSteppingDelta = 0x10000 / Steps;
-
-                VolumeData->Values = ExAllocatePool(NonPagedPool, sizeof(LONG) * Steps);
-                if (!VolumeData->Values)
-                {
-                    ExFreePool(Desc);
-                    ExFreePool(VolumeData);
-
-                    return STATUS_INSUFFICIENT_RESOURCES;
-                }
-
-                Value = Range->Bounds.SignedMinimum;
-                for(Index = 0; Index < Steps; Index++)
-                {
-                    VolumeData->Values[Index] = Value;
-                    Value += Range->SteppingDelta;
-                }
-                InsertTailList(&MixerLine->LineControlsExtraData, &VolumeData->Header.Entry);
-           }
-       }
-       ExFreePool(Desc);
-    }
-
-
-    DPRINT("Status %x Name %S\n", Status, MixerControl->szName);
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-AddMixerSourceLine(
-    IN OUT LPMIXER_INFO MixerInfo,
-    IN PFILE_OBJECT FileObject,
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG DeviceIndex,
-    IN ULONG PinId,
-    IN ULONG bBridgePin,
-    IN ULONG bTargetPin)
-{
-    LPMIXERLINE_EXT SrcLine, DstLine;
-    NTSTATUS Status;
-    KSP_PIN Pin;
-    LPWSTR PinName;
-    GUID NodeType;
-    ULONG BytesReturned, ControlCount, Index;
-    PULONG Nodes;
-
-    if (!bTargetPin)
-    {
-        /* allocate src mixer line */
-        SrcLine = (LPMIXERLINE_EXT)ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_EXT));
-
-        if (!SrcLine)
-            return STATUS_INSUFFICIENT_RESOURCES;
-
-        /* zero struct */
-        RtlZeroMemory(SrcLine, sizeof(MIXERLINE_EXT));
-
-    }
-    else
-    {
-        ASSERT(!IsListEmpty(&MixerInfo->LineList));
-        SrcLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
-    }
-
-    /* get destination line */
-    DstLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
-    ASSERT(DstLine);
-
-
-    if (!bTargetPin)
-    {
-        /* initialize mixer src line */
-        SrcLine->DeviceIndex = DeviceIndex;
-        SrcLine->PinId = PinId;
-        SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
-
-        /* initialize mixer destination line */
-        SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
-        SrcLine->Line.dwDestination = 0;
-        SrcLine->Line.dwSource = DstLine->Line.cConnections;
-        SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000);
-        SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE;
-        SrcLine->Line.dwUser = 0;
-        SrcLine->Line.cChannels = DstLine->Line.cChannels;
-        SrcLine->Line.cConnections = 0;
-        SrcLine->Line.Target.dwType = 1;
-        SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
-        SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
-        SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
-        SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
-        InitializeListHead(&SrcLine->LineControlsExtraData);
-        wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
-
-    }
-
-    /* allocate a node arrary */
-    Nodes = ExAllocatePool(NonPagedPool, sizeof(ULONG) * NodeTypes->Count);
-
-    if (!Nodes)
-    {
-        /* not enough memory */
-        if (!bTargetPin)
-        {
-            ExFreePool(SrcLine);
-        }
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* clear nodes array */
-    RtlZeroMemory(Nodes, sizeof(ULONG) * NodeTypes->Count);
-
-    Status = GetControlsFromPin(NodeConnections, NodeTypes, PinId, bTargetPin, Nodes);
-    if (!NT_SUCCESS(Status))
-    {
-        /* something went wrong */
-        if (!bTargetPin)
-        {
-            ExFreePool(SrcLine);
-        }
-        ExFreePool(Nodes);
-        return Status;
-    }
-
-    /* now count all nodes controlled by that pin */
-    ControlCount = 0;
-    for(Index = 0; Index < NodeTypes->Count; Index++)
-    {
-        if (Nodes[Index])
-            ControlCount++;
-    }
-
-    /* now allocate the line controls */
-    if (ControlCount)
-    {
-        SrcLine->LineControls = ExAllocatePool(NonPagedPool, sizeof(MIXERCONTROLW) * ControlCount);
-
-        if (!SrcLine->LineControls)
-        {
-            /* no memory available */
-            if (!bTargetPin)
-            {
-                ExFreePool(SrcLine);
-            }
-            ExFreePool(Nodes);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        SrcLine->NodeIds = ExAllocatePool(NonPagedPool, sizeof(ULONG) * ControlCount);
-        if (!SrcLine->NodeIds)
-        {
-            /* no memory available */
-            ExFreePool(SrcLine->LineControls);
-            if (!bTargetPin)
-            {
-                ExFreePool(SrcLine);
-            }
-            ExFreePool(Nodes);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        /* zero line controls */
-        RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW) * ControlCount);
-        RtlZeroMemory(SrcLine->NodeIds, sizeof(ULONG) * ControlCount);
-
-        ControlCount = 0;
-        for(Index = 0; Index < NodeTypes->Count; Index++)
-        {
-            if (Nodes[Index])
-            {
-                /* store the node index for retrieving / setting details */
-                SrcLine->NodeIds[ControlCount] = Index;
-
-                Status = AddMixerControl(MixerInfo, FileObject, NodeTypes, Index, SrcLine, &SrcLine->LineControls[ControlCount]);
-                if (NT_SUCCESS(Status))
-                {
-                    /* increment control count on success */
-                    ControlCount++;
-                }
-            }
-        }
-        /* store control count */
-        SrcLine->Line.cControls = ControlCount;
-    }
-
-    /* release nodes array */
-    ExFreePool(Nodes);
-
-    /* get pin category */
-    Pin.PinId = PinId;
-    Pin.Reserved = 0;
-    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-    Pin.Property.Set = KSPROPSETID_Pin;
-    Pin.Property.Id = KSPROPERTY_PIN_CATEGORY;
-
-    /* try get pin category */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (LPVOID)&NodeType, sizeof(GUID), &BytesReturned);
-    if (NT_SUCCESS(Status))
-    {
-        //FIXME
-        //map component type
-    }
-
-    /* retrieve pin name */
-    Pin.PinId = PinId;
-    Pin.Reserved = 0;
-    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-    Pin.Property.Set = KSPROPSETID_Pin;
-    Pin.Property.Id = KSPROPERTY_PIN_NAME;
-
-    /* try get pin name size */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
-
-    if (Status != STATUS_MORE_ENTRIES)
-    {
-        SrcLine->Line.szShortName[0] = L'\0';
-        SrcLine->Line.szName[0] = L'\0';
-    }
-    else
-    {
-        PinName = (LPWSTR)ExAllocatePool(NonPagedPool, BytesReturned);
-        if (PinName)
-        {
-            /* try get pin name */
-            Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (LPVOID)PinName, BytesReturned, &BytesReturned);
-
-            if (NT_SUCCESS(Status))
-            {
-                RtlMoveMemory(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
-                SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
-
-                RtlMoveMemory(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
-                SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
-            }
-            ExFreePool(PinName);
-        }
-    }
-
-    /* insert src line */
-    if (!bTargetPin)
-    {
-        InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
-        DstLine->Line.cConnections++;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-AddMixerSourceLines(
-    IN OUT LPMIXER_INFO MixerInfo,
-    IN PFILE_OBJECT FileObject,
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN ULONG DeviceIndex,
-    IN ULONG PinsCount,
-    IN ULONG BridgePinIndex,
-    IN ULONG TargetPinIndex,
-    IN PULONG Pins)
-{
-    ULONG Index;
-    NTSTATUS Status = STATUS_SUCCESS;
-
-    for(Index = PinsCount; Index > 0; Index--)
-    {
-        if (Pins[Index-1])
-        {
-            AddMixerSourceLine(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, Index-1, (Index -1 == BridgePinIndex), (Index -1 == TargetPinIndex));
-        }
-    }
-    return Status;
-}
-
-
-
-NTSTATUS
-HandlePhysicalConnection(
-    IN OUT LPMIXER_INFO MixerInfo,
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG bInput,
-    IN PKSPIN_PHYSICALCONNECTION OutConnection)
-{
-    PULONG PinsRef = NULL, PinConnectionIndex = NULL, PinsSrcRef;
-    ULONG PinsRefCount, Index, PinConnectionIndexCount, DeviceIndex;
-    NTSTATUS Status;
-    HANDLE hDevice = NULL;
-    PFILE_OBJECT FileObject = NULL;
-    PKSMULTIPLE_ITEM NodeTypes = NULL;
-    PKSMULTIPLE_ITEM NodeConnections = NULL;
-    PULONG MixerControls;
-    ULONG MixerControlsCount;
-
-
-    /* open the connected filter */
-    Status = OpenDevice(OutConnection->SymbolicLinkName, &hDevice, &FileObject);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("OpenDevice failed with %x\n", Status);
-        return Status;
-    }
-
-    /* get device index */
-    DeviceIndex = GetDeviceIndexFromPnpName(DeviceObject, OutConnection->SymbolicLinkName);
-
-    /* get connected filter pin count */
-    PinsRefCount = GetPinCount(FileObject);
-    ASSERT(PinsRefCount);
-
-    PinsRef = AllocatePinArray(PinsRefCount);
-    if (!PinsRef)
-    {
-        /* no memory */
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto cleanup;
-    }
-
-    /* get topology node types */
-    Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("GetFilterNodeProperty failed with %x\n", Status);
-        goto cleanup;
-    }
-
-    /* get topology connections */
-    Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("GetFilterNodeProperty failed with %x\n", Status);
-        goto cleanup;
-    }
-    /*  gets connection index of the bridge pin which connects to a node */
-    DPRINT("Pin %u\n", OutConnection->Pin);
-    Status = GetNodeIndexes(NodeConnections, OutConnection->Pin, FALSE, !bInput, &PinConnectionIndexCount, &PinConnectionIndex);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("GetNodeIndexes failed with %x\n", Status);
-        goto cleanup;
-    }
-
-    /* there should be no split in the bride pin */
-    ASSERT(PinConnectionIndexCount == 1);
-
-    /* find all target pins of this connection */
-    Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, FALSE, PinConnectionIndex[0], PinsRef);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("GetTargetPinsByNodeConnectionIndex failed with %x\n", Status);
-        goto cleanup;
-    }
-
-    for(Index = 0; Index < PinsRefCount; Index++)
-    {
-        if (PinsRef[Index])
-        {
-
-            /* found a target pin, now get all references */
-            Status = GetNodeIndexes(NodeConnections, Index, FALSE, FALSE, &MixerControlsCount, &MixerControls);
-            if (!NT_SUCCESS(Status))
-                break;
-
-            /* sanity check */
-            ASSERT(MixerControlsCount == 1);
-
-
-            PinsSrcRef = AllocatePinArray(PinsRefCount);
-            if (!PinsSrcRef)
-            {
-                /* no memory */
-                ExFreePool(MixerControls);
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                goto cleanup;
-            }
-            /* now get all connected source pins */
-            Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, TRUE, MixerControls[0], PinsSrcRef);
-            if (!NT_SUCCESS(Status))
-            {
-                /* no memory */
-                ExFreePool(MixerControls);
-                ExFreePool(PinsSrcRef);
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                goto cleanup;
-            }
-
-            /* add pins from target line */
-            if (!bInput)
-            {
-                // dont add bridge pin for input mixers
-                PinsSrcRef[Index] = TRUE;
-                PinsSrcRef[OutConnection->Pin] = TRUE;
-            }
-            PinsSrcRef[OutConnection->Pin] = TRUE;
-
-            Status = AddMixerSourceLines(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
-
-            ExFreePool(MixerControls);
-            ExFreePool(PinsSrcRef);
-        }
-    }
-
-cleanup:
-
-    if (PinsRef)
-        ExFreePool(PinsRef);
-
-    if (NodeConnections)
-        ExFreePool(NodeConnections);
-
-    if (NodeTypes)
-        ExFreePool(NodeTypes);
-
-    if (FileObject)
-        ObDereferenceObject(FileObject);
-
-    if (hDevice)
-        ZwClose(hDevice);
-
-    if (PinConnectionIndex)
-        ExFreePool(PinConnectionIndex);
-
-
-    return Status;
-}
-
-
-
-NTSTATUS
-InitializeMixer(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG DeviceIndex,
-    IN OUT LPMIXER_INFO MixerInfo,
-    IN HANDLE hDevice,
-    IN PFILE_OBJECT FileObject,
-    IN ULONG PinCount,
-    IN PKSMULTIPLE_ITEM NodeTypes,
-    IN PKSMULTIPLE_ITEM NodeConnections,
-    IN ULONG NodeIndex,
-    IN ULONG bInput)
-{
-    WCHAR Buffer[100];
-    LPWSTR Device;
-    NTSTATUS Status;
-    PULONG Pins;
-    ULONG Index;
-    PKSPIN_PHYSICALCONNECTION OutConnection;
-    LPMIXERLINE_EXT DestinationLine;
-
-    DestinationLine = ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_EXT));
-    if (!DestinationLine)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* intialize mixer caps */
-    MixerInfo->MixCaps.wMid = MM_MICROSOFT; //FIXME
-    MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; //FIXME
-    MixerInfo->MixCaps.vDriverVersion = 1; //FIXME
-    MixerInfo->MixCaps.fdwSupport = 0;
-    MixerInfo->MixCaps.cDestinations = 1;
-    MixerInfo->DeviceIndex = DeviceIndex;
-
-    /* get target pnp name */
-    Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, &Device);
-    if (NT_SUCCESS(Status))
-    {
-        /* find product name */
-        Status = FindProductName(Device, sizeof(Buffer) / sizeof(WCHAR), Buffer);
-        if (NT_SUCCESS(Status))
-        {
-            if (bInput)
-                wcscat(Buffer, L" Input");
-            else
-                wcscat(Buffer, L" output");
-            RtlMoveMemory(MixerInfo->MixCaps.szPname, Buffer, min(MAXPNAMELEN, wcslen(Buffer)+1) * sizeof(WCHAR));
-            MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
-        }
-        ExFreePool(Device);
-    }
-
-    /* initialize mixer destination line */
-    RtlZeroMemory(DestinationLine, sizeof(MIXERLINE_EXT));
-    DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
-    DestinationLine->Line.dwSource = MAXULONG;
-    DestinationLine->Line.dwLineID = DESTINATION_LINE;
-    DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
-    DestinationLine->Line.dwUser = 0;
-    DestinationLine->Line.dwComponentType = (bInput == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
-    DestinationLine->Line.cChannels = 2; //FIXME
-    wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME
-    wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME
-    DestinationLine->Line.Target.dwType = (bInput == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
-    DestinationLine->Line.Target.dwDeviceID = !bInput;
-    DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
-    DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
-    DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
-    wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
-
-    /* initialize source line list */
-    InitializeListHead(&MixerInfo->LineList);
-    InitializeListHead(&DestinationLine->LineControlsExtraData);
-
-    /* insert destination line */
-    InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry);
-
-    Pins = AllocatePinArray(PinCount);
-    if (!Pins)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    if (bInput)
-    {
-        Status = GetTargetPins(NodeTypes, NodeConnections, NodeIndex, TRUE, Pins, PinCount);
-    }
-    else
-    {
-        Status = GetTargetPins(NodeTypes, NodeConnections, NodeIndex, FALSE, Pins, PinCount);
-    }
-
-    for(Index = 0; Index < PinCount; Index++)
-    {
-        if (Pins[Index])
-        {
-            Status = GetPhysicalConnection(FileObject, Index, &OutConnection);
-            if (NT_SUCCESS(Status))
-            {
-                Status = HandlePhysicalConnection(MixerInfo, DeviceObject, bInput, OutConnection);
-                ExFreePool(OutConnection);
-            }
-        }
-    }
-    ExFreePool(Pins);
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-WdmAudMixerInitialize(
-    IN PDEVICE_OBJECT DeviceObject)
-{
-    ULONG DeviceCount, Index, Count, NodeIndex, PinCount;
-    NTSTATUS Status;
-    HANDLE hDevice;
-    PFILE_OBJECT FileObject;
-    PKSMULTIPLE_ITEM NodeTypes, NodeConnections;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-
-    /* get number of devices */
-    DeviceCount = GetSysAudioDeviceCount(DeviceObject);
-
-    if (!DeviceCount)
-    {
-        /* no audio devices available atm */
-        DeviceExtension->MixerInfoCount = 0;
-        DeviceExtension->MixerInfo = NULL;
-        return STATUS_SUCCESS;
-    }
-
-    /* each virtual audio device can at most have an input + output mixer */
-    DeviceExtension->MixerInfo = ExAllocatePool(NonPagedPool, sizeof(MIXER_INFO) * DeviceCount * 2);
-    if (!DeviceExtension->MixerInfo)
-    {
-        /* not enough memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* clear mixer info */
-    RtlZeroMemory(DeviceExtension->MixerInfo, sizeof(MIXER_INFO) * DeviceCount * 2);
-
-    Index = 0;
-    Count = 0;
-    do
-    {
-        /* open the virtual audio device */
-        Status = OpenSysAudioDeviceByIndex(DeviceObject, Index, &hDevice, &FileObject);
-
-        if (NT_SUCCESS(Status))
-        {
-            /* retrieve all available node types */
-            Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
-            if (!NT_SUCCESS(Status))
-            {
-                ObDereferenceObject(FileObject);
-                ZwClose(hDevice);
-                break;
-            }
-
-            Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
-            if (!NT_SUCCESS(Status))
-            {
-                ObDereferenceObject(FileObject);
-                ZwClose(hDevice);
-                ExFreePool(NodeTypes);
-                break;
-            }
-
-            /* get num of pins */
-            PinCount = GetPinCount(FileObject);
-            /* get the first available dac node index */
-            NodeIndex = GetNodeTypeIndex(NodeTypes, (LPGUID)&KSNODETYPE_DAC);
-            if (NodeIndex != (ULONG)-1)
-            {
-                Status = InitializeMixer(DeviceObject, Index, &DeviceExtension->MixerInfo[Count], hDevice, FileObject, PinCount, NodeTypes, NodeConnections, NodeIndex, FALSE);
-                if (NT_SUCCESS(Status))
-                {
-                    /* increment mixer offset */
-                    Count++;
-                }
-            }
-
-            /* get the first available adc node index */
-            NodeIndex = GetNodeTypeIndex(NodeTypes, (LPGUID)&KSNODETYPE_ADC);
-            if (NodeIndex != (ULONG)-1)
-            {
-                Status = InitializeMixer(DeviceObject, Index, &DeviceExtension->MixerInfo[Count], hDevice, FileObject, PinCount, NodeTypes, NodeConnections, NodeIndex, TRUE);
-                if (NT_SUCCESS(Status))
-                {
-                    /* increment mixer offset */
-                    Count++;
-                }
-            }
-
-            /* free node connections array */
-            ExFreePool(NodeTypes);
-            ExFreePool(NodeConnections);
-
-            /* close virtual audio device */
-            ObDereferenceObject(FileObject);
-            ZwClose(hDevice);
-
-        }
-        /* increment virtual audio device index */
-        Index++;
-    }while(Index < DeviceCount);
-
-    /* store mixer count */
-    DeviceExtension->MixerInfoCount = Count;
-
-    return Status;
-}
-
-
-
-NTSTATUS
-WdmAudMixerCapabilities(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo,
-    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
-{
-    if ((ULONG)DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
-    {
-        /* invalid parameter */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* copy cached mixer caps */
-    RtlMoveMemory(&DeviceInfo->u.MixCaps, &DeviceExtension->MixerInfo[(ULONG)DeviceInfo->DeviceIndex].MixCaps, sizeof(MIXERCAPSW));
-
-    return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-WdmAudControlOpenMixer(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    ULONG Index;
-    PWDMAUD_HANDLE Handels;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    NTSTATUS Status;
-    PKEVENT EventObject = NULL;
-
-    DPRINT("WdmAudControlOpenMixer\n");
-
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
-    {
-        /* mixer index doesnt exist */
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-    }
-
-    if (DeviceInfo->u.hNotifyEvent)
-    {
-        Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
-
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
-            DbgBreakPoint();
-            return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-        }
-    }
-
-
-    for(Index = 0; Index < ClientInfo->NumPins; Index++)
-    {
-        if (ClientInfo->hPins[Index].Handle == (HANDLE)DeviceInfo->DeviceIndex && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
-        {
-            /* re-use pseudo handle */
-            DeviceInfo->hDevice = (HANDLE)DeviceInfo->DeviceIndex;
-            ClientInfo->hPins[Index].NotifyEvent = EventObject;
-            return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-        }
-    }
-
-    Handels = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
-
-    if (Handels)
-    {
-        if (ClientInfo->NumPins)
-        {
-            RtlMoveMemory(Handels, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
-            ExFreePool(ClientInfo->hPins);
-        }
-
-        ClientInfo->hPins = Handels;
-        ClientInfo->hPins[ClientInfo->NumPins].Handle = (HANDLE)DeviceInfo->DeviceIndex;
-        ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
-        ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
-        ClientInfo->NumPins++;
-    }
-    else
-    {
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    DeviceInfo->hDevice = (HANDLE)DeviceInfo->DeviceIndex;
-
-    return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-}
-
-NTSTATUS
-NTAPI
-WdmAudGetLineInfo(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    LPMIXERLINE_EXT MixerLineSrc;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
-
-    if (DeviceInfo->Flags == MIXER_GETLINEINFOF_DESTINATION)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        if (DeviceInfo->u.MixLine.dwDestination != 0)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-        MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DESTINATION_LINE);
-        ASSERT(MixerLineSrc);
-
-        /* copy cached data */
-        RtlCopyMemory(&DeviceInfo->u.MixLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
-        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    else if (DeviceInfo->Flags == MIXER_GETLINEINFOF_SOURCE)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DESTINATION_LINE);
-        ASSERT(MixerLineSrc);
-
-        if (DeviceInfo->u.MixLine.dwSource >= MixerLineSrc->Line.cConnections)
-        {
-            DPRINT1("dwSource %u > Destinations %u\n", DeviceInfo->u.MixLine.dwSource, MixerLineSrc->Line.cConnections);
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLine(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixLine.dwSource);
-        if (MixerLineSrc)
-        {
-            DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
-            RtlCopyMemory(&DeviceInfo->u.MixLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
-        }
-        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    else if (DeviceInfo->Flags == MIXER_GETLINEINFOF_LINEID)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixLine.dwLineID);
-        if (!MixerLineSrc)
-        {
-            DPRINT1("Failed to find Line with id %u\n", DeviceInfo->u.MixLine.dwLineID);
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        /* copy cached data */
-        RtlCopyMemory(&DeviceInfo->u.MixLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
-        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    else if (DeviceInfo->Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLineByComponentType(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixLine.dwComponentType);
-        if (!MixerLineSrc)
-        {
-            DPRINT1("Failed to find component type %x\n", DeviceInfo->u.MixLine.dwComponentType);
-            return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-        }
-
-        ASSERT(MixerLineSrc);
-
-        /* copy cached data */
-        RtlCopyMemory(&DeviceInfo->u.MixLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
-        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-    }
-
-    DPRINT("Flags %x\n", DeviceInfo->Flags);
-    UNIMPLEMENTED;
-
-    //DbgBreakPoint();
-    return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
-
-}
-
-NTSTATUS
-NTAPI
-WdmAudGetLineControls(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    LPMIXERLINE_EXT MixerLineSrc;
-    LPMIXERCONTROLW MixerControl;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    ULONG Index;
-    NTSTATUS Status;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
-
-    if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ALL)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwLineID);
-        ASSERT(MixerLineSrc);
-        if (MixerLineSrc)
-        {
-            RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERCONTROLW));
-        }
-        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    else if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-
-        MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwLineID);
-        ASSERT(MixerLineSrc);
-
-        Index = 0;
-        for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
-        {
-            DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType);
-            if (DeviceInfo->u.MixControls.dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
-            {
-                RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
-                return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-            }
-        }
-        DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", DeviceInfo->u.MixControls.dwControlType, DeviceInfo->u.MixControls.dwLineID, MixerLineSrc->Line.cControls);
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
-    }
-    else if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ONEBYID)
-    {
-        if ((ULONG_PTR)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
-        {
-            /* invalid parameter */
-            return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-        }
-        DPRINT("MixerId %u ControlId %u\n",(ULONG_PTR)DeviceInfo->hDevice,  DeviceInfo->u.MixControls.dwControlID);
-        Status = GetMixerControlById(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwControlID, NULL, &MixerControl, NULL);
-        if (NT_SUCCESS(Status))
-        {
-            RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerControl, sizeof(MIXERCONTROLW));
-        }
-        return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
-    }
-
-    UNIMPLEMENTED;
-    //DbgBreakPoint();
-    return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
-
-}
-
-NTSTATUS
-SetGetControlDetails(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG DeviceId,
-    IN ULONG NodeId,
-    IN PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN ULONG bSet,
-    IN ULONG PropertyId,
-    IN ULONG Channel,
-    IN PLONG InputValue)
-{
-    KSNODEPROPERTY_AUDIO_CHANNEL Property;
-    NTSTATUS Status;
-    HANDLE hDevice;
-    PFILE_OBJECT FileObject;
-    LONG Value;
-    ULONG BytesReturned;
-
-    if (bSet)
-        Value = *InputValue;
-
-    /* open virtual audio device */
-    Status = OpenSysAudioDeviceByIndex(DeviceObject, DeviceId, &hDevice, &FileObject);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        return Status;
-    }
-
-    /* setup the request */
-    RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL));
-
-    Property.NodeProperty.NodeId = NodeId;
-    Property.NodeProperty.Property.Id = PropertyId;
-    Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY;
-    Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
-    Property.Channel = Channel;
-
-    if (bSet)
-        Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_SET;
-    else
-        Property.NodeProperty.Property.Flags |= KSPROPERTY_TYPE_GET;
-
-    /* send the request */
-    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Value, sizeof(LONG), &BytesReturned);
-
-    ObDereferenceObject(FileObject);
-    ZwClose(hDevice);
-
-    if (!bSet)
-    {
-        *InputValue = Value;
-    }
-
-    DPRINT("Status %x bSet %u NodeId %u Value %d PropertyId %u\n", Status, bSet, NodeId, Value, PropertyId);
-    return Status;
-}
-
-NTSTATUS
-NotifyWdmAudClients(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG NotificationType,
-    IN HANDLE hMixer,
-    IN ULONG Value)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    PLIST_ENTRY Entry;
-    PWDMAUD_CLIENT CurClient;
-    PMIXER_EVENT Event;
-    KIRQL OldIrql;
-    ULONG Index;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* acquire client context lock */
-    KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
-
-    /* point to first entry */
-    Entry = DeviceExtension->WdmAudClientList.Flink;
-
-    /* iterate through all clients */
-    while(Entry != &DeviceExtension->WdmAudClientList)
-    {
-        /* get client context */
-        CurClient = (PWDMAUD_CLIENT)CONTAINING_RECORD(Entry, WDMAUD_CLIENT, Entry);
-
-        /* now iterate through all pins and try to find an matching handle */
-        for(Index = 0; Index < CurClient->NumPins; Index++)
-        {
-            if (CurClient->hPins[Index].Handle == hMixer && CurClient->hPins[Index].Type == MIXER_DEVICE_TYPE && CurClient->hPins[Index].NotifyEvent)
-            {
-                /* allocate event entry */
-                Event = (PMIXER_EVENT)ExAllocatePool(NonPagedPool, sizeof(MIXER_EVENT));
-                if (!Event)
-                {
-                    /* no memory */
-                    return STATUS_INSUFFICIENT_RESOURCES;
-                }
-
-                /* initialize event entry */
-                Event->hMixer = hMixer;
-                Event->NotificationType = NotificationType;
-                Event->Value = Value;
-
-                /* insert event entry */
-                InsertTailList(&CurClient->MixerEventList, &Event->Entry);
-
-                DPRINT("Notifying %p hMixer %p Value %x NotificationType %u\n", CurClient->hPins[Index].NotifyEvent, hMixer, Value, NotificationType);
-
-                /* now signal the event */
-                KeSetEvent(CurClient->hPins[Index].NotifyEvent, 0, FALSE);
-
-
-
-                /* search next client */
-                break;
-            }
-        }
-
-        /* move to next client */
-        Entry = Entry->Flink;
-    }
-
-    /* release client context lock */
-    KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
-
-    /* done */
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-SetGetMuteControlDetails(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG DeviceId,
-    IN ULONG NodeId,
-    IN ULONG dwLineID,
-    IN PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN ULONG bSet)
-{
-    LPMIXERCONTROLDETAILS_BOOLEAN Input;
-    LONG Value;
-    NTSTATUS Status;
-
-    if (DeviceInfo->u.MixDetails.cbDetails != sizeof(MIXERCONTROLDETAILS_BOOLEAN))
-        return STATUS_INVALID_PARAMETER;
-
-    /* get input */
-    Input = (LPMIXERCONTROLDETAILS_BOOLEAN)DeviceInfo->u.MixDetails.paDetails;
-
-    /* FIXME SEH */
-    if (bSet)
-        Value = Input->fValue;
-
-    /* set control details */
-    Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
-
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    /* FIXME SEH */
-    if (!bSet)
-    {
-        Input->fValue = Value;
-        return Status;
-    }
-    else
-    {
-        /* notify clients of a line change */
-        NotifyWdmAudClients(DeviceObject, MM_MIXM_LINE_CHANGE, DeviceInfo->hDevice, dwLineID);
-    }
-
-
-    return Status;
-}
-
-ULONG
-GetVolumeControlIndex(
-    LPMIXERVOLUME_DATA VolumeData,
-    LONG Value)
-{
-    ULONG Index;
-
-    for(Index = 0; Index < VolumeData->ValuesCount; Index++)
-    {
-        if (VolumeData->Values[Index] > Value)
-        {
-            return VolumeData->InputSteppingDelta * Index;
-        }
-    }
-    return VolumeData->InputSteppingDelta * (VolumeData->ValuesCount-1);
-}
-
-
-NTSTATUS
-SetGetVolumeControlDetails(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG DeviceId,
-    IN ULONG NodeId,
-    IN PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN ULONG bSet,
-    LPMIXERCONTROLW MixerControl,
-    LPMIXERLINE_EXT MixerLine)
-{
-    LPMIXERCONTROLDETAILS_UNSIGNED Input;
-    LONG Value, Index, Channel = 0;
-    ULONG dwValue;
-    NTSTATUS Status;
-    LPMIXERVOLUME_DATA VolumeData;
-
-    if (DeviceInfo->u.MixDetails.cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED))
-        return STATUS_INVALID_PARAMETER;
-
-    VolumeData = (LPMIXERVOLUME_DATA)GetMixerControlDataById(&MixerLine->LineControlsExtraData, MixerControl->dwControlID);
-    if (!VolumeData)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-
-    /* get input */
-    Input = (LPMIXERCONTROLDETAILS_UNSIGNED)DeviceInfo->u.MixDetails.paDetails;
-
-    if (bSet)
-    {
-        /* FIXME SEH */
-        Value = Input->dwValue;
-        Index = Value / VolumeData->InputSteppingDelta;
-
-        if (Index >= VolumeData->ValuesCount)
-        {
-            DPRINT1("Index %u out of bounds %u \n", Index, VolumeData->ValuesCount);
-            DbgBreakPoint();
-            return STATUS_INVALID_PARAMETER;
-        }
-
-        Value = VolumeData->Values[Index];
-    }
-
-    /* set control details */
-    if (bSet)
-    {
-        Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
-        Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
-    }
-    else
-    {
-        Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
-    }
-
-    if (!bSet)
-    {
-        dwValue = GetVolumeControlIndex(VolumeData, (LONG)Value);
-        /* FIXME SEH */
-        Input->dwValue = dwValue;
-    }
-    else
-    {
-        /* notify clients of a line change */
-        NotifyWdmAudClients(DeviceObject, MM_MIXM_CONTROL_CHANGE, DeviceInfo->hDevice, MixerControl->dwControlID);
-    }
-    return Status;
-}
-
-NTSTATUS
-NTAPI
-WdmAudGetMixerEvent(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    PMIXER_EVENT Event = NULL;
-    PLIST_ENTRY Entry;
-    KIRQL OldIrql;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* acquire client context lock */
-    KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql);
-
-    /* point to first entry */
-    Entry = ClientInfo->MixerEventList.Flink;
-
-    while(Entry != &ClientInfo->MixerEventList)
-    {
-        /* get mixer event */
-        Event = (PMIXER_EVENT)CONTAINING_RECORD(Entry, MIXER_EVENT, Entry);
-
-        if (Event->hMixer == DeviceInfo->hDevice)
-        {
-            /* found an event for that particular device */
-            RemoveEntryList(&Event->Entry);
-            break;
-        }
-
-        /* no match found */
-        Event = NULL;
-
-        /* move to next entry */
-        Entry = Entry->Flink;
-    }
-
-    /* release client context lock */
-    KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
-
-    if (!Event)
-    {
-        /* no events available */
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-    }
-
-    /* store event result */
-    DeviceInfo->u.MixerEvent.hMixer = Event->hMixer;
-    DeviceInfo->u.MixerEvent.NotificationType = Event->NotificationType;
-    DeviceInfo->u.MixerEvent.Value = Event->Value;
-
-    /* free event info */
-    ExFreePool(Event);
-
-    /* done */
-    return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-}
-
-NTSTATUS
-NTAPI
-WdmAudSetControlDetails(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    LPMIXERLINE_EXT MixerLine;
-    LPMIXERCONTROLW MixerControl;
-    ULONG NodeId;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    NTSTATUS Status;
-
-    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
-
-    DPRINT("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", 
-            DeviceInfo->u.MixDetails.cbStruct, sizeof(MIXERCONTROLDETAILS), DeviceInfo->u.MixDetails.dwControlID, DeviceInfo->u.MixDetails.cChannels, DeviceInfo->u.MixDetails.cMultipleItems, DeviceInfo->u.MixDetails.cbDetails, DeviceInfo->u.MixDetails.paDetails, DeviceInfo->Flags);
-
-    if (DeviceInfo->Flags & MIXER_GETCONTROLDETAILSF_LISTTEXT)
-    {
-        UNIMPLEMENTED;
-        return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
-    }
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* get mixer control */
-     Status = GetMixerControlById(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixDetails.dwControlID, &MixerLine, &MixerControl, &NodeId);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("MixerControl %x not found\n", DeviceInfo->u.MixDetails.dwControlID);
-        return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-    }
-
-    Status = STATUS_NOT_IMPLEMENTED;
-    DPRINT("dwLineId %x dwControlID %x dwControlType %x\n", MixerLine->Line.dwLineID, MixerControl->dwControlID, MixerControl->dwControlType);
-    if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
-    {
-        /* send the request */
-        Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, MixerLine->Line.dwLineID, DeviceInfo, TRUE);
-    }
-    else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
-    {
-        Status = SetGetVolumeControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, TRUE, MixerControl, MixerLine);
-    }
-    return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
-
-}
-
-NTSTATUS
-NTAPI
-WdmAudGetControlDetails(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    LPMIXERLINE_EXT MixerLine;
-    LPMIXERCONTROLW MixerControl;
-    ULONG NodeId;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    NTSTATUS Status;
-
-    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
-
-    DPRINT("cbStruct %u Expected %u dwControlID %u cChannels %u cMultipleItems %u cbDetails %u paDetails %p Flags %x\n", 
-            DeviceInfo->u.MixDetails.cbStruct, sizeof(MIXERCONTROLDETAILS), DeviceInfo->u.MixDetails.dwControlID, DeviceInfo->u.MixDetails.cChannels, DeviceInfo->u.MixDetails.cMultipleItems, DeviceInfo->u.MixDetails.cbDetails, DeviceInfo->u.MixDetails.paDetails, DeviceInfo->Flags);
-
-    if (DeviceInfo->Flags & MIXER_GETCONTROLDETAILSF_LISTTEXT)
-    {
-        UNIMPLEMENTED;
-        return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
-    }
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* get mixer control */
-     Status = GetMixerControlById(&DeviceExtension->MixerInfo[(ULONG_PTR)DeviceInfo->hDevice], DeviceInfo->u.MixDetails.dwControlID, &MixerLine, &MixerControl, &NodeId);
-
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("MixerControl %x not found\n", DeviceInfo->u.MixDetails.dwControlID);
-        return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
-    }
-
-    Status = STATUS_NOT_IMPLEMENTED;
-    DPRINT("dwLineId %x dwControlID %x dwControlType %x\n", MixerLine->Line.dwLineID, MixerControl->dwControlID, MixerControl->dwControlType);
-    if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
-    {
-        /* send the request */
-        Status = SetGetMuteControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, MixerLine->Line.dwLineID, DeviceInfo, FALSE);
-    }
-    else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
-    {
-        Status = SetGetVolumeControlDetails(DeviceObject, MixerLine->DeviceIndex, NodeId, DeviceInfo, FALSE, MixerControl, MixerLine);
-    }
-
-    return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
-
-}
-
diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c
new file mode 100644 (file)
index 0000000..1d8a806
--- /dev/null
@@ -0,0 +1,663 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/wdm/audio/legacy/wdmaud/mmixer.c
+ * PURPOSE:         WDM Legacy Mixer
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+#include "wdmaud.h"
+
+
+PVOID Alloc(ULONG NumBytes);
+MIXER_STATUS Close(HANDLE hDevice);
+VOID Free(PVOID Block);
+VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes);
+MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice);
+MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned);
+MIXER_STATUS Enum(IN  PVOID EnumContext, IN  ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey);
+MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey);
+MIXER_STATUS CloseKey(IN HANDLE hKey);
+MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType);
+PVOID AllocEventData(IN ULONG ExtraSize);
+VOID FreeEventData(IN PVOID EventData);
+
+MIXER_CONTEXT MixerContext =
+{
+    sizeof(MIXER_CONTEXT),
+    NULL,
+    Alloc,
+    Control,
+    Free,
+    Open,
+    Close,
+    Copy,
+    OpenKey,
+    QueryKeyValue,
+    CloseKey,
+    AllocEventData,
+    FreeEventData
+};
+
+GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
+
+MIXER_STATUS
+QueryKeyValue(
+    IN HANDLE hKey,
+    IN LPWSTR lpKeyName,
+    OUT PVOID * ResultBuffer,
+    OUT PULONG ResultLength,
+    OUT PULONG KeyType)
+{
+    NTSTATUS Status;
+    UNICODE_STRING KeyName;
+    ULONG Length;
+    PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
+
+    /* initialize key name */
+    RtlInitUnicodeString(&KeyName, lpKeyName);
+
+    /* now query MatchingDeviceId key */
+    Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, NULL, 0, &Length);
+
+    /* check for success */
+    if (Status != STATUS_BUFFER_TOO_SMALL)
+        return MM_STATUS_UNSUCCESSFUL;
+
+    /* allocate a buffer for key data */
+    PartialInformation = ExAllocatePool(NonPagedPool, Length);
+
+    if (!PartialInformation)
+        return MM_STATUS_NO_MEMORY;
+
+
+    /* now query MatchingDeviceId key */
+    Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePool(PartialInformation);
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+
+    if (KeyType)
+    {
+        /* return key type */
+        *KeyType = PartialInformation->Type;
+    }
+
+    if (ResultLength)
+    {
+        /* return data length */
+        *ResultLength = PartialInformation->DataLength;
+    }
+
+    *ResultBuffer = ExAllocatePool(NonPagedPool, PartialInformation->DataLength);
+    if (!*ResultBuffer)
+    {
+        /* not enough memory */
+        ExFreePool(PartialInformation);
+        return MM_STATUS_NO_MEMORY;
+    }
+
+    /* copy key value */
+    RtlMoveMemory(*ResultBuffer, PartialInformation->Data, PartialInformation->DataLength);
+
+    /* free key info */
+    ExFreePool(PartialInformation);
+
+    return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+OpenKey(
+    IN HANDLE hKey,
+    IN LPWSTR lpSubKeyName,
+    IN ULONG DesiredAccess,
+    OUT PHANDLE OutKey)
+{
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING SubKeyName;
+    NTSTATUS Status;
+
+    /* initialize sub key name */
+    RtlInitUnicodeString(&SubKeyName, lpSubKeyName);
+
+    /* initialize key attributes */
+    InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL);
+
+    /* open the key */
+    Status = ZwOpenKey(OutKey, DesiredAccess, &ObjectAttributes);
+
+    if (NT_SUCCESS(Status))
+        return MM_STATUS_SUCCESS;
+    else
+        return MM_STATUS_UNSUCCESSFUL;
+}
+
+MIXER_STATUS
+CloseKey(
+    IN HANDLE hKey)
+{
+    if (ZwClose(hKey) == STATUS_SUCCESS)
+        return MM_STATUS_SUCCESS;
+    else
+        return MM_STATUS_UNSUCCESSFUL;
+}
+
+
+PVOID Alloc(ULONG NumBytes)
+{
+    PVOID Mem = ExAllocatePool(NonPagedPool, NumBytes);
+    if (!Mem)
+        return Mem;
+
+    RtlZeroMemory(Mem, NumBytes);
+    return Mem;
+}
+
+MIXER_STATUS
+Close(HANDLE hDevice)
+{
+    if (ZwClose(hDevice) == STATUS_SUCCESS)
+        return MM_STATUS_SUCCESS;
+    else
+        return MM_STATUS_UNSUCCESSFUL;
+}
+
+VOID
+Free(PVOID Block)
+{
+    ExFreePool(Block);
+}
+
+VOID
+Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
+{
+    RtlMoveMemory(Src, Dst, NumBytes);
+}
+
+MIXER_STATUS
+Open(
+    IN LPWSTR DevicePath,
+    OUT PHANDLE hDevice)
+{
+    if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS)
+        return MM_STATUS_SUCCESS;
+    else
+        return MM_STATUS_UNSUCCESSFUL;
+}
+
+MIXER_STATUS
+Control(
+    IN HANDLE hMixer,
+    IN ULONG dwIoControlCode,
+    IN PVOID lpInBuffer,
+    IN ULONG nInBufferSize,
+    OUT PVOID lpOutBuffer,
+    ULONG nOutBufferSize,
+    PULONG lpBytesReturned)
+{
+    NTSTATUS Status;
+    PFILE_OBJECT FileObject;
+
+    /* get file object */
+    Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("failed to reference %p with %lx\n", hMixer, Status);
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+
+    /* perform request */
+    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
+
+    /* release object reference */
+    ObDereferenceObject(FileObject);
+
+    if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+    {
+        /* more data is available */
+        return MM_STATUS_MORE_ENTRIES;
+    }
+    else if (Status == STATUS_SUCCESS)
+    {
+        /* operation succeeded */
+        return MM_STATUS_SUCCESS;
+    }
+    else
+    {
+        DPRINT("Failed with %lx\n", Status);
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+}
+
+MIXER_STATUS
+Enum(
+    IN  PVOID EnumContext,
+    IN  ULONG DeviceIndex,
+    OUT LPWSTR * DeviceName,
+    OUT PHANDLE OutHandle,
+    OUT PHANDLE OutKey)
+{
+    PDEVICE_OBJECT DeviceObject;
+    ULONG DeviceCount;
+    NTSTATUS Status;
+    UNICODE_STRING KeyName;
+
+    /* get enumeration context */
+    DeviceObject = (PDEVICE_OBJECT)EnumContext;
+
+    /* get device count */
+    DeviceCount = GetSysAudioDeviceCount(DeviceObject);
+
+    if (DeviceIndex >= DeviceCount)
+    {
+        /* no more devices */
+        return MM_STATUS_NO_MORE_DEVICES;
+    }
+
+    /* get device name */
+    Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to retrieve device name */
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+
+    /* intialize key name */
+    RtlInitUnicodeString(&KeyName, *DeviceName);
+
+    /* open device interface key */
+    Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey);
+#if 0
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to open key */
+        DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status);
+        ExFreePool(*DeviceName);
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+#endif
+
+    /* open device handle */
+    Status = OpenDevice(*DeviceName, OutHandle, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to open device */
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+
+    return MM_STATUS_SUCCESS;
+}
+
+PVOID
+AllocEventData(
+    IN ULONG ExtraSize)
+{
+    PKSEVENTDATA Data = (PKSEVENTDATA)ExAllocatePool(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize);
+    if (!Data)
+        return NULL;
+
+    Data->EventObject.Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
+    if (!Data->EventHandle.Event)
+    {
+        ExFreePool(Data);
+        return NULL;
+    }
+
+    KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE);
+
+    Data->NotificationType = KSEVENTF_EVENT_HANDLE;
+    return Data;
+}
+
+VOID
+FreeEventData(IN PVOID EventData)
+{
+    PKSEVENTDATA Data = (PKSEVENTDATA)EventData;
+
+    ExFreePool(Data->EventHandle.Event);
+    ExFreePool(Data);
+}
+
+NTSTATUS
+WdmAudMixerInitialize(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    MIXER_STATUS Status;
+
+    /* initialize the mixer library */
+    Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject);
+
+    if (Status != MM_STATUS_SUCCESS)
+    {
+        /* failed to initialize mmixer library */
+        DPRINT("MMixerInitialize failed with %lx\n", Status);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+WdmAudMixerCapabilities(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo,
+    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
+{
+    if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS)
+        return STATUS_SUCCESS;
+
+    return STATUS_INVALID_PARAMETER;
+}
+
+NTSTATUS
+WdmAudControlOpenMixer(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    HANDLE hMixer;
+    PWDMAUD_HANDLE Handles;
+    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+    NTSTATUS Status;
+    PKEVENT EventObject = NULL;
+
+    DPRINT("WdmAudControlOpenMixer\n");
+
+    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    if (DeviceInfo->u.hNotifyEvent)
+    {
+        Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
+            DbgBreakPoint();
+            return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
+        }
+    }
+
+    if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS)
+    {
+        ObDereferenceObject(EventObject);
+        DPRINT1("Failed to open mixer\n");
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
+    }
+
+
+    Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
+
+    if (Handles)
+    {
+        if (ClientInfo->NumPins)
+        {
+            RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
+            ExFreePool(ClientInfo->hPins);
+        }
+
+        ClientInfo->hPins = Handles;
+        ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer;
+        ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
+        ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
+        ClientInfo->NumPins++;
+    }
+    else
+    {
+        ObDereferenceObject(EventObject);
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+    }
+
+    DeviceInfo->hDevice = hMixer;
+
+    return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+NTSTATUS
+NTAPI
+WdmAudGetControlDetails(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    MIXER_STATUS Status;
+
+    /* clear hmixer type flag */
+    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
+
+    /* query mmixer library */
+    Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
+
+    if (Status == MM_STATUS_SUCCESS)
+        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+    else
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+NTSTATUS
+NTAPI
+WdmAudGetLineInfo(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    MIXER_STATUS Status;
+
+    /* clear hmixer type flag */
+    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
+
+    /* query mixer library */
+    Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
+
+    if (Status == MM_STATUS_SUCCESS)
+        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+    else
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+NTSTATUS
+NTAPI
+WdmAudGetLineControls(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    MIXER_STATUS Status;
+
+    /* clear hmixer type flag */
+    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
+
+    /* query mixer library */
+    Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
+
+    if (Status == MM_STATUS_SUCCESS)
+        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+    else
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+
+
+}
+
+NTSTATUS
+NTAPI
+WdmAudSetControlDetails(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    MIXER_STATUS Status;
+
+    /* clear hmixer type flag */
+    DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
+
+    /* query mixer library */
+    Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
+
+    if (Status == MM_STATUS_SUCCESS)
+        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+    else
+        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+NTSTATUS
+NTAPI
+WdmAudGetMixerEvent(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    UNIMPLEMENTED
+    return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
+}
+
+ULONG
+WdmAudGetMixerDeviceCount()
+{
+    return MMixerGetCount(&MixerContext);
+}
+
+ULONG
+WdmAudGetWaveInDeviceCount()
+{
+    return MMixerGetWaveInCount(&MixerContext);
+}
+
+ULONG
+WdmAudGetWaveOutDeviceCount()
+{
+    return MMixerGetWaveOutCount(&MixerContext);
+}
+
+NTSTATUS
+WdmAudGetMixerPnpNameByIndex(
+    IN  ULONG DeviceIndex,
+    OUT LPWSTR * Device)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+WdmAudGetPnpNameByIndexAndType(
+    IN ULONG DeviceIndex, 
+    IN SOUND_DEVICE_TYPE DeviceType, 
+    OUT LPWSTR *Device)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+WdmAudWaveCapabilities(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN PWDMAUD_CLIENT ClientInfo,
+    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
+{
+    MIXER_STATUS Status;
+
+    if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
+    {
+        /* get capabilities */
+        Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
+    }
+    else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
+    {
+        /* get capabilities */
+        Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
+    }
+    else
+    {
+        ASSERT(0);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    if (Status == MM_STATUS_SUCCESS)
+        return STATUS_SUCCESS;
+    else
+        return STATUS_UNSUCCESSFUL;
+}
+
+
+MIXER_STATUS
+CreatePinCallback(
+    IN PVOID Ctx,
+    IN ULONG VirtualDeviceId,
+    IN ULONG PinId,
+    IN HANDLE hFilter,
+    IN PKSPIN_CONNECT PinConnect,
+    IN ACCESS_MASK DesiredAccess,
+    OUT PHANDLE PinHandle)
+{
+    ULONG BytesReturned;
+    SYSAUDIO_INSTANCE_INFO InstanceInfo;
+    NTSTATUS Status;
+    ULONG FreeIndex;
+    PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
+
+    /* setup property request */
+    InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
+    InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
+    InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
+    InstanceInfo.Flags = 0;
+    InstanceInfo.DeviceNumber = VirtualDeviceId;
+
+    /* attach to virtual device */
+    Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
+
+    if (!NT_SUCCESS(Status))
+        return MM_STATUS_UNSUCCESSFUL;
+
+    /* close existing pin */
+    FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
+
+    /* now create the pin */
+    Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+        return MM_STATUS_UNSUCCESSFUL;
+
+    /* store the handle */
+    Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to insert handle */
+        ZwClose(*PinHandle);
+        return MM_STATUS_UNSUCCESSFUL;
+    }
+
+    return MM_STATUS_SUCCESS;
+}
+
+NTSTATUS
+WdmAudControlOpenWave(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  PIRP Irp,
+    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
+    IN  PWDMAUD_CLIENT ClientInfo)
+{
+    MIXER_STATUS Status;
+    PIN_CREATE_CONTEXT Context;
+
+    Context.ClientInfo = ClientInfo;
+    Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Context.DeviceType = DeviceInfo->DeviceType;
+
+    Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
+
+    if (Status == MM_STATUS_SUCCESS)
+        return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
+    else
+        return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
+}
index dd61c34..5820abc 100644 (file)
@@ -2,12 +2,37 @@
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Kernel Streaming
  * FILE:            drivers/wdm/audio/legacy/wdmaud/sup.c
- * PURPOSE:         System Audio graph builder
+ * PURPOSE:         Misc support routines
  * PROGRAMMER:      Andrew Greenwood
  *                  Johannes Anderwald
  */
 #include "wdmaud.h"
 
+ULONG
+GetSysAudioDeviceCount(
+    IN  PDEVICE_OBJECT DeviceObject)
+{
+    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+    KSPROPERTY Pin;
+    ULONG Count, BytesReturned;
+    NTSTATUS Status;
+
+    /* setup the query request */
+    Pin.Set = KSPROPSETID_Sysaudio;
+    Pin.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
+    Pin.Flags = KSPROPERTY_TYPE_GET;
+
+    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* query sysaudio for the device count */
+    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
+    if (!NT_SUCCESS(Status))
+        return 0;
+
+    return Count;
+}
+
+
 NTSTATUS
 SetIrpIoStatus(
     IN PIRP Irp,
@@ -21,7 +46,7 @@ SetIrpIoStatus(
 
 }
 
-NTSTATUS
+ULONG
 ClosePin(
     IN  PWDMAUD_CLIENT ClientInfo,
     IN  ULONG FilterId,
@@ -298,3 +323,83 @@ FindProductName(
     return Status;
 }
 
+NTSTATUS
+GetSysAudioDevicePnpName(
+    IN  PDEVICE_OBJECT DeviceObject,
+    IN  ULONG DeviceIndex,
+    OUT LPWSTR * Device)
+{
+    ULONG BytesReturned;
+    KSP_PIN Pin;
+    NTSTATUS Status;
+    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+
+   /* first check if the device index is within bounds */
+   if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject))
+       return STATUS_INVALID_PARAMETER;
+
+    /* setup the query request */
+    Pin.Property.Set = KSPROPSETID_Sysaudio;
+    Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME;
+    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
+    Pin.PinId = DeviceIndex;
+
+    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* query sysaudio for the device path */
+    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned);
+
+    /* check if the request failed */
+    if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0)
+        return STATUS_UNSUCCESSFUL;
+
+    /* allocate buffer for the device */
+    *Device = ExAllocatePool(NonPagedPool, BytesReturned);
+    if (!Device)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* query sysaudio again for the device path */
+    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), (PVOID)*Device, BytesReturned, &BytesReturned);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed */
+        ExFreePool(*Device);
+        return Status;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+OpenDevice(
+    IN LPWSTR Device,
+    OUT PHANDLE DeviceHandle,
+    OUT PFILE_OBJECT * FileObject)
+{
+    NTSTATUS Status;
+    HANDLE hDevice;
+
+    /* now open the device */
+    Status = WdmAudOpenSysAudioDevice(Device, &hDevice);
+
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    *DeviceHandle = hDevice;
+
+    if (FileObject)
+    {
+        Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL);
+
+        if (!NT_SUCCESS(Status))
+        {
+            ZwClose(hDevice);
+        }
+    }
+
+    return Status;
+
+}
diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c b/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c
deleted file mode 100644 (file)
index be57468..0000000
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS Kernel Streaming
- * FILE:            drivers/wdm/audio/legacy/wdmaud/wave.c
- * PURPOSE:         Wave Out enumeration
- * PROGRAMMER:      Andrew Greenwood
- *                  Johannes Anderwald
- */
-#include "wdmaud.h"
-
-
-typedef struct
-{
-    ULONG SampleRate;
-    ULONG Bit8Mono;
-    ULONG Bit8Stereo;
-    ULONG Bit16Mono;
-    ULONG Bit16Stereo;
-}AUDIO_RANGE;
-
-#define AUDIO_TEST_RANGE (5)
-
-static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] =
-{
-    {
-        11025,
-        WAVE_FORMAT_1M08,
-        WAVE_FORMAT_1S08,
-        WAVE_FORMAT_1M16,
-        WAVE_FORMAT_1S16
-    },
-    {
-        22050,
-        WAVE_FORMAT_2M08,
-        WAVE_FORMAT_2S08,
-        WAVE_FORMAT_2M16,
-        WAVE_FORMAT_2S16
-    },
-    {
-        44100,
-        WAVE_FORMAT_4M08,
-        WAVE_FORMAT_4S08,
-        WAVE_FORMAT_4M16,
-        WAVE_FORMAT_4S16
-    },
-    {
-        48000,
-        WAVE_FORMAT_48M08,
-        WAVE_FORMAT_48S08,
-        WAVE_FORMAT_48M16,
-        WAVE_FORMAT_48S16
-    },
-    {
-        96000,
-        WAVE_FORMAT_96M08,
-        WAVE_FORMAT_96S08,
-        WAVE_FORMAT_96M16,
-        WAVE_FORMAT_96S16
-    }
-};
-
-LPWAVE_INFO
-AllocateWaveInfo()
-{
-    /* allocate wav info */
-    LPWAVE_INFO WaveOutInfo = ExAllocatePool(NonPagedPool, sizeof(WAVE_INFO));
-    if (!WaveOutInfo)
-        return NULL;
-
-    /* zero wave info struct */
-    RtlZeroMemory(WaveOutInfo, sizeof(WAVE_INFO));
-
-    return WaveOutInfo;
-}
-
-PKSPIN_CONNECT
-AllocatePinConnect(
-    ULONG DataFormatSize)
-{
-    PKSPIN_CONNECT Connect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + DataFormatSize);
-    if (!Connect)
-        return NULL;
-
-    /* zero pin connect struct */
-    RtlZeroMemory(Connect, sizeof(KSPIN_CONNECT) + DataFormatSize);
-
-    return Connect;
-}
-
-NTSTATUS
-GetWaveInfoByIndexAndType(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  ULONG DeviceIndex,
-    IN  SOUND_DEVICE_TYPE DeviceType,
-    OUT LPWAVE_INFO *OutWaveInfo)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    ULONG Index = 0;
-    PLIST_ENTRY Entry, ListHead;
-    LPWAVE_INFO WaveInfo;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    if (DeviceType == WAVE_IN_DEVICE_TYPE)
-        ListHead = &DeviceExtension->WaveInList;
-    else
-        ListHead = &DeviceExtension->WaveOutList;
-
-    /* get first entry */
-    Entry = ListHead->Flink;
-
-    while(Entry != ListHead)
-    {
-        WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry);
-
-        if (Index == DeviceIndex)
-        {
-            *OutWaveInfo = WaveInfo;
-            return STATUS_SUCCESS;
-        }
-        Index++;
-        Entry = Entry->Flink;
-    }
-
-    return STATUS_NOT_FOUND;
-}
-
-
-VOID
-InitializePinConnect(
-    IN OUT PKSPIN_CONNECT PinConnect,
-    IN ULONG PinId)
-{
-    PinConnect->Interface.Set = KSINTERFACESETID_Standard;
-    PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
-    PinConnect->Interface.Flags = 0;
-    PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
-    PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
-    PinConnect->Medium.Flags = 0;
-    PinConnect->PinToHandle = NULL;
-    PinConnect->PinId = PinId;
-    PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
-    PinConnect->Priority.PrioritySubClass = 1;
-}
-
-VOID
-InitializeDataFormat(
-    IN PKSDATAFORMAT_WAVEFORMATEX DataFormat,
-    LPWAVEFORMATEX WaveFormatEx)
-{
-
-    DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
-    DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels;
-    DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
-    DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
-    DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
-    DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
-    DataFormat->WaveFormatEx.cbSize = 0;
-    DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
-    DataFormat->DataFormat.Flags = 0;
-    DataFormat->DataFormat.Reserved = 0;
-    DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
-
-    DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-    DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
-    DataFormat->DataFormat.SampleSize = 4;
-}
-
-
-NTSTATUS
-AttachToVirtualAudioDevice(
-    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    IN ULONG VirtualDeviceId)
-{
-    ULONG BytesReturned;
-    SYSAUDIO_INSTANCE_INFO InstanceInfo;
-
-    /* setup property request */
-    InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
-    InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
-    InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
-    InstanceInfo.Flags = 0;
-    InstanceInfo.DeviceNumber = VirtualDeviceId;
-
-    /* attach to virtual device */
-   return KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
-
-}
-
-NTSTATUS
-GetAudioPinDataRanges(
-    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    IN ULONG FilterId,
-    IN ULONG PinId,
-    IN OUT PKSMULTIPLE_ITEM * OutMultipleItem)
-{
-    KSP_PIN PinProperty;
-    ULONG BytesReturned = 0;
-    NTSTATUS Status;
-    PKSMULTIPLE_ITEM MultipleItem;
-
-    /* retrieve size of data ranges buffer */
-    PinProperty.Reserved = FilterId;
-    PinProperty.PinId = PinId;
-    PinProperty.Property.Set = KSPROPSETID_Pin;
-    PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
-    PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
-
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
-    if (Status != STATUS_MORE_ENTRIES)
-    {
-        return Status;
-    }
-
-    MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
-    if (!MultipleItem)
-    {
-        /* not enough memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        ExFreePool(MultipleItem);
-        return Status;
-    }
-
-    /* save result */
-    *OutMultipleItem = MultipleItem;
-    return Status;
-}
-
-NTSTATUS
-FindAudioDataRange(
-    PKSMULTIPLE_ITEM MultipleItem,
-    PKSDATARANGE_AUDIO * OutDataRangeAudio)
-{
-    ULONG Index;
-    PKSDATARANGE_AUDIO DataRangeAudio;
-    PKSDATARANGE DataRange;
-
-    DataRange = (PKSDATARANGE) (MultipleItem + 1);
-    for(Index = 0; Index < MultipleItem->Count; Index++)
-    {
-        if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO))
-        {
-            DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange;
-            if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) &&
-                IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
-                IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX))
-            {
-                DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency,
-                                                         DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels);
-                *OutDataRangeAudio = DataRangeAudio;
-                return STATUS_SUCCESS;
-            }
-        }
-    }
-    return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-NTAPI
-OpenWavePin(
-    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    IN ULONG FilterId,
-    IN ULONG PinId,
-    IN LPWAVEFORMATEX WaveFormatEx,
-    IN ACCESS_MASK DesiredAccess,
-    OUT PHANDLE PinHandle)
-{
-    PKSPIN_CONNECT PinConnect;
-    PKSDATAFORMAT_WAVEFORMATEX DataFormat;
-    NTSTATUS Status;
-
-    /* allocate pin connect */
-    PinConnect = AllocatePinConnect(sizeof(KSDATAFORMAT_WAVEFORMATEX));
-    if (!PinConnect)
-    {
-        /* no memory */
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* initialize pin connect struct */
-    InitializePinConnect(PinConnect, PinId);
-
-    /* get offset to dataformat */
-    DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1);
-    /* initialize with requested wave format */
-    InitializeDataFormat(DataFormat, WaveFormatEx);
-
-    /* first attach to the virtual device */
-    Status = AttachToVirtualAudioDevice(DeviceExtension, FilterId);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed */
-        ExFreePool(PinConnect);
-        return Status;
-    }
-
-    /* now create the pin */
-    Status = KsCreatePin(DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
-
-    /* free create info */
-    ExFreePool(PinConnect);
-
-    return Status;
-}
-
-ULONG
-GetPinInstanceCount(
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    ULONG FilterId,
-    ULONG PinId)
-{
-    KSP_PIN PinRequest;
-    KSPIN_CINSTANCES PinInstances;
-    ULONG BytesReturned;
-    NTSTATUS Status;
-
-    /* query the instance count */
-    PinRequest.Reserved = FilterId;
-    PinRequest.PinId = PinId;
-    PinRequest.Property.Set = KSPROPSETID_Pin;
-    PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
-    PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
-
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
-    ASSERT(Status == STATUS_SUCCESS);
-    return PinInstances.CurrentCount;
-}
-
-
-NTSTATUS
-CheckSampleFormat(
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    LPWAVE_INFO WaveInfo,
-    ULONG SampleRate,
-    ULONG NumChannels,
-    ULONG BitsPerSample)
-{
-    NTSTATUS Status = STATUS_SUCCESS;
-#if 0
-
-    WAVEFORMATEX WaveFormat;
-    HANDLE PinHandle;
-
-    /* clear wave format */
-    RtlZeroMemory(&WaveFormat, sizeof(WAVEFORMATEX));
-
-    WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
-    WaveFormat.nChannels = NumChannels;
-    WaveFormat.nSamplesPerSec = SampleRate;
-    WaveFormat.nAvgBytesPerSec = SampleRate * NumChannels * (BitsPerSample/8);
-    WaveFormat.nBlockAlign = (NumChannels * BitsPerSample) / 8;
-    WaveFormat.wBitsPerSample = BitsPerSample;
-    WaveFormat.cbSize = sizeof(WAVEFORMATEX);
-
-    Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &WaveFormat, GENERIC_READ | GENERIC_WRITE, &PinHandle);
-
-    if (NT_SUCCESS(Status))
-    {
-        /* success */
-        ZwClose(PinHandle);
-
-        while(GetPinInstanceCount(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId))
-            KeStallExecutionProcessor(5);
-    }
-
-    DPRINT("SampleRate %u BitsPerSample %u NumChannels %u Status %x bInput %u\n", SampleRate, BitsPerSample, NumChannels, Status, WaveInfo->bInput);
-#endif
-
-
-    return Status;
-}
-
-
-NTSTATUS
-CheckFormat(
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension,
-    PKSDATARANGE_AUDIO DataRangeAudio,
-    LPWAVE_INFO WaveInfo)
-{
-    ULONG Index, SampleFrequency;
-    ULONG Result = 0;
-    NTSTATUS Status;
-
-    for(Index = 0; Index < AUDIO_TEST_RANGE; Index++)
-    {
-        SampleFrequency = TestRange[Index].SampleRate;
-
-        if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency)
-        {
-            /* the audio adapter supports the sample frequency */
-            if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8)
-            {
-                /* check if pin supports the sample rate in 8-Bit Mono */
-                Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 8);
-                if (NT_SUCCESS(Status))
-                {
-                    Result |= TestRange[Index].Bit8Mono;
-                }
-
-                if (DataRangeAudio->MaximumChannels > 1)
-                {
-                    /* check if pin supports the sample rate in 8-Bit Stereo */
-                    Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 8);
-                    if (NT_SUCCESS(Status))
-                    {
-                        Result |= TestRange[Index].Bit8Stereo;
-                    }
-                }
-            }
-
-            if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16)
-            {
-                /* check if pin supports the sample rate in 16-Bit Mono */
-                Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 1, 16);
-                if (NT_SUCCESS(Status))
-                {
-                    Result |= TestRange[Index].Bit16Mono;
-                }
-
-                if (DataRangeAudio->MaximumChannels > 1)
-                {
-                    /* check if pin supports the sample rate in 16-Bit Stereo */
-                    Status = CheckSampleFormat(DeviceExtension, WaveInfo, SampleFrequency, 2, 16);
-                    if (NT_SUCCESS(Status))
-                    {
-                        Result |= TestRange[Index].Bit16Stereo;
-                    }
-                }
-            }
-        }
-    }
-
-
-    if (WaveInfo->bInput)
-        WaveInfo->u.InCaps.dwFormats = Result;
-    else
-        WaveInfo->u.OutCaps.dwFormats = Result;
-
-    DPRINT("Format %x bInput %u\n", Result, WaveInfo->bInput);
-
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-InitializeWaveInfo(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN ULONG FilterId,
-    IN ULONG PinId,
-    IN ULONG bInput)
-{
-    KSP_PIN PinProperty;
-    KSCOMPONENTID ComponentId;
-    NTSTATUS Status;
-    ULONG BytesReturned;
-    WCHAR DeviceName[MAX_PATH];
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    PKSMULTIPLE_ITEM MultipleItem;
-    PKSDATARANGE_AUDIO DataRangeAudio;
-    LPWAVE_INFO WaveInfo = AllocateWaveInfo();
-
-
-    if (!WaveInfo)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* initialize wave info */
-    WaveInfo->bInput = bInput;
-    WaveInfo->FilterId = FilterId;
-    WaveInfo->PinId = PinId;
-
-    /* setup request to return component id */
-    PinProperty.PinId = FilterId;
-    PinProperty.Property.Set = KSPROPSETID_Sysaudio;
-    PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID;
-    PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* query sysaudio for component id */
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
-    if (NT_SUCCESS(Status))
-    {
-        if (bInput)
-        {
-            WaveInfo->u.InCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
-            WaveInfo->u.InCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
-        }
-        else
-        {
-            WaveInfo->u.OutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
-            WaveInfo->u.OutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
-        }
-    }
-    else
-    {
-        /* set up something useful */
-        if (bInput)
-        {
-            WaveInfo->u.InCaps.wMid = MM_MICROSOFT;
-            WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED;
-            WaveInfo->u.InCaps.vDriverVersion = 1;
-        }
-        else
-        {
-            WaveInfo->u.OutCaps.wMid = MM_MICROSOFT;
-            WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED;
-            WaveInfo->u.OutCaps.vDriverVersion = 1;
-        }
-    }
-
-    /* retrieve pnp base name */
-    PinProperty.PinId = FilterId;
-    PinProperty.Property.Set = KSPROPSETID_Sysaudio;
-    PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME;
-    PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
-
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)DeviceName, sizeof(DeviceName), &BytesReturned);
-    if (NT_SUCCESS(Status))
-    {
-        /* find product name */
-        if (bInput)
-            Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.OutCaps.szPname);
-        else
-            Status = FindProductName(DeviceName, MAXPNAMELEN, WaveInfo->u.InCaps.szPname);
-
-        /* check for success */
-        if (!NT_SUCCESS(Status))
-        {
-            if (bInput)
-                WaveInfo->u.OutCaps.szPname[0] = L'\0';
-            else
-                WaveInfo->u.InCaps.szPname[0] = L'\0';
-        }
-    }
-
-    Status = GetAudioPinDataRanges(DeviceExtension, FilterId, PinId, &MultipleItem);
-    if (NT_SUCCESS(Status))
-    {
-        /* find a audio data range */
-        Status = FindAudioDataRange(MultipleItem, &DataRangeAudio);
-
-        if (NT_SUCCESS(Status))
-        {
-            if (bInput)
-            {
-                WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels;
-            }
-            else
-            {
-                WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels;
-            }
-            CheckFormat(DeviceExtension, DataRangeAudio, WaveInfo);
-        }
-        ExFreePool(MultipleItem);
-    }
-
-    if (bInput)
-    {
-        InsertTailList(&DeviceExtension->WaveInList, &WaveInfo->Entry);
-        DeviceExtension->WaveInDeviceCount++;
-    }
-    else
-    {
-        InsertTailList(&DeviceExtension->WaveOutList, &WaveInfo->Entry);
-        DeviceExtension->WaveOutDeviceCount++;
-    }
-
-
-    return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-NTAPI
-WdmAudWaveInitialize(
-    IN PDEVICE_OBJECT DeviceObject)
-{
-    KSP_PIN Pin;
-    ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins;
-    NTSTATUS Status;
-    KSPIN_COMMUNICATION Communication;
-    KSPIN_DATAFLOW DataFlow;
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-
-    Pin.Property.Set = KSPROPSETID_Sysaudio;
-    Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
-    Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* set wave count to zero */
-    DeviceExtension->WaveInDeviceCount = 0;
-    DeviceExtension->WaveOutDeviceCount = 0;
-
-    /* intialize list head */
-    InitializeListHead(&DeviceExtension->WaveInList);
-    InitializeListHead(&DeviceExtension->WaveOutList);
-
-    Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
-    if (!NT_SUCCESS(Status))
-        return STATUS_UNSUCCESSFUL;
-
-    Result = 0;
-    for(Index = 0; Index < Count; Index++)
-    {
-        /* query number of pins */
-        Pin.Reserved = Index; // see sysaudio
-        Pin.Property.Flags = KSPROPERTY_TYPE_GET;
-        Pin.Property.Set = KSPROPSETID_Pin;
-        Pin.Property.Id = KSPROPERTY_PIN_CTYPES;
-        Pin.PinId = 0;
-
-        Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
-        if (NT_SUCCESS(Status))
-        {
-            /* enumerate now all pins */
-            for(SubIndex = 0; SubIndex < NumPins; SubIndex++)
-            {
-                Pin.PinId = SubIndex;
-                Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
-                Communication = KSPIN_COMMUNICATION_NONE;
-
-                /* get pin communication type */
-                KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
-
-                Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
-                DataFlow = 0;
-
-                /* get pin dataflow type */
-                KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
-
-                if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
-                {
-                    /* found a wave out device */
-                    InitializeWaveInfo(DeviceObject, Index, SubIndex, FALSE);
-                }
-                else if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
-                {
-                    /* found a wave in device */
-                    InitializeWaveInfo(DeviceObject, Index, SubIndex, TRUE);
-                }
-            }
-        }
-    }
-
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-WdmAudControlOpenWave(
-    IN  PDEVICE_OBJECT DeviceObject,
-    IN  PIRP Irp,
-    IN  PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN  PWDMAUD_CLIENT ClientInfo)
-{
-    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
-    LPWAVE_INFO WaveInfo;
-    NTSTATUS Status;
-    ACCESS_MASK DesiredAccess = 0;
-    HANDLE PinHandle;
-    ULONG FreeIndex;
-
-    if (DeviceInfo->u.WaveFormatEx.wFormatTag != WAVE_FORMAT_PCM)
-    {
-        DPRINT("FIXME: Only WAVE_FORMAT_PCM is supported RequestFormat %x\n", DeviceInfo->u.WaveFormatEx.wFormatTag);
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-    }
-
-    /* get device extension */
-    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    /* find destination wave */
-    Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed to find wave info */
-        DbgBreakPoint();
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-    }
-
-    /* close pin handle which uses same virtual audio device id and pin id */
-    FreeIndex = ClosePin(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType);
-
-    /* get desired access */
-    if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
-    {
-        DesiredAccess |= GENERIC_READ;
-    }
-     else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
-    {
-        DesiredAccess |= GENERIC_WRITE;
-    }
-
-    /* now try open the pin */
-    Status = OpenWavePin(DeviceExtension, WaveInfo->FilterId, WaveInfo->PinId, &DeviceInfo->u.WaveFormatEx, DesiredAccess, &PinHandle);
-
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed to open the pin */
-        return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, 0);
-    }
-
-    /* store the handle */
-    Status = InsertPinHandle(ClientInfo, WaveInfo->FilterId, WaveInfo->PinId, DeviceInfo->DeviceType, PinHandle, FreeIndex);
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed to insert handle */
-        ZwClose(PinHandle);
-        return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
-    }
-
-    /* store pin handle */
-    DeviceInfo->hDevice = PinHandle;
-    return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
-}
-
-NTSTATUS
-WdmAudWaveCapabilities(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PWDMAUD_DEVICE_INFO DeviceInfo,
-    IN PWDMAUD_CLIENT ClientInfo,
-    IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
-{
-    LPWAVE_INFO WaveInfo;
-    NTSTATUS Status;
-
-    /* find destination wave */
-    Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
-    if (!NT_SUCCESS(Status))
-    {
-        /* failed to find wave info */
-        DbgBreakPoint();
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
-    {
-        RtlMoveMemory(&DeviceInfo->u.WaveInCaps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW));
-    }
-    else
-    {
-        RtlMoveMemory(&DeviceInfo->u.WaveOutCaps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW));
-    }
-
-    return STATUS_SUCCESS;
-}
-
index c8e5332..c0dcfcc 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <wchar.h>
+#include "mmixer.h"
 
 #include "interface.h"
 
-typedef struct
-{
-    LIST_ENTRY Entry;
-    HANDLE hMixer;
-    ULONG NotificationType;
-    ULONG Value;
-}MIXER_EVENT, *PMIXER_EVENT;
-
-
 typedef struct
 {
     HANDLE Handle;
@@ -44,60 +36,6 @@ typedef struct
     LIST_ENTRY MixerEventList;
 }WDMAUD_CLIENT, *PWDMAUD_CLIENT;
 
-typedef struct
-{
-    LIST_ENTRY Entry;
-    ULONG dwControlID;
-}MIXERCONTROL_DATA, *LPMIXERCONTROL_DATA;
-
-typedef struct
-{
-    MIXERCONTROL_DATA Header;
-    LONG SignedMinimum;
-    LONG SignedMaximum;
-    LONG SteppingDelta;
-    ULONG InputSteppingDelta;
-    ULONG ValuesCount;
-    PLONG Values;
-}MIXERVOLUME_DATA, *LPMIXERVOLUME_DATA;
-
-
-
-typedef struct
-{
-    LIST_ENTRY Entry;
-    ULONG PinId;
-    ULONG DeviceIndex;
-    MIXERLINEW Line;
-    LPMIXERCONTROLW LineControls;
-    PULONG          NodeIds;
-    LIST_ENTRY LineControlsExtraData;
-}MIXERLINE_EXT, *LPMIXERLINE_EXT;
-
-
-typedef struct
-{
-    MIXERCAPSW    MixCaps;
-    ULONG DeviceIndex;
-    LIST_ENTRY    LineList;
-    ULONG ControlId;
-}MIXER_INFO, *LPMIXER_INFO;
-
-
-typedef struct
-{
-    LIST_ENTRY Entry;
-    ULONG FilterId;
-    ULONG PinId;
-    ULONG bInput;
-    union
-    {
-        WAVEOUTCAPSW OutCaps;
-        WAVEINCAPSW  InCaps;
-    }u;
-}WAVE_INFO, *LPWAVE_INFO;
-
-
 typedef struct
 {
     LIST_ENTRY Entry;
@@ -117,18 +55,17 @@ typedef struct
     HANDLE hSysAudio;
     PFILE_OBJECT FileObject;
 
-    ULONG MixerInfoCount;
-    LPMIXER_INFO MixerInfo;
-
-    ULONG WaveInDeviceCount;
-    LIST_ENTRY WaveInList;
-
-    ULONG WaveOutDeviceCount;
-    LIST_ENTRY WaveOutList;
-
     LIST_ENTRY WdmAudClientList;
 }WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
 
+typedef struct
+{
+    PWDMAUD_CLIENT ClientInfo;
+    PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+    SOUND_DEVICE_TYPE DeviceType;
+}PIN_CREATE_CONTEXT, *PPIN_CREATE_CONTEXT;
+
+
 NTSTATUS
 NTAPI
 OpenWavePin(
@@ -279,7 +216,7 @@ NTAPI
 WdmAudWaveInitialize(
     IN PDEVICE_OBJECT DeviceObject);
 
-NTSTATUS
+ULONG
 ClosePin(
     IN  PWDMAUD_CLIENT ClientInfo,
     IN  ULONG FilterId,
@@ -295,18 +232,51 @@ InsertPinHandle(
     IN  HANDLE PinHandle,
     IN  ULONG FreeIndex);
 
-
 NTSTATUS
-GetWaveInfoByIndexAndType(
+GetSysAudioDevicePnpName(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  ULONG DeviceIndex,
-    IN  SOUND_DEVICE_TYPE DeviceType,
-    OUT LPWAVE_INFO *OutWaveInfo);
+    OUT LPWSTR * Device);
 
 NTSTATUS
-GetSysAudioDevicePnpName(
+OpenSysAudioDeviceByIndex(
     IN  PDEVICE_OBJECT DeviceObject,
+    IN  ULONG DeviceIndex,
+    IN  PHANDLE DeviceHandle,
+    IN  PFILE_OBJECT * FileObject);
+
+NTSTATUS
+OpenDevice(
+    IN LPWSTR Device,
+    OUT PHANDLE DeviceHandle,
+    OUT PFILE_OBJECT * FileObject);
+
+ULONG
+WdmAudGetMixerDeviceCount();
+
+ULONG
+WdmAudGetWaveInDeviceCount();
+
+ULONG
+WdmAudGetWaveOutDeviceCount();
+
+NTSTATUS
+WdmAudGetMixerPnpNameByIndex(
     IN  ULONG DeviceIndex,
     OUT LPWSTR * Device);
 
+NTSTATUS
+WdmAudGetPnpNameByIndexAndType(
+    IN ULONG DeviceIndex, 
+    IN SOUND_DEVICE_TYPE DeviceType, 
+    OUT LPWSTR *Device);
+
+
+/* sup.c */
+
+ULONG
+GetSysAudioDeviceCount(
+    IN  PDEVICE_OBJECT DeviceObject);
+
+
 #endif
index 1b3acd1..6c6595c 100644 (file)
@@ -2,17 +2,20 @@
 <!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
 <module name="wdmaud_kernel" type="kernelmodedriver" installbase="system32/drivers" installname="wdmaud.sys">
        <include base="wdmaud_kernel">.</include>
-       <define name="_COMDDK_" />
+       <include base="mmixer">.</include>
        <include base="ReactOS">include/reactos/libs/sound</include>
+       <define name="_COMDDK_" />
+       <library>mmixer</library>
        <library>ntoskrnl</library>
+       <library>rtl</library>
+       <library>libcntpr</library>
        <library>ks</library>
        <library>pseh</library>
        <library>hal</library>
        <file>control.c</file>
        <file>deviface.c</file>
        <file>entry.c</file>
-       <file>mixer.c</file>
-       <file>wave.c</file>
+       <file>mmixer.c</file>
        <file>sup.c</file>
        <file>wdmaud.rc</file>
 </module>
index fa7183d..7f117e3 100644 (file)
@@ -75,6 +75,15 @@ typedef PVOID (*PMIXER_ALLOC_EVENT_DATA)(
 typedef VOID (*PMIXER_FREE_EVENT_DATA)(
     IN PVOID EventData);
 
+typedef MIXER_STATUS (*PIN_CREATE_CALLBACK)(
+    IN PVOID Context,
+    IN ULONG DeviceId,
+    IN ULONG PinId,
+    IN HANDLE hFilter,
+    IN PKSPIN_CONNECT PinConnect,
+    IN ACCESS_MASK DesiredAccess,
+    OUT PHANDLE PinHandle);
+
 typedef struct
 {
      ULONG SizeOfStruct;
@@ -172,6 +181,8 @@ MMixerOpenWave(
     IN ULONG DeviceIndex,
     IN ULONG bWaveIn,
     IN LPWAVEFORMATEX WaveFormat,
+    IN PIN_CREATE_CALLBACK CreateCallback,
+    IN PVOID Context,
     OUT PHANDLE PinHandle);
 
 MIXER_STATUS
index f35d167..0149df2 100644 (file)
@@ -588,7 +588,7 @@ MMixerGetDataByDeviceName(
     while(Entry != &MixerList->MixerData)
     {
         MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
-        if (wcsicmp(DeviceName, MixerData->DeviceName) == 0)
+        if (wcsicmp(&DeviceName[2], &MixerData->DeviceName[2]) == 0)
         {
             // found entry
             return MixerData;
index 498c61b..c156378 100644 (file)
@@ -233,12 +233,15 @@ MMixerOpenWavePin(
     IN ULONG PinId,
     IN LPWAVEFORMATEX WaveFormatEx,
     IN ACCESS_MASK DesiredAccess,
+    IN PIN_CREATE_CALLBACK CreateCallback,
+    IN PVOID Context,
     OUT PHANDLE PinHandle)
 {
     PKSPIN_CONNECT PinConnect;
     PKSDATAFORMAT_WAVEFORMATEX DataFormat;
     LPMIXER_DATA MixerData;
     NTSTATUS Status;
+    MIXER_STATUS MixerStatus;
 
     MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
     if (!MixerData)
@@ -260,16 +263,28 @@ MMixerOpenWavePin(
     /* initialize with requested wave format */
     MMixerInitializeDataFormat(DataFormat, WaveFormatEx);
 
-    /* now create the pin */
-    Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
+    if (CreateCallback)
+    {
+        /* let the callback handle the creation */
+        MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
+    }
+    else
+    {
+        /* now create the pin */
+        Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
+
+        /* normalize status */
+        if (Status == STATUS_SUCCESS)
+            MixerStatus = MM_STATUS_SUCCESS;
+        else
+            MixerStatus = MM_STATUS_UNSUCCESSFUL;
+    }
 
     /* free create info */
     MixerContext->Free(PinConnect);
 
-    if (Status == STATUS_SUCCESS)
-        return MM_STATUS_SUCCESS;
-    else
-        return MM_STATUS_UNSUCCESSFUL;
+    /* done */
+    return MixerStatus;
 }
 
 VOID
@@ -415,6 +430,8 @@ MMixerOpenWave(
     IN ULONG DeviceIndex,
     IN ULONG bWaveIn,
     IN LPWAVEFORMATEX WaveFormat,
+    IN PIN_CREATE_CALLBACK CreateCallback,
+    IN PVOID Context,
     OUT PHANDLE PinHandle)
 {
     PMIXER_LIST MixerList;
@@ -459,7 +476,7 @@ MMixerOpenWave(
     }
 
     /* now try open the pin */
-    return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, PinHandle);
+    return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, CreateCallback, Context, PinHandle);
 }
 
 MIXER_STATUS