mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 05:52:56 +00:00
[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
This commit is contained in:
parent
bfa7d233cd
commit
a19cbab2fc
13 changed files with 891 additions and 3321 deletions
|
@ -156,7 +156,7 @@ dll\directx\dinput8\dinput8.dll 1
|
||||||
dll\directx\dmusic\dmusic.dll 1
|
dll\directx\dmusic\dmusic.dll 1
|
||||||
dll\directx\dplay\dplay.dll 1
|
dll\directx\dplay\dplay.dll 1
|
||||||
dll\directx\dplayx\dplayx.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\dxdiagn\dxdiagn.dll 1
|
||||||
dll\directx\wine\ddraw\ddraw.dll 1
|
dll\directx\wine\ddraw\ddraw.dll 1
|
||||||
dll\directx\d3d8thk\d3d8thk.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\miniport\usbuhci\usbuhci.sys 2
|
||||||
;drivers\usb\usbhub\usbhub.sys 2
|
;drivers\usb\usbhub\usbhub.sys 2
|
||||||
;drivers\usb\usbport\usbport.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\vga\vgaddi.dll 1
|
||||||
drivers\video\displays\framebuf\framebuf.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\sysaudio\sysaudio.sys 2
|
||||||
drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2
|
drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2
|
||||||
drivers\wdm\audio\backpln\portcls\portcls.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\wdm\audio\drm\drmk\drmk.sys 2
|
||||||
drivers\wmi\wmilib.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\wlanapi\wlanapi_winetest.exe 7 optional
|
||||||
modules\rostests\winetests\ws2_32\ws2_32_winetest.exe 7 optional
|
modules\rostests\winetests\ws2_32\ws2_32_winetest.exe 7 optional
|
||||||
|
|
||||||
|
|
||||||
modules\wallpaper\Angelus_02_ROSWP.bmp 4 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
|
||||||
|
|
|
@ -467,7 +467,7 @@ WdmAudSetWdmWaveDeviceFormatByMMixer(
|
||||||
|
|
||||||
bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE);
|
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)
|
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,17 +8,7 @@
|
||||||
*/
|
*/
|
||||||
#include "wdmaud.h"
|
#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_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
|
NTSTATUS
|
||||||
WdmAudControlOpen(
|
WdmAudControlOpen(
|
||||||
|
@ -55,15 +45,15 @@ WdmAudControlDeviceType(
|
||||||
|
|
||||||
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
Result = DeviceExtension->MixerInfoCount;
|
Result = WdmAudGetMixerDeviceCount();
|
||||||
}
|
}
|
||||||
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
Result = DeviceExtension->WaveOutDeviceCount;
|
Result = WdmAudGetWaveInDeviceCount();
|
||||||
}
|
}
|
||||||
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
Result = DeviceExtension->WaveInDeviceCount;
|
Result = WdmAudGetWaveOutDeviceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store result count */
|
/* store result count */
|
||||||
|
@ -221,7 +211,6 @@ WdmAudGetDeviceInterface(
|
||||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
LPWSTR Device;
|
LPWSTR Device;
|
||||||
LPWAVE_INFO WaveInfo;
|
|
||||||
ULONG Size, Length;
|
ULONG Size, Length;
|
||||||
|
|
||||||
/* get device extension */
|
/* get device extension */
|
||||||
|
@ -233,7 +222,7 @@ WdmAudGetDeviceInterface(
|
||||||
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
/* get wave info */
|
/* get wave info */
|
||||||
Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
|
Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
|
||||||
|
|
||||||
/* check for success */
|
/* check for success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -242,14 +231,6 @@ WdmAudGetDeviceInterface(
|
||||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = GetSysAudioDevicePnpName(DeviceObject, WaveInfo->FilterId, &Device);
|
|
||||||
/* check for success */
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* invalid device id */
|
|
||||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calculate length */
|
/* calculate length */
|
||||||
Length = (wcslen(Device)+1) * sizeof(WCHAR);
|
Length = (wcslen(Device)+1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
@ -275,13 +256,13 @@ WdmAudGetDeviceInterface(
|
||||||
}
|
}
|
||||||
else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
|
if (DeviceInfo->DeviceIndex >= WdmAudGetMixerDeviceCount())
|
||||||
{
|
{
|
||||||
/* invalid device id */
|
/* invalid device id */
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
|
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 */
|
/* check for success */
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -308,8 +289,6 @@ WdmAudGetDeviceInterface(
|
||||||
//FIXME SEH
|
//FIXME SEH
|
||||||
RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
|
RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExFreePool(Device);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,7 @@ WdmAudInstallDevice(
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = WdmAudMixerInitialize(DeviceObject);
|
Status = WdmAudMixerInitialize(DeviceObject);
|
||||||
DPRINT("WdmAudMixerInitialize Status %x\n", Status);
|
DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount());
|
||||||
Status = WdmAudWaveInitialize(DeviceObject);
|
|
||||||
DPRINT("WdmAudWaveInitialize Status %x\n", Status);
|
|
||||||
|
|
||||||
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
|
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
|
||||||
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
663
reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c
Normal file
663
reactos/drivers/wdm/audio/legacy/wdmaud/mmixer.c
Normal file
|
@ -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));
|
||||||
|
}
|
|
@ -2,12 +2,37 @@
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS Kernel Streaming
|
* PROJECT: ReactOS Kernel Streaming
|
||||||
* FILE: drivers/wdm/audio/legacy/wdmaud/sup.c
|
* FILE: drivers/wdm/audio/legacy/wdmaud/sup.c
|
||||||
* PURPOSE: System Audio graph builder
|
* PURPOSE: Misc support routines
|
||||||
* PROGRAMMER: Andrew Greenwood
|
* PROGRAMMER: Andrew Greenwood
|
||||||
* Johannes Anderwald
|
* Johannes Anderwald
|
||||||
*/
|
*/
|
||||||
#include "wdmaud.h"
|
#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
|
NTSTATUS
|
||||||
SetIrpIoStatus(
|
SetIrpIoStatus(
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
|
@ -21,7 +46,7 @@ SetIrpIoStatus(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
ULONG
|
||||||
ClosePin(
|
ClosePin(
|
||||||
IN PWDMAUD_CLIENT ClientInfo,
|
IN PWDMAUD_CLIENT ClientInfo,
|
||||||
IN ULONG FilterId,
|
IN ULONG FilterId,
|
||||||
|
@ -298,3 +323,83 @@ FindProductName(
|
||||||
return Status;
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,18 +13,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include "mmixer.h"
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
LIST_ENTRY Entry;
|
|
||||||
HANDLE hMixer;
|
|
||||||
ULONG NotificationType;
|
|
||||||
ULONG Value;
|
|
||||||
}MIXER_EVENT, *PMIXER_EVENT;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
|
@ -44,60 +36,6 @@ typedef struct
|
||||||
LIST_ENTRY MixerEventList;
|
LIST_ENTRY MixerEventList;
|
||||||
}WDMAUD_CLIENT, *PWDMAUD_CLIENT;
|
}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
|
typedef struct
|
||||||
{
|
{
|
||||||
LIST_ENTRY Entry;
|
LIST_ENTRY Entry;
|
||||||
|
@ -117,18 +55,17 @@ typedef struct
|
||||||
HANDLE hSysAudio;
|
HANDLE hSysAudio;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
ULONG MixerInfoCount;
|
|
||||||
LPMIXER_INFO MixerInfo;
|
|
||||||
|
|
||||||
ULONG WaveInDeviceCount;
|
|
||||||
LIST_ENTRY WaveInList;
|
|
||||||
|
|
||||||
ULONG WaveOutDeviceCount;
|
|
||||||
LIST_ENTRY WaveOutList;
|
|
||||||
|
|
||||||
LIST_ENTRY WdmAudClientList;
|
LIST_ENTRY WdmAudClientList;
|
||||||
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
|
}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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
OpenWavePin(
|
OpenWavePin(
|
||||||
|
@ -279,7 +216,7 @@ NTAPI
|
||||||
WdmAudWaveInitialize(
|
WdmAudWaveInitialize(
|
||||||
IN PDEVICE_OBJECT DeviceObject);
|
IN PDEVICE_OBJECT DeviceObject);
|
||||||
|
|
||||||
NTSTATUS
|
ULONG
|
||||||
ClosePin(
|
ClosePin(
|
||||||
IN PWDMAUD_CLIENT ClientInfo,
|
IN PWDMAUD_CLIENT ClientInfo,
|
||||||
IN ULONG FilterId,
|
IN ULONG FilterId,
|
||||||
|
@ -295,18 +232,51 @@ InsertPinHandle(
|
||||||
IN HANDLE PinHandle,
|
IN HANDLE PinHandle,
|
||||||
IN ULONG FreeIndex);
|
IN ULONG FreeIndex);
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
GetWaveInfoByIndexAndType(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN ULONG DeviceIndex,
|
|
||||||
IN SOUND_DEVICE_TYPE DeviceType,
|
|
||||||
OUT LPWAVE_INFO *OutWaveInfo);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
GetSysAudioDevicePnpName(
|
GetSysAudioDevicePnpName(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN ULONG DeviceIndex,
|
IN ULONG DeviceIndex,
|
||||||
OUT LPWSTR * Device);
|
OUT LPWSTR * Device);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
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
|
#endif
|
||||||
|
|
|
@ -2,17 +2,20 @@
|
||||||
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
|
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
|
||||||
<module name="wdmaud_kernel" type="kernelmodedriver" installbase="system32/drivers" installname="wdmaud.sys">
|
<module name="wdmaud_kernel" type="kernelmodedriver" installbase="system32/drivers" installname="wdmaud.sys">
|
||||||
<include base="wdmaud_kernel">.</include>
|
<include base="wdmaud_kernel">.</include>
|
||||||
<define name="_COMDDK_" />
|
<include base="mmixer">.</include>
|
||||||
<include base="ReactOS">include/reactos/libs/sound</include>
|
<include base="ReactOS">include/reactos/libs/sound</include>
|
||||||
|
<define name="_COMDDK_" />
|
||||||
|
<library>mmixer</library>
|
||||||
<library>ntoskrnl</library>
|
<library>ntoskrnl</library>
|
||||||
|
<library>rtl</library>
|
||||||
|
<library>libcntpr</library>
|
||||||
<library>ks</library>
|
<library>ks</library>
|
||||||
<library>pseh</library>
|
<library>pseh</library>
|
||||||
<library>hal</library>
|
<library>hal</library>
|
||||||
<file>control.c</file>
|
<file>control.c</file>
|
||||||
<file>deviface.c</file>
|
<file>deviface.c</file>
|
||||||
<file>entry.c</file>
|
<file>entry.c</file>
|
||||||
<file>mixer.c</file>
|
<file>mmixer.c</file>
|
||||||
<file>wave.c</file>
|
|
||||||
<file>sup.c</file>
|
<file>sup.c</file>
|
||||||
<file>wdmaud.rc</file>
|
<file>wdmaud.rc</file>
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -75,6 +75,15 @@ typedef PVOID (*PMIXER_ALLOC_EVENT_DATA)(
|
||||||
typedef VOID (*PMIXER_FREE_EVENT_DATA)(
|
typedef VOID (*PMIXER_FREE_EVENT_DATA)(
|
||||||
IN PVOID EventData);
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG SizeOfStruct;
|
ULONG SizeOfStruct;
|
||||||
|
@ -172,6 +181,8 @@ MMixerOpenWave(
|
||||||
IN ULONG DeviceIndex,
|
IN ULONG DeviceIndex,
|
||||||
IN ULONG bWaveIn,
|
IN ULONG bWaveIn,
|
||||||
IN LPWAVEFORMATEX WaveFormat,
|
IN LPWAVEFORMATEX WaveFormat,
|
||||||
|
IN PIN_CREATE_CALLBACK CreateCallback,
|
||||||
|
IN PVOID Context,
|
||||||
OUT PHANDLE PinHandle);
|
OUT PHANDLE PinHandle);
|
||||||
|
|
||||||
MIXER_STATUS
|
MIXER_STATUS
|
||||||
|
|
|
@ -588,7 +588,7 @@ MMixerGetDataByDeviceName(
|
||||||
while(Entry != &MixerList->MixerData)
|
while(Entry != &MixerList->MixerData)
|
||||||
{
|
{
|
||||||
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
|
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
|
// found entry
|
||||||
return MixerData;
|
return MixerData;
|
||||||
|
|
|
@ -233,12 +233,15 @@ MMixerOpenWavePin(
|
||||||
IN ULONG PinId,
|
IN ULONG PinId,
|
||||||
IN LPWAVEFORMATEX WaveFormatEx,
|
IN LPWAVEFORMATEX WaveFormatEx,
|
||||||
IN ACCESS_MASK DesiredAccess,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN PIN_CREATE_CALLBACK CreateCallback,
|
||||||
|
IN PVOID Context,
|
||||||
OUT PHANDLE PinHandle)
|
OUT PHANDLE PinHandle)
|
||||||
{
|
{
|
||||||
PKSPIN_CONNECT PinConnect;
|
PKSPIN_CONNECT PinConnect;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
PKSDATAFORMAT_WAVEFORMATEX DataFormat;
|
||||||
LPMIXER_DATA MixerData;
|
LPMIXER_DATA MixerData;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
MIXER_STATUS MixerStatus;
|
||||||
|
|
||||||
MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
|
MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId);
|
||||||
if (!MixerData)
|
if (!MixerData)
|
||||||
|
@ -260,16 +263,28 @@ MMixerOpenWavePin(
|
||||||
/* initialize with requested wave format */
|
/* initialize with requested wave format */
|
||||||
MMixerInitializeDataFormat(DataFormat, WaveFormatEx);
|
MMixerInitializeDataFormat(DataFormat, WaveFormatEx);
|
||||||
|
|
||||||
/* now create the pin */
|
if (CreateCallback)
|
||||||
Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle);
|
{
|
||||||
|
/* 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 */
|
/* free create info */
|
||||||
MixerContext->Free(PinConnect);
|
MixerContext->Free(PinConnect);
|
||||||
|
|
||||||
if (Status == STATUS_SUCCESS)
|
/* done */
|
||||||
return MM_STATUS_SUCCESS;
|
return MixerStatus;
|
||||||
else
|
|
||||||
return MM_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -415,6 +430,8 @@ MMixerOpenWave(
|
||||||
IN ULONG DeviceIndex,
|
IN ULONG DeviceIndex,
|
||||||
IN ULONG bWaveIn,
|
IN ULONG bWaveIn,
|
||||||
IN LPWAVEFORMATEX WaveFormat,
|
IN LPWAVEFORMATEX WaveFormat,
|
||||||
|
IN PIN_CREATE_CALLBACK CreateCallback,
|
||||||
|
IN PVOID Context,
|
||||||
OUT PHANDLE PinHandle)
|
OUT PHANDLE PinHandle)
|
||||||
{
|
{
|
||||||
PMIXER_LIST MixerList;
|
PMIXER_LIST MixerList;
|
||||||
|
@ -459,7 +476,7 @@ MMixerOpenWave(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now try open the pin */
|
/* 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
|
MIXER_STATUS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue