mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 16:36:07 +00:00
- Rewrite Wave API to enumerate wave out / in devices at startup
- Improves speedup of application minus short delay in system boot - Enumerate controls for source and destination lines svn path=/trunk/; revision=43254
This commit is contained in:
parent
2f541881a8
commit
347609e691
7 changed files with 1503 additions and 765 deletions
|
@ -19,114 +19,6 @@ const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010,
|
|||
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
|
||||
SetIrpIoStatus(
|
||||
IN PIRP Irp,
|
||||
IN NTSTATUS Status,
|
||||
IN ULONG Length)
|
||||
{
|
||||
Irp->IoStatus.Information = Length;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetFilterIdAndPinId(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN PULONG FilterId,
|
||||
IN PULONG PinId)
|
||||
{
|
||||
KSP_PIN Pin;
|
||||
ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins;
|
||||
NTSTATUS Status;
|
||||
KSPIN_COMMUNICATION Communication;
|
||||
KSPIN_DATAFLOW DataFlow;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
|
||||
{
|
||||
DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo->DeviceType);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
Pin.Property.Set = KSPROPSETID_Sysaudio;
|
||||
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
|
||||
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||
|
||||
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
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 (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
|
||||
{
|
||||
if(DeviceInfo->DeviceIndex == Result)
|
||||
{
|
||||
/* found the index */
|
||||
*FilterId = Index;
|
||||
*PinId = SubIndex;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Result++;
|
||||
}
|
||||
}
|
||||
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
||||
{
|
||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
|
||||
{
|
||||
if(DeviceInfo->DeviceIndex == Result)
|
||||
{
|
||||
/* found the index */
|
||||
*FilterId = Index;
|
||||
*PinId = SubIndex;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
Result++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
WdmAudControlOpen(
|
||||
|
@ -135,174 +27,17 @@ WdmAudControlOpen(
|
|||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo)
|
||||
{
|
||||
SYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG BytesReturned;
|
||||
NTSTATUS Status;
|
||||
ACCESS_MASK DesiredAccess = 0;
|
||||
HANDLE PinHandle;
|
||||
KSPIN_CONNECT * PinConnect;
|
||||
ULONG Length, Index;
|
||||
KSDATAFORMAT_WAVEFORMATEX * DataFormat;
|
||||
ULONG FilterId;
|
||||
ULONG PinId;
|
||||
ULONG FreeIndex;
|
||||
|
||||
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
{
|
||||
return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||
}
|
||||
|
||||
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
|
||||
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
||||
{
|
||||
DPRINT1("FIXME: only waveout / wavein devices are supported\n");
|
||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||
return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Invalid device index %u\n", DeviceInfo->DeviceIndex);
|
||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||
}
|
||||
|
||||
/* close pin handle which uses same virtual audio device id and pin id */
|
||||
FreeIndex = MAXULONG;
|
||||
for(Index = 0; Index < ClientInfo->NumPins; Index++)
|
||||
{
|
||||
if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceInfo->DeviceType)
|
||||
{
|
||||
ZwClose(ClientInfo->hPins[Index].Handle);
|
||||
ClientInfo->hPins[Index].Handle = NULL;
|
||||
FreeIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT);
|
||||
PinConnect = ExAllocatePool(NonPagedPool, Length);
|
||||
if (!PinConnect)
|
||||
{
|
||||
/* no memory */
|
||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||
}
|
||||
|
||||
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
{
|
||||
DesiredAccess |= GENERIC_READ;
|
||||
}
|
||||
|
||||
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == AUX_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
{
|
||||
DesiredAccess |= GENERIC_WRITE;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
DataFormat = (KSDATAFORMAT_WAVEFORMATEX*) (PinConnect + 1);
|
||||
DataFormat->WaveFormatEx.wFormatTag = DeviceInfo->u.WaveFormatEx.wFormatTag;
|
||||
DataFormat->WaveFormatEx.nChannels = DeviceInfo->u.WaveFormatEx.nChannels;
|
||||
DataFormat->WaveFormatEx.nSamplesPerSec = DeviceInfo->u.WaveFormatEx.nSamplesPerSec;
|
||||
DataFormat->WaveFormatEx.nBlockAlign = DeviceInfo->u.WaveFormatEx.nBlockAlign;
|
||||
DataFormat->WaveFormatEx.nAvgBytesPerSec = DeviceInfo->u.WaveFormatEx.nAvgBytesPerSec;
|
||||
DataFormat->WaveFormatEx.wBitsPerSample = DeviceInfo->u.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;
|
||||
|
||||
/* 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 = FilterId;
|
||||
|
||||
/* first open the virtual device */
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
ExFreePool(PinConnect);
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
/* now create the pin */
|
||||
Status = KsCreatePin(DeviceExtension->hSysAudio, PinConnect, DesiredAccess, &PinHandle);
|
||||
|
||||
/* free create info */
|
||||
ExFreePool(PinConnect);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
PWDMAUD_HANDLE Handels;
|
||||
|
||||
if (FreeIndex != MAXULONG)
|
||||
{
|
||||
/* re-use a free index */
|
||||
ClientInfo->hPins[Index].Handle = PinHandle;
|
||||
ClientInfo->hPins[Index].FilterId = FilterId;
|
||||
ClientInfo->hPins[Index].PinId = PinId;
|
||||
ClientInfo->hPins[Index].Type = DeviceInfo->DeviceType;
|
||||
|
||||
DeviceInfo->hDevice = PinHandle;
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
Handels = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
|
||||
|
||||
if (Handels)
|
||||
{
|
||||
if (ClientInfo->NumPins)
|
||||
{
|
||||
RtlMoveMemory(Handels, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
|
||||
ExFreePool(ClientInfo->hPins);
|
||||
}
|
||||
|
||||
ClientInfo->hPins = Handels;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceInfo->DeviceType;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId;
|
||||
ClientInfo->NumPins++;
|
||||
}
|
||||
DeviceInfo->hDevice = PinHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceInfo->hDevice = NULL;
|
||||
}
|
||||
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -312,85 +47,23 @@ WdmAudControlDeviceType(
|
|||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo)
|
||||
{
|
||||
KSP_PIN Pin;
|
||||
ULONG Count, BytesReturned, Index, SubIndex, Result, NumPins;
|
||||
ULONG Result = 0;
|
||||
NTSTATUS Status;
|
||||
KSPIN_COMMUNICATION Communication;
|
||||
KSPIN_DATAFLOW DataFlow;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
{
|
||||
DeviceInfo->DeviceCount = DeviceExtension->MixerInfoCount;
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
Result = DeviceExtension->MixerInfoCount;
|
||||
}
|
||||
|
||||
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
|
||||
else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
DPRINT("FIXME: Unsupported device type %x\n", DeviceInfo->DeviceType);
|
||||
DeviceInfo->DeviceCount = 0;
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
Pin.Property.Set = KSPROPSETID_Sysaudio;
|
||||
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
|
||||
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||
|
||||
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status);
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
Result = 0;
|
||||
/* now enumerate all available filters */
|
||||
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 */
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
continue;
|
||||
|
||||
Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
|
||||
DataFlow = 0;
|
||||
|
||||
/* get pin dataflow type */
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
continue;
|
||||
|
||||
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
|
||||
Result++;
|
||||
Result = DeviceExtension->WaveOutDeviceCount;
|
||||
}
|
||||
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
||||
{
|
||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
|
||||
Result++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Result = DeviceExtension->WaveInDeviceCount;
|
||||
}
|
||||
|
||||
/* store result count */
|
||||
|
@ -436,253 +109,6 @@ WdmAudControlDeviceState(
|
|||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
ULONG
|
||||
CheckFormatSupport(
|
||||
IN PKSDATARANGE_AUDIO DataRangeAudio,
|
||||
ULONG SampleFrequency,
|
||||
ULONG Mono8Bit,
|
||||
ULONG Stereo8Bit,
|
||||
ULONG Mono16Bit,
|
||||
ULONG Stereo16Bit)
|
||||
{
|
||||
ULONG Result = 0;
|
||||
|
||||
if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency)
|
||||
{
|
||||
if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8)
|
||||
{
|
||||
Result |= Mono8Bit;
|
||||
if (DataRangeAudio->MaximumChannels >= 2)
|
||||
{
|
||||
Result |= Stereo8Bit;
|
||||
}
|
||||
}
|
||||
|
||||
if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16)
|
||||
{
|
||||
Result |= Mono16Bit;
|
||||
if (DataRangeAudio->MaximumChannels >= 2)
|
||||
{
|
||||
Result |= Stereo8Bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
|
||||
}
|
||||
|
||||
PKEY_VALUE_PARTIAL_INFORMATION
|
||||
ReadKeyValue(
|
||||
IN HANDLE hSubKey,
|
||||
IN PUNICODE_STRING KeyName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Length;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
|
||||
|
||||
/* now query MatchingDeviceId key */
|
||||
Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, NULL, 0, &Length);
|
||||
|
||||
/* check for success */
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
return NULL;
|
||||
|
||||
/* allocate a buffer for key data */
|
||||
PartialInformation = ExAllocatePool(NonPagedPool, Length);
|
||||
|
||||
if (!PartialInformation)
|
||||
return NULL;
|
||||
|
||||
|
||||
/* now query MatchingDeviceId key */
|
||||
Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(PartialInformation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PartialInformation->Type != REG_SZ)
|
||||
{
|
||||
/* invalid key type */
|
||||
ExFreePool(PartialInformation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PartialInformation;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CompareProductName(
|
||||
IN HANDLE hSubKey,
|
||||
IN LPWSTR PnpName,
|
||||
IN ULONG ProductNameSize,
|
||||
OUT LPWSTR ProductName)
|
||||
{
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
|
||||
UNICODE_STRING DriverDescName = RTL_CONSTANT_STRING(L"DriverDesc");
|
||||
UNICODE_STRING MatchingDeviceIdName = RTL_CONSTANT_STRING(L"MatchingDeviceId");
|
||||
ULONG Length;
|
||||
LPWSTR DeviceName;
|
||||
|
||||
/* read MatchingDeviceId value */
|
||||
PartialInformation = ReadKeyValue(hSubKey, &MatchingDeviceIdName);
|
||||
|
||||
if (!PartialInformation)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
||||
/* extract last '&' */
|
||||
DeviceName = wcsrchr((LPWSTR)PartialInformation->Data, L'&');
|
||||
ASSERT(DeviceName);
|
||||
/* terminate it */
|
||||
DeviceName[0] = L'\0';
|
||||
|
||||
Length = wcslen((LPWSTR)PartialInformation->Data);
|
||||
|
||||
DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR)PartialInformation->Data, PnpName, Length);
|
||||
|
||||
if (_wcsnicmp((LPWSTR)PartialInformation->Data, &PnpName[4], Length))
|
||||
{
|
||||
ExFreePool(PartialInformation);
|
||||
return STATUS_NO_MATCH;
|
||||
}
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(PartialInformation);
|
||||
|
||||
/* read DriverDescName value */
|
||||
PartialInformation = ReadKeyValue(hSubKey, &DriverDescName);
|
||||
|
||||
if (!PartialInformation)
|
||||
{
|
||||
/* failed to read driver desc key */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* copy key name */
|
||||
Length = min(ProductNameSize * sizeof(WCHAR), PartialInformation->DataLength);
|
||||
RtlMoveMemory(ProductName, (PVOID)PartialInformation->Data, Length);
|
||||
|
||||
/* zero terminate it */
|
||||
ProductName[ProductNameSize-1] = L'\0';
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(PartialInformation);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
FindProductName(
|
||||
IN LPWSTR PnpName,
|
||||
IN ULONG ProductNameSize,
|
||||
OUT LPWSTR ProductName)
|
||||
{
|
||||
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}");
|
||||
|
||||
UNICODE_STRING SubKeyName;
|
||||
WCHAR SubKey[20];
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hKey, hSubKey;
|
||||
NTSTATUS Status;
|
||||
ULONG Length, Index;
|
||||
PKEY_FULL_INFORMATION KeyInformation;
|
||||
|
||||
for(Index = 0; Index < wcslen(PnpName); Index++)
|
||||
{
|
||||
if (PnpName[Index] == '#')
|
||||
PnpName[Index] = L'\\';
|
||||
}
|
||||
|
||||
|
||||
/* initialize key attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL);
|
||||
|
||||
/* open the key */
|
||||
Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
/* query num of subkeys */
|
||||
Status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &Length);
|
||||
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
DPRINT1("ZwQueryKey failed with %x\n", Status);
|
||||
/* failed */
|
||||
ZwClose(hKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* allocate key information struct */
|
||||
KeyInformation = ExAllocatePool(NonPagedPool, Length);
|
||||
if (!KeyInformation)
|
||||
{
|
||||
/* no memory */
|
||||
ZwClose(hKey);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* query num of subkeys */
|
||||
Status = ZwQueryKey(hKey, KeyFullInformation, (PVOID)KeyInformation, Length, &Length);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ZwQueryKey failed with %x\n", Status);
|
||||
ExFreePool(KeyInformation);
|
||||
ZwClose(hKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now iterate through all subkeys */
|
||||
for(Index = 0; Index < KeyInformation->SubKeys; Index++)
|
||||
{
|
||||
/* subkeys are always in the format 0000-XXXX */
|
||||
swprintf(SubKey, L"%04u", Index);
|
||||
|
||||
/* initialize subkey name */
|
||||
RtlInitUnicodeString(&SubKeyName, SubKey);
|
||||
|
||||
/* initialize key attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL);
|
||||
|
||||
/* open the sub key */
|
||||
Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes);
|
||||
|
||||
/* check for success */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* compare product name */
|
||||
Status = CompareProductName(hSubKey, PnpName, ProductNameSize, ProductName);
|
||||
|
||||
/* close subkey */
|
||||
ZwClose(hSubKey);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(KeyInformation);
|
||||
|
||||
/* close key */
|
||||
ZwClose(hKey);
|
||||
|
||||
/* no matching key found */
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
WdmAudCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -692,19 +118,6 @@ WdmAudCapabilities(
|
|||
{
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||
KSP_PIN PinProperty;
|
||||
KSCOMPONENTID ComponentId;
|
||||
KSMULTIPLE_ITEM * MultipleItem;
|
||||
ULONG BytesReturned;
|
||||
PKSDATARANGE_AUDIO DataRangeAudio;
|
||||
PKSDATARANGE DataRange;
|
||||
ULONG Index;
|
||||
ULONG wChannels = 0;
|
||||
ULONG dwFormats = 0;
|
||||
ULONG dwSupport = 0;
|
||||
ULONG FilterId;
|
||||
ULONG PinId;
|
||||
WCHAR DeviceName[MAX_PATH];
|
||||
|
||||
DPRINT("WdmAudCapabilities entered\n");
|
||||
|
||||
|
@ -713,115 +126,12 @@ WdmAudCapabilities(
|
|||
if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
{
|
||||
Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
|
||||
Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId);
|
||||
if (!NT_SUCCESS(Status))
|
||||
else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
DPRINT1("Invalid device index provided %u\n", DeviceInfo->DeviceIndex);
|
||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||
Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
|
||||
}
|
||||
|
||||
PinProperty.PinId = FilterId;
|
||||
PinProperty.Property.Set = KSPROPSETID_Sysaudio;
|
||||
PinProperty.Property.Id = KSPROPERTY_SYSAUDIO_COMPONENT_ID;
|
||||
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||
|
||||
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
|
||||
|
||||
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
|
||||
DeviceInfo->u.WaveOutCaps.vDriverVersion = MAKELONG(ComponentId.Version, ComponentId.Revision);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
Status = FindProductName(DeviceName, MAXPNAMELEN, DeviceInfo->u.WaveOutCaps.szPname);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DeviceInfo->u.WaveOutCaps.szPname[0] = L'\0';
|
||||
}
|
||||
}
|
||||
|
||||
PinProperty.Reserved = DeviceInfo->DeviceIndex;
|
||||
PinProperty.PinId = PinId;
|
||||
PinProperty.Property.Set = KSPROPSETID_Pin;
|
||||
PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES;
|
||||
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||
|
||||
BytesReturned = 0;
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
return SetIrpIoStatus(Irp, Status, 0);
|
||||
}
|
||||
|
||||
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
|
||||
if (!MultipleItem)
|
||||
{
|
||||
/* no memory */
|
||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||
}
|
||||
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(MultipleItem);
|
||||
return SetIrpIoStatus(Irp, Status, 0);
|
||||
}
|
||||
|
||||
DataRange = (PKSDATARANGE) (MultipleItem + 1);
|
||||
for(Index = 0; Index < MultipleItem->Count; Index++)
|
||||
{
|
||||
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
|
||||
{
|
||||
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);
|
||||
|
||||
dwFormats |= CheckFormatSupport(DataRangeAudio, 11025, WAVE_FORMAT_1M08, WAVE_FORMAT_1S08, WAVE_FORMAT_1M16, WAVE_FORMAT_1S16);
|
||||
dwFormats |= CheckFormatSupport(DataRangeAudio, 22050, WAVE_FORMAT_2M08, WAVE_FORMAT_2S08, WAVE_FORMAT_2M16, WAVE_FORMAT_2S16);
|
||||
dwFormats |= CheckFormatSupport(DataRangeAudio, 44100, WAVE_FORMAT_4M08, WAVE_FORMAT_4S08, WAVE_FORMAT_4M16, WAVE_FORMAT_4S16);
|
||||
dwFormats |= CheckFormatSupport(DataRangeAudio, 48000, WAVE_FORMAT_48M08, WAVE_FORMAT_48S08, WAVE_FORMAT_48M16, WAVE_FORMAT_48S16);
|
||||
dwFormats |= CheckFormatSupport(DataRangeAudio, 96000, WAVE_FORMAT_96M08, WAVE_FORMAT_96S08, WAVE_FORMAT_96M16, WAVE_FORMAT_96S16);
|
||||
|
||||
|
||||
wChannels = DataRangeAudio->MaximumChannels;
|
||||
dwSupport = WAVECAPS_VOLUME; //FIXME get info from nodes
|
||||
}
|
||||
}
|
||||
}
|
||||
DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
|
||||
}
|
||||
|
||||
DeviceInfo->u.WaveOutCaps.dwFormats = dwFormats;
|
||||
DeviceInfo->u.WaveOutCaps.dwSupport = dwSupport;
|
||||
DeviceInfo->u.WaveOutCaps.wChannels = wChannels;
|
||||
|
||||
ExFreePool(MultipleItem);
|
||||
|
||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
|
@ -846,6 +156,7 @@ WdmAudIoctlClose(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ WdmAudInstallDevice(
|
|||
|
||||
Status = WdmAudMixerInitialize(DeviceObject);
|
||||
DPRINT("WdmAudMixerInitialize Status %x\n", Status);
|
||||
Status = WdmAudWaveInitialize(DeviceObject);
|
||||
DPRINT("WdmAudWaveInitialize Status %x\n", Status);
|
||||
|
||||
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
|
||||
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
||||
|
|
|
@ -21,6 +21,7 @@ const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0
|
|||
const GUID KSNODETYPE_CHORUS = {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
|
||||
const GUID KSNODETYPE_REVERB = {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
|
||||
const GUID KSNODETYPE_SUPERMIX = {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
|
||||
const GUID KSNODETYPE_SUM = {0xDA441A60L, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
|
||||
|
||||
#define DESTINATION_LINE 0xFFFF0000
|
||||
|
||||
|
@ -62,7 +63,7 @@ GetSourceMixerLineByLineId(
|
|||
while(Entry != &MixerInfo->LineList)
|
||||
{
|
||||
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
||||
DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID);
|
||||
DPRINT1("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID);
|
||||
if (MixerLineSrc->Line.dwLineID == dwLineID)
|
||||
return MixerLineSrc;
|
||||
|
||||
|
@ -719,36 +720,260 @@ AllocatePinArray(
|
|||
return Pins;
|
||||
}
|
||||
|
||||
PKSTOPOLOGY_CONNECTION
|
||||
GetConnectionByIndex(
|
||||
IN PKSMULTIPLE_ITEM MultipleItem,
|
||||
IN ULONG Index)
|
||||
{
|
||||
PKSTOPOLOGY_CONNECTION Descriptor;
|
||||
|
||||
ASSERT(Index < MultipleItem->Count);
|
||||
|
||||
Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
|
||||
return &Descriptor[Index];
|
||||
}
|
||||
|
||||
LPGUID
|
||||
GetNodeType(
|
||||
IN PKSMULTIPLE_ITEM MultipleItem,
|
||||
IN ULONG Index)
|
||||
{
|
||||
LPGUID NodeType;
|
||||
|
||||
ASSERT(Index < MultipleItem->Count);
|
||||
|
||||
NodeType = (LPGUID)(MultipleItem + 1);
|
||||
return &NodeType[Index];
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetControlsFromPinByConnectionIndex(
|
||||
IN PKSMULTIPLE_ITEM NodeConnections,
|
||||
IN PKSMULTIPLE_ITEM NodeTypes,
|
||||
IN ULONG bUpDirection,
|
||||
IN ULONG NodeConnectionIndex,
|
||||
OUT PULONG Nodes)
|
||||
{
|
||||
PKSTOPOLOGY_CONNECTION CurConnection;
|
||||
LPGUID NodeType;
|
||||
ULONG NodeIndex;
|
||||
NTSTATUS Status;
|
||||
ULONG NodeConnectionCount, Index;
|
||||
PULONG NodeConnection;
|
||||
|
||||
|
||||
/* get current connection */
|
||||
CurConnection = GetConnectionByIndex(NodeConnections, NodeConnectionIndex);
|
||||
|
||||
if (bUpDirection)
|
||||
NodeIndex = CurConnection->FromNode;
|
||||
else
|
||||
NodeIndex = CurConnection->ToNode;
|
||||
|
||||
/* get target node type of current connection */
|
||||
NodeType = GetNodeType(NodeTypes, NodeIndex);
|
||||
|
||||
if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_SUM) || IsEqualGUIDAligned(NodeType, &KSNODETYPE_MUX))
|
||||
{
|
||||
if (bUpDirection)
|
||||
{
|
||||
/* add the sum / mux node to destination line */
|
||||
//Nodes[NodeIndex] = TRUE;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* now add the node */
|
||||
Nodes[NodeIndex] = TRUE;
|
||||
|
||||
|
||||
/* get all node indexes referenced by that node */
|
||||
if (bUpDirection)
|
||||
{
|
||||
Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
for(Index = 0; Index < NodeConnectionCount; Index++)
|
||||
{
|
||||
/* iterate recursively into the nodes */
|
||||
Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
}
|
||||
/* free node connection indexes */
|
||||
ExFreePool(NodeConnection);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetControlsFromPin(
|
||||
IN PKSMULTIPLE_ITEM NodeConnections,
|
||||
IN PKSMULTIPLE_ITEM NodeTypes,
|
||||
IN ULONG PinId,
|
||||
IN ULONG bUpDirection,
|
||||
OUT PULONG Nodes)
|
||||
{
|
||||
ULONG NodeConnectionCount, Index;
|
||||
NTSTATUS Status;
|
||||
PULONG NodeConnection;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(PinId != (ULONG)-1);
|
||||
|
||||
/* get all node indexes referenced by that pin */
|
||||
if (bUpDirection)
|
||||
Status = GetNodeIndexes(NodeConnections, PinId, FALSE, FALSE, &NodeConnectionCount, &NodeConnection);
|
||||
else
|
||||
Status = GetNodeIndexes(NodeConnections, PinId, FALSE, TRUE, &NodeConnectionCount, &NodeConnection);
|
||||
|
||||
for(Index = 0; Index < NodeConnectionCount; Index++)
|
||||
{
|
||||
/* get all associated controls */
|
||||
Status = GetControlsFromPinByConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
|
||||
}
|
||||
|
||||
ExFreePool(NodeConnection);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
AddMixerControl(
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PKSMULTIPLE_ITEM NodeTypes,
|
||||
IN ULONG NodeIndex,
|
||||
OUT LPMIXERCONTROLW MixerControl)
|
||||
{
|
||||
LPGUID NodeType;
|
||||
KSP_NODE Node;
|
||||
ULONG BytesReturned;
|
||||
NTSTATUS Status;
|
||||
LPWSTR Name;
|
||||
|
||||
|
||||
/* initialize mixer control */
|
||||
MixerControl->cbStruct = sizeof(MIXERCONTROLW);
|
||||
MixerControl->dwControlID = MixerInfo->ControlId;
|
||||
|
||||
/* get node type */
|
||||
NodeType = GetNodeType(NodeTypes, NodeIndex);
|
||||
/* store control type */
|
||||
MixerControl->dwControlType = GetControlTypeFromTopologyNode(NodeType);
|
||||
|
||||
MixerControl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; //FIXME
|
||||
MixerControl->cMultipleItems = 0; //FIXME
|
||||
|
||||
if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
|
||||
{
|
||||
MixerControl->Bounds.dwMinimum = 0;
|
||||
MixerControl->Bounds.dwMaximum = 1;
|
||||
}
|
||||
else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
|
||||
{
|
||||
MixerControl->Bounds.dwMinimum = 0;
|
||||
MixerControl->Bounds.dwMaximum = 0xFFFF;
|
||||
MixerControl->Metrics.cSteps = 0xC0; //FIXME
|
||||
}
|
||||
|
||||
/* setup request to retrieve name */
|
||||
Node.NodeId = NodeIndex;
|
||||
Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME;
|
||||
Node.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||
Node.Property.Set = KSPROPSETID_Topology;
|
||||
Node.Reserved = 0;
|
||||
|
||||
/* get node name size */
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned);
|
||||
|
||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
ASSERT(BytesReturned != 0);
|
||||
Name = ExAllocatePool(NonPagedPool, BytesReturned);
|
||||
if (!Name)
|
||||
{
|
||||
/* not enough memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* get node name */
|
||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
RtlMoveMemory(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
|
||||
MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
|
||||
RtlMoveMemory(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
|
||||
MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
}
|
||||
|
||||
/* free name buffer */
|
||||
ExFreePool(Name);
|
||||
}
|
||||
|
||||
MixerInfo->ControlId++;
|
||||
|
||||
DPRINT("Status %x Name %S\n", Status, MixerControl->szName);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
AddMixerSourceLine(
|
||||
IN OUT LPMIXER_INFO MixerInfo,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PKSMULTIPLE_ITEM NodeConnections,
|
||||
IN PKSMULTIPLE_ITEM NodeTypes,
|
||||
IN ULONG DeviceIndex,
|
||||
IN ULONG PinId)
|
||||
IN ULONG PinId,
|
||||
IN ULONG bBridgePin,
|
||||
IN ULONG bTargetPin)
|
||||
{
|
||||
LPMIXERLINE_EXT SrcLine, DstLine;
|
||||
NTSTATUS Status;
|
||||
KSP_PIN Pin;
|
||||
LPWSTR PinName;
|
||||
GUID NodeType;
|
||||
ULONG BytesReturned;
|
||||
ULONG BytesReturned, ControlCount, Index;
|
||||
PULONG Nodes;
|
||||
|
||||
if (!bTargetPin)
|
||||
{
|
||||
/* allocate src mixer line */
|
||||
SrcLine = (LPMIXERLINE_EXT)ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_EXT));
|
||||
|
||||
if (!SrcLine)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* zero struct */
|
||||
RtlZeroMemory(SrcLine, sizeof(MIXERLINE_EXT));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(!IsListEmpty(&MixerInfo->LineList));
|
||||
SrcLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
||||
}
|
||||
|
||||
/* get destination line */
|
||||
DstLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
||||
ASSERT(DstLine);
|
||||
|
||||
|
||||
if (!bTargetPin)
|
||||
{
|
||||
/* initialize mixer src line */
|
||||
SrcLine->DeviceIndex = DeviceIndex;
|
||||
SrcLine->PinId = PinId;
|
||||
SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
|
||||
|
||||
/* get destination line */
|
||||
DstLine = GetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
||||
|
||||
/* initialize mixer destination line */
|
||||
SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
|
||||
SrcLine->Line.dwDestination = 0;
|
||||
|
@ -758,28 +983,106 @@ AddMixerSourceLine(
|
|||
SrcLine->Line.dwUser = 0;
|
||||
SrcLine->Line.cChannels = DstLine->Line.cChannels;
|
||||
SrcLine->Line.cConnections = 0;
|
||||
SrcLine->Line.cControls = 1; //FIXME
|
||||
SrcLine->Line.Target.dwType = 1;
|
||||
SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
|
||||
SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
|
||||
SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
|
||||
SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
|
||||
wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
|
||||
|
||||
//HACK
|
||||
SrcLine->LineControls = ExAllocatePool(NonPagedPool, SrcLine->Line.cControls * sizeof(MIXERCONTROLW));
|
||||
if (!SrcLine->LineControls)
|
||||
}
|
||||
|
||||
/* allocate a node arrary */
|
||||
Nodes = ExAllocatePool(NonPagedPool, sizeof(ULONG) * NodeTypes->Count);
|
||||
|
||||
if (!Nodes)
|
||||
{
|
||||
/* not enough memory */
|
||||
if (!bTargetPin)
|
||||
{
|
||||
ExFreePool(SrcLine);
|
||||
}
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* clear line controls */
|
||||
RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW));
|
||||
/* clear nodes array */
|
||||
RtlZeroMemory(Nodes, sizeof(ULONG) * NodeTypes->Count);
|
||||
|
||||
/* fill in pseudo mixer control */
|
||||
SrcLine->LineControls->dwControlID = 1; //FIXME
|
||||
SrcLine->LineControls->cbStruct = sizeof(MIXERCONTROLW);
|
||||
SrcLine->LineControls->fdwControl = 0;
|
||||
SrcLine->LineControls->cMultipleItems = 0;
|
||||
wcscpy(SrcLine->LineControls->szName, L"test");
|
||||
wcscpy(SrcLine->LineControls->szShortName, L"test");
|
||||
Status = GetControlsFromPin(NodeConnections, NodeTypes, PinId, bTargetPin, Nodes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* something went wrong */
|
||||
if (!bTargetPin)
|
||||
{
|
||||
ExFreePool(SrcLine);
|
||||
}
|
||||
ExFreePool(Nodes);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now count all nodes controlled by that pin */
|
||||
ControlCount = 0;
|
||||
for(Index = 0; Index < NodeTypes->Count; Index++)
|
||||
{
|
||||
if (Nodes[Index])
|
||||
ControlCount++;
|
||||
}
|
||||
|
||||
/* now allocate the line controls */
|
||||
if (ControlCount)
|
||||
{
|
||||
SrcLine->LineControls = ExAllocatePool(NonPagedPool, sizeof(MIXERCONTROLW) * ControlCount);
|
||||
|
||||
if (!SrcLine->LineControls)
|
||||
{
|
||||
/* no memory available */
|
||||
if (!bTargetPin)
|
||||
{
|
||||
ExFreePool(SrcLine);
|
||||
}
|
||||
ExFreePool(Nodes);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
SrcLine->NodeIds = ExAllocatePool(NonPagedPool, sizeof(ULONG) * ControlCount);
|
||||
if (!SrcLine->NodeIds)
|
||||
{
|
||||
/* no memory available */
|
||||
ExFreePool(SrcLine->LineControls);
|
||||
if (!bTargetPin)
|
||||
{
|
||||
ExFreePool(SrcLine);
|
||||
}
|
||||
ExFreePool(Nodes);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* zero line controls */
|
||||
RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW) * ControlCount);
|
||||
RtlZeroMemory(SrcLine->NodeIds, sizeof(ULONG) * ControlCount);
|
||||
|
||||
ControlCount = 0;
|
||||
for(Index = 0; Index < NodeTypes->Count; Index++)
|
||||
{
|
||||
if (Nodes[Index])
|
||||
{
|
||||
/* store the node index for retrieving / setting details */
|
||||
SrcLine->NodeIds[ControlCount] = Index;
|
||||
|
||||
Status = AddMixerControl(MixerInfo, FileObject, NodeTypes, Index, &SrcLine->LineControls[ControlCount]);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* increment control count on success */
|
||||
ControlCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* store control count */
|
||||
SrcLine->Line.cControls = ControlCount;
|
||||
}
|
||||
|
||||
/* release nodes array */
|
||||
ExFreePool(Nodes);
|
||||
|
||||
/* get pin category */
|
||||
Pin.PinId = PinId;
|
||||
|
@ -831,17 +1134,12 @@ AddMixerSourceLine(
|
|||
}
|
||||
}
|
||||
|
||||
SrcLine->Line.Target.dwType = 1;
|
||||
SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
|
||||
SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
|
||||
SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
|
||||
SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
|
||||
wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
|
||||
|
||||
|
||||
/* insert src line */
|
||||
if (!bTargetPin)
|
||||
{
|
||||
InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
|
||||
DstLine->Line.cConnections++;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -851,8 +1149,12 @@ NTSTATUS
|
|||
AddMixerSourceLines(
|
||||
IN OUT LPMIXER_INFO MixerInfo,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
IN PKSMULTIPLE_ITEM NodeConnections,
|
||||
IN PKSMULTIPLE_ITEM NodeTypes,
|
||||
IN ULONG DeviceIndex,
|
||||
IN ULONG PinsCount,
|
||||
IN ULONG BridgePinIndex,
|
||||
IN ULONG TargetPinIndex,
|
||||
IN PULONG Pins)
|
||||
{
|
||||
ULONG Index;
|
||||
|
@ -862,7 +1164,7 @@ AddMixerSourceLines(
|
|||
{
|
||||
if (Pins[Index-1])
|
||||
{
|
||||
AddMixerSourceLine(MixerInfo, FileObject, DeviceIndex, Index-1);
|
||||
AddMixerSourceLine(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, Index-1, (Index -1 == BridgePinIndex), (Index -1 == TargetPinIndex));
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
|
@ -987,7 +1289,7 @@ HandlePhysicalConnection(
|
|||
PinsSrcRef[OutConnection->Pin] = TRUE;
|
||||
}
|
||||
|
||||
Status = AddMixerSourceLines(MixerInfo, FileObject, DeviceIndex, PinsRefCount, PinsSrcRef);
|
||||
Status = AddMixerSourceLines(MixerInfo, FileObject, NodeConnections, NodeTypes, DeviceIndex, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
|
||||
|
||||
ExFreePool(MixerControls);
|
||||
ExFreePool(PinsSrcRef);
|
||||
|
@ -1045,10 +1347,6 @@ InitializeMixer(
|
|||
if (!DestinationLine)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* initialize mixer info */
|
||||
MixerInfo->hMixer = hDevice;
|
||||
MixerInfo->MixerFileObject = FileObject;
|
||||
|
||||
/* intialize mixer caps */
|
||||
MixerInfo->MixCaps.wMid = MM_MICROSOFT; //FIXME
|
||||
MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; //FIXME
|
||||
|
@ -1083,7 +1381,6 @@ InitializeMixer(
|
|||
DestinationLine->Line.dwUser = 0;
|
||||
DestinationLine->Line.dwComponentType = (bInput == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
|
||||
DestinationLine->Line.cChannels = 2; //FIXME
|
||||
DestinationLine->Line.cControls = 0; //FIXME
|
||||
wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME
|
||||
wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME
|
||||
DestinationLine->Line.Target.dwType = (bInput == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
|
||||
|
@ -1411,6 +1708,7 @@ WdmAudGetLineControls(
|
|||
{
|
||||
LPMIXERLINE_EXT MixerLineSrc;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Index;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
@ -1427,15 +1725,12 @@ WdmAudGetLineControls(
|
|||
ASSERT(MixerLineSrc);
|
||||
if (MixerLineSrc)
|
||||
{
|
||||
RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERLINECONTROLSW));
|
||||
RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERCONTROLW));
|
||||
}
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
else if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
|
||||
{
|
||||
DPRINT1("dwLineID %u\n",DeviceInfo->u.MixControls.dwLineID);
|
||||
UNIMPLEMENTED
|
||||
//HACK
|
||||
if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount)
|
||||
{
|
||||
/* invalid parameter */
|
||||
|
@ -1444,12 +1739,19 @@ WdmAudGetLineControls(
|
|||
|
||||
MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwLineID);
|
||||
ASSERT(MixerLineSrc);
|
||||
if (MixerLineSrc)
|
||||
|
||||
Index = 0;
|
||||
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
||||
{
|
||||
RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERLINECONTROLSW));
|
||||
}
|
||||
if (DeviceInfo->u.MixControls.dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
|
||||
{
|
||||
RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
}
|
||||
DPRINT1("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x\n", DeviceInfo->u.MixControls.dwControlType, DeviceInfo->u.MixControls.dwLineID);
|
||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
|
||||
}
|
||||
|
||||
UNIMPLEMENTED;
|
||||
//DbgBreakPoint();
|
||||
|
|
300
reactos/drivers/wdm/audio/legacy/wdmaud/sup.c
Normal file
300
reactos/drivers/wdm/audio/legacy/wdmaud/sup.c
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* 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
|
||||
* PROGRAMMER: Andrew Greenwood
|
||||
* Johannes Anderwald
|
||||
*/
|
||||
#include "wdmaud.h"
|
||||
|
||||
NTSTATUS
|
||||
SetIrpIoStatus(
|
||||
IN PIRP Irp,
|
||||
IN NTSTATUS Status,
|
||||
IN ULONG Length)
|
||||
{
|
||||
Irp->IoStatus.Information = Length;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ClosePin(
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN ULONG FilterId,
|
||||
IN ULONG PinId,
|
||||
IN SOUND_DEVICE_TYPE DeviceType)
|
||||
{
|
||||
ULONG Index;
|
||||
|
||||
for(Index = 0; Index < ClientInfo->NumPins; Index++)
|
||||
{
|
||||
if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceType)
|
||||
{
|
||||
if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE)
|
||||
{
|
||||
ZwClose(ClientInfo->hPins[Index].Handle);
|
||||
}
|
||||
ClientInfo->hPins[Index].Handle = NULL;
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
return MAXULONG;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InsertPinHandle(
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN ULONG FilterId,
|
||||
IN ULONG PinId,
|
||||
IN SOUND_DEVICE_TYPE DeviceType,
|
||||
IN HANDLE PinHandle,
|
||||
IN ULONG FreeIndex)
|
||||
{
|
||||
PWDMAUD_HANDLE Handles;
|
||||
|
||||
if (FreeIndex != MAXULONG)
|
||||
{
|
||||
/* re-use a free index */
|
||||
ClientInfo->hPins[FreeIndex].Handle = PinHandle;
|
||||
ClientInfo->hPins[FreeIndex].FilterId = FilterId;
|
||||
ClientInfo->hPins[FreeIndex].PinId = PinId;
|
||||
ClientInfo->hPins[FreeIndex].Type = DeviceType;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
|
||||
|
||||
if (!Handles)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
if (ClientInfo->NumPins)
|
||||
{
|
||||
RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
|
||||
ExFreePool(ClientInfo->hPins);
|
||||
}
|
||||
|
||||
ClientInfo->hPins = Handles;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceType;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId;
|
||||
ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId;
|
||||
ClientInfo->NumPins++;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PKEY_VALUE_PARTIAL_INFORMATION
|
||||
ReadKeyValue(
|
||||
IN HANDLE hSubKey,
|
||||
IN PUNICODE_STRING KeyName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Length;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
|
||||
|
||||
/* now query MatchingDeviceId key */
|
||||
Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, NULL, 0, &Length);
|
||||
|
||||
/* check for success */
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
return NULL;
|
||||
|
||||
/* allocate a buffer for key data */
|
||||
PartialInformation = ExAllocatePool(NonPagedPool, Length);
|
||||
|
||||
if (!PartialInformation)
|
||||
return NULL;
|
||||
|
||||
|
||||
/* now query MatchingDeviceId key */
|
||||
Status = ZwQueryValueKey(hSubKey, KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(PartialInformation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PartialInformation->Type != REG_SZ)
|
||||
{
|
||||
/* invalid key type */
|
||||
ExFreePool(PartialInformation);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PartialInformation;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CompareProductName(
|
||||
IN HANDLE hSubKey,
|
||||
IN LPWSTR PnpName,
|
||||
IN ULONG ProductNameSize,
|
||||
OUT LPWSTR ProductName)
|
||||
{
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
|
||||
UNICODE_STRING DriverDescName = RTL_CONSTANT_STRING(L"DriverDesc");
|
||||
UNICODE_STRING MatchingDeviceIdName = RTL_CONSTANT_STRING(L"MatchingDeviceId");
|
||||
ULONG Length;
|
||||
LPWSTR DeviceName;
|
||||
|
||||
/* read MatchingDeviceId value */
|
||||
PartialInformation = ReadKeyValue(hSubKey, &MatchingDeviceIdName);
|
||||
|
||||
if (!PartialInformation)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
||||
/* extract last '&' */
|
||||
DeviceName = wcsrchr((LPWSTR)PartialInformation->Data, L'&');
|
||||
ASSERT(DeviceName);
|
||||
/* terminate it */
|
||||
DeviceName[0] = L'\0';
|
||||
|
||||
Length = wcslen((LPWSTR)PartialInformation->Data);
|
||||
|
||||
DPRINT("DeviceName %S PnpName %S Length %u\n", (LPWSTR)PartialInformation->Data, PnpName, Length);
|
||||
|
||||
if (_wcsnicmp((LPWSTR)PartialInformation->Data, &PnpName[4], Length))
|
||||
{
|
||||
ExFreePool(PartialInformation);
|
||||
return STATUS_NO_MATCH;
|
||||
}
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(PartialInformation);
|
||||
|
||||
/* read DriverDescName value */
|
||||
PartialInformation = ReadKeyValue(hSubKey, &DriverDescName);
|
||||
|
||||
if (!PartialInformation)
|
||||
{
|
||||
/* failed to read driver desc key */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* copy key name */
|
||||
Length = min(ProductNameSize * sizeof(WCHAR), PartialInformation->DataLength);
|
||||
RtlMoveMemory(ProductName, (PVOID)PartialInformation->Data, Length);
|
||||
|
||||
/* zero terminate it */
|
||||
ProductName[ProductNameSize-1] = L'\0';
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(PartialInformation);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
FindProductName(
|
||||
IN LPWSTR PnpName,
|
||||
IN ULONG ProductNameSize,
|
||||
OUT LPWSTR ProductName)
|
||||
{
|
||||
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E96C-E325-11CE-BFC1-08002BE10318}");
|
||||
|
||||
UNICODE_STRING SubKeyName;
|
||||
WCHAR SubKey[20];
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE hKey, hSubKey;
|
||||
NTSTATUS Status;
|
||||
ULONG Length, Index;
|
||||
PKEY_FULL_INFORMATION KeyInformation;
|
||||
|
||||
for(Index = 0; Index < wcslen(PnpName); Index++)
|
||||
{
|
||||
if (PnpName[Index] == '#')
|
||||
PnpName[Index] = L'\\';
|
||||
}
|
||||
|
||||
|
||||
/* initialize key attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, NULL, NULL);
|
||||
|
||||
/* open the key */
|
||||
Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
/* query num of subkeys */
|
||||
Status = ZwQueryKey(hKey, KeyFullInformation, NULL, 0, &Length);
|
||||
|
||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
DPRINT1("ZwQueryKey failed with %x\n", Status);
|
||||
/* failed */
|
||||
ZwClose(hKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* allocate key information struct */
|
||||
KeyInformation = ExAllocatePool(NonPagedPool, Length);
|
||||
if (!KeyInformation)
|
||||
{
|
||||
/* no memory */
|
||||
ZwClose(hKey);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* query num of subkeys */
|
||||
Status = ZwQueryKey(hKey, KeyFullInformation, (PVOID)KeyInformation, Length, &Length);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ZwQueryKey failed with %x\n", Status);
|
||||
ExFreePool(KeyInformation);
|
||||
ZwClose(hKey);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now iterate through all subkeys */
|
||||
for(Index = 0; Index < KeyInformation->SubKeys; Index++)
|
||||
{
|
||||
/* subkeys are always in the format 0000-XXXX */
|
||||
swprintf(SubKey, L"%04u", Index);
|
||||
|
||||
/* initialize subkey name */
|
||||
RtlInitUnicodeString(&SubKeyName, SubKey);
|
||||
|
||||
/* initialize key attributes */
|
||||
InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL);
|
||||
|
||||
/* open the sub key */
|
||||
Status = ZwOpenKey(&hSubKey, GENERIC_READ, &ObjectAttributes);
|
||||
|
||||
/* check for success */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* compare product name */
|
||||
Status = CompareProductName(hSubKey, PnpName, ProductNameSize, ProductName);
|
||||
|
||||
/* close subkey */
|
||||
ZwClose(hSubKey);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* free buffer */
|
||||
ExFreePool(KeyInformation);
|
||||
|
||||
/* close key */
|
||||
ZwClose(hKey);
|
||||
|
||||
/* no matching key found */
|
||||
return Status;
|
||||
}
|
||||
|
756
reactos/drivers/wdm/audio/legacy/wdmaud/wave.c
Normal file
756
reactos/drivers/wdm/audio/legacy/wdmaud/wave.c
Normal file
|
@ -0,0 +1,756 @@
|
|||
/*
|
||||
* 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_UNSUCCESSFUL, 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;
|
||||
}
|
||||
|
|
@ -40,21 +40,33 @@ typedef struct
|
|||
ULONG DeviceIndex;
|
||||
MIXERLINEW Line;
|
||||
LPMIXERCONTROLW LineControls;
|
||||
PULONG NodeIds;
|
||||
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE hMixer;
|
||||
PFILE_OBJECT MixerFileObject;
|
||||
|
||||
MIXERCAPSW MixCaps;
|
||||
|
||||
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;
|
||||
|
@ -77,6 +89,12 @@ typedef struct
|
|||
ULONG MixerInfoCount;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
|
||||
ULONG WaveInDeviceCount;
|
||||
LIST_ENTRY WaveInList;
|
||||
|
||||
ULONG WaveOutDeviceCount;
|
||||
LIST_ENTRY WaveOutList;
|
||||
|
||||
|
||||
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
|
||||
|
||||
|
@ -86,6 +104,16 @@ typedef struct
|
|||
PIRP Irp;
|
||||
}CONTEXT_WRITE, *PCONTEXT_WRITE;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
OpenWavePin(
|
||||
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
|
||||
IN ULONG FilterId,
|
||||
IN ULONG PinId,
|
||||
IN LPWAVEFORMATEX WaveFormatEx,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
OUT PHANDLE PinHandle);
|
||||
|
||||
NTSTATUS
|
||||
WdmAudRegisterDeviceInterface(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
|
@ -120,6 +148,14 @@ WdmAudControlOpenMixer(
|
|||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo);
|
||||
|
||||
NTSTATUS
|
||||
WdmAudControlOpenWave(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo);
|
||||
|
||||
|
||||
ULONG
|
||||
GetNumOfMixerDevices(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
@ -148,6 +184,13 @@ WdmAudMixerCapabilities(
|
|||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
WdmAudWaveCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN PWDMAUD_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
WdmAudFrameSize(
|
||||
|
@ -192,5 +235,26 @@ NTSTATUS
|
|||
WdmAudMixerInitialize(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
WdmAudWaveInitialize(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
NTSTATUS
|
||||
ClosePin(
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN ULONG FilterId,
|
||||
IN ULONG PinId,
|
||||
IN SOUND_DEVICE_TYPE DeviceType);
|
||||
|
||||
NTSTATUS
|
||||
InsertPinHandle(
|
||||
IN PWDMAUD_CLIENT ClientInfo,
|
||||
IN ULONG FilterId,
|
||||
IN ULONG PinId,
|
||||
IN SOUND_DEVICE_TYPE DeviceType,
|
||||
IN HANDLE PinHandle,
|
||||
IN ULONG FreeIndex);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
<library>ntoskrnl</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>sup.c</file>
|
||||
<file>wdmaud.rc</file>
|
||||
</module>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue