- 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:
Johannes Anderwald 2009-08-10 07:14:04 +00:00
parent 2aa4d40fff
commit 732ce0ed84
6 changed files with 422 additions and 668 deletions

View file

@ -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;

View file

@ -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,262 +79,12 @@ SysAudioOpenVirtualDevice(
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber); Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
ASSERT(Entry != NULL); ASSERT(Entry != NULL);
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); /* store device entry in FsContext2
} * see pin.c DispatchCreateSysAudioPin for details
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
*/ */
IoStack->FileObject->FsContext2 = (PVOID)Entry;
MixerPinConnect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
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
@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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;
} }

View file

@ -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,7 +110,9 @@ GetListEntry(
IN ULONG Index); IN ULONG Index);
NTSTATUS NTSTATUS
CreateSysAudioPin( NTAPI
DispatchCreateSysAudioPin(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp); IN PIRP Irp);
ULONG ULONG
@ -139,4 +120,18 @@ 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