2009-02-20 17:52:47 +00:00
/*
* COPYRIGHT : See COPYING in the top level directory
* PROJECT : ReactOS Kernel Streaming
* FILE : drivers / wdm / audio / sysaudio / control . c
* PURPOSE : System Audio graph builder
* PROGRAMMER : Johannes Anderwald
*/
# include "sysaudio.h"
const GUID KSPROPSETID_Sysaudio = { 0xCBE3FAA0L , 0xCC75 , 0x11D0 , { 0xB4 , 0x65 , 0x00 , 0x00 , 0x1A , 0x18 , 0x18 , 0xE6 } } ;
const GUID KSPROPSETID_Sysaudio_Pin = { 0xA3A53220L , 0xC6E4 , 0x11D0 , { 0xB4 , 0x65 , 0x00 , 0x00 , 0x1A , 0x18 , 0x18 , 0xE6 } } ;
const GUID KSPROPSETID_General = { 0x1464EDA5L , 0x6A8F , 0x11D1 , { 0x9A , 0xA7 , 0x00 , 0xA0 , 0xC9 , 0x22 , 0x31 , 0x96 } } ;
2009-02-22 18:58:51 +00:00
const GUID KSPROPSETID_Pin = { 0x8C134960L , 0x51AD , 0x11CF , { 0x87 , 0x8A , 0x94 , 0xF8 , 0x01 , 0xC1 , 0x00 , 0x00 } } ;
const GUID KSPROPSETID_Connection = { 0x1D58C920L , 0xAC9B , 0x11CF , { 0xA5 , 0xD6 , 0x28 , 0xDB , 0x04 , 0xC1 , 0x00 , 0x00 } } ;
2009-06-08 21:37:20 +00:00
const GUID KSPROPSETID_Topology = { 0x720D4AC0L , 0x7533 , 0x11D0 , { 0xA5 , 0xD6 , 0x28 , 0xDB , 0x04 , 0xC1 , 0x00 , 0x00 } } ;
2009-03-11 09:30:33 +00:00
const GUID KSDATAFORMAT_TYPE_AUDIO = { 0x73647561L , 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 } } ;
2009-02-20 17:52:47 +00:00
2009-04-14 14:59:51 +00:00
NTSTATUS
ComputeCompatibleFormat (
2009-06-07 18:22:24 +00:00
IN PKSAUDIO_SUBDEVICE_ENTRY Entry ,
2009-04-14 14:59:51 +00:00
IN ULONG PinId ,
IN PSYSAUDIODEVEXT DeviceExtension ,
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat ,
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat ) ;
2009-06-07 18:22:24 +00:00
NTSTATUS
NTAPI
KspCreateObjectType (
IN HANDLE ParentHandle ,
IN LPWSTR ObjectType ,
PVOID CreateParameters ,
UINT CreateParametersSize ,
IN ACCESS_MASK DesiredAccess ,
OUT PHANDLE NodeHandle )
{
NTSTATUS Status ;
IO_STATUS_BLOCK IoStatusBlock ;
OBJECT_ATTRIBUTES ObjectAttributes ;
UNICODE_STRING Name ;
2009-07-09 21:49:04 +00:00
Name . Length = Name . MaximumLength = ( wcslen ( ObjectType ) + 1 ) * sizeof ( WCHAR ) + CreateParametersSize ;
2009-06-07 18:22:24 +00:00
Name . MaximumLength + = sizeof ( WCHAR ) ;
Name . Buffer = ExAllocatePool ( NonPagedPool , Name . MaximumLength ) ;
if ( ! Name . Buffer )
{
return STATUS_INSUFFICIENT_RESOURCES ;
}
wcscpy ( Name . Buffer , ObjectType ) ;
Name . Buffer [ wcslen ( ObjectType ) ] = ' \\ ' ;
RtlMoveMemory ( Name . Buffer + wcslen ( ObjectType ) + 1 , CreateParameters , CreateParametersSize ) ;
Name . Buffer [ Name . Length / 2 ] = L ' \0 ' ;
InitializeObjectAttributes ( & ObjectAttributes , & Name , OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF , ParentHandle , NULL ) ;
Status = IoCreateFile ( NodeHandle ,
DesiredAccess ,
& ObjectAttributes ,
& IoStatusBlock ,
NULL ,
0 ,
0 ,
FILE_OPEN ,
FILE_SYNCHRONOUS_IO_NONALERT ,
NULL ,
0 ,
CreateFileTypeNone ,
NULL ,
IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK ) ;
2009-07-09 21:49:04 +00:00
ExFreePool ( Name . Buffer ) ;
2009-06-07 18:22:24 +00:00
return Status ;
}
KSDDKAPI
NTSTATUS
NTAPI
KsoCreatePin (
IN HANDLE FilterHandle ,
IN PKSPIN_CONNECT Connect ,
IN ACCESS_MASK DesiredAccess ,
OUT PHANDLE ConnectionHandle ,
IN LPWSTR ObjectClass )
{
WCHAR szBuffer [ 100 ] ;
UINT ConnectSize = sizeof ( KSPIN_CONNECT ) ;
PKSDATAFORMAT_WAVEFORMATEX Format = ( PKSDATAFORMAT_WAVEFORMATEX ) ( Connect + 1 ) ;
if ( Format - > DataFormat . FormatSize = = sizeof ( KSDATAFORMAT ) | |
Format - > DataFormat . FormatSize = = sizeof ( KSDATAFORMAT ) + sizeof ( WAVEFORMATEX ) )
{
ConnectSize + = Format - > DataFormat . FormatSize ;
}
swprintf ( szBuffer , L " %s \\ {146F1A80-4791-11D0-A5D6-28DB04C10000} " , ObjectClass ) ;
return KspCreateObjectType ( FilterHandle ,
szBuffer ,
( PVOID ) Connect ,
ConnectSize ,
DesiredAccess ,
ConnectionHandle ) ;
}
2009-02-20 17:52:47 +00:00
NTSTATUS
SetIrpIoStatus (
IN PIRP Irp ,
IN NTSTATUS Status ,
IN ULONG Length )
{
Irp - > IoStatus . Information = Length ;
Irp - > IoStatus . Status = Status ;
2009-03-12 22:11:53 +00:00
if ( Status ! = STATUS_PENDING )
{
IoCompleteRequest ( Irp , IO_NO_INCREMENT ) ;
}
else
{
IoMarkIrpPending ( Irp ) ;
}
2009-02-20 17:52:47 +00:00
return Status ;
}
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY
2009-02-20 17:52:47 +00:00
GetListEntry (
IN PLIST_ENTRY Head ,
IN ULONG Index )
{
2009-06-07 18:22:24 +00:00
PKSAUDIO_DEVICE_ENTRY DeviceEntry ;
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry ;
PLIST_ENTRY SubEntry , Entry = Head - > Flink ;
2009-02-20 17:52:47 +00:00
2009-06-07 18:22:24 +00:00
while ( Entry ! = Head )
{
DeviceEntry = ( PKSAUDIO_DEVICE_ENTRY ) CONTAINING_RECORD ( Entry , KSAUDIO_DEVICE_ENTRY , Entry ) ;
if ( Index < DeviceEntry - > NumSubDevices )
{
SubEntry = DeviceEntry - > SubDeviceList . Flink ;
while ( SubEntry ! = & DeviceEntry - > SubDeviceList & & Index - - )
SubEntry = SubEntry - > Flink ;
SubDeviceEntry = ( PKSAUDIO_SUBDEVICE_ENTRY ) CONTAINING_RECORD ( SubEntry , KSAUDIO_SUBDEVICE_ENTRY , Entry ) ;
return SubDeviceEntry ;
}
else
{
Index - = DeviceEntry - > NumSubDevices ;
}
2009-02-20 17:52:47 +00:00
2009-06-07 18:22:24 +00:00
Entry = Entry - > Flink ;
2009-02-20 17:52:47 +00:00
2009-06-07 18:22:24 +00:00
}
2009-06-08 21:37:20 +00:00
DPRINT1 ( " Not Found index %u \n " , Index ) ;
2009-06-07 18:22:24 +00:00
return NULL ;
2009-02-20 17:52:47 +00:00
}
NTSTATUS
SysAudioOpenVirtualDevice (
IN PIRP Irp ,
IN ULONG DeviceNumber ,
PSYSAUDIODEVEXT DeviceExtension )
{
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY Entry ;
2009-02-20 17:52:47 +00:00
PKSOBJECT_CREATE_ITEM CreateItem ;
/* access the create item */
CreateItem = KSCREATE_ITEM_IRP_STORAGE ( Irp ) ;
ASSERT ( CreateItem ) ;
if ( DeviceNumber > = DeviceExtension - > NumberOfKsAudioDevices )
{
/* invalid device index */
return SetIrpIoStatus ( Irp , STATUS_INVALID_PARAMETER , 0 ) ;
}
2009-03-25 19:14:04 +00:00
/* get device context */
Entry = GetListEntry ( & DeviceExtension - > KsAudioDeviceList , DeviceNumber ) ;
ASSERT ( Entry ! = NULL ) ;
2009-02-25 15:55:21 +00:00
2009-02-20 17:52:47 +00:00
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , 0 ) ;
2009-02-22 18:58:51 +00:00
}
2009-03-12 22:11:53 +00:00
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 ;
2009-04-19 22:01:57 +00:00
DPRINT ( " InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u \n " , InputFormat , InputFormat - > FormatSize , sizeof ( KSDATAFORMAT_WAVEFORMATEX ) , sizeof ( KSDATAFORMAT ) , sizeof ( WAVEFORMATEX ) ) ;
2009-03-12 22:11:53 +00:00
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 ;
2009-04-19 22:01:57 +00:00
DPRINT ( " OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u \n " , OutputFormat , OutputFormat - > FormatSize , sizeof ( KSDATAFORMAT_WAVEFORMATEX ) , sizeof ( KSDATAFORMAT ) , sizeof ( WAVEFORMATEX ) ) ;
2009-03-12 22:11:53 +00:00
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 ,
2009-06-10 18:28:15 +00:00
OUT PHANDLE MixerPinHandle )
2009-03-12 22:11:53 +00:00
{
NTSTATUS Status ;
HANDLE PinHandle ;
PFILE_OBJECT FileObject ;
2009-06-09 14:50:24 +00:00
Status = KsoCreatePin ( KMixerHandle , PinConnect , GENERIC_READ | GENERIC_WRITE , & PinHandle , L " KMixer " ) ;
2009-03-12 22:11:53 +00:00
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 ) ;
}
2009-06-10 18:28:15 +00:00
ObDereferenceObject ( FileObject ) ;
2009-03-12 22:11:53 +00:00
* MixerPinHandle = PinHandle ;
return Status ;
}
2009-02-22 18:58:51 +00:00
VOID
NTAPI
CreatePinWorkerRoutine (
IN PDEVICE_OBJECT DeviceObject ,
IN PVOID Context )
{
NTSTATUS Status ;
2009-04-14 14:59:51 +00:00
HANDLE RealPinHandle = NULL , VirtualPinHandle = NULL , Filter ;
2009-06-10 18:28:15 +00:00
PFILE_OBJECT VirtualFileObject = NULL ;
2009-04-15 10:41:41 +00:00
PKSDATAFORMAT_WAVEFORMATEX InputFormat ;
2009-04-14 14:59:51 +00:00
PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL ;
PKSPIN_CONNECT MixerPinConnect = NULL ;
2009-02-22 18:58:51 +00:00
PPIN_WORKER_CONTEXT WorkerContext = ( PPIN_WORKER_CONTEXT ) Context ;
2009-03-11 09:30:33 +00:00
2009-02-22 18:58:51 +00:00
Filter = WorkerContext - > PinConnect - > PinToHandle ;
WorkerContext - > PinConnect - > PinToHandle = NULL ;
2009-03-12 22:11:53 +00:00
DPRINT ( " CreatePinWorkerRoutine entered \n " ) ;
2009-02-27 13:19:10 +00:00
ASSERT ( WorkerContext - > Entry ) ;
ASSERT ( WorkerContext - > PinConnect ) ;
ASSERT ( WorkerContext - > Entry - > Pins ) ;
ASSERT ( WorkerContext - > Entry - > NumberOfPins > WorkerContext - > PinConnect - > PinId ) ;
2009-02-22 18:58:51 +00:00
2009-04-15 10:41:41 +00:00
/* Fetch input format */
InputFormat = ( PKSDATAFORMAT_WAVEFORMATEX ) ( WorkerContext - > PinConnect + 1 ) ;
2009-04-14 14:59:51 +00:00
/* Let's try to create the audio irp pin */
2009-06-07 18:22:24 +00:00
Status = KsoCreatePin ( WorkerContext - > Entry - > Handle , WorkerContext - > PinConnect , GENERIC_READ | GENERIC_WRITE , & RealPinHandle , WorkerContext - > Entry - > ObjectClass ) ;
2009-03-11 09:30:33 +00:00
2009-04-14 14:59:51 +00:00
if ( ! NT_SUCCESS ( Status ) )
2009-03-11 09:30:33 +00:00
{
2009-04-14 14:59:51 +00:00
/* 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 )
2009-03-11 09:30:33 +00:00
{
2009-04-14 14:59:51 +00:00
SetIrpIoStatus ( WorkerContext - > Irp , STATUS_UNSUCCESSFUL , 0 ) ;
2009-03-11 09:30:33 +00:00
ExFreePool ( WorkerContext - > DispatchContext ) ;
2009-04-22 10:57:28 +00:00
IoFreeWorkItem ( WorkerContext - > WorkItem ) ;
ExFreePool ( WorkerContext ) ;
2009-03-11 09:30:33 +00:00
return ;
}
2009-06-28 20:06:45 +00:00
/* Zero pin connect */
RtlZeroMemory ( MixerPinConnect , sizeof ( KSPIN_CONNECT ) + sizeof ( KSDATAFORMAT_WAVEFORMATEX ) ) ;
2009-04-14 14:59:51 +00:00
/* Copy initial connect details */
RtlMoveMemory ( MixerPinConnect , WorkerContext - > PinConnect , sizeof ( KSPIN_CONNECT ) ) ;
2009-03-11 09:30:33 +00:00
2009-04-14 14:59:51 +00:00
OutputFormat = ( PKSDATAFORMAT_WAVEFORMATEX ) ( MixerPinConnect + 1 ) ;
2009-03-11 09:30:33 +00:00
2009-06-28 20:06:45 +00:00
Status = ComputeCompatibleFormat ( WorkerContext - > Entry , WorkerContext - > PinConnect - > PinId , WorkerContext - > DeviceExtension , InputFormat , OutputFormat ) ;
2009-03-11 09:30:33 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
2009-04-14 14:59:51 +00:00
DPRINT1 ( " ComputeCompatibleFormat failed with %x \n " , Status ) ;
2009-03-11 09:30:33 +00:00
SetIrpIoStatus ( WorkerContext - > Irp , STATUS_UNSUCCESSFUL , 0 ) ;
ExFreePool ( WorkerContext - > DispatchContext ) ;
2009-04-14 14:59:51 +00:00
ExFreePool ( MixerPinConnect ) ;
2009-04-22 10:57:28 +00:00
IoFreeWorkItem ( WorkerContext - > WorkItem ) ;
ExFreePool ( WorkerContext ) ;
2009-03-11 09:30:33 +00:00
return ;
}
2009-04-14 14:59:51 +00:00
/* Retry with Mixer format */
2009-06-07 18:22:24 +00:00
Status = KsoCreatePin ( WorkerContext - > Entry - > Handle , MixerPinConnect , GENERIC_READ | GENERIC_WRITE , & RealPinHandle , WorkerContext - > Entry - > ObjectClass ) ;
2009-03-11 09:30:33 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
2009-04-22 15:01:18 +00:00
/* This should not fail */
2009-04-14 14:59:51 +00:00
DPRINT1 ( " KsCreatePin failed with %x \n " , Status ) ;
2009-04-22 15:01:18 +00:00
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 ) ;
2009-03-11 09:30:33 +00:00
return ;
}
}
2009-06-10 18:28:15 +00:00
ASSERT ( WorkerContext - > Entry - > Pins [ WorkerContext - > PinConnect - > PinId ] . MaxPinInstanceCount ) ;
2009-02-22 18:58:51 +00:00
2009-04-14 14:59:51 +00:00
WorkerContext - > Entry - > Pins [ WorkerContext - > PinConnect - > PinId ] . References = 0 ;
WorkerContext - > DispatchContext - > Handle = RealPinHandle ;
WorkerContext - > DispatchContext - > PinId = WorkerContext - > PinConnect - > PinId ;
WorkerContext - > DispatchContext - > AudioEntry = WorkerContext - > Entry ;
2009-02-22 18:58:51 +00:00
2009-04-14 14:59:51 +00:00
/* Do we need to transform the audio stream */
if ( OutputFormat ! = NULL )
{
/* Now create the mixer pin */
Status = CreateMixerPinAndSetFormat ( WorkerContext - > DeviceExtension - > KMixerHandle ,
MixerPinConnect ,
2009-04-15 10:41:41 +00:00
( PKSDATAFORMAT ) InputFormat ,
2009-04-14 14:59:51 +00:00
( PKSDATAFORMAT ) OutputFormat ,
2009-06-10 18:28:15 +00:00
& WorkerContext - > DispatchContext - > hMixerPin ) ;
2009-02-22 18:58:51 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
2009-04-14 14:59:51 +00:00
DPRINT1 ( " Failed to create Mixer Pin with %x \n " , Status ) ;
goto cleanup ;
2009-02-22 18:58:51 +00:00
}
2009-03-12 22:11:53 +00:00
2009-02-22 18:58:51 +00:00
}
2009-04-03 17:06:16 +00:00
DPRINT1 ( " creating virtual pin \n " ) ;
2009-02-22 18:58:51 +00:00
/* now create the virtual audio pin which is exposed to wdmaud */
2009-06-09 14:50:24 +00:00
Status = KsoCreatePin ( Filter , WorkerContext - > PinConnect , GENERIC_READ | GENERIC_WRITE , & VirtualPinHandle , L " SysAudio " ) ;
2009-02-22 18:58:51 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
2009-04-14 14:59:51 +00:00
DPRINT1 ( " Failed to create virtual pin %x \n " , Status ) ;
goto cleanup ;
2009-02-22 18:58:51 +00:00
}
/* get pin file object */
2009-02-25 15:55:21 +00:00
Status = ObReferenceObjectByHandle ( VirtualPinHandle ,
2009-02-22 18:58:51 +00:00
GENERIC_READ | GENERIC_WRITE ,
2009-04-14 14:59:51 +00:00
IoFileObjectType , KernelMode , ( PVOID * ) & VirtualFileObject , NULL ) ;
2009-02-22 18:58:51 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
DPRINT1 ( " Failed to get file object with %x \n " , Status ) ;
2009-04-14 14:59:51 +00:00
goto cleanup ;
2009-02-22 18:58:51 +00:00
}
2009-02-20 17:52:47 +00:00
2009-02-25 15:55:21 +00:00
ASSERT ( WorkerContext - > Entry - > Pins ! = NULL ) ;
2009-06-10 18:28:15 +00:00
ASSERT ( WorkerContext - > Entry - > NumberOfPins > WorkerContext - > PinConnect - > PinId ) ;
2009-02-25 15:55:21 +00:00
2009-06-10 18:28:15 +00:00
/* increment reference count */
WorkerContext - > Entry - > Pins [ WorkerContext - > PinConnect - > PinId ] . References + + ;
2009-02-25 15:55:21 +00:00
2009-06-10 18:28:15 +00:00
/* store the pin handle there if the pin can only be instantiated once*/
WorkerContext - > Entry - > Pins [ WorkerContext - > PinConnect - > PinId ] . PinHandle = VirtualPinHandle ;
2009-02-22 18:58:51 +00:00
/* store pin context */
2009-04-14 14:59:51 +00:00
VirtualFileObject - > FsContext2 = ( PVOID ) WorkerContext - > DispatchContext ;
2009-02-22 18:58:51 +00:00
2009-06-10 18:28:15 +00:00
/* release virtual file object */
ObDereferenceObject ( VirtualFileObject ) ;
2009-03-12 22:11:53 +00:00
DPRINT ( " Successfully created virtual pin %p \n " , VirtualPinHandle ) ;
2009-02-25 15:55:21 +00:00
* ( ( PHANDLE ) WorkerContext - > Irp - > UserBuffer ) = VirtualPinHandle ;
2009-02-22 18:58:51 +00:00
SetIrpIoStatus ( WorkerContext - > Irp , STATUS_SUCCESS , sizeof ( HANDLE ) ) ;
2009-04-22 10:57:28 +00:00
IoFreeWorkItem ( WorkerContext - > WorkItem ) ;
ExFreePool ( WorkerContext ) ;
2009-04-14 14:59:51 +00:00
return ;
cleanup :
if ( RealPinHandle )
ZwClose ( RealPinHandle ) ;
if ( WorkerContext - > DispatchContext - > hMixerPin )
ZwClose ( WorkerContext - > DispatchContext - > hMixerPin ) ;
ExFreePool ( WorkerContext - > DispatchContext ) ;
SetIrpIoStatus ( WorkerContext - > Irp , Status , 0 ) ;
2009-04-22 10:57:28 +00:00
IoFreeWorkItem ( WorkerContext - > WorkItem ) ;
ExFreePool ( WorkerContext ) ;
2009-02-20 17:52:47 +00:00
}
2009-02-27 11:22:16 +00:00
NTSTATUS
HandleSysAudioFilterPinProperties (
PIRP Irp ,
PKSPROPERTY Property ,
PSYSAUDIODEVEXT DeviceExtension )
{
PIO_STACK_LOCATION IoStack ;
NTSTATUS Status ;
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY Entry ;
2009-02-27 11:22:16 +00:00
ULONG BytesReturned ;
PKSP_PIN Pin ;
// in order to access pin properties of a sysaudio device
// the caller must provide a KSP_PIN struct, where
// Reserved member points to virtual device index
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
if ( IoStack - > Parameters . DeviceIoControl . InputBufferLength < sizeof ( KSP_PIN ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSPROPERTY ) + sizeof ( ULONG ) ) ;
}
Pin = ( PKSP_PIN ) Property ;
Entry = GetListEntry ( & DeviceExtension - > KsAudioDeviceList , ( ( KSP_PIN * ) Property ) - > Reserved ) ;
if ( ! Entry )
{
/* invalid device index */
return SetIrpIoStatus ( Irp , STATUS_INVALID_PARAMETER , 0 ) ;
}
if ( ! Entry - > Pins )
{
/* expected pins */
return SetIrpIoStatus ( Irp , STATUS_UNSUCCESSFUL , 0 ) ;
}
if ( Entry - > NumberOfPins < = Pin - > PinId )
{
/* invalid pin id */
return SetIrpIoStatus ( Irp , STATUS_INVALID_PARAMETER , 0 ) ;
}
if ( Property - > Id = = KSPROPERTY_PIN_CTYPES )
{
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( ULONG ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( ULONG ) ) ;
}
/* store result */
* ( ( PULONG ) Irp - > UserBuffer ) = Entry - > NumberOfPins ;
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , sizeof ( ULONG ) ) ;
}
else if ( Property - > Id = = KSPROPERTY_PIN_COMMUNICATION )
{
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( KSPIN_COMMUNICATION ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSPIN_COMMUNICATION ) ) ;
}
/* store result */
* ( ( KSPIN_COMMUNICATION * ) Irp - > UserBuffer ) = Entry - > Pins [ Pin - > PinId ] . Communication ;
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , sizeof ( KSPIN_COMMUNICATION ) ) ;
}
else if ( Property - > Id = = KSPROPERTY_PIN_DATAFLOW )
{
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( KSPIN_DATAFLOW ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSPIN_DATAFLOW ) ) ;
}
/* store result */
* ( ( KSPIN_DATAFLOW * ) Irp - > UserBuffer ) = Entry - > Pins [ Pin - > PinId ] . DataFlow ;
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , sizeof ( KSPIN_DATAFLOW ) ) ;
}
else
{
/* forward request to the filter implementing the property */
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY ,
( PVOID ) IoStack - > Parameters . DeviceIoControl . Type3InputBuffer ,
IoStack - > Parameters . DeviceIoControl . InputBufferLength ,
Irp - > UserBuffer ,
IoStack - > Parameters . DeviceIoControl . OutputBufferLength ,
& BytesReturned ) ;
return SetIrpIoStatus ( Irp , Status , BytesReturned ) ;
}
}
2009-04-14 14:59:51 +00:00
NTSTATUS
2009-03-12 22:11:53 +00:00
ComputeCompatibleFormat (
2009-06-07 18:22:24 +00:00
IN PKSAUDIO_SUBDEVICE_ENTRY Entry ,
2009-03-12 22:11:53 +00:00
IN ULONG PinId ,
IN PSYSAUDIODEVEXT DeviceExtension ,
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat ,
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat )
2009-03-08 16:25:28 +00:00
{
2009-03-12 22:11:53 +00:00
BOOL bFound ;
2009-03-08 16:25:28 +00:00
ULONG BytesReturned ;
2009-04-14 14:59:51 +00:00
PKSP_PIN PinRequest ;
2009-03-08 16:25:28 +00:00
NTSTATUS Status ;
2009-03-12 22:11:53 +00:00
PKSMULTIPLE_ITEM MultipleItem ;
2009-04-14 14:59:51 +00:00
ULONG Length ;
PKSDATARANGE_AUDIO AudioRange ;
ULONG Index ;
2009-03-08 16:25:28 +00:00
2009-04-14 14:59:51 +00:00
Length = sizeof ( KSP_PIN ) + sizeof ( KSMULTIPLE_ITEM ) + ClientFormat - > DataFormat . FormatSize ;
PinRequest = ExAllocatePool ( NonPagedPool , Length ) ;
if ( ! PinRequest )
2009-03-12 22:11:53 +00:00
return STATUS_UNSUCCESSFUL ;
2009-04-14 14:59:51 +00:00
PinRequest - > PinId = PinId ;
PinRequest - > Property . Set = KSPROPSETID_Pin ;
PinRequest - > Property . Flags = KSPROPERTY_TYPE_GET ;
PinRequest - > Property . Id = KSPROPERTY_PIN_DATAINTERSECTION ;
MultipleItem = ( PKSMULTIPLE_ITEM ) ( PinRequest + 1 ) ;
MultipleItem - > Count = 1 ;
MultipleItem - > Size = sizeof ( KSMULTIPLE_ITEM ) + ClientFormat - > DataFormat . FormatSize ;
RtlMoveMemory ( MultipleItem + 1 , ClientFormat , ClientFormat - > DataFormat . FormatSize ) ;
/* Query the miniport data intersection handler */
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY , ( PVOID ) PinRequest , Length , ( PVOID ) MixerFormat , sizeof ( KSDATAFORMAT_WAVEFORMATEX ) , & BytesReturned ) ;
DPRINT ( " Status %x \n " , Status ) ;
if ( NT_SUCCESS ( Status ) )
{
ExFreePool ( PinRequest ) ;
return Status ;
2009-03-12 22:11:53 +00:00
}
2009-03-08 16:25:28 +00:00
2009-04-14 14:59:51 +00:00
/* Setup request block */
PinRequest - > Property . Id = KSPROPERTY_PIN_DATARANGES ;
/* Query pin data ranges */
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY , ( PVOID ) PinRequest , sizeof ( KSP_PIN ) , NULL , 0 , & BytesReturned ) ;
2009-03-11 09:30:33 +00:00
2009-03-12 22:11:53 +00:00
if ( Status ! = STATUS_BUFFER_TOO_SMALL )
{
2009-04-14 14:59:51 +00:00
/* Failed to data ranges */
return Status ;
2009-03-12 22:11:53 +00:00
}
MultipleItem = ExAllocatePool ( NonPagedPool , BytesReturned ) ;
if ( ! MultipleItem )
{
2009-04-14 14:59:51 +00:00
ExFreePool ( PinRequest ) ;
2009-03-12 22:11:53 +00:00
return STATUS_NO_MEMORY ;
}
2009-04-14 14:59:51 +00:00
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY , ( PVOID ) PinRequest , sizeof ( KSP_PIN ) , ( PVOID ) MultipleItem , BytesReturned , & BytesReturned ) ;
2009-03-12 22:11:53 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
DPRINT ( " Property Request KSPROPERTY_PIN_DATARANGES failed with %x \n " , Status ) ;
ExFreePool ( MultipleItem ) ;
2009-04-14 14:59:51 +00:00
ExFreePool ( PinRequest ) ;
2009-03-12 22:11:53 +00:00
return STATUS_UNSUCCESSFUL ;
}
2009-03-08 16:25:28 +00:00
2009-03-12 22:11:53 +00:00
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 ) ;
2009-06-28 20:06:45 +00:00
continue ;
2009-03-12 22:11:53 +00:00
}
2009-04-14 14:59:51 +00:00
/* Select best quality available */
2009-04-15 10:41:41 +00:00
2009-03-12 22:11:53 +00:00
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 ;
2009-04-15 10:41:41 +00:00
# ifndef NO_AC97_HACK
/* HACK: AC97 does not support mono render / record */
MixerFormat - > WaveFormatEx . nChannels = 2 ;
/*HACK: AC97 only supports 16-Bit Bits */
MixerFormat - > WaveFormatEx . wBitsPerSample = 16 ;
# else
MixerFormat - > WaveFormatEx . nChannels = min ( ClientFormat - > WaveFormatEx . nSamplesPerSec , AudioRange - > MaximumChannels ) ;
2009-04-14 14:59:51 +00:00
MixerFormat - > WaveFormatEx . wBitsPerSample = AudioRange - > MaximumBitsPerSample ;
2009-04-15 10:41:41 +00:00
# endif
# ifdef KMIXER_RESAMPLING_IMPLEMENTED
MixerFormat - > WaveFormatEx . nSamplesPerSec = AudioRange - > MaximumSampleFrequency ;
# else
MixerFormat - > WaveFormatEx . nSamplesPerSec = max ( AudioRange - > MinimumSampleFrequency , min ( ClientFormat - > WaveFormatEx . nSamplesPerSec , AudioRange - > MaximumSampleFrequency ) ) ;
# endif
2009-03-12 22:11:53 +00:00
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 ) ;
}
#if 0
2009-04-14 14:59:51 +00:00
DPRINT1 ( " \n Num Max Channels %u Channels %u Old Channels %u \n Max SampleRate %u SampleRate %u Old SampleRate %u \n Max BitsPerSample %u BitsPerSample %u Old BitsPerSample %u \n " ,
AudioRange - > MaximumChannels , MixerFormat - > WaveFormatEx . nChannels , ClientFormat - > WaveFormatEx . nChannels ,
AudioRange - > MaximumSampleFrequency , MixerFormat - > WaveFormatEx . nSamplesPerSec , ClientFormat - > WaveFormatEx . nSamplesPerSec ,
AudioRange - > MaximumBitsPerSample , MixerFormat - > WaveFormatEx . wBitsPerSample , ClientFormat - > WaveFormatEx . wBitsPerSample ) ;
2009-03-12 22:11:53 +00:00
# endif
2009-04-14 14:59:51 +00:00
ExFreePool ( MultipleItem ) ;
ExFreePool ( PinRequest ) ;
2009-03-12 22:11:53 +00:00
if ( bFound )
return STATUS_SUCCESS ;
else
return STATUS_NOT_IMPLEMENTED ;
2009-03-08 16:25:28 +00:00
}
2009-04-03 17:06:16 +00:00
NTSTATUS
GetPinInstanceCount (
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY Entry ,
2009-04-03 17:06:16 +00:00
PKSPIN_CINSTANCES PinInstances ,
PKSPIN_CONNECT PinConnect )
{
KSP_PIN PinRequest ;
ULONG BytesReturned ;
/* query the instance count */
PinRequest . PinId = PinConnect - > PinId ;
PinRequest . Property . Set = KSPROPSETID_Pin ;
PinRequest . Property . Flags = KSPROPERTY_TYPE_GET ;
PinRequest . Property . Id = KSPROPERTY_PIN_CINSTANCES ;
return KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY , ( PVOID ) & PinRequest , sizeof ( KSP_PIN ) , ( PVOID ) PinInstances , sizeof ( KSPIN_CINSTANCES ) , & BytesReturned ) ;
}
2009-02-27 11:22:16 +00:00
NTSTATUS
HandleSysAudioFilterPinCreation (
PIRP Irp ,
PKSPROPERTY Property ,
PSYSAUDIODEVEXT DeviceExtension ,
PDEVICE_OBJECT DeviceObject )
{
2009-04-14 14:59:51 +00:00
ULONG Length ;
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY Entry ;
2009-02-27 11:22:16 +00:00
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 ;
2009-04-22 10:57:28 +00:00
PIO_WORKITEM WorkItem ;
2009-02-27 11:22:16 +00:00
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 ) ;
}
2009-04-03 17:06:16 +00:00
/* query instance count */
Status = GetPinInstanceCount ( Entry , & PinInstances , PinConnect ) ;
2009-03-12 22:11:53 +00:00
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 )
{
2009-02-27 11:22:16 +00:00
/* pin already exists */
ASSERT ( Entry - > Pins [ PinConnect - > PinId ] . PinHandle ! = NULL ) ;
2009-06-10 18:28:15 +00:00
ASSERT ( Entry - > Pins [ PinConnect - > PinId ] . References ) ;
2009-02-27 11:22:16 +00:00
2009-06-10 18:28:15 +00:00
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 ) ;
}
2009-04-22 10:57:28 +00:00
/* create dispatch pin context */
2009-02-27 11:22:16 +00:00
DispatchContext = ExAllocatePool ( NonPagedPool , sizeof ( DISPATCH_CONTEXT ) ) ;
if ( ! DispatchContext )
{
2009-04-14 14:59:51 +00:00
/* no memory */
2009-02-27 11:22:16 +00:00
return SetIrpIoStatus ( Irp , STATUS_NO_MEMORY , 0 ) ;
}
2009-04-03 17:06:16 +00:00
2009-04-22 10:57:28 +00:00
/* allocate worker context */
WorkerContext = ExAllocatePool ( NonPagedPool , sizeof ( PIN_WORKER_CONTEXT ) ) ;
if ( ! WorkerContext )
{
/* no memory */
ExFreePool ( DispatchContext ) ;
return SetIrpIoStatus ( Irp , STATUS_NO_MEMORY , 0 ) ;
}
2009-04-03 17:06:16 +00:00
2009-04-22 10:57:28 +00:00
/* allocate work item */
WorkItem = IoAllocateWorkItem ( DeviceObject ) ;
if ( ! WorkerContext )
{
/* no memory */
ExFreePool ( DispatchContext ) ;
ExFreePool ( WorkerContext ) ;
return SetIrpIoStatus ( Irp , STATUS_NO_MEMORY , 0 ) ;
}
2009-04-03 17:06:16 +00:00
2009-02-27 11:22:16 +00:00
/* prepare context */
RtlZeroMemory ( WorkerContext , sizeof ( PIN_WORKER_CONTEXT ) ) ;
RtlZeroMemory ( DispatchContext , sizeof ( DISPATCH_CONTEXT ) ) ;
2009-04-03 17:06:16 +00:00
DPRINT ( " PinInstances.CurrentCount %u \n " , PinInstances . CurrentCount ) ;
2009-03-12 22:11:53 +00:00
if ( PinInstances . CurrentCount < PinInstances . PossibleCount )
2009-02-27 11:22:16 +00:00
{
WorkerContext - > CreateRealPin = TRUE ;
}
/* set up context */
WorkerContext - > DispatchContext = DispatchContext ;
WorkerContext - > Entry = Entry ;
WorkerContext - > Irp = Irp ;
WorkerContext - > PinConnect = PinConnect ;
2009-03-11 09:30:33 +00:00
WorkerContext - > DeviceExtension = DeviceExtension ;
2009-04-22 10:57:28 +00:00
WorkerContext - > WorkItem = WorkItem ;
2009-02-27 11:22:16 +00:00
DPRINT ( " Queing Irp %p \n " , Irp ) ;
/* queue the work item */
IoMarkIrpPending ( Irp ) ;
Irp - > IoStatus . Status = STATUS_PENDING ;
Irp - > IoStatus . Information = 0 ;
2009-04-22 10:57:28 +00:00
IoQueueWorkItem ( WorkItem , CreatePinWorkerRoutine , DelayedWorkQueue , ( PVOID ) WorkerContext ) ;
2009-02-27 11:22:16 +00:00
/* mark irp as pending */
return STATUS_PENDING ;
}
2009-02-20 17:52:47 +00:00
NTSTATUS
SysAudioHandleProperty (
PDEVICE_OBJECT DeviceObject ,
PIRP Irp )
{
PIO_STACK_LOCATION IoStack ;
NTSTATUS Status = STATUS_NOT_IMPLEMENTED ;
KSPROPERTY PropertyRequest ;
KSCOMPONENTID ComponentId ;
PULONG Index ;
PKSPROPERTY Property ;
PSYSAUDIODEVEXT DeviceExtension ;
2009-06-07 18:22:24 +00:00
PKSAUDIO_SUBDEVICE_ENTRY Entry ;
2009-02-20 17:52:47 +00:00
PSYSAUDIO_INSTANCE_INFO InstanceInfo ;
2009-03-25 19:14:04 +00:00
ULONG BytesReturned ;
2009-02-20 17:52:47 +00:00
PKSOBJECT_CREATE_ITEM CreateItem ;
UNICODE_STRING GuidString ;
2009-06-08 21:37:20 +00:00
PKSP_PIN Pin ;
2009-02-20 17:52:47 +00:00
/* access the create item */
CreateItem = KSCREATE_ITEM_IRP_STORAGE ( Irp ) ;
IoStack = IoGetCurrentIrpStackLocation ( Irp ) ;
if ( IoStack - > Parameters . DeviceIoControl . InputBufferLength < sizeof ( KSPROPERTY ) )
{
2009-02-27 11:22:16 +00:00
/* buffer must be at least of sizeof KSPROPERTY */
2009-02-20 17:52:47 +00:00
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSPROPERTY ) ) ;
}
Property = ( PKSPROPERTY ) IoStack - > Parameters . DeviceIoControl . Type3InputBuffer ;
DeviceExtension = ( PSYSAUDIODEVEXT ) DeviceObject - > DeviceExtension ;
2009-02-23 21:51:41 +00:00
if ( IsEqualGUIDAligned ( & Property - > Set , & KSPROPSETID_Pin ) )
{
2009-02-27 11:22:16 +00:00
return HandleSysAudioFilterPinProperties ( Irp , Property , DeviceExtension ) ;
2009-02-23 21:51:41 +00:00
}
2009-06-08 21:37:20 +00:00
else if ( IsEqualGUIDAligned ( & Property - > Set , & KSPROPSETID_Topology ) )
{
if ( IoStack - > Parameters . DeviceIoControl . InputBufferLength < sizeof ( KSP_PIN ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSP_PIN ) ) ;
}
Pin = ( PKSP_PIN ) IoStack - > Parameters . DeviceIoControl . Type3InputBuffer ;
Entry = GetListEntry ( & DeviceExtension - > KsAudioDeviceList , Pin - > Reserved ) ;
ASSERT ( Entry ! = NULL ) ;
/* forward request to the filter implementing the property */
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY ,
( PVOID ) IoStack - > Parameters . DeviceIoControl . Type3InputBuffer ,
IoStack - > Parameters . DeviceIoControl . InputBufferLength ,
Irp - > UserBuffer ,
IoStack - > Parameters . DeviceIoControl . OutputBufferLength ,
& BytesReturned ) ;
return SetIrpIoStatus ( Irp , Status , BytesReturned ) ;
}
2009-02-23 21:51:41 +00:00
else if ( IsEqualGUIDAligned ( & Property - > Set , & KSPROPSETID_Sysaudio ) )
2009-02-20 17:52:47 +00:00
{
if ( Property - > Id = = KSPROPERTY_SYSAUDIO_COMPONENT_ID )
{
if ( IoStack - > Parameters . DeviceIoControl . InputBufferLength < sizeof ( KSPROPERTY ) + sizeof ( ULONG ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSPROPERTY ) + sizeof ( ULONG ) ) ;
}
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( KSCOMPONENTID ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( KSCOMPONENTID ) ) ;
}
Index = ( PULONG ) ( Property + 1 ) ;
if ( DeviceExtension - > NumberOfKsAudioDevices < = * Index )
{
/* invalid index */
return SetIrpIoStatus ( Irp , STATUS_INVALID_PARAMETER , 0 ) ;
}
Entry = GetListEntry ( & DeviceExtension - > KsAudioDeviceList , * Index ) ;
ASSERT ( Entry ! = NULL ) ;
PropertyRequest . Set = KSPROPSETID_General ;
PropertyRequest . Id = KSPROPERTY_GENERAL_COMPONENTID ;
PropertyRequest . Flags = KSPROPERTY_TYPE_GET ;
/* call the filter */
2009-02-23 21:51:41 +00:00
Status = KsSynchronousIoControlDevice ( Entry - > FileObject , KernelMode , IOCTL_KS_PROPERTY , ( PVOID ) & PropertyRequest , sizeof ( KSPROPERTY ) , ( PVOID ) & ComponentId , sizeof ( KSCOMPONENTID ) , & BytesReturned ) ;
2009-02-20 17:52:47 +00:00
if ( ! NT_SUCCESS ( Status ) )
{
2009-04-03 17:06:16 +00:00
DPRINT ( " KsSynchronousIoControlDevice failed with %x for KSPROPERTY_GENERAL_COMPONENTID \n " , Status ) ;
2009-02-20 17:52:47 +00:00
return SetIrpIoStatus ( Irp , Status , 0 ) ;
}
RtlMoveMemory ( Irp - > UserBuffer , & ComponentId , sizeof ( KSCOMPONENTID ) ) ;
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , sizeof ( KSCOMPONENTID ) ) ;
}
else if ( Property - > Id = = KSPROPERTY_SYSAUDIO_DEVICE_COUNT )
{
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( ULONG ) )
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( ULONG ) ) ;
}
2009-02-27 11:22:16 +00:00
2009-02-20 17:52:47 +00:00
* ( ( PULONG ) Irp - > UserBuffer ) = DeviceExtension - > NumberOfKsAudioDevices ;
return SetIrpIoStatus ( Irp , STATUS_SUCCESS , sizeof ( ULONG ) ) ;
}
else if ( Property - > Id = = KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE )
{
if ( IoStack - > Parameters . DeviceIoControl . OutputBufferLength < sizeof ( ULONG ) )
{
/* too small buffer */
2009-03-25 19:14:04 +00:00
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( ULONG ) ) ;
2009-02-20 17:52:47 +00:00
}
if ( Property - > Flags & KSPROPERTY_TYPE_SET )
{
Index = ( PULONG ) Irp - > UserBuffer ;
return SysAudioOpenVirtualDevice ( Irp , * Index , DeviceExtension ) ;
}
}
else if ( Property - > Id = = KSPROPERTY_SYSAUDIO_INSTANCE_INFO )
{
2009-02-21 20:18:44 +00:00
if ( IoStack - > Parameters . DeviceIoControl . InputBufferLength < sizeof ( SYSAUDIO_INSTANCE_INFO ) )
2009-02-20 17:52:47 +00:00
{
/* too small buffer */
return SetIrpIoStatus ( Irp , STATUS_BUFFER_TOO_SMALL , sizeof ( SYSAUDIO_INSTANCE_INFO ) ) ;
}
/* get input parameter */
InstanceInfo = ( PSYSAUDIO_INSTANCE_INFO ) Property ;
if ( Property - > Flags & KSPROPERTY_TYPE_SET )
{
return SysAudioOpenVirtualDevice ( Irp , InstanceInfo - > DeviceNumber , DeviceExtension ) ;
}
}
2009-02-22 18:58:51 +00:00
else if ( Property - > Id = = ( ULONG ) - 1 )
{
/* ros specific pin creation request */
2009-04-03 17:06:16 +00:00
DPRINT ( " Initiating create request \n " ) ;
2009-02-27 11:22:16 +00:00
return HandleSysAudioFilterPinCreation ( Irp , Property , DeviceExtension , DeviceObject ) ;
2009-02-22 18:58:51 +00:00
}
2009-02-20 17:52:47 +00:00
}
RtlStringFromGUID ( & Property - > Set , & GuidString ) ;
DPRINT1 ( " Unhandeled property Set |%S| Id %u Flags %x \n " , GuidString . Buffer , Property - > Id , Property - > Flags ) ;
RtlFreeUnicodeString ( & GuidString ) ;
2009-02-23 23:24:58 +00:00
return SetIrpIoStatus ( Irp , STATUS_UNSUCCESSFUL , 0 ) ;
2009-02-20 17:52:47 +00:00
}