mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +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\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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,7 +222,7 @@ 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);
|
||||
Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -242,14 +231,6 @@ WdmAudGetDeviceInterface(
|
|||
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 */
|
||||
Length = (wcslen(Device)+1) * sizeof(WCHAR);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
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
|
||||
* 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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include "mmixer.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
HANDLE hMixer;
|
||||
ULONG NotificationType;
|
||||
ULONG Value;
|
||||
}MIXER_EVENT, *PMIXER_EVENT;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE Handle;
|
||||
|
@ -44,60 +36,6 @@ typedef struct
|
|||
LIST_ENTRY MixerEventList;
|
||||
}WDMAUD_CLIENT, *PWDMAUD_CLIENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
ULONG dwControlID;
|
||||
}MIXERCONTROL_DATA, *LPMIXERCONTROL_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MIXERCONTROL_DATA Header;
|
||||
LONG SignedMinimum;
|
||||
LONG SignedMaximum;
|
||||
LONG SteppingDelta;
|
||||
ULONG InputSteppingDelta;
|
||||
ULONG ValuesCount;
|
||||
PLONG Values;
|
||||
}MIXERVOLUME_DATA, *LPMIXERVOLUME_DATA;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
ULONG PinId;
|
||||
ULONG DeviceIndex;
|
||||
MIXERLINEW Line;
|
||||
LPMIXERCONTROLW LineControls;
|
||||
PULONG NodeIds;
|
||||
LIST_ENTRY LineControlsExtraData;
|
||||
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MIXERCAPSW MixCaps;
|
||||
ULONG DeviceIndex;
|
||||
LIST_ENTRY LineList;
|
||||
ULONG ControlId;
|
||||
}MIXER_INFO, *LPMIXER_INFO;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
ULONG FilterId;
|
||||
ULONG PinId;
|
||||
ULONG bInput;
|
||||
union
|
||||
{
|
||||
WAVEOUTCAPSW OutCaps;
|
||||
WAVEINCAPSW InCaps;
|
||||
}u;
|
||||
}WAVE_INFO, *LPWAVE_INFO;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
|
@ -117,18 +55,17 @@ typedef struct
|
|||
HANDLE hSysAudio;
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
ULONG MixerInfoCount;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
|
||||
ULONG WaveInDeviceCount;
|
||||
LIST_ENTRY WaveInList;
|
||||
|
||||
ULONG WaveOutDeviceCount;
|
||||
LIST_ENTRY WaveOutList;
|
||||
|
||||
LIST_ENTRY WdmAudClientList;
|
||||
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PWDMAUD_CLIENT ClientInfo;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
SOUND_DEVICE_TYPE DeviceType;
|
||||
}PIN_CREATE_CONTEXT, *PPIN_CREATE_CONTEXT;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
OpenWavePin(
|
||||
|
@ -279,7 +216,7 @@ NTAPI
|
|||
WdmAudWaveInitialize(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
NTSTATUS
|
||||
ULONG
|
||||
ClosePin(
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN ULONG FilterId,
|
||||
|
@ -295,18 +232,51 @@ InsertPinHandle(
|
|||
IN HANDLE PinHandle,
|
||||
IN ULONG FreeIndex);
|
||||
|
||||
|
||||
NTSTATUS
|
||||
GetWaveInfoByIndexAndType(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG DeviceIndex,
|
||||
IN SOUND_DEVICE_TYPE DeviceType,
|
||||
OUT LPWAVE_INFO *OutWaveInfo);
|
||||
|
||||
NTSTATUS
|
||||
GetSysAudioDevicePnpName(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG DeviceIndex,
|
||||
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
|
||||
|
|
|
@ -2,17 +2,20 @@
|
|||
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
|
||||
<module name="wdmaud_kernel" type="kernelmodedriver" installbase="system32/drivers" installname="wdmaud.sys">
|
||||
<include base="wdmaud_kernel">.</include>
|
||||
<define name="_COMDDK_" />
|
||||
<include base="mmixer">.</include>
|
||||
<include base="ReactOS">include/reactos/libs/sound</include>
|
||||
<define name="_COMDDK_" />
|
||||
<library>mmixer</library>
|
||||
<library>ntoskrnl</library>
|
||||
<library>rtl</library>
|
||||
<library>libcntpr</library>
|
||||
<library>ks</library>
|
||||
<library>pseh</library>
|
||||
<library>hal</library>
|
||||
<file>control.c</file>
|
||||
<file>deviface.c</file>
|
||||
<file>entry.c</file>
|
||||
<file>mixer.c</file>
|
||||
<file>wave.c</file>
|
||||
<file>mmixer.c</file>
|
||||
<file>sup.c</file>
|
||||
<file>wdmaud.rc</file>
|
||||
</module>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue