mirror of
https://github.com/reactos/reactos.git
synced 2025-06-16 11:38:29 +00:00
[WDMAUD]
- Remove ReactOS specific pin creation hack [SYSAUDIO] - Refactor sysaudio pin creation - Remove ReactOS specific pin creation hack - Remove unused functions svn path=/trunk/; revision=42580
This commit is contained in:
parent
2aa4d40fff
commit
732ce0ed84
6 changed files with 422 additions and 668 deletions
|
@ -135,7 +135,7 @@ WdmAudControlOpen(
|
||||||
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
IN PWDMAUD_DEVICE_INFO DeviceInfo,
|
||||||
IN PWDMAUD_CLIENT ClientInfo)
|
IN PWDMAUD_CLIENT ClientInfo)
|
||||||
{
|
{
|
||||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
SYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -185,21 +185,16 @@ WdmAudControlOpen(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT);
|
||||||
InstanceInfo = ExAllocatePool(NonPagedPool, Length);
|
PinConnect = ExAllocatePool(NonPagedPool, Length);
|
||||||
if (!InstanceInfo)
|
if (!PinConnect)
|
||||||
{
|
{
|
||||||
/* no memory */
|
/* no memory */
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceInfo->Property.Set = KSPROPSETID_Sysaudio;
|
|
||||||
InstanceInfo->Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
|
|
||||||
InstanceInfo->Property.Flags = KSPROPERTY_TYPE_SET;
|
|
||||||
InstanceInfo->Flags = 0;
|
|
||||||
InstanceInfo->DeviceNumber = FilterId;
|
|
||||||
|
|
||||||
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ||
|
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ||
|
||||||
DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE ||
|
DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE ||
|
||||||
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||||
|
@ -215,17 +210,14 @@ WdmAudControlOpen(
|
||||||
DesiredAccess |= GENERIC_WRITE;
|
DesiredAccess |= GENERIC_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinConnect = (KSPIN_CONNECT*)(InstanceInfo + 1);
|
|
||||||
|
|
||||||
|
|
||||||
PinConnect->Interface.Set = KSINTERFACESETID_Standard;
|
PinConnect->Interface.Set = KSINTERFACESETID_Standard;
|
||||||
PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
|
PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
|
||||||
PinConnect->Interface.Flags = 0;
|
PinConnect->Interface.Flags = 0;
|
||||||
PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
|
PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
|
||||||
PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
|
PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
|
||||||
PinConnect->Medium.Flags = 0;
|
PinConnect->Medium.Flags = 0;
|
||||||
|
PinConnect->PinToHandle = NULL;
|
||||||
PinConnect->PinId = PinId;
|
PinConnect->PinId = PinId;
|
||||||
PinConnect->PinToHandle = DeviceExtension->hSysAudio;
|
|
||||||
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
|
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
|
||||||
PinConnect->Priority.PrioritySubClass = 1;
|
PinConnect->Priority.PrioritySubClass = 1;
|
||||||
|
|
||||||
|
@ -247,9 +239,29 @@ WdmAudControlOpen(
|
||||||
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
||||||
DataFormat->DataFormat.SampleSize = 4;
|
DataFormat->DataFormat.SampleSize = 4;
|
||||||
|
|
||||||
/* ros specific pin creation request */
|
/* setup property request */
|
||||||
InstanceInfo->Property.Id = (ULONG)-1;
|
InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
|
||||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, Length, &PinHandle, sizeof(HANDLE), &BytesReturned);
|
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))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
PWDMAUD_HANDLE Handels;
|
PWDMAUD_HANDLE Handels;
|
||||||
|
|
|
@ -18,15 +18,6 @@ const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010,
|
||||||
const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 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 KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
ComputeCompatibleFormat(
|
|
||||||
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
|
||||||
IN ULONG PinId,
|
|
||||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
|
||||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
|
||||||
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat);
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SetIrpIoStatus(
|
SetIrpIoStatus(
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
|
@ -70,11 +61,13 @@ SysAudioOpenVirtualDevice(
|
||||||
PSYSAUDIODEVEXT DeviceExtension)
|
PSYSAUDIODEVEXT DeviceExtension)
|
||||||
{
|
{
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
/* access the create item */
|
/* get current irp stack */
|
||||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
ASSERT(CreateItem);
|
|
||||||
|
/* sanity check */
|
||||||
|
ASSERT(IoStack->FileObject);
|
||||||
|
|
||||||
if (DeviceNumber >= DeviceExtension->NumberOfKsAudioDevices)
|
if (DeviceNumber >= DeviceExtension->NumberOfKsAudioDevices)
|
||||||
{
|
{
|
||||||
|
@ -86,264 +79,14 @@ SysAudioOpenVirtualDevice(
|
||||||
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
|
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
|
||||||
ASSERT(Entry != NULL);
|
ASSERT(Entry != NULL);
|
||||||
|
|
||||||
|
/* store device entry in FsContext2
|
||||||
|
* see pin.c DispatchCreateSysAudioPin for details
|
||||||
|
*/
|
||||||
|
IoStack->FileObject->FsContext2 = (PVOID)Entry;
|
||||||
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
SetMixerInputOutputFormat(
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PKSDATAFORMAT InputFormat,
|
|
||||||
IN PKSDATAFORMAT OutputFormat)
|
|
||||||
{
|
|
||||||
KSP_PIN PinRequest;
|
|
||||||
ULONG BytesReturned;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* re-using pin */
|
|
||||||
PinRequest.Property.Set = KSPROPSETID_Connection;
|
|
||||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
|
||||||
|
|
||||||
/* set the input format */
|
|
||||||
PinRequest.PinId = 0;
|
|
||||||
DPRINT("InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", InputFormat, InputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
|
|
||||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
|
|
||||||
(PVOID)&PinRequest,
|
|
||||||
sizeof(KSP_PIN),
|
|
||||||
(PVOID)InputFormat,
|
|
||||||
InputFormat->FormatSize,
|
|
||||||
&BytesReturned);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
/* set the the output format */
|
|
||||||
PinRequest.PinId = 1;
|
|
||||||
DPRINT("OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", OutputFormat, OutputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
|
|
||||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
|
|
||||||
(PVOID)&PinRequest,
|
|
||||||
sizeof(KSP_PIN),
|
|
||||||
(PVOID)OutputFormat,
|
|
||||||
OutputFormat->FormatSize,
|
|
||||||
&BytesReturned);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CreateMixerPinAndSetFormat(
|
|
||||||
IN HANDLE KMixerHandle,
|
|
||||||
IN KSPIN_CONNECT *PinConnect,
|
|
||||||
IN PKSDATAFORMAT InputFormat,
|
|
||||||
IN PKSDATAFORMAT OutputFormat,
|
|
||||||
OUT PHANDLE MixerPinHandle)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
HANDLE PinHandle;
|
|
||||||
PFILE_OBJECT FileObject;
|
|
||||||
|
|
||||||
Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to create Mixer Pin with %x\n", Status);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(PinHandle,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to get file object with %x\n", Status);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(FileObject);
|
|
||||||
ZwClose(PinHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObDereferenceObject(FileObject);
|
|
||||||
|
|
||||||
*MixerPinHandle = PinHandle;
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
CreatePinWorkerRoutine(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PVOID Context)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
HANDLE RealPinHandle = NULL, VirtualPinHandle = NULL, Filter;
|
|
||||||
PFILE_OBJECT VirtualFileObject = NULL;
|
|
||||||
PKSDATAFORMAT_WAVEFORMATEX InputFormat;
|
|
||||||
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
|
|
||||||
PKSPIN_CONNECT MixerPinConnect = NULL;
|
|
||||||
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
|
||||||
|
|
||||||
Filter = WorkerContext->PinConnect->PinToHandle;
|
|
||||||
|
|
||||||
WorkerContext->PinConnect->PinToHandle = NULL;
|
|
||||||
|
|
||||||
DPRINT("CreatePinWorkerRoutine entered\n");
|
|
||||||
|
|
||||||
ASSERT(WorkerContext->Entry);
|
|
||||||
ASSERT(WorkerContext->PinConnect);
|
|
||||||
ASSERT(WorkerContext->Entry->Pins);
|
|
||||||
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
|
|
||||||
|
|
||||||
/* Fetch input format */
|
|
||||||
InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(WorkerContext->PinConnect + 1);
|
|
||||||
|
|
||||||
|
|
||||||
/* Let's try to create the audio irp pin */
|
|
||||||
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* the audio irp pin didnt accept the input format
|
|
||||||
* let's compute a compatible format
|
|
||||||
*/
|
|
||||||
|
|
||||||
MixerPinConnect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
|
||||||
if (!MixerPinConnect)
|
|
||||||
{
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
|
||||||
IoFreeWorkItem(WorkerContext->WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero pin connect */
|
|
||||||
RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
|
||||||
|
|
||||||
/* Copy initial connect details */
|
|
||||||
RtlMoveMemory(MixerPinConnect, WorkerContext->PinConnect, sizeof(KSPIN_CONNECT));
|
|
||||||
|
|
||||||
|
|
||||||
OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1);
|
|
||||||
|
|
||||||
Status = ComputeCompatibleFormat(WorkerContext->Entry, WorkerContext->PinConnect->PinId, WorkerContext->DeviceExtension, InputFormat, OutputFormat);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("ComputeCompatibleFormat failed with %x\n", Status);
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
|
||||||
ExFreePool(MixerPinConnect);
|
|
||||||
IoFreeWorkItem(WorkerContext->WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retry with Mixer format */
|
|
||||||
Status = KsCreatePin(WorkerContext->Entry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); //, WorkerContext->Entry->ObjectClass);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* This should not fail */
|
|
||||||
DPRINT1("KsCreatePin failed with %x\n", Status);
|
|
||||||
DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels);
|
|
||||||
DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels);
|
|
||||||
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
|
||||||
ExFreePool(MixerPinConnect);
|
|
||||||
IoFreeWorkItem(WorkerContext->WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount);
|
|
||||||
|
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0;
|
|
||||||
WorkerContext->DispatchContext->Handle = RealPinHandle;
|
|
||||||
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
|
|
||||||
WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry;
|
|
||||||
|
|
||||||
/* Do we need to transform the audio stream */
|
|
||||||
if (OutputFormat != NULL)
|
|
||||||
{
|
|
||||||
/* Now create the mixer pin */
|
|
||||||
Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
|
|
||||||
MixerPinConnect,
|
|
||||||
(PKSDATAFORMAT)InputFormat,
|
|
||||||
(PKSDATAFORMAT)OutputFormat,
|
|
||||||
&WorkerContext->DispatchContext->hMixerPin);
|
|
||||||
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to create Mixer Pin with %x\n", Status);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT1("creating virtual pin\n");
|
|
||||||
/* now create the virtual audio pin which is exposed to wdmaud */
|
|
||||||
Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle); //, L"SysAudio");
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to create virtual pin %x\n", Status);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get pin file object */
|
|
||||||
Status = ObReferenceObjectByHandle(VirtualPinHandle,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
IoFileObjectType, KernelMode, (PVOID*)&VirtualFileObject, NULL);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to get file object with %x\n", Status);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(WorkerContext->Entry->Pins != NULL);
|
|
||||||
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
|
|
||||||
|
|
||||||
/* increment reference count */
|
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
|
|
||||||
|
|
||||||
/* store the pin handle there if the pin can only be instantiated once*/
|
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = VirtualPinHandle;
|
|
||||||
|
|
||||||
/* store pin context */
|
|
||||||
VirtualFileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
|
|
||||||
|
|
||||||
/* release virtual file object */
|
|
||||||
ObDereferenceObject(VirtualFileObject);
|
|
||||||
|
|
||||||
DPRINT("Successfully created virtual pin %p\n", VirtualPinHandle);
|
|
||||||
*((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
|
|
||||||
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
|
|
||||||
IoFreeWorkItem(WorkerContext->WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
return;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (RealPinHandle)
|
|
||||||
ZwClose(RealPinHandle);
|
|
||||||
|
|
||||||
if (WorkerContext->DispatchContext->hMixerPin)
|
|
||||||
ZwClose(WorkerContext->DispatchContext->hMixerPin);
|
|
||||||
|
|
||||||
|
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, Status, 0);
|
|
||||||
IoFreeWorkItem(WorkerContext->WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
HandleSysAudioFilterPinProperties(
|
HandleSysAudioFilterPinProperties(
|
||||||
PIRP Irp,
|
PIRP Irp,
|
||||||
|
@ -382,7 +125,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry->NumberOfPins <= Pin->PinId)
|
if (Entry->PinDescriptorsCount <= Pin->PinId)
|
||||||
{
|
{
|
||||||
/* invalid pin id */
|
/* invalid pin id */
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||||
|
@ -396,7 +139,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
|
||||||
}
|
}
|
||||||
/* store result */
|
/* store result */
|
||||||
*((PULONG)Irp->UserBuffer) = Entry->NumberOfPins;
|
*((PULONG)Irp->UserBuffer) = Entry->PinDescriptorsCount;
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
|
||||||
}
|
}
|
||||||
else if (Property->Id == KSPROPERTY_PIN_COMMUNICATION)
|
else if (Property->Id == KSPROPERTY_PIN_COMMUNICATION)
|
||||||
|
@ -407,7 +150,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_COMMUNICATION));
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_COMMUNICATION));
|
||||||
}
|
}
|
||||||
/* store result */
|
/* store result */
|
||||||
*((KSPIN_COMMUNICATION*)Irp->UserBuffer) = Entry->Pins[Pin->PinId].Communication;
|
*((KSPIN_COMMUNICATION*)Irp->UserBuffer) = Entry->PinDescriptors[Pin->PinId].Communication;
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_COMMUNICATION));
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_COMMUNICATION));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -419,7 +162,7 @@ HandleSysAudioFilterPinProperties(
|
||||||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_DATAFLOW));
|
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_DATAFLOW));
|
||||||
}
|
}
|
||||||
/* store result */
|
/* store result */
|
||||||
*((KSPIN_DATAFLOW*)Irp->UserBuffer) = Entry->Pins[Pin->PinId].DataFlow;
|
*((KSPIN_DATAFLOW*)Irp->UserBuffer) = Entry->PinDescriptors[Pin->PinId].DataFlow;
|
||||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_DATAFLOW));
|
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_DATAFLOW));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -441,7 +184,6 @@ NTSTATUS
|
||||||
ComputeCompatibleFormat(
|
ComputeCompatibleFormat(
|
||||||
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
IN ULONG PinId,
|
IN ULONG PinId,
|
||||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
|
||||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||||
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat)
|
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat)
|
||||||
{
|
{
|
||||||
|
@ -591,149 +333,6 @@ GetPinInstanceCount(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
HandleSysAudioFilterPinCreation(
|
|
||||||
PIRP Irp,
|
|
||||||
PKSPROPERTY Property,
|
|
||||||
PSYSAUDIODEVEXT DeviceExtension,
|
|
||||||
PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
ULONG Length;
|
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
|
||||||
KSPIN_CONNECT * PinConnect;
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
|
||||||
NTSTATUS Status;
|
|
||||||
KSPIN_CINSTANCES PinInstances;
|
|
||||||
PPIN_WORKER_CONTEXT WorkerContext;
|
|
||||||
PDISPATCH_CONTEXT DispatchContext;
|
|
||||||
PIO_WORKITEM WorkItem;
|
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
|
|
||||||
Length = sizeof(KSDATAFORMAT) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Length ||
|
|
||||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HANDLE))
|
|
||||||
{
|
|
||||||
/* invalid parameters */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* access the create item */
|
|
||||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
|
||||||
|
|
||||||
/* get input parameter */
|
|
||||||
InstanceInfo = (PSYSAUDIO_INSTANCE_INFO)Property;
|
|
||||||
if (DeviceExtension->NumberOfKsAudioDevices <= InstanceInfo->DeviceNumber)
|
|
||||||
{
|
|
||||||
/* invalid parameters */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get sysaudio entry */
|
|
||||||
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, InstanceInfo->DeviceNumber);
|
|
||||||
if (!Entry)
|
|
||||||
{
|
|
||||||
/* invalid device index */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Entry->Pins)
|
|
||||||
{
|
|
||||||
/* should not happen */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get connect details */
|
|
||||||
PinConnect = (KSPIN_CONNECT*)(InstanceInfo + 1);
|
|
||||||
|
|
||||||
if (Entry->NumberOfPins <= PinConnect->PinId)
|
|
||||||
{
|
|
||||||
DPRINT("Invalid PinId %x\n", PinConnect->PinId);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* query instance count */
|
|
||||||
Status = GetPinInstanceCount(Entry, &PinInstances, PinConnect);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status);
|
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PinInstances.PossibleCount == 0)
|
|
||||||
{
|
|
||||||
/* caller wanted to open an instance-less pin */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
|
||||||
{
|
|
||||||
/* pin already exists */
|
|
||||||
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
|
|
||||||
ASSERT(Entry->Pins[PinConnect->PinId].References);
|
|
||||||
|
|
||||||
DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, Entry->Pins[PinConnect->PinId].References);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
/* create dispatch pin context */
|
|
||||||
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
|
|
||||||
if (!DispatchContext)
|
|
||||||
{
|
|
||||||
/* no memory */
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate worker context */
|
|
||||||
WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
|
|
||||||
if (!WorkerContext)
|
|
||||||
{
|
|
||||||
/* no memory */
|
|
||||||
ExFreePool(DispatchContext);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate work item */
|
|
||||||
WorkItem = IoAllocateWorkItem(DeviceObject);
|
|
||||||
if (!WorkerContext)
|
|
||||||
{
|
|
||||||
/* no memory */
|
|
||||||
ExFreePool(DispatchContext);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare context */
|
|
||||||
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
|
|
||||||
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
|
|
||||||
|
|
||||||
DPRINT("PinInstances.CurrentCount %u\n", PinInstances.CurrentCount);
|
|
||||||
|
|
||||||
if (PinInstances.CurrentCount < PinInstances.PossibleCount)
|
|
||||||
{
|
|
||||||
WorkerContext->CreateRealPin = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up context */
|
|
||||||
WorkerContext->DispatchContext = DispatchContext;
|
|
||||||
WorkerContext->Entry = Entry;
|
|
||||||
WorkerContext->Irp = Irp;
|
|
||||||
WorkerContext->PinConnect = PinConnect;
|
|
||||||
WorkerContext->DeviceExtension = DeviceExtension;
|
|
||||||
WorkerContext->WorkItem = WorkItem;
|
|
||||||
|
|
||||||
DPRINT("Queing Irp %p\n", Irp);
|
|
||||||
/* queue the work item */
|
|
||||||
IoMarkIrpPending(Irp);
|
|
||||||
Irp->IoStatus.Status = STATUS_PENDING;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)WorkerContext);
|
|
||||||
|
|
||||||
/* mark irp as pending */
|
|
||||||
return STATUS_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
SysAudioHandleProperty(
|
SysAudioHandleProperty(
|
||||||
PDEVICE_OBJECT DeviceObject,
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
@ -874,12 +473,6 @@ SysAudioHandleProperty(
|
||||||
return SysAudioOpenVirtualDevice(Irp, InstanceInfo->DeviceNumber, DeviceExtension);
|
return SysAudioOpenVirtualDevice(Irp, InstanceInfo->DeviceNumber, DeviceExtension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Property->Id == (ULONG)-1)
|
|
||||||
{
|
|
||||||
/* ros specific pin creation request */
|
|
||||||
DPRINT("Initiating create request\n");
|
|
||||||
return HandleSysAudioFilterPinCreation(Irp, Property, DeviceExtension, DeviceObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlStringFromGUID(&Property->Set, &GuidString);
|
RtlStringFromGUID(&Property->Set, &GuidString);
|
||||||
|
|
|
@ -16,19 +16,65 @@ const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {
|
||||||
|
|
||||||
#define IOCTL_KS_OBJECT_CLASS CTL_CODE(FILE_DEVICE_KS, 0x7, METHOD_NEITHER, FILE_ANY_ACCESS)
|
#define IOCTL_KS_OBJECT_CLASS CTL_CODE(FILE_DEVICE_KS, 0x7, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
BuildPinDescriptor(
|
||||||
|
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry,
|
||||||
|
IN ULONG Count)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
KSP_PIN PinRequest;
|
||||||
|
KSPIN_DATAFLOW DataFlow;
|
||||||
|
KSPIN_COMMUNICATION Communication;
|
||||||
|
ULONG NumWaveOutPin, NumWaveInPin;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
|
||||||
|
NumWaveInPin = 0;
|
||||||
|
NumWaveOutPin = 0;
|
||||||
|
for(Index = 0; Index < Count; Index++)
|
||||||
|
{
|
||||||
|
/* retrieve data flow */
|
||||||
|
PinRequest.PinId = Index;
|
||||||
|
PinRequest.Property.Set = KSPROPSETID_Pin;
|
||||||
|
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
|
||||||
|
/* get dataflow direction */
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_PIN_DATAFLOW;
|
||||||
|
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceEntry->PinDescriptors[Index].DataFlow = DataFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get irp flow direction */
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
|
||||||
|
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DeviceEntry->PinDescriptors[Index].Communication = Communication;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
|
||||||
|
NumWaveOutPin++;
|
||||||
|
|
||||||
|
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
|
||||||
|
NumWaveInPin++;
|
||||||
|
|
||||||
|
/* FIXME query for interface, dataformat etc */
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->PinDescriptorsCount, NumWaveInPin, NumWaveOutPin);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
QueryFilterRoutine(
|
QueryFilterRoutine(
|
||||||
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry)
|
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry)
|
||||||
{
|
{
|
||||||
KSPROPERTY PropertyRequest;
|
KSPROPERTY PropertyRequest;
|
||||||
KSP_PIN PinRequest;
|
ULONG Count;
|
||||||
KSPIN_DATAFLOW DataFlow;
|
|
||||||
KSPIN_COMMUNICATION Communication;
|
|
||||||
KSPIN_CINSTANCES PinInstances;
|
|
||||||
ULONG Count, Index;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
ULONG NumWaveOutPin, NumWaveInPin;
|
|
||||||
|
|
||||||
DPRINT("Querying filter...\n");
|
DPRINT("Querying filter...\n");
|
||||||
|
|
||||||
|
@ -50,6 +96,23 @@ QueryFilterRoutine(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* allocate pin descriptor array */
|
||||||
|
DeviceEntry->PinDescriptors = ExAllocatePool(NonPagedPool, Count * sizeof(KSPIN_DESCRIPTOR));
|
||||||
|
if (!DeviceEntry->PinDescriptors)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero array pin descriptor array */
|
||||||
|
RtlZeroMemory(DeviceEntry->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR));
|
||||||
|
|
||||||
|
/* build the device descriptor */
|
||||||
|
Status = BuildPinDescriptor(DeviceEntry, Count);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
/* allocate pin array */
|
/* allocate pin array */
|
||||||
DeviceEntry->Pins = ExAllocatePool(NonPagedPool, Count * sizeof(PIN_INFO));
|
DeviceEntry->Pins = ExAllocatePool(NonPagedPool, Count * sizeof(PIN_INFO));
|
||||||
if (!DeviceEntry->Pins)
|
if (!DeviceEntry->Pins)
|
||||||
|
@ -58,51 +121,11 @@ QueryFilterRoutine(
|
||||||
DPRINT1("Failed to allocate memory Pins %u Block %x\n", Count, Count * sizeof(PIN_INFO));
|
DPRINT1("Failed to allocate memory Pins %u Block %x\n", Count, Count * sizeof(PIN_INFO));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear array */
|
/* clear array */
|
||||||
RtlZeroMemory(DeviceEntry->Pins, sizeof(PIN_INFO) * Count);
|
RtlZeroMemory(DeviceEntry->Pins, sizeof(PIN_INFO) * Count);
|
||||||
DeviceEntry->NumberOfPins = Count;
|
DeviceEntry->PinDescriptorsCount = Count;
|
||||||
|
|
||||||
NumWaveInPin = 0;
|
|
||||||
NumWaveOutPin = 0;
|
|
||||||
for(Index = 0; Index < Count; Index++)
|
|
||||||
{
|
|
||||||
/* get max instance count */
|
|
||||||
PinRequest.PinId = Index;
|
|
||||||
PinRequest.Property.Set = KSPROPSETID_Pin;
|
|
||||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
|
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DeviceEntry->Pins[Index].MaxPinInstanceCount = PinInstances.PossibleCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get dataflow direction */
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_PIN_DATAFLOW;
|
|
||||||
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DeviceEntry->Pins[Index].DataFlow = DataFlow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get irp flow direction */
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
|
|
||||||
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DeviceEntry->Pins[Index].Communication = Communication;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
|
|
||||||
NumWaveOutPin++;
|
|
||||||
|
|
||||||
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
|
|
||||||
NumWaveInPin++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, NumWaveInPin, NumWaveOutPin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -29,44 +29,6 @@ Dispatch_fnDeviceIoControl(
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnRead(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
/* unsupported request */
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnWrite(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
/* unsupported request */
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnFlush(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
Dispatch_fnClose(
|
Dispatch_fnClose(
|
||||||
|
@ -81,123 +43,20 @@ Dispatch_fnClose(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnQuerySecurity(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
DPRINT("Dispatch_fnQuerySecurity called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnSetSecurity(
|
|
||||||
PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
{
|
|
||||||
|
|
||||||
DPRINT("Dispatch_fnSetSecurity called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnFastDeviceIoControl(
|
|
||||||
PFILE_OBJECT FileObject,
|
|
||||||
BOOLEAN Wait,
|
|
||||||
PVOID InputBuffer,
|
|
||||||
ULONG InputBufferLength,
|
|
||||||
PVOID OutputBuffer,
|
|
||||||
ULONG OutputBufferLength,
|
|
||||||
ULONG IoControlCode,
|
|
||||||
PIO_STATUS_BLOCK IoStatus,
|
|
||||||
PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
DPRINT("Dispatch_fnFastDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnFastRead(
|
|
||||||
PFILE_OBJECT FileObject,
|
|
||||||
PLARGE_INTEGER FileOffset,
|
|
||||||
ULONG Length,
|
|
||||||
BOOLEAN Wait,
|
|
||||||
ULONG LockKey,
|
|
||||||
PVOID Buffer,
|
|
||||||
PIO_STATUS_BLOCK IoStatus,
|
|
||||||
PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
DPRINT("Dispatch_fnFastRead called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
Dispatch_fnFastWrite(
|
|
||||||
PFILE_OBJECT FileObject,
|
|
||||||
PLARGE_INTEGER FileOffset,
|
|
||||||
ULONG Length,
|
|
||||||
BOOLEAN Wait,
|
|
||||||
ULONG LockKey,
|
|
||||||
PVOID Buffer,
|
|
||||||
PIO_STATUS_BLOCK IoStatus,
|
|
||||||
PDEVICE_OBJECT DeviceObject)
|
|
||||||
{
|
|
||||||
DPRINT("Dispatch_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static KSDISPATCH_TABLE DispatchTable =
|
static KSDISPATCH_TABLE DispatchTable =
|
||||||
{
|
{
|
||||||
Dispatch_fnDeviceIoControl,
|
Dispatch_fnDeviceIoControl,
|
||||||
Dispatch_fnRead,
|
KsDispatchInvalidDeviceRequest,
|
||||||
Dispatch_fnWrite,
|
KsDispatchInvalidDeviceRequest,
|
||||||
Dispatch_fnFlush,
|
KsDispatchInvalidDeviceRequest,
|
||||||
Dispatch_fnClose,
|
Dispatch_fnClose,
|
||||||
Dispatch_fnQuerySecurity,
|
KsDispatchInvalidDeviceRequest,
|
||||||
Dispatch_fnSetSecurity,
|
KsDispatchInvalidDeviceRequest,
|
||||||
Dispatch_fnFastDeviceIoControl,
|
KsDispatchFastIoDeviceControlFailure,
|
||||||
Dispatch_fnFastRead,
|
KsDispatchFastReadFailure,
|
||||||
Dispatch_fnFastWrite,
|
KsDispatchFastWriteFailure,
|
||||||
};
|
};
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
DispatchCreateSysAudioPin(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("DispatchCreateSysAudio entered\n");
|
|
||||||
/* create the virtual pin */
|
|
||||||
Status = CreateSysAudioPin(Irp);
|
|
||||||
|
|
||||||
/* store result */
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
Irp->IoStatus.Status = Status;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
DispatchCreateSysAudio(
|
DispatchCreateSysAudio(
|
||||||
|
@ -208,9 +67,7 @@ DispatchCreateSysAudio(
|
||||||
KSOBJECT_HEADER ObjectHeader;
|
KSOBJECT_HEADER ObjectHeader;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
|
||||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
DPRINT1("DispatchCreateSysAudio entered\n");
|
||||||
|
|
||||||
DPRINT("DispatchCreateSysAudio entered\n");
|
|
||||||
|
|
||||||
/* allocate create item */
|
/* allocate create item */
|
||||||
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||||
|
@ -227,12 +84,12 @@ DispatchCreateSysAudio(
|
||||||
|
|
||||||
/* setup create context */
|
/* setup create context */
|
||||||
CreateItem->Create = DispatchCreateSysAudioPin;
|
CreateItem->Create = DispatchCreateSysAudioPin;
|
||||||
RtlInitUnicodeString(&CreateItem->ObjectClass, KS_NAME_PIN);
|
RtlInitUnicodeString(&CreateItem->ObjectClass, KSSTRING_Pin);
|
||||||
|
|
||||||
/* allocate object header */
|
/* allocate object header */
|
||||||
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
|
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
|
||||||
|
|
||||||
DPRINT("KsAllocateObjectHeader result %x\n", Status);
|
DPRINT1("KsAllocateObjectHeader result %x\n", Status);
|
||||||
/* complete the irp */
|
/* complete the irp */
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
|
@ -420,13 +420,287 @@ static KSDISPATCH_TABLE PinTable =
|
||||||
};
|
};
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CreateSysAudioPin(
|
SetMixerInputOutputFormat(
|
||||||
IN PIRP Irp)
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PKSDATAFORMAT InputFormat,
|
||||||
|
IN PKSDATAFORMAT OutputFormat)
|
||||||
|
{
|
||||||
|
KSP_PIN PinRequest;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* re-using pin */
|
||||||
|
PinRequest.Property.Set = KSPROPSETID_Connection;
|
||||||
|
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
||||||
|
|
||||||
|
/* set the input format */
|
||||||
|
PinRequest.PinId = 0;
|
||||||
|
DPRINT("InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", InputFormat, InputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
|
||||||
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
|
||||||
|
(PVOID)&PinRequest,
|
||||||
|
sizeof(KSP_PIN),
|
||||||
|
(PVOID)InputFormat,
|
||||||
|
InputFormat->FormatSize,
|
||||||
|
&BytesReturned);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
/* set the the output format */
|
||||||
|
PinRequest.PinId = 1;
|
||||||
|
DPRINT("OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", OutputFormat, OutputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
|
||||||
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
|
||||||
|
(PVOID)&PinRequest,
|
||||||
|
sizeof(KSP_PIN),
|
||||||
|
(PVOID)OutputFormat,
|
||||||
|
OutputFormat->FormatSize,
|
||||||
|
&BytesReturned);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CreateMixerPinAndSetFormat(
|
||||||
|
IN HANDLE KMixerHandle,
|
||||||
|
IN KSPIN_CONNECT *PinConnect,
|
||||||
|
IN PKSDATAFORMAT InputFormat,
|
||||||
|
IN PKSDATAFORMAT OutputFormat,
|
||||||
|
OUT PHANDLE MixerPinHandle)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
HANDLE PinHandle;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
|
Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create Mixer Pin with %x\n", Status);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle(PinHandle,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to get file object with %x\n", Status);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
ZwClose(PinHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
|
*MixerPinHandle = PinHandle;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
InstantiatePins(
|
||||||
|
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry,
|
||||||
|
IN PKSPIN_CONNECT Connect,
|
||||||
|
IN PDISPATCH_CONTEXT DispatchContext,
|
||||||
|
IN PSYSAUDIODEVEXT DeviceExtension)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE RealPinHandle;
|
||||||
|
PKSDATAFORMAT_WAVEFORMATEX InputFormat;
|
||||||
|
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
|
||||||
|
PKSPIN_CONNECT MixerPinConnect = NULL;
|
||||||
|
KSPIN_CINSTANCES PinInstances;
|
||||||
|
|
||||||
|
DPRINT("InstantiatePins entered\n");
|
||||||
|
|
||||||
|
/* query instance count */
|
||||||
|
Status = GetPinInstanceCount(DeviceEntry, &PinInstances, Connect);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed to query instance count */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* can be the pin be instantiated */
|
||||||
|
if (PinInstances.PossibleCount == 0)
|
||||||
|
{
|
||||||
|
/* caller wanted to open an instance-less pin */
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* has the maximum instance count been exceeded */
|
||||||
|
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
||||||
|
{
|
||||||
|
/* FIXME pin already exists
|
||||||
|
* and kmixer infrastructure is not implemented
|
||||||
|
*/
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch input format */
|
||||||
|
InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1);
|
||||||
|
|
||||||
|
/* Let's try to create the audio irp pin */
|
||||||
|
Status = KsCreatePin(DeviceEntry->Handle, Connect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* the audio irp pin didnt accept the input format
|
||||||
|
* let's compute a compatible format
|
||||||
|
*/
|
||||||
|
MixerPinConnect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
||||||
|
if (!MixerPinConnect)
|
||||||
|
{
|
||||||
|
/* not enough memory */
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero pin connect */
|
||||||
|
RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
||||||
|
|
||||||
|
/* Copy initial connect details */
|
||||||
|
RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT));
|
||||||
|
|
||||||
|
|
||||||
|
OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1);
|
||||||
|
|
||||||
|
Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("ComputeCompatibleFormat failed with %x\n", Status);
|
||||||
|
ExFreePool(MixerPinConnect);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retry with Mixer format */
|
||||||
|
Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* This should not fail */
|
||||||
|
DPRINT1("KsCreatePin failed with %x\n", Status);
|
||||||
|
DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels);
|
||||||
|
DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels);
|
||||||
|
|
||||||
|
ExFreePool(MixerPinConnect);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceEntry->Pins[Connect->PinId].References = 0;
|
||||||
|
|
||||||
|
/* initialize dispatch context */
|
||||||
|
DispatchContext->Handle = RealPinHandle;
|
||||||
|
DispatchContext->PinId = Connect->PinId;
|
||||||
|
DispatchContext->AudioEntry = DeviceEntry;
|
||||||
|
|
||||||
|
|
||||||
|
/* Do we need to transform the audio stream */
|
||||||
|
if (OutputFormat != NULL)
|
||||||
|
{
|
||||||
|
/* Now create the mixer pin */
|
||||||
|
Status = CreateMixerPinAndSetFormat(DeviceExtension->KMixerHandle,
|
||||||
|
MixerPinConnect,
|
||||||
|
(PKSDATAFORMAT)InputFormat,
|
||||||
|
(PKSDATAFORMAT)OutputFormat,
|
||||||
|
&DispatchContext->hMixerPin);
|
||||||
|
|
||||||
|
/* check for success */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create Mixer Pin with %x\n", Status);
|
||||||
|
ExFreePool(MixerPinConnect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* done */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DispatchCreateSysAudioPin(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
KSOBJECT_HEADER ObjectHeader;
|
KSOBJECT_HEADER ObjectHeader;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
||||||
|
PKSPIN_CONNECT Connect = NULL;
|
||||||
|
PDISPATCH_CONTEXT DispatchContext;
|
||||||
|
|
||||||
|
DPRINT("DispatchCreateSysAudioPin entered\n");
|
||||||
|
|
||||||
|
/* get current stack location */
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* sanity checks */
|
||||||
|
ASSERT(IoStack->FileObject);
|
||||||
|
ASSERT(IoStack->FileObject->RelatedFileObject);
|
||||||
|
ASSERT(IoStack->FileObject->RelatedFileObject->FsContext2);
|
||||||
|
|
||||||
|
/* get current attached virtual device */
|
||||||
|
DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)IoStack->FileObject->RelatedFileObject->FsContext2;
|
||||||
|
|
||||||
|
/* now validate pin connect request */
|
||||||
|
Status = KsValidateConnectRequest(Irp, DeviceEntry->PinDescriptorsCount, DeviceEntry->PinDescriptors, &Connect);
|
||||||
|
|
||||||
|
/* check for success */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate dispatch context */
|
||||||
|
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
|
||||||
|
if (!DispatchContext)
|
||||||
|
{
|
||||||
|
/* failed */
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero dispatch context */
|
||||||
|
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
|
||||||
|
|
||||||
/* allocate object header */
|
/* allocate object header */
|
||||||
Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
|
Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed */
|
||||||
|
ExFreePool(DispatchContext);
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now instantiate the pins */
|
||||||
|
Status = InstantiatePins(DeviceEntry, Connect, DispatchContext, (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed */
|
||||||
|
KsFreeObjectHeader(ObjectHeader);
|
||||||
|
ExFreePool(DispatchContext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* store dispatch context */
|
||||||
|
IoStack->FileObject->FsContext2 = (PVOID)DispatchContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME create items for clocks / allocators */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,11 +13,8 @@
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG MaxPinInstanceCount; // maximum times a audio irp pin can be instantiated
|
|
||||||
HANDLE PinHandle; // handle to audio irp pin
|
HANDLE PinHandle; // handle to audio irp pin
|
||||||
ULONG References; // number of clients having a reference to this audio irp pin
|
ULONG References; // number of clients having a reference to this audio irp pin
|
||||||
KSPIN_DATAFLOW DataFlow; // specifies data flow
|
|
||||||
KSPIN_COMMUNICATION Communication; // pin type
|
|
||||||
}PIN_INFO;
|
}PIN_INFO;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -28,9 +25,9 @@ typedef struct
|
||||||
HANDLE Handle; // handle to audio sub device
|
HANDLE Handle; // handle to audio sub device
|
||||||
PFILE_OBJECT FileObject; // file objecto to audio sub device
|
PFILE_OBJECT FileObject; // file objecto to audio sub device
|
||||||
|
|
||||||
ULONG NumberOfPins; // number of pins of audio device
|
|
||||||
PIN_INFO * Pins; // array of PIN_INFO
|
PIN_INFO * Pins; // array of PIN_INFO
|
||||||
|
ULONG PinDescriptorsCount; // number of pin descriptors
|
||||||
|
KSPIN_DESCRIPTOR *PinDescriptors; // pin descriptors array
|
||||||
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -65,24 +62,6 @@ typedef struct
|
||||||
HANDLE hMixerPin; // handle to mixer pin
|
HANDLE hMixerPin; // handle to mixer pin
|
||||||
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
}DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
|
||||||
|
|
||||||
// struct PIN_WORKER_CONTEXT
|
|
||||||
//
|
|
||||||
// This structure holds all information required
|
|
||||||
// to create audio irp pin, mixer pin and virtual sysaudio pin
|
|
||||||
//
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
PIRP Irp;
|
|
||||||
BOOL CreateRealPin;
|
|
||||||
BOOL CreateMixerPin;
|
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
|
||||||
KSPIN_CONNECT * PinConnect;
|
|
||||||
PDISPATCH_CONTEXT DispatchContext;
|
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
|
||||||
PKSDATAFORMAT_WAVEFORMATEX MixerFormat;
|
|
||||||
PIO_WORKITEM WorkItem;
|
|
||||||
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PIO_WORKITEM WorkItem;
|
PIO_WORKITEM WorkItem;
|
||||||
|
@ -131,12 +110,28 @@ GetListEntry(
|
||||||
IN ULONG Index);
|
IN ULONG Index);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CreateSysAudioPin(
|
NTAPI
|
||||||
IN PIRP Irp);
|
DispatchCreateSysAudioPin(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
GetDeviceCount(
|
GetDeviceCount(
|
||||||
PSYSAUDIODEVEXT DeviceExtension,
|
PSYSAUDIODEVEXT DeviceExtension,
|
||||||
BOOL WaveIn);
|
BOOL WaveIn);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
GetPinInstanceCount(
|
||||||
|
PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
|
PKSPIN_CINSTANCES PinInstances,
|
||||||
|
PKSPIN_CONNECT PinConnect);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ComputeCompatibleFormat(
|
||||||
|
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
|
IN ULONG PinId,
|
||||||
|
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||||
|
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue