From a19cbab2fc439e135949c616016b9dec7d3162ae Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Thu, 11 Feb 2010 21:04:57 +0000 Subject: [PATCH] [WDMAUD_KERNEL] - 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 --- reactos/boot/bootdata/packages/reactos.dff | 22 +- reactos/dll/win32/wdmaud.drv/mmixer.c | 2 +- .../drivers/wdm/audio/legacy/wdmaud/control.c | 33 +- .../drivers/wdm/audio/legacy/wdmaud/entry.c | 4 +- .../drivers/wdm/audio/legacy/wdmaud/mixer.c | 2438 ----------------- .../drivers/wdm/audio/legacy/wdmaud/mmixer.c | 663 +++++ reactos/drivers/wdm/audio/legacy/wdmaud/sup.c | 109 +- .../drivers/wdm/audio/legacy/wdmaud/wave.c | 756 ----- .../drivers/wdm/audio/legacy/wdmaud/wdmaud.h | 126 +- .../wdm/audio/legacy/wdmaud/wdmaud.rbuild | 9 +- reactos/lib/drivers/sound/mmixer/mmixer.h | 11 + reactos/lib/drivers/sound/mmixer/sup.c | 2 +- reactos/lib/drivers/sound/mmixer/wave.c | 31 +- 13 files changed, 888 insertions(+), 3318 deletions(-) delete mode 100644 reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c create mode 100644 reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c delete mode 100644 reactos/drivers/wdm/audio/legacy/wdmaud/wave.c diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index df124e93293..733aba39959 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -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 diff --git a/reactos/dll/win32/wdmaud.drv/mmixer.c b/reactos/dll/win32/wdmaud.drv/mmixer.c index 6ef1515c025..0b7cac15a2d 100644 --- a/reactos/dll/win32/wdmaud.drv/mmixer.c +++ b/reactos/dll/win32/wdmaud.drv/mmixer.c @@ -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) { diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c index b5f1c53a968..07e9ef846d2 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/control.c @@ -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)); } diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c b/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c index 013be6aa020..20421ead5e4 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c @@ -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 index 5de3872e55d..00000000000 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c +++ /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 index 00000000000..1d8a806d430 --- /dev/null +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -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)); +} diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c b/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c index dd61c34f1f4..5820abc2500 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/sup.c @@ -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 index be57468d2ad..00000000000 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wave.c +++ /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; -} - diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index c8e53320e1e..c0dcfcca848 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -13,18 +13,10 @@ #include #include #include +#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 diff --git a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild index 1b3acd12e84..6c6595ca37b 100644 --- a/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild +++ b/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.rbuild @@ -2,17 +2,20 @@ . - + . include/reactos/libs/sound + + mmixer ntoskrnl + rtl + libcntpr ks pseh hal control.c deviface.c entry.c - mixer.c - wave.c + mmixer.c sup.c wdmaud.rc diff --git a/reactos/lib/drivers/sound/mmixer/mmixer.h b/reactos/lib/drivers/sound/mmixer/mmixer.h index fa7183da71d..7f117e36223 100644 --- a/reactos/lib/drivers/sound/mmixer/mmixer.h +++ b/reactos/lib/drivers/sound/mmixer/mmixer.h @@ -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 diff --git a/reactos/lib/drivers/sound/mmixer/sup.c b/reactos/lib/drivers/sound/mmixer/sup.c index f35d16744e5..0149df28d43 100644 --- a/reactos/lib/drivers/sound/mmixer/sup.c +++ b/reactos/lib/drivers/sound/mmixer/sup.c @@ -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; diff --git a/reactos/lib/drivers/sound/mmixer/wave.c b/reactos/lib/drivers/sound/mmixer/wave.c index 498c61bee22..c156378f289 100644 --- a/reactos/lib/drivers/sound/mmixer/wave.c +++ b/reactos/lib/drivers/sound/mmixer/wave.c @@ -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 -- 2.17.1