mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
- Disable some debug prints
- Close the real pin on exit / when a new wave stream is played. This should fix stuttering when changing the sample rate - Always create the mixer pin svn path=/trunk/; revision=39992
This commit is contained in:
parent
8c83602d51
commit
e5f6e4c0e8
7 changed files with 447 additions and 295 deletions
|
@ -10,7 +10,7 @@ Dispatch_fnDeviceIoControl(
|
||||||
IIrpTarget * IrpTarget;
|
IIrpTarget * IrpTarget;
|
||||||
PKSOBJECT_CREATE_ITEM CreateItem;
|
PKSOBJECT_CREATE_ITEM CreateItem;
|
||||||
|
|
||||||
DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
//DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
/* access the create item */
|
/* access the create item */
|
||||||
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
|
||||||
|
@ -114,7 +114,7 @@ Dispatch_fnClose(
|
||||||
|
|
||||||
IrpTarget = (IIrpTarget*)CreateItem->Context;
|
IrpTarget = (IIrpTarget*)CreateItem->Context;
|
||||||
|
|
||||||
DPRINT1("IrpTarget %p\n", IrpTarget);
|
//DPRINT1("IrpTarget %p\n", IrpTarget);
|
||||||
|
|
||||||
return IrpTarget->lpVtbl->Close(IrpTarget, DeviceObject, Irp);
|
return IrpTarget->lpVtbl->Close(IrpTarget, DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ typedef struct
|
||||||
PMINIPORTWAVECYCLICSTREAM Stream;
|
PMINIPORTWAVECYCLICSTREAM Stream;
|
||||||
KSSTATE State;
|
KSSTATE State;
|
||||||
PKSDATAFORMAT Format;
|
PKSDATAFORMAT Format;
|
||||||
|
KSPIN_CONNECT * ConnectDetails;
|
||||||
|
|
||||||
PVOID CommonBuffer;
|
PVOID CommonBuffer;
|
||||||
ULONG CommonBufferSize;
|
ULONG CommonBufferSize;
|
||||||
|
@ -184,8 +185,8 @@ IServiceSink_fnRequestService(
|
||||||
}
|
}
|
||||||
DPRINT1("Stopping %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
DPRINT1("Stopping %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
||||||
|
|
||||||
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE);
|
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||||
This->State = KSSTATE_PAUSE;
|
This->State = KSSTATE_STOP;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +307,7 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
DPRINT1("IPortPinWave_HandleKsProperty entered\n");
|
//DPRINT1("IPortPinWave_HandleKsProperty entered\n");
|
||||||
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
|
||||||
{
|
{
|
||||||
|
@ -365,7 +366,16 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
|
PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
|
||||||
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
if (Property->Flags & KSPROPERTY_TYPE_SET)
|
||||||
{
|
{
|
||||||
PKSDATAFORMAT NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
|
PKSDATAFORMAT NewDataFormat;
|
||||||
|
if (!RtlCompareMemory(DataFormat, This->Format, DataFormat->FormatSize))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = DataFormat->FormatSize;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
|
||||||
if (!NewDataFormat)
|
if (!NewDataFormat)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
@ -377,11 +387,18 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
|
|
||||||
if (This->Stream)
|
if (This->Stream)
|
||||||
{
|
{
|
||||||
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
|
ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
||||||
|
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
|
||||||
|
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
|
||||||
|
ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
This->State = KSSTATE_STOP;
|
This->State = KSSTATE_STOP;
|
||||||
DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nChannels,
|
DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
|
||||||
((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.wBitsPerSample,
|
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
|
||||||
((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nSamplesPerSec);
|
((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
|
||||||
|
|
||||||
Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat);
|
Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
@ -399,7 +416,6 @@ IPortPinWaveCyclic_HandleKsProperty(
|
||||||
|
|
||||||
}
|
}
|
||||||
DPRINT1("Failed to set format\n");
|
DPRINT1("Failed to set format\n");
|
||||||
DbgBreakPoint();
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -549,8 +565,20 @@ IPortPinWaveCyclic_fnFlush(
|
||||||
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CloseStreamRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PMINIPORTWAVECYCLICSTREAM Stream = (PMINIPORTWAVECYCLICSTREAM)Context;
|
||||||
|
|
||||||
|
DPRINT("CloseStreamRoutine %p\n", Stream);
|
||||||
|
Stream->lpVtbl->Release(Stream);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -559,9 +587,50 @@ IPortPinWaveCyclic_fnClose(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
|
ISubdevice *ISubDevice;
|
||||||
|
NTSTATUS Status;
|
||||||
|
SUBDEVICE_DESCRIPTOR * Descriptor;
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
|
||||||
|
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
|
||||||
DPRINT1("IPortPinWaveCyclic_fnClose\n");
|
DPRINT1("IPortPinWaveCyclic_fnClose\n");
|
||||||
|
|
||||||
//FIXME
|
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ISubDevice->lpVtbl->Release(ISubDevice);
|
||||||
|
Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount--;
|
||||||
|
DPRINT1("InstanceCount %u\n", Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (This->Stream)
|
||||||
|
{
|
||||||
|
This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
This->ServiceGroup->lpVtbl->RemoveMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
|
||||||
|
This->ServiceGroup->lpVtbl->Release(This->ServiceGroup);
|
||||||
|
This->DmaChannel->lpVtbl->Release(This->DmaChannel);
|
||||||
|
|
||||||
|
if (This->Format)
|
||||||
|
ExFreePool(This->Format);
|
||||||
|
|
||||||
|
This->IrpQueue->lpVtbl->Release(This->IrpQueue);
|
||||||
|
|
||||||
|
|
||||||
|
if (This->Stream)
|
||||||
|
{
|
||||||
|
WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||||
|
if (WorkItem)
|
||||||
|
{
|
||||||
|
IoQueueWorkItem(WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)This->Stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
@ -716,6 +785,7 @@ IPortPinWaveCyclic_fnInit(
|
||||||
This->Port = Port;
|
This->Port = Port;
|
||||||
This->Filter = Filter;
|
This->Filter = Filter;
|
||||||
This->KsPinDescriptor = KsPinDescriptor;
|
This->KsPinDescriptor = KsPinDescriptor;
|
||||||
|
This->ConnectDetails = ConnectDetails;
|
||||||
This->Miniport = GetWaveCyclicMiniport(Port);
|
This->Miniport = GetWaveCyclicMiniport(Port);
|
||||||
|
|
||||||
DeviceObject = GetDeviceObject(Port);
|
DeviceObject = GetDeviceObject(Port);
|
||||||
|
|
|
@ -163,42 +163,32 @@ Pin_fnDeviceIoControl(
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
PKSPROPERTY Property;
|
PKSP_PIN Property;
|
||||||
DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
//DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSPROPERTY) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX))
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX))
|
||||||
{
|
{
|
||||||
Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
Property = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection))
|
if (IsEqualGUIDAligned(&Property->Property.Set, &KSPROPSETID_Connection))
|
||||||
{
|
{
|
||||||
if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT && Property->Flags == KSPROPERTY_TYPE_SET)
|
if (Property->Property.Id == KSPROPERTY_CONNECTION_DATAFORMAT && Property->Property.Flags == KSPROPERTY_TYPE_SET)
|
||||||
{
|
{
|
||||||
PKSDATAFORMAT_WAVEFORMATEX WaveFormat2;
|
PKSDATAFORMAT_WAVEFORMATEX Formats;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX WaveFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
PKSDATAFORMAT_WAVEFORMATEX WaveFormat;
|
||||||
|
|
||||||
if (!WaveFormat)
|
Formats = (PKSDATAFORMAT_WAVEFORMATEX)IoStack->FileObject->FsContext2;
|
||||||
{
|
WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Irp->UserBuffer;
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
return STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IoStack->FileObject->FsContext2)
|
ASSERT(Property->PinId == 0 || Property->PinId == 1);
|
||||||
{
|
ASSERT(Formats);
|
||||||
ExFreePool(IoStack->FileObject->FsContext2);
|
ASSERT(WaveFormat);
|
||||||
}
|
|
||||||
|
|
||||||
WaveFormat2 = (PKSDATAFORMAT_WAVEFORMATEX)Irp->UserBuffer;
|
|
||||||
WaveFormat->WaveFormatEx.nChannels = WaveFormat2->WaveFormatEx.nChannels;
|
|
||||||
WaveFormat->WaveFormatEx.nSamplesPerSec = WaveFormat2->WaveFormatEx.nSamplesPerSec;
|
|
||||||
WaveFormat->WaveFormatEx.wBitsPerSample = WaveFormat2->WaveFormatEx.wBitsPerSample;
|
|
||||||
|
|
||||||
IoStack->FileObject->FsContext2 = (PVOID)WaveFormat;
|
|
||||||
|
|
||||||
|
Formats[Property->PinId].WaveFormatEx.nChannels = WaveFormat->WaveFormatEx.nChannels;
|
||||||
|
Formats[Property->PinId].WaveFormatEx.wBitsPerSample = WaveFormat->WaveFormatEx.wBitsPerSample;
|
||||||
|
Formats[Property->PinId].WaveFormatEx.nSamplesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec;
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
@ -207,7 +197,7 @@ Pin_fnDeviceIoControl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DPRINT1("Size %u Expected %u\n",IoStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
@ -365,54 +355,34 @@ Pin_fnFastWrite(
|
||||||
PIO_STATUS_BLOCK IoStatus,
|
PIO_STATUS_BLOCK IoStatus,
|
||||||
PDEVICE_OBJECT DeviceObject)
|
PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PKSPIN_CONNECT ConnectDetails;
|
|
||||||
PKSSTREAM_HEADER StreamHeader;
|
PKSSTREAM_HEADER StreamHeader;
|
||||||
PVOID BufferOut;
|
PVOID BufferOut;
|
||||||
ULONG BufferLength;
|
ULONG BufferLength;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\\";
|
PKSDATAFORMAT_WAVEFORMATEX Formats;
|
||||||
|
PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX BaseFormat, TransformedFormat;
|
|
||||||
|
|
||||||
//DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
//DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
|
Formats = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2;
|
||||||
|
|
||||||
BaseFormat = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2;
|
InputFormat = Formats;
|
||||||
if (!BaseFormat)
|
OutputFormat = (Formats + 1);
|
||||||
{
|
|
||||||
DPRINT1("Expected DataFormat\n");
|
|
||||||
DbgBreakPoint();
|
|
||||||
IoStatus->Status = STATUS_UNSUCCESSFUL;
|
|
||||||
IoStatus->Information = 0;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FileObject->FileName.Length < wcslen(PinName) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT))
|
|
||||||
{
|
|
||||||
DPRINT1("Expected DataFormat\n");
|
|
||||||
DbgBreakPoint();
|
|
||||||
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
||||||
IoStatus->Information = 0;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectDetails = (PKSPIN_CONNECT)(FileObject->FileName.Buffer + wcslen(PinName));
|
|
||||||
TransformedFormat = (PKSDATAFORMAT_WAVEFORMATEX)(ConnectDetails + 1);
|
|
||||||
StreamHeader = (PKSSTREAM_HEADER)Buffer;
|
StreamHeader = (PKSSTREAM_HEADER)Buffer;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
DPRINT1("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n",
|
DPRINT1("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n",
|
||||||
BaseFormat->WaveFormatEx.nChannels, TransformedFormat->WaveFormatEx.nChannels,
|
InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels,
|
||||||
BaseFormat->WaveFormatEx.nSamplesPerSec, TransformedFormat->WaveFormatEx.nSamplesPerSec,
|
InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec,
|
||||||
BaseFormat->WaveFormatEx.wBitsPerSample, TransformedFormat->WaveFormatEx.wBitsPerSample);
|
InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (BaseFormat->WaveFormatEx.wBitsPerSample != TransformedFormat->WaveFormatEx.wBitsPerSample)
|
if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample)
|
||||||
{
|
{
|
||||||
Status = PerformQualityConversion(StreamHeader->Data,
|
Status = PerformQualityConversion(StreamHeader->Data,
|
||||||
StreamHeader->DataUsed,
|
StreamHeader->DataUsed,
|
||||||
BaseFormat->WaveFormatEx.wBitsPerSample,
|
InputFormat->WaveFormatEx.wBitsPerSample,
|
||||||
TransformedFormat->WaveFormatEx.wBitsPerSample,
|
OutputFormat->WaveFormatEx.wBitsPerSample,
|
||||||
&BufferOut,
|
&BufferOut,
|
||||||
&BufferLength);
|
&BufferLength);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
|
@ -424,10 +394,10 @@ Pin_fnFastWrite(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BaseFormat->WaveFormatEx.nSamplesPerSec != TransformedFormat->WaveFormatEx.nSamplesPerSec)
|
if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec)
|
||||||
{
|
{
|
||||||
/* sample format conversion must be done in a deferred routine */
|
/* sample format conversion must be done in a deferred routine */
|
||||||
DPRINT1("SampleRate conversion not available yet\n");
|
DPRINT1("SampleRate conversion not available yet %u %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +427,18 @@ CreatePin(
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KSOBJECT_HEADER ObjectHeader;
|
KSOBJECT_HEADER ObjectHeader;
|
||||||
|
PKSDATAFORMAT DataFormat;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
|
|
||||||
|
DataFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2);
|
||||||
|
if (!DataFormat)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
RtlZeroMemory(DataFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2);
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
IoStack->FileObject->FsContext2 = (PVOID)DataFormat;
|
||||||
|
|
||||||
/* allocate object header */
|
/* allocate object header */
|
||||||
Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
|
Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
|
||||||
|
|
|
@ -144,7 +144,7 @@ WdmAudControlOpen(
|
||||||
|
|
||||||
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
|
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
|
||||||
{
|
{
|
||||||
DPRINT1("FIXME: only waveout devices are supported\n");
|
DPRINT1("FIXME: only waveout / wavein devices are supported\n");
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,6 @@ WdmAudControlOpen(
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||||
InstanceInfo = ExAllocatePool(NonPagedPool, Length);
|
InstanceInfo = ExAllocatePool(NonPagedPool, Length);
|
||||||
if (!InstanceInfo)
|
if (!InstanceInfo)
|
||||||
|
@ -343,8 +342,6 @@ WdmAudControlDeviceType(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
DPRINT1("KSPROPERTY_PIN_CTYPES index %u failed with %x\n", Index, Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,7 +367,7 @@ WdmAudControlDeviceState(
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
DPRINT1("WdmAudControlDeviceState\n");
|
//DPRINT1("WdmAudControlDeviceState\n");
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
@ -389,7 +386,7 @@ WdmAudControlDeviceState(
|
||||||
|
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
|
|
||||||
DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
|
//DPRINT1("WdmAudControlDeviceState Status %x\n", Status);
|
||||||
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +465,6 @@ WdmAudCapabilities(
|
||||||
|
|
||||||
DPRINT("WdmAudCapabilities entered\n");
|
DPRINT("WdmAudCapabilities entered\n");
|
||||||
|
|
||||||
|
|
||||||
Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId);
|
Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -595,7 +591,7 @@ WdmAudDeviceControl(
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
DPRINT1("WdmAudDeviceControl entered\n");
|
DPRINT("WdmAudDeviceControl entered\n");
|
||||||
|
|
||||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
|
||||||
{
|
{
|
||||||
|
@ -621,7 +617,7 @@ WdmAudDeviceControl(
|
||||||
}
|
}
|
||||||
ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
|
ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
|
||||||
|
|
||||||
DPRINT1("WdmAudDeviceControl entered\n");
|
DPRINT("WdmAudDeviceControl entered\n");
|
||||||
|
|
||||||
switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
|
switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,14 @@ SetIrpIoStatus(
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = Length;
|
Irp->IoStatus.Information = Length;
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
if (Status != STATUS_PENDING)
|
||||||
|
{
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
}
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -139,6 +146,90 @@ SysAudioOpenVirtualDevice(
|
||||||
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;
|
||||||
|
//DPRINT1("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;
|
||||||
|
//DPRINT1("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,
|
||||||
|
OUT PFILE_OBJECT *MixerFileObject)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
*MixerPinHandle = PinHandle;
|
||||||
|
*MixerFileObject = FileObject;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CreatePinWorkerRoutine(
|
CreatePinWorkerRoutine(
|
||||||
|
@ -147,22 +238,22 @@ CreatePinWorkerRoutine(
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PSYSAUDIO_CLIENT AudioClient;
|
PSYSAUDIO_CLIENT AudioClient;
|
||||||
HANDLE RealPinHandle, VirtualPinHandle, MixerPinHandle = NULL;
|
HANDLE RealPinHandle, VirtualPinHandle;
|
||||||
HANDLE Filter;
|
HANDLE Filter;
|
||||||
ULONG NumHandels, BytesReturned;
|
ULONG NumHandels;
|
||||||
PFILE_OBJECT FileObject, MixerFileObject = NULL;
|
PFILE_OBJECT FileObject;
|
||||||
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
|
PSYSAUDIO_PIN_HANDLE ClientPinHandle;
|
||||||
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context;
|
||||||
PKSPIN_CONNECT PinConnect = NULL;
|
PKSPIN_CONNECT PinConnect = NULL;
|
||||||
KSPROPERTY PinRequest;
|
PKSDATAFORMAT ClientFormat;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX ClientFormat;
|
KSP_PIN PinRequest;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
|
||||||
Filter = WorkerContext->PinConnect->PinToHandle;
|
Filter = WorkerContext->PinConnect->PinToHandle;
|
||||||
|
|
||||||
|
|
||||||
WorkerContext->PinConnect->PinToHandle = NULL;
|
WorkerContext->PinConnect->PinToHandle = NULL;
|
||||||
|
|
||||||
DPRINT1("CreatePinWorkerRoutine entered\n");
|
DPRINT("CreatePinWorkerRoutine entered\n");
|
||||||
|
|
||||||
ASSERT(WorkerContext->Entry);
|
ASSERT(WorkerContext->Entry);
|
||||||
ASSERT(WorkerContext->PinConnect);
|
ASSERT(WorkerContext->PinConnect);
|
||||||
|
@ -170,7 +261,7 @@ CreatePinWorkerRoutine(
|
||||||
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
|
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
|
||||||
|
|
||||||
PinConnect = WorkerContext->PinConnect;
|
PinConnect = WorkerContext->PinConnect;
|
||||||
ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
|
ClientFormat = (PKSDATAFORMAT)(PinConnect + 1);
|
||||||
|
|
||||||
if (WorkerContext->CreateMixerPin)
|
if (WorkerContext->CreateMixerPin)
|
||||||
{
|
{
|
||||||
|
@ -188,8 +279,14 @@ CreatePinWorkerRoutine(
|
||||||
RtlMoveMemory(PinConnect, WorkerContext->PinConnect, sizeof(KSPIN_CONNECT));
|
RtlMoveMemory(PinConnect, WorkerContext->PinConnect, sizeof(KSPIN_CONNECT));
|
||||||
RtlMoveMemory((PinConnect + 1), WorkerContext->MixerFormat, WorkerContext->MixerFormat->DataFormat.FormatSize);
|
RtlMoveMemory((PinConnect + 1), WorkerContext->MixerFormat, WorkerContext->MixerFormat->DataFormat.FormatSize);
|
||||||
|
|
||||||
|
Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
|
||||||
|
PinConnect,
|
||||||
|
(PKSDATAFORMAT)(WorkerContext->PinConnect + 1),
|
||||||
|
(PKSDATAFORMAT)WorkerContext->MixerFormat,
|
||||||
|
&WorkerContext->DispatchContext->hMixerPin,
|
||||||
|
&WorkerContext->DispatchContext->MixerFileObject);
|
||||||
|
|
||||||
Status = KsCreatePin(WorkerContext->DeviceExtension->KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &MixerPinHandle);
|
ExFreePool(WorkerContext->MixerFormat);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
@ -199,36 +296,23 @@ CreatePinWorkerRoutine(
|
||||||
ExFreePool(WorkerContext);
|
ExFreePool(WorkerContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Status = ObReferenceObjectByHandle(MixerPinHandle,
|
else
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
{
|
||||||
IoFileObjectType, KernelMode, (PVOID*)&MixerFileObject, NULL);
|
Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle,
|
||||||
|
WorkerContext->PinConnect,
|
||||||
|
(PKSDATAFORMAT)(WorkerContext->PinConnect + 1),
|
||||||
|
(PKSDATAFORMAT)(WorkerContext->PinConnect + 1),
|
||||||
|
&WorkerContext->DispatchContext->hMixerPin,
|
||||||
|
&WorkerContext->DispatchContext->MixerFileObject);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to get file object with %x\n", Status);
|
DPRINT1("Failed to create Mixer Pin with %x\n", Status);
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
ExFreePool(WorkerContext->DispatchContext);
|
||||||
ExFreePool(WorkerContext);
|
ExFreePool(WorkerContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerContext->DispatchContext->hMixerPin = MixerPinHandle;
|
|
||||||
WorkerContext->DispatchContext->MixerFileObject = MixerFileObject;
|
|
||||||
|
|
||||||
PinRequest.Set = KSPROPSETID_Connection;
|
|
||||||
PinRequest.Flags = KSPROPERTY_TYPE_SET;
|
|
||||||
PinRequest.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
|
||||||
|
|
||||||
DPRINT1("ClientFormat %p Channels %u Samples %u Bits %u\n", ClientFormat, ClientFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.wBitsPerSample);
|
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(MixerFileObject, KernelMode, IOCTL_KS_PROPERTY,
|
|
||||||
(PVOID)&PinRequest,
|
|
||||||
sizeof(KSPROPERTY),
|
|
||||||
(PVOID)ClientFormat,
|
|
||||||
sizeof(KSDATAFORMAT_WAVEFORMATEX),
|
|
||||||
&BytesReturned);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WorkerContext->CreateRealPin)
|
if (WorkerContext->CreateRealPin)
|
||||||
|
@ -244,7 +328,18 @@ CreatePinWorkerRoutine(
|
||||||
DPRINT1("Status %x\n", Status);
|
DPRINT1("Status %x\n", Status);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to create Pin with %x\n", Status);
|
PKSDATAFORMAT_WAVEFORMATEX RequestedFormat = (PKSDATAFORMAT_WAVEFORMATEX)(WorkerContext->PinConnect + 1);
|
||||||
|
DPRINT1("Failed to create Pin with %x\nNumChannels: %u BitsPerSample %u SampleRate %u\n", Status,
|
||||||
|
RequestedFormat->WaveFormatEx.nChannels, RequestedFormat->WaveFormatEx.wBitsPerSample, RequestedFormat->WaveFormatEx.nSamplesPerSec);
|
||||||
|
|
||||||
|
if (WorkerContext->CreateMixerPin)
|
||||||
|
{
|
||||||
|
/* The mixer pin format should have been accepted */
|
||||||
|
ObDereferenceObject(WorkerContext->DispatchContext->MixerFileObject);
|
||||||
|
ZwClose(WorkerContext->DispatchContext->hMixerPin);
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
ExFreePool(WorkerContext->DispatchContext);
|
||||||
ExFreePool(WorkerContext);
|
ExFreePool(WorkerContext);
|
||||||
|
@ -256,7 +351,6 @@ CreatePinWorkerRoutine(
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
||||||
|
|
||||||
DPRINT1("Status %x\n", Status);
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to get file object with %x\n", Status);
|
DPRINT1("Failed to get file object with %x\n", Status);
|
||||||
|
@ -272,7 +366,7 @@ CreatePinWorkerRoutine(
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
|
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 1;
|
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0;
|
||||||
WorkerContext->DispatchContext->Handle = RealPinHandle;
|
WorkerContext->DispatchContext->Handle = RealPinHandle;
|
||||||
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
|
WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId;
|
||||||
WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry;
|
WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry;
|
||||||
|
@ -291,16 +385,33 @@ CreatePinWorkerRoutine(
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("Failed to get file object with %x\n", Status);
|
DPRINT1("Failed to get file object with %x %p\n", Status, WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle);
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
ExFreePool(WorkerContext->DispatchContext);
|
ExFreePool(WorkerContext->DispatchContext);
|
||||||
ExFreePool(WorkerContext);
|
ExFreePool(WorkerContext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WorkerContext->DispatchContext->FileObject = FileObject;
|
WorkerContext->DispatchContext->FileObject = FileObject;
|
||||||
|
|
||||||
|
|
||||||
|
/* re-using pin */
|
||||||
|
PinRequest.Property.Set = KSPROPSETID_Connection;
|
||||||
|
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
||||||
|
PinRequest.PinId = PinConnect->PinId;
|
||||||
|
|
||||||
|
if (WorkerContext->MixerFormat)
|
||||||
|
ClientFormat = (PKSDATAFORMAT)WorkerContext->MixerFormat;
|
||||||
|
else
|
||||||
|
ClientFormat = (PKSDATAFORMAT)(WorkerContext->PinConnect + 1);
|
||||||
|
|
||||||
|
/* set the format on the real pin */
|
||||||
|
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY),
|
||||||
|
(PVOID)ClientFormat, ClientFormat->FormatSize, &BytesReturned);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("creating virtual pin\n");
|
DPRINT("creating virtual pin\n");
|
||||||
/* now create the virtual audio pin which is exposed to wdmaud */
|
/* now create the virtual audio pin which is exposed to wdmaud */
|
||||||
Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle);
|
Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle);
|
||||||
|
|
||||||
|
@ -369,27 +480,28 @@ CreatePinWorkerRoutine(
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = TRUE;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = TRUE;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = RealPinHandle;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = RealPinHandle;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = MixerPinHandle;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin;
|
||||||
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = VirtualPinHandle;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = VirtualPinHandle;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId;
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = MixerPinHandle;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin;
|
||||||
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// increase reference count
|
/// increase reference count
|
||||||
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
|
|
||||||
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++;
|
AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++;
|
||||||
|
WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* store pin context */
|
/* store pin context */
|
||||||
FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
|
FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
|
||||||
|
|
||||||
DPRINT1("Successfully created virtual pin %p\n", VirtualPinHandle);
|
DPRINT("Successfully created virtual pin %p\n", VirtualPinHandle);
|
||||||
*((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
|
*((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
|
||||||
|
|
||||||
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
|
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
|
||||||
|
@ -488,48 +600,97 @@ HandleSysAudioFilterPinProperties(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
BOOL
|
||||||
SetPinFormat(
|
ComputeCompatibleFormat(
|
||||||
PKSAUDIO_DEVICE_ENTRY Entry,
|
IN PKSAUDIO_DEVICE_ENTRY Entry,
|
||||||
KSPIN_CONNECT * PinConnect,
|
IN ULONG PinId,
|
||||||
ULONG Length)
|
IN PSYSAUDIODEVEXT DeviceExtension,
|
||||||
|
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
|
||||||
|
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat)
|
||||||
{
|
{
|
||||||
KSP_PIN PinRequest;
|
BOOL bFound;
|
||||||
PFILE_OBJECT FileObject;
|
|
||||||
ULONG BytesReturned;
|
ULONG BytesReturned;
|
||||||
|
KSP_PIN PinRequest;
|
||||||
|
PKSDATARANGE_AUDIO AudioRange;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
ULONG Index;
|
||||||
|
PKSMULTIPLE_ITEM MultipleItem;
|
||||||
|
|
||||||
/* re-using pin */
|
if (!DeviceExtension->KMixerHandle || !DeviceExtension->KMixerFileObject)
|
||||||
PinRequest.Property.Set = KSPROPSETID_Connection;
|
{
|
||||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
|
DPRINT1("KMixer is not available\n");
|
||||||
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
|
return STATUS_UNSUCCESSFUL;
|
||||||
PinRequest.PinId = PinConnect->PinId;
|
}
|
||||||
|
|
||||||
|
PinRequest.PinId = PinId;
|
||||||
|
PinRequest.Property.Set = KSPROPSETID_Pin;
|
||||||
|
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_PIN_DATARANGES;
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
|
||||||
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
|
||||||
|
if (!MultipleItem)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
|
||||||
|
ExFreePool(MultipleItem);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1);
|
||||||
|
bFound = FALSE;
|
||||||
|
for(Index = 0; Index < MultipleItem->Count; Index++)
|
||||||
|
{
|
||||||
|
if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
||||||
|
}
|
||||||
|
MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
|
||||||
|
MixerFormat->DataFormat.Flags = 0;
|
||||||
|
MixerFormat->DataFormat.Reserved = 0;
|
||||||
|
MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
|
||||||
|
MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||||
|
MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
||||||
|
MixerFormat->DataFormat.SampleSize = 4;
|
||||||
|
MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag;
|
||||||
|
MixerFormat->WaveFormatEx.nChannels = min(AudioRange->MaximumChannels, ClientFormat->WaveFormatEx.nChannels);
|
||||||
|
MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(AudioRange->MaximumSampleFrequency, ClientFormat->WaveFormatEx.nSamplesPerSec));
|
||||||
|
MixerFormat->WaveFormatEx.wBitsPerSample = max(AudioRange->MinimumBitsPerSample, min(AudioRange->MaximumBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample));
|
||||||
|
MixerFormat->WaveFormatEx.cbSize = 0;
|
||||||
|
MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8;
|
||||||
|
MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8);
|
||||||
|
|
||||||
|
bFound = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
||||||
|
}
|
||||||
|
ExFreePool(MultipleItem);
|
||||||
|
|
||||||
|
|
||||||
/* get pin file object */
|
#if 0
|
||||||
Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
|
DPRINT1("\nNum Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n ClientFormat %p",
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels,
|
||||||
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
|
MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec,
|
||||||
|
MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample, ClientFormat);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (bFound)
|
||||||
{
|
return STATUS_SUCCESS;
|
||||||
DPRINT1("Failed to get pin file object with %x\n", Status);
|
else
|
||||||
return Status;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
|
||||||
|
|
||||||
Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
|
||||||
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY),
|
|
||||||
(PVOID)(PinConnect + 1), Length, &BytesReturned);
|
|
||||||
ObDereferenceObject(FileObject);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* set the format on the mixer pin */
|
|
||||||
UNIMPLEMENTED
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,10 +716,9 @@ HandleSysAudioFilterPinCreation(
|
||||||
PDISPATCH_CONTEXT DispatchContext;
|
PDISPATCH_CONTEXT DispatchContext;
|
||||||
ULONG Index, SubIndex;
|
ULONG Index, SubIndex;
|
||||||
BOOL CreateMixerPin;
|
BOOL CreateMixerPin;
|
||||||
PKSDATARANGE_AUDIO AudioRange;
|
ULONG DeviceId;
|
||||||
PKSDATAFORMAT_WAVEFORMATEX MixerFormat = NULL, ClientFormat;
|
PKSDATAFORMAT_WAVEFORMATEX MixerFormat = NULL, ClientFormat;
|
||||||
|
|
||||||
PKSMULTIPLE_ITEM MultipleItem;
|
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
@ -612,6 +772,27 @@ HandleSysAudioFilterPinCreation(
|
||||||
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Retry:
|
||||||
|
/* get the instances count */
|
||||||
|
PinRequest.PinId = PinConnect->PinId;
|
||||||
|
PinRequest.Property.Set = KSPROPSETID_Pin;
|
||||||
|
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
||||||
|
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
|
||||||
|
|
||||||
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* check the format */
|
/* check the format */
|
||||||
PinRequest.PinId = PinConnect->PinId;
|
PinRequest.PinId = PinConnect->PinId;
|
||||||
PinRequest.Property.Set = KSPROPSETID_Pin;
|
PinRequest.Property.Set = KSPROPSETID_Pin;
|
||||||
|
@ -620,12 +801,6 @@ HandleSysAudioFilterPinCreation(
|
||||||
|
|
||||||
CreateMixerPin = FALSE;
|
CreateMixerPin = FALSE;
|
||||||
BytesReturned = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) - sizeof(SYSAUDIO_INSTANCE_INFO);
|
BytesReturned = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) - sizeof(SYSAUDIO_INSTANCE_INFO);
|
||||||
if (BytesReturned != sizeof(KSDATAFORMAT_WAVEFORMATEX))
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
|
ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)ClientFormat, BytesReturned, &BytesReturned);
|
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)ClientFormat, BytesReturned, &BytesReturned);
|
||||||
|
@ -640,136 +815,58 @@ HandleSysAudioFilterPinCreation(
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PinRequest.PinId = PinConnect->PinId;
|
|
||||||
PinRequest.Property.Set = KSPROPSETID_Pin;
|
|
||||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_PIN_DATARANGES;
|
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
|
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
|
|
||||||
if (!MultipleItem)
|
|
||||||
{
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MixerFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
MixerFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX));
|
||||||
if (!MixerFormat)
|
if (!MixerFormat)
|
||||||
{
|
{
|
||||||
ExFreePool(MultipleItem);
|
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
|
Status = ComputeCompatibleFormat(Entry, PinConnect->PinId, DeviceExtension, ClientFormat, MixerFormat);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
|
|
||||||
ExFreePool(MixerFormat);
|
ExFreePool(MixerFormat);
|
||||||
ExFreePool(MultipleItem);
|
return SetIrpIoStatus(Irp, Status, 0);
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
}
|
||||||
|
CreateMixerPin = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
CreateMixerPin = FALSE;
|
DeviceId = (ULONG)-1;
|
||||||
AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1);
|
|
||||||
for(Index = 0; Index < MultipleItem->Count; Index++)
|
/* scan the clientinfo if the client has already opened device with the specified pin */
|
||||||
|
for (Index = 0; Index < ClientInfo->NumDevices; Index++)
|
||||||
|
{
|
||||||
|
if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber)
|
||||||
{
|
{
|
||||||
if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
|
DeviceId = Index;
|
||||||
|
if (ClientInfo->Devs[Index].ClientHandlesCount)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
for(SubIndex = 0; SubIndex < ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++)
|
||||||
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
{
|
||||||
|
if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId == PinConnect->PinId)
|
||||||
|
{
|
||||||
|
/* the pin has been already opened by the client, re-use it */
|
||||||
|
ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE);
|
||||||
|
|
||||||
|
DispatchContext = ClientInfo->Devs[Index].ClientHandles[SubIndex].DispatchContext;
|
||||||
|
ObDereferenceObject(DispatchContext->MixerFileObject);
|
||||||
|
ObDereferenceObject(DispatchContext->FileObject);
|
||||||
|
ZwClose(DispatchContext->hMixerPin);
|
||||||
|
ZwClose(DispatchContext->Handle);
|
||||||
|
ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId = (ULONG)-1;
|
||||||
|
goto Retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
|
|
||||||
MixerFormat->DataFormat.Flags = 0;
|
|
||||||
MixerFormat->DataFormat.Reserved = 0;
|
|
||||||
MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
|
|
||||||
MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
|
||||||
MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
|
|
||||||
MixerFormat->DataFormat.SampleSize = 4;
|
|
||||||
MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag;
|
|
||||||
MixerFormat->WaveFormatEx.nChannels = min(AudioRange->MaximumChannels, ClientFormat->WaveFormatEx.nChannels);
|
|
||||||
MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(AudioRange->MaximumSampleFrequency, ClientFormat->WaveFormatEx.nSamplesPerSec));
|
|
||||||
MixerFormat->WaveFormatEx.wBitsPerSample = max(AudioRange->MinimumBitsPerSample, min(AudioRange->MaximumBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample));
|
|
||||||
MixerFormat->WaveFormatEx.cbSize = 0;
|
|
||||||
MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8;
|
|
||||||
MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8);
|
|
||||||
|
|
||||||
CreateMixerPin = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
|
|
||||||
}
|
}
|
||||||
ExFreePool(MultipleItem);
|
|
||||||
if (!CreateMixerPin)
|
|
||||||
{
|
|
||||||
ExFreePool(MixerFormat);
|
|
||||||
DPRINT1("No Format found :(\n");
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
DPRINT1("\nNum Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n ClientFormat %p",
|
|
||||||
MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels,
|
|
||||||
MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec,
|
|
||||||
MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample, ClientFormat);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the instances count */
|
ASSERT(DeviceId != (ULONG)-1);
|
||||||
PinRequest.PinId = PinConnect->PinId;
|
|
||||||
PinRequest.Property.Set = KSPROPSETID_Pin;
|
|
||||||
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
|
|
||||||
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
|
|
||||||
|
|
||||||
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status);
|
|
||||||
if (MixerFormat)
|
|
||||||
ExFreePool(MixerFormat);
|
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PinInstances.PossibleCount == 0)
|
|
||||||
{
|
|
||||||
/* caller wanted to open an instance-less pin */
|
|
||||||
if (MixerFormat)
|
|
||||||
ExFreePool(MixerFormat);
|
|
||||||
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
||||||
{
|
{
|
||||||
for (Index = 0; Index < ClientInfo->NumDevices; Index++)
|
|
||||||
{
|
|
||||||
if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber)
|
|
||||||
{
|
|
||||||
if (ClientInfo->Devs[Index].ClientHandlesCount)
|
|
||||||
{
|
|
||||||
for(SubIndex = 0; SubIndex < ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++)
|
|
||||||
{
|
|
||||||
if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId == PinConnect->PinId)
|
|
||||||
{
|
|
||||||
/* reuse opened pin */
|
|
||||||
Length = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
|
|
||||||
Status = SetPinFormat(Entry, PinConnect, Length);
|
|
||||||
DPRINT1("Reusing instance handle Status %x\n", Status);
|
|
||||||
ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE);
|
|
||||||
*((PHANDLE)Irp->UserBuffer) = ClientInfo->Devs[Index].ClientHandles[SubIndex].hPin;
|
|
||||||
return SetIrpIoStatus(Irp, Status, sizeof(HANDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pin already exists */
|
/* pin already exists */
|
||||||
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
|
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
|
||||||
if (Entry->Pins[PinConnect->PinId].References > 1)
|
if (Entry->Pins[PinConnect->PinId].References)
|
||||||
{
|
{
|
||||||
/* FIXME need ksmixer */
|
/* FIXME need ksmixer */
|
||||||
DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, 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);
|
||||||
|
@ -816,28 +913,14 @@ HandleSysAudioFilterPinCreation(
|
||||||
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
|
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
|
||||||
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
|
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
|
||||||
|
|
||||||
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
|
DPRINT1("PinInstances.CurrentCount %u\n", PinInstances.CurrentCount);
|
||||||
|
|
||||||
|
if (PinInstances.CurrentCount < PinInstances.PossibleCount)
|
||||||
{
|
{
|
||||||
/* re-using pin */
|
|
||||||
Status = SetPinFormat(Entry, PinConnect, Length);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
if (MixerFormat)
|
|
||||||
ExFreePool(MixerFormat);
|
|
||||||
IoFreeWorkItem(WorkItem);
|
|
||||||
ExFreePool(WorkerContext);
|
|
||||||
ExFreePool(DispatchContext);
|
|
||||||
return SetIrpIoStatus(Irp, Status, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* create the real pin */
|
|
||||||
WorkerContext->CreateRealPin = TRUE;
|
WorkerContext->CreateRealPin = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set up context */
|
/* set up context */
|
||||||
|
|
||||||
WorkerContext->DispatchContext = DispatchContext;
|
WorkerContext->DispatchContext = DispatchContext;
|
||||||
WorkerContext->Entry = Entry;
|
WorkerContext->Entry = Entry;
|
||||||
WorkerContext->Irp = Irp;
|
WorkerContext->Irp = Irp;
|
||||||
|
|
|
@ -24,7 +24,7 @@ Dispatch_fnDeviceIoControl(
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
DPRINT("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
//DPRINT("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
|
||||||
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
|
||||||
|
@ -95,6 +95,8 @@ Dispatch_fnClose(
|
||||||
PIO_STACK_LOCATION IoStatus;
|
PIO_STACK_LOCATION IoStatus;
|
||||||
ULONG Index, SubIndex;
|
ULONG Index, SubIndex;
|
||||||
PSYSAUDIODEVEXT DeviceExtension;
|
PSYSAUDIODEVEXT DeviceExtension;
|
||||||
|
PDISPATCH_CONTEXT DispatchContext;
|
||||||
|
|
||||||
|
|
||||||
IoStatus = IoGetCurrentIrpStackLocation(Irp);
|
IoStatus = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
@ -105,6 +107,7 @@ Dispatch_fnClose(
|
||||||
DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices);
|
DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices);
|
||||||
for(Index = 0; Index < Client->NumDevices; Index++)
|
for(Index = 0; Index < Client->NumDevices; Index++)
|
||||||
{
|
{
|
||||||
|
DPRINT1("Index %u Device %u Handels Count %u\n", Index, Client->Devs[Index].DeviceId, Client->Devs[Index].ClientHandlesCount);
|
||||||
if (Client->Devs[Index].ClientHandlesCount)
|
if (Client->Devs[Index].ClientHandlesCount)
|
||||||
{
|
{
|
||||||
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Client->Devs[Index].DeviceId);
|
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Client->Devs[Index].DeviceId);
|
||||||
|
@ -112,7 +115,9 @@ Dispatch_fnClose(
|
||||||
|
|
||||||
for(SubIndex = 0; SubIndex < Client->Devs[Index].ClientHandlesCount; SubIndex++)
|
for(SubIndex = 0; SubIndex < Client->Devs[Index].ClientHandlesCount; SubIndex++)
|
||||||
{
|
{
|
||||||
ASSERT(Entry->NumberOfPins > Client->Devs[Index].ClientHandles[SubIndex].PinId);
|
if (Client->Devs[Index].ClientHandles[SubIndex].PinId == (ULONG)-1)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (Client->Devs[Index].ClientHandles[SubIndex].bHandle)
|
if (Client->Devs[Index].ClientHandles[SubIndex].bHandle)
|
||||||
{
|
{
|
||||||
DPRINT1("Closing handle %p\n", Client->Devs[Index].ClientHandles[SubIndex].hPin);
|
DPRINT1("Closing handle %p\n", Client->Devs[Index].ClientHandles[SubIndex].hPin);
|
||||||
|
@ -125,6 +130,21 @@ Dispatch_fnClose(
|
||||||
/* this is pin which can only be instantiated once
|
/* this is pin which can only be instantiated once
|
||||||
* so we just need to release the reference count on that pin */
|
* so we just need to release the reference count on that pin */
|
||||||
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
|
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--;
|
||||||
|
|
||||||
|
DispatchContext = (PDISPATCH_CONTEXT)Client->Devs[Index].ClientHandles[SubIndex].DispatchContext;
|
||||||
|
ObDereferenceObject(DispatchContext->MixerFileObject);
|
||||||
|
ObDereferenceObject(DispatchContext->FileObject);
|
||||||
|
ZwClose(DispatchContext->hMixerPin);
|
||||||
|
ExFreePool(DispatchContext);
|
||||||
|
|
||||||
|
//DPRINT1("Index %u DeviceIndex %u Pin %u References %u\n", Index, Client->Devs[Index].DeviceId, SubIndex, Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References);
|
||||||
|
if (!Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References)
|
||||||
|
{
|
||||||
|
DPRINT1("Closing pin %p\n", Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle);
|
||||||
|
|
||||||
|
ZwClose(Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle);
|
||||||
|
Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExFreePool(Client->Devs[Index].ClientHandles);
|
ExFreePool(Client->Devs[Index].ClientHandles);
|
||||||
|
|
|
@ -7,6 +7,7 @@ typedef struct
|
||||||
ULONG PinId;
|
ULONG PinId;
|
||||||
HANDLE hPin;
|
HANDLE hPin;
|
||||||
HANDLE hMixer;
|
HANDLE hMixer;
|
||||||
|
PVOID DispatchContext;
|
||||||
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
|
}SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue