mirror of
https://github.com/reactos/reactos.git
synced 2025-06-16 05:18: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_CLIENT ClientInfo)
|
||||
{
|
||||
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||
SYSAUDIO_INSTANCE_INFO InstanceInfo;
|
||||
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG BytesReturned;
|
||||
NTSTATUS Status;
|
||||
|
@ -185,21 +185,16 @@ WdmAudControlOpen(
|
|||
}
|
||||
|
||||
|
||||
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||
InstanceInfo = ExAllocatePool(NonPagedPool, Length);
|
||||
if (!InstanceInfo)
|
||||
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT);
|
||||
PinConnect = ExAllocatePool(NonPagedPool, Length);
|
||||
if (!PinConnect)
|
||||
{
|
||||
/* no memory */
|
||||
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;
|
||||
|
||||
if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE ||
|
||||
DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
|
||||
|
@ -215,17 +210,14 @@ WdmAudControlOpen(
|
|||
DesiredAccess |= GENERIC_WRITE;
|
||||
}
|
||||
|
||||
PinConnect = (KSPIN_CONNECT*)(InstanceInfo + 1);
|
||||
|
||||
|
||||
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->PinToHandle = DeviceExtension->hSysAudio;
|
||||
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
|
||||
PinConnect->Priority.PrioritySubClass = 1;
|
||||
|
||||
|
@ -247,9 +239,29 @@ WdmAudControlOpen(
|
|||
DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
||||
DataFormat->DataFormat.SampleSize = 4;
|
||||
|
||||
/* ros specific pin creation request */
|
||||
InstanceInfo->Property.Id = (ULONG)-1;
|
||||
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, Length, &PinHandle, sizeof(HANDLE), &BytesReturned);
|
||||
/* 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;
|
||||
|
|
|
@ -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_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
|
||||
SetIrpIoStatus(
|
||||
IN PIRP Irp,
|
||||
|
@ -70,11 +61,13 @@ SysAudioOpenVirtualDevice(
|
|||
PSYSAUDIODEVEXT DeviceExtension)
|
||||
{
|
||||
PKSAUDIO_DEVICE_ENTRY Entry;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
|
||||
/* access the create item */
|
||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||
ASSERT(CreateItem);
|
||||
/* get current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(IoStack->FileObject);
|
||||
|
||||
if (DeviceNumber >= DeviceExtension->NumberOfKsAudioDevices)
|
||||
{
|
||||
|
@ -86,264 +79,14 @@ SysAudioOpenVirtualDevice(
|
|||
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
HandleSysAudioFilterPinProperties(
|
||||
PIRP Irp,
|
||||
|
@ -382,7 +125,7 @@ HandleSysAudioFilterPinProperties(
|
|||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||
}
|
||||
|
||||
if (Entry->NumberOfPins <= Pin->PinId)
|
||||
if (Entry->PinDescriptorsCount <= Pin->PinId)
|
||||
{
|
||||
/* invalid pin id */
|
||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||
|
@ -396,7 +139,7 @@ HandleSysAudioFilterPinProperties(
|
|||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
|
||||
}
|
||||
/* store result */
|
||||
*((PULONG)Irp->UserBuffer) = Entry->NumberOfPins;
|
||||
*((PULONG)Irp->UserBuffer) = Entry->PinDescriptorsCount;
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
|
||||
}
|
||||
else if (Property->Id == KSPROPERTY_PIN_COMMUNICATION)
|
||||
|
@ -407,7 +150,7 @@ HandleSysAudioFilterPinProperties(
|
|||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_COMMUNICATION));
|
||||
}
|
||||
/* 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));
|
||||
|
||||
}
|
||||
|
@ -419,7 +162,7 @@ HandleSysAudioFilterPinProperties(
|
|||
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_DATAFLOW));
|
||||
}
|
||||
/* 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));
|
||||
}
|
||||
else
|
||||
|
@ -441,7 +184,6 @@ NTSTATUS
|
|||
ComputeCompatibleFormat(
|
||||
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||
IN ULONG PinId,
|
||||
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||
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
|
||||
SysAudioHandleProperty(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -874,12 +473,6 @@ SysAudioHandleProperty(
|
|||
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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
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
|
||||
QueryFilterRoutine(
|
||||
IN PKSAUDIO_DEVICE_ENTRY DeviceEntry)
|
||||
{
|
||||
KSPROPERTY PropertyRequest;
|
||||
KSP_PIN PinRequest;
|
||||
KSPIN_DATAFLOW DataFlow;
|
||||
KSPIN_COMMUNICATION Communication;
|
||||
KSPIN_CINSTANCES PinInstances;
|
||||
ULONG Count, Index;
|
||||
ULONG Count;
|
||||
NTSTATUS Status;
|
||||
ULONG BytesReturned;
|
||||
ULONG NumWaveOutPin, NumWaveInPin;
|
||||
|
||||
DPRINT("Querying filter...\n");
|
||||
|
||||
|
@ -50,6 +96,23 @@ QueryFilterRoutine(
|
|||
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 */
|
||||
DeviceEntry->Pins = ExAllocatePool(NonPagedPool, Count * sizeof(PIN_INFO));
|
||||
if (!DeviceEntry->Pins)
|
||||
|
@ -58,51 +121,11 @@ QueryFilterRoutine(
|
|||
DPRINT1("Failed to allocate memory Pins %u Block %x\n", Count, Count * sizeof(PIN_INFO));
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear array */
|
||||
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
|
||||
|
|
|
@ -29,44 +29,6 @@ Dispatch_fnDeviceIoControl(
|
|||
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
|
||||
NTAPI
|
||||
Dispatch_fnClose(
|
||||
|
@ -81,123 +43,20 @@ Dispatch_fnClose(
|
|||
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 =
|
||||
{
|
||||
Dispatch_fnDeviceIoControl,
|
||||
Dispatch_fnRead,
|
||||
Dispatch_fnWrite,
|
||||
Dispatch_fnFlush,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
Dispatch_fnClose,
|
||||
Dispatch_fnQuerySecurity,
|
||||
Dispatch_fnSetSecurity,
|
||||
Dispatch_fnFastDeviceIoControl,
|
||||
Dispatch_fnFastRead,
|
||||
Dispatch_fnFastWrite,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchInvalidDeviceRequest,
|
||||
KsDispatchFastIoDeviceControlFailure,
|
||||
KsDispatchFastReadFailure,
|
||||
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
|
||||
NTAPI
|
||||
DispatchCreateSysAudio(
|
||||
|
@ -208,9 +67,7 @@ DispatchCreateSysAudio(
|
|||
KSOBJECT_HEADER ObjectHeader;
|
||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||
|
||||
static LPWSTR KS_NAME_PIN = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}";
|
||||
|
||||
DPRINT("DispatchCreateSysAudio entered\n");
|
||||
DPRINT1("DispatchCreateSysAudio entered\n");
|
||||
|
||||
/* allocate create item */
|
||||
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
|
||||
|
@ -227,12 +84,12 @@ DispatchCreateSysAudio(
|
|||
|
||||
/* setup create context */
|
||||
CreateItem->Create = DispatchCreateSysAudioPin;
|
||||
RtlInitUnicodeString(&CreateItem->ObjectClass, KS_NAME_PIN);
|
||||
RtlInitUnicodeString(&CreateItem->ObjectClass, KSSTRING_Pin);
|
||||
|
||||
/* allocate object header */
|
||||
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
|
||||
|
||||
DPRINT("KsAllocateObjectHeader result %x\n", Status);
|
||||
DPRINT1("KsAllocateObjectHeader result %x\n", Status);
|
||||
/* complete the irp */
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
|
|
|
@ -420,13 +420,287 @@ static KSDISPATCH_TABLE PinTable =
|
|||
};
|
||||
|
||||
NTSTATUS
|
||||
CreateSysAudioPin(
|
||||
IN PIRP Irp)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,8 @@
|
|||
|
||||
typedef struct
|
||||
{
|
||||
ULONG MaxPinInstanceCount; // maximum times a audio irp pin can be instantiated
|
||||
HANDLE PinHandle; // handle to 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;
|
||||
|
||||
typedef struct
|
||||
|
@ -28,9 +25,9 @@ typedef struct
|
|||
HANDLE Handle; // handle 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
|
||||
|
||||
ULONG PinDescriptorsCount; // number of pin descriptors
|
||||
KSPIN_DESCRIPTOR *PinDescriptors; // pin descriptors array
|
||||
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
|
||||
|
||||
typedef struct
|
||||
|
@ -65,24 +62,6 @@ typedef struct
|
|||
HANDLE hMixerPin; // handle to mixer pin
|
||||
}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
|
||||
{
|
||||
PIO_WORKITEM WorkItem;
|
||||
|
@ -131,12 +110,28 @@ GetListEntry(
|
|||
IN ULONG Index);
|
||||
|
||||
NTSTATUS
|
||||
CreateSysAudioPin(
|
||||
IN PIRP Irp);
|
||||
NTAPI
|
||||
DispatchCreateSysAudioPin(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
ULONG
|
||||
GetDeviceCount(
|
||||
PSYSAUDIODEVEXT DeviceExtension,
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue