- Also Store audio filter object header in FsContext member

- Create the pin on the correct filter by using the filters object class
- Remove filter object class before performing actual create request
- Remove object header from audio filter when closing
- Retrieve internal object class name with internal IOCTL_KS_OBJECT_CLASS
- Avoid using interface name as ReactOS doesn't support it
- Store object class name when creating the object header for the audio sub device
- Implement IPortFilterTopology interface
- Activate pin property handle for port topology driver 
- There is no need to create a handle to sysaudio for each application opening wdmaud, use only one connection per driver basis
- Pass object create class to pin creation method by duplicating KsCreatePin
- Audio devices should now be accessible again

svn path=/trunk/; revision=41341
This commit is contained in:
Johannes Anderwald 2009-06-07 18:22:24 +00:00
parent 60e3f374fa
commit 7a728c427a
20 changed files with 843 additions and 168 deletions

View file

@ -352,7 +352,7 @@ KsAllocateObjectHeader(
}
/* was the request for a pin/clock/node */
if (IoStack->FileObject)
if (IoStack->FileObject->FileName.Buffer)
{
/* store the object in the file object */
ASSERT(IoStack->FileObject->FsContext == NULL);
@ -360,9 +360,10 @@ KsAllocateObjectHeader(
}
else
{
/* the object header is for device */
/* the object header is for a audio filter */
ASSERT(DeviceHeader->DeviceIndex < DeviceHeader->MaxItems);
DeviceHeader->ItemList[DeviceHeader->DeviceIndex].ObjectHeader = ObjectHeader;
IoStack->FileObject->FsContext = ObjectHeader;
}
/* store result */
@ -720,7 +721,7 @@ KsCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
//PIO_STACK_LOCATION IoStack;
PIO_STACK_LOCATION IoStack;
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
ULONG Index;
@ -729,7 +730,7 @@ KsCreate(
DPRINT("KS / CREATE\n");
/* get current stack location */
//IoStack = IoGetCurrentIrpStackLocation(Irp);
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* get device header */
@ -756,11 +757,41 @@ KsCreate(
return Status;
}
}
else if (DeviceHeader->ItemList[Index].bCreated && IoStack->FileObject->FileName.Buffer != NULL)
{
ULONG Length = wcslen(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem->ObjectClass.Buffer);
/* filter for that type has already exists */
if (!_wcsnicmp(DeviceHeader->ItemList[Index].ObjectHeader->CreateItem->ObjectClass.Buffer,
IoStack->FileObject->FileName.Buffer,
Length))
{
if (IoStack->FileObject->FileName.Buffer[0] != L'{')
{
RtlMoveMemory(IoStack->FileObject->FileName.Buffer, &IoStack->FileObject->FileName.Buffer[Length+1],
IoStack->FileObject->FileName.Length - Length * sizeof(WCHAR));
IoStack->FileObject->FileName.Length -= Length * sizeof(WCHAR);
}
KSCREATE_ITEM_IRP_STORAGE(Irp) = &DeviceHeader->ItemList[Index].CreateItem;
Status = DeviceHeader->ItemList[Index].CreateItem.Create(DeviceObject, Irp);
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
return Status;
}
}
}
/* release lock */
KeReleaseSpinLock(&DeviceHeader->ItemListLock, OldLevel);
return Status;
Irp->IoStatus.Information = 0;
/* set return status */
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
static NTAPI
@ -771,9 +802,17 @@ KsClose(
{
PIO_STACK_LOCATION IoStack;
PKSIOBJECT_HEADER ObjectHeader;
PDEVICE_EXTENSION DeviceExtension;
PKSIDEVICE_HEADER DeviceHeader;
ULONG Index;
/* get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* get device extension */
DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
/* get device header */
DeviceHeader = DeviceExtension->DeviceHeader;
DPRINT("KS / CLOSE\n");
@ -782,11 +821,20 @@ KsClose(
ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
for(Index = 0; Index < DeviceHeader->MaxItems; Index++)
{
if (DeviceHeader->ItemList[Index].ObjectHeader == ObjectHeader)
{
DeviceHeader->ItemList[Index].ObjectHeader = NULL;
}
}
return ObjectHeader->DispatchTable.Close(DeviceObject, Irp);
}
else
{
DPRINT1("Expected Object Header\n");
DPRINT1("Expected Object Header FileObject %p FsContext %p\n", IoStack->FileObject, IoStack->FileObject->FsContext);
KeBugCheckEx(0, 0, 0, 0, 0);
return STATUS_SUCCESS;
}
}
@ -809,6 +857,15 @@ KsDeviceControl(
ObjectHeader = (PKSIOBJECT_HEADER) IoStack->FileObject->FsContext;
KSCREATE_ITEM_IRP_STORAGE(Irp) = ObjectHeader->CreateItem;
if (IoStack->MajorFunction == IRP_MJ_DEVICE_CONTROL && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_OBJECT_CLASS)
{
*((LPWSTR*)Irp->UserBuffer) = ObjectHeader->CreateItem->ObjectClass.Buffer;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(LPWSTR);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
}
else

View file

@ -3,7 +3,7 @@
#include <ntifs.h>
#include <ntddk.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <portcls.h>
#include <ks.h>
@ -16,6 +16,6 @@
#define TAG_DEVICE_HEADER TAG('H','D','S','K')
#define IOCTL_KS_OBJECT_CLASS CTL_CODE(FILE_DEVICE_KS, 0x7, METHOD_NEITHER, FILE_ANY_ACCESS)
#endif

View file

@ -288,7 +288,7 @@ PcRegisterSubdevice(
*/
Status = IoRegisterDeviceInterface(DeviceExt->PhysicalDeviceObject,
&SubDeviceDescriptor->Interfaces[Index],
&RefName,
NULL, //&RefName,
&SymbolicLinkName);
if (NT_SUCCESS(Status))
{

View file

@ -211,7 +211,8 @@ NTSTATUS
NTAPI
NewDispatchObject(
IN PIRP Irp,
IN IIrpTarget * Target)
IN IIrpTarget * Target,
IN LPWSTR Name)
{
NTSTATUS Status;
KSOBJECT_HEADER ObjectHeader;
@ -223,6 +224,7 @@ NewDispatchObject(
return STATUS_INSUFFICIENT_RESOURCES;
CreateItem->Context = (PVOID)Target;
RtlInitUnicodeString(&CreateItem->ObjectClass, Name);
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->FileObject);

View file

@ -0,0 +1,364 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/filter_topology.c
* PURPOSE: portcls topology filter
* PROGRAMMER: Johannes Anderwald
*/
#include "private.h"
typedef struct
{
IPortFilterTopologyVtbl *lpVtbl;
LONG ref;
IPortTopology* Port;
SUBDEVICE_DESCRIPTOR * Descriptor;
}IPortFilterTopologyImpl;
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnQueryInterface(
IPortFilterTopology* iface,
IN REFIID refiid,
OUT PVOID* Output)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
{
*Output = &This->lpVtbl;
InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
{
*Output = This->Port;
This->Port->lpVtbl->AddRef(This->Port);
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterTopology_fnAddRef(
IPortFilterTopology* iface)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
return InterlockedIncrement(&This->ref);
}
/*
* @implemented
*/
ULONG
NTAPI
IPortFilterTopology_fnRelease(
IPortFilterTopology* iface)
{
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
InterlockedDecrement(&This->ref);
if (This->ref == 0)
{
FreeItem(This, TAG_PORTCLASS);
return 0;
}
return This->ref;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnNewIrpTarget(
IN IPortFilterTopology* iface,
OUT struct IIrpTarget **OutTarget,
IN WCHAR * Name,
IN PUNKNOWN Unknown,
IN POOL_TYPE PoolType,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
DPRINT("IPortFilterTopology_fnNewIrpTarget entered\n");
return STATUS_NOT_SUPPORTED;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnDeviceIoControl(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
ISubdevice *SubDevice = NULL;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface;
IoStack = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(SubDevice != NULL);
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
ASSERT(Status == STATUS_SUCCESS);
ASSERT(Descriptor != NULL);
SubDevice->lpVtbl->Release(SubDevice);
return PcPropertyHandler(Irp, Descriptor);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnRead(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnWrite(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnFlush(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnClose(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
//PMINIPORTTOPOLOGY Miniport;
//IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface;
/* release reference to port */
//This->Port->lpVtbl->Release(This->Port);
/* get the miniport driver */
//Miniport = GetTopologyMiniport(This->Port);
/* release miniport driver */
//Miniport->lpVtbl->Release(Miniport);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnQuerySecurity(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
IPortFilterTopology_fnSetSecurity(
IN IPortFilterTopology* iface,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastDeviceIoControl(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastRead(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
IPortFilterTopology_fnFastWrite(
IN IPortFilterTopology* iface,
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN PVOID Buffer,
OUT PIO_STATUS_BLOCK StatusBlock,
IN PDEVICE_OBJECT DeviceObject)
{
return FALSE;
}
/*
* @implemented
*/
static
NTSTATUS
NTAPI
IPortFilterTopology_fnInit(
IN IPortFilterTopology* iface,
IN IPortTopology* Port)
{
ISubdevice * ISubDevice;
SUBDEVICE_DESCRIPTOR * Descriptor;
NTSTATUS Status;
IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface;
/* get our private interface */
Status = Port->lpVtbl->QueryInterface(Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* get the subdevice descriptor */
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
/* release subdevice interface */
ISubDevice->lpVtbl->Release(ISubDevice);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
/* save descriptor */
This->Descriptor = Descriptor;
/* increment reference count */
Port->lpVtbl->AddRef(Port);
/* store port object */
This->Port = Port;
return STATUS_SUCCESS;
}
static IPortFilterTopologyVtbl vt_IPortFilterTopology =
{
IPortFilterTopology_fnQueryInterface,
IPortFilterTopology_fnAddRef,
IPortFilterTopology_fnRelease,
IPortFilterTopology_fnNewIrpTarget,
IPortFilterTopology_fnDeviceIoControl,
IPortFilterTopology_fnRead,
IPortFilterTopology_fnWrite,
IPortFilterTopology_fnFlush,
IPortFilterTopology_fnClose,
IPortFilterTopology_fnQuerySecurity,
IPortFilterTopology_fnSetSecurity,
IPortFilterTopology_fnFastDeviceIoControl,
IPortFilterTopology_fnFastRead,
IPortFilterTopology_fnFastWrite,
IPortFilterTopology_fnInit
};
NTSTATUS
NewPortFilterTopology(
OUT IPortFilterTopology ** OutFilter)
{
IPortFilterTopologyImpl * This;
This = AllocateItem(NonPagedPool, sizeof(IPortFilterTopologyImpl), TAG_PORTCLASS);
if (!This)
return STATUS_INSUFFICIENT_RESOURCES;
/* initialize IPortFilterTopology */
This->ref = 1;
This->lpVtbl = &vt_IPortFilterTopology;
/* return result */
*OutFilter = (IPortFilterTopology*)&This->lpVtbl;
return STATUS_SUCCESS;
}

View file

@ -248,7 +248,9 @@ IPortFilterWaveCyclic_fnClose(
/* release reference to port */
This->Port->lpVtbl->Release(This->Port);
/* get the miniport driver */
Miniport = GetWaveCyclicMiniport(This->Port);
/* release miniport driver */
Miniport->lpVtbl->Release(Miniport);
@ -256,7 +258,7 @@ IPortFilterWaveCyclic_fnClose(
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
/*

View file

@ -687,4 +687,26 @@ DECLARE_INTERFACE_(IDmaChannelInit, IUnknown)
#undef INTERFACE
/*****************************************************************************
* IPortFilterTopology
*****************************************************************************
*/
#undef INTERFACE
#define INTERFACE IPortFilterTopology
DECLARE_INTERFACE_(IPortFilterTopology, IIrpTarget)
{
DEFINE_ABSTRACT_UNKNOWN()
DEFINE_ABSTRACT_IRPTARGET()
STDMETHOD_(NTSTATUS, Init)(THIS_
IN PPORTTOPOLOGY Port)PURE;
};
typedef IPortFilterTopology *PPORTFILTERTOPOLOGY;
#undef INTERFACE
#endif

View file

@ -23,6 +23,7 @@ typedef struct
PPCFILTER_DESCRIPTOR pDescriptor;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
IPortFilterTopology * Filter;
}IPortTopologyImpl;
typedef struct
@ -44,27 +45,26 @@ static GUID InterfaceGuids[2] =
}
};
#if 0
static
KSPROPERTY_SET PinPropertySet =
{
&KSPROPSETID_Pin,
0,
NULL,
0,
NULL
};
DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterTopologyTopologySet, TopologyPropertyHandler);
DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterTopologyPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
static
KSPROPERTY_SET TopologyPropertySet =
KSPROPERTY_SET TopologyPropertySet[] =
{
&KSPROPSETID_Topology,
4,
NULL,
0,
NULL
{
&KSPROPSETID_Topology,
sizeof(PortFilterTopologyTopologySet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyTopologySet,
0,
NULL
},
{
&KSPROPSETID_Pin,
sizeof(PortFilterTopologyPinSet) / sizeof(KSPROPERTY_ITEM),
(const KSPROPERTY_ITEM*)&PortFilterTopologyPinSet,
0,
NULL
}
};
#endif
//---------------------------------------------------------------
@ -223,13 +223,13 @@ IPortTopology_fnInit(
}
/* create the subdevice descriptor */
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
2,
InterfaceGuids,
0,
NULL,
0,
NULL,
2,
TopologyPropertySet,
0,
0,
0,
@ -339,10 +339,45 @@ ISubDevice_fnNewIrpTarget(
IN PIRP Irp,
IN KSOBJECT_CREATE *CreateObject)
{
//IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
NTSTATUS Status;
IPortFilterTopology * Filter;
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
UNIMPLEMENTED
return STATUS_UNSUCCESSFUL;
/* is there already an instance of the filter */
if (This->Filter)
{
/* it is, let's return the result */
*OutTarget = (IIrpTarget*)This->Filter;
/* increment reference */
This->Filter->lpVtbl->AddRef(This->Filter);
return STATUS_SUCCESS;
}
/* create new instance of filter */
Status = NewPortFilterTopology(&Filter);
if (!NT_SUCCESS(Status))
{
/* not enough memory */
return Status;
}
/* initialize the filter */
Status = Filter->lpVtbl->Init(Filter, (IPortTopology*)This);
if (!NT_SUCCESS(Status))
{
/* destroy filter */
Filter->lpVtbl->Release(Filter);
/* return status */
return Status;
}
/* store result */
*OutTarget = (IIrpTarget*)Filter;
/* store for later re-use */
This->Filter = Filter;
/* return status */
return Status;
}
static
@ -366,7 +401,7 @@ ISubDevice_fnGetDescriptor(
{
IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice);
DPRINT("ISubDevice_GetDescriptor this %p\n", This);
DPRINT("ISubDevice_GetDescriptor this %p Descp %p\n", This, This->SubDeviceDescriptor);
*Descriptor = This->SubDeviceDescriptor;
return STATUS_SUCCESS;
}
@ -477,7 +512,7 @@ CreatePinWorkerRoutine(
if (NT_SUCCESS(Status))
{
/* create the dispatch object */
Status = NewDispatchObject(WorkerContext->Irp, Pin);
Status = NewDispatchObject(WorkerContext->Irp, Pin, NULL);
DPRINT("Pin %p\n", Pin);
}
@ -573,7 +608,7 @@ PcCreateItemDispatch(
if (IoStack->FileObject->FileName.Buffer == NULL)
{
/* create the dispatch object */
Status = NewDispatchObject(Irp, Filter);
Status = NewDispatchObject(Irp, Filter, CreateItem->ObjectClass.Buffer);
DPRINT1("Filter %p\n", Filter);
}
@ -645,3 +680,11 @@ NewPortTopology(
return STATUS_SUCCESS;
}
PMINIPORTTOPOLOGY
GetTopologyMiniport(
PPORTTOPOLOGY Port)
{
IPortTopologyImpl * This = (IPortTopologyImpl*)Port;
return This->pMiniport;
}

View file

@ -593,28 +593,40 @@ ISubDevice_fnNewIrpTarget(
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
/* is there already an instance of the filter */
if (This->Filter)
{
/* it is, let's return the result */
*OutTarget = (IIrpTarget*)This->Filter;
/* increment reference */
This->Filter->lpVtbl->AddRef(This->Filter);
return STATUS_SUCCESS;
}
/* create new instance of filter */
Status = NewPortFilterWaveCyclic(&Filter);
if (!NT_SUCCESS(Status))
{
/* not enough memory */
return Status;
}
/* initialize the filter */
Status = Filter->lpVtbl->Init(Filter, (IPortWaveCyclic*)This);
if (!NT_SUCCESS(Status))
{
/* destroy filter */
Filter->lpVtbl->Release(Filter);
/* return status */
return Status;
}
/* store result */
*OutTarget = (IIrpTarget*)Filter;
/* store for later re-use */
This->Filter = Filter;
/* return status */
return Status;
}

View file

@ -19,6 +19,7 @@
<file>dma_slave.c</file>
<file>drm.c</file>
<file>drm_port.c</file>
<file>filter_topology.c</file>
<file>filter_dmus.c</file>
<file>filter_wavecyclic.c</file>
<file>filter_wavepci.c</file>

View file

@ -9,7 +9,7 @@
#include <ntddk.h>
#include <portcls.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <dmusicks.h>
@ -147,11 +147,20 @@ NewPortWaveRT(
#endif
NTSTATUS
NewPortFilterTopology(
OUT IPortFilterTopology ** OutFilter);
PMINIPORTTOPOLOGY
GetTopologyMiniport(
PPORTTOPOLOGY Port);
NTSTATUS
NTAPI
NewDispatchObject(
IN PIRP Irp,
IN IIrpTarget * Target);
IN IIrpTarget * Target,
IN LPWSTR Name);
PMINIPORTWAVECYCLIC
GetWaveCyclicMiniport(

View file

@ -44,6 +44,7 @@ GetFilterIdAndPinId(
NTSTATUS Status;
KSPIN_COMMUNICATION Communication;
KSPIN_DATAFLOW DataFlow;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE)
{
@ -55,7 +56,9 @@ GetFilterIdAndPinId(
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
return STATUS_UNSUCCESSFUL;
@ -69,7 +72,7 @@ GetFilterIdAndPinId(
Pin.Property.Id = KSPROPERTY_PIN_CTYPES;
Pin.PinId = 0;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
if (NT_SUCCESS(Status))
{
/* enumerate now all pins */
@ -80,13 +83,13 @@ GetFilterIdAndPinId(
Communication = KSPIN_COMMUNICATION_NONE;
/* get pin communication type */
KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
DataFlow = 0;
/* get pin dataflow type */
KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
@ -132,6 +135,7 @@ WdmAudControlOpen(
IN PWDMAUD_CLIENT ClientInfo)
{
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
ULONG BytesReturned;
NTSTATUS Status;
ACCESS_MASK DesiredAccess = 0;
@ -169,7 +173,9 @@ WdmAudControlOpen(
InstanceInfo->Flags = 0;
InstanceInfo->DeviceNumber = FilterId;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
if (!NT_SUCCESS(Status))
{
@ -204,7 +210,7 @@ WdmAudControlOpen(
PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
PinConnect->Medium.Flags = 0;
PinConnect->PinId = PinId;
PinConnect->PinToHandle = ClientInfo->hSysAudio;
PinConnect->PinToHandle = DeviceExtension->hSysAudio;
PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
PinConnect->Priority.PrioritySubClass = 1;
@ -231,7 +237,7 @@ WdmAudControlOpen(
/* ros specific pin creation request */
InstanceInfo->Property.Id = (ULONG)-1;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, Length, &PinHandle, sizeof(HANDLE), &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)InstanceInfo, Length, &PinHandle, sizeof(HANDLE), &BytesReturned);
if (NT_SUCCESS(Status))
{
PHANDLE Handels;
@ -283,8 +289,9 @@ WdmAudControlDeviceType(
NTSTATUS Status;
KSPIN_COMMUNICATION Communication;
KSPIN_DATAFLOW DataFlow;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
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 && DeviceInfo->DeviceType != MIXER_DEVICE_TYPE)
{
DPRINT1("FIXME: Unsupported device type %x\n", DeviceInfo->DeviceType);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
@ -294,7 +301,8 @@ WdmAudControlDeviceType(
Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
{
DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_COUNT failed with %x\n", Status);
@ -311,7 +319,7 @@ WdmAudControlDeviceType(
Pin.Property.Id = KSPROPERTY_PIN_CTYPES;
Pin.PinId = 0;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned);
if (NT_SUCCESS(Status))
{
/* enumerate now all pins */
@ -322,13 +330,17 @@ WdmAudControlDeviceType(
Communication = KSPIN_COMMUNICATION_NONE;
/* get pin communication type */
KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
if (!NT_SUCCESS(Status))
continue;
Pin.Property.Id = KSPROPERTY_PIN_DATAFLOW;
DataFlow = 0;
/* get pin dataflow type */
KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
if (!NT_SUCCESS(Status))
continue;
if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
{
@ -432,6 +444,7 @@ WdmAudCapabilities(
IN PWDMAUD_DEVICE_INFO DeviceInfo,
IN PWDMAUD_CLIENT ClientInfo)
{
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
KSP_PIN PinProperty;
KSCOMPONENTID ComponentId;
@ -462,7 +475,8 @@ WdmAudCapabilities(
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
if (NT_SUCCESS(Status))
{
DeviceInfo->u.WaveOutCaps.wMid = ComponentId.Manufacturer.Data1 - 0xd5a47fa7;
@ -476,7 +490,7 @@ WdmAudCapabilities(
PinProperty.Property.Flags = KSPROPERTY_TYPE_GET;
BytesReturned = 0;
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
return SetIrpIoStatus(Irp, Status, 0);
@ -489,7 +503,7 @@ WdmAudCapabilities(
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
Status = KsSynchronousIoControlDevice(ClientInfo->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
if (!NT_SUCCESS(Status))
{
ExFreePool(MultipleItem);

View file

@ -94,6 +94,8 @@ WdmAudOpenSysAudioDevices(
LPWSTR SymbolicLinkList;
SYSAUDIO_ENTRY * Entry;
ULONG Length;
HANDLE hSysAudio;
PFILE_OBJECT FileObject;
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
if (DeviceExtension->DeviceInterfaceSupport)
@ -135,7 +137,28 @@ WdmAudOpenSysAudioDevices(
InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry);
DeviceExtension->NumSysAudioDevices++;
DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer);
Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open sysaudio %x\n", Status);
return Status;
}
/* get the file object */
Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference FileObject %x\n", Status);
ZwClose(hSysAudio);
return Status;
}
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceExtension->hSysAudio = hSysAudio;
DeviceExtension->FileObject = FileObject;
}
return Status;
}
@ -180,10 +203,6 @@ WdmAudOpenSysaudio(
IN PWDMAUD_CLIENT *pClient)
{
PWDMAUD_CLIENT Client;
NTSTATUS Status;
HANDLE hSysAudio;
PSYSAUDIO_ENTRY SysEntry;
PFILE_OBJECT FileObject;
PWDMAUD_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@ -200,34 +219,6 @@ WdmAudOpenSysaudio(
}
RtlZeroMemory(Client, sizeof(WDMAUD_CLIENT));
/* open the first sysaudio device available */
SysEntry = (PSYSAUDIO_ENTRY)DeviceExtension->SysAudioDeviceList.Flink;
DPRINT1("Opening device %S\n", SysEntry->SymbolicLink.Buffer);
Status = WdmAudOpenSysAudioDevice(SysEntry->SymbolicLink.Buffer, &hSysAudio);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to open sysaudio %x\n", Status);
ExFreePool(Client);
return Status;
}
/* get the file object */
Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference FileObject %x\n", Status);
ExFreePool(Client);
ZwClose(hSysAudio);
return Status;
}
Client->hSysAudio = hSysAudio;
Client->FileObject = FileObject;
Client->hProcess = PsGetCurrentProcessId();
*pClient = Client;
return STATUS_SUCCESS;

View file

@ -215,8 +215,6 @@ WdmAudCleanup(
ExFreePool(pClient->hPins);
}
ObDereferenceObject(pClient->FileObject);
ZwClose(pClient->hSysAudio);
ExFreePool(pClient);
IoStack->FileObject->FsContext = NULL;
}

View file

@ -5,7 +5,7 @@
#include <ntddk.h>
#include <portcls.h>
#include <ks.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <ksmedia.h>
#include <mmsystem.h>
@ -15,8 +15,6 @@
typedef struct
{
HANDLE hProcess;
HANDLE hSysAudio;
PFILE_OBJECT FileObject;
ULONG NumPins;
HANDLE * hPins;
@ -38,6 +36,8 @@ typedef struct
KSPIN_LOCK Lock;
ULONG NumSysAudioDevices;
LIST_ENTRY SysAudioDeviceList;
HANDLE hSysAudio;
PFILE_OBJECT FileObject;
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;

View file

@ -19,13 +19,95 @@ const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce,
NTSTATUS
ComputeCompatibleFormat(
IN PKSAUDIO_DEVICE_ENTRY Entry,
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
IN ULONG PinId,
IN PSYSAUDIODEVEXT DeviceExtension,
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat);
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;
Name.Length = (wcslen(ObjectType) + 1) * sizeof(WCHAR) + CreateParametersSize;
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);
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);
}
NTSTATUS
SetIrpIoStatus(
IN PIRP Irp,
@ -46,20 +128,39 @@ SetIrpIoStatus(
}
PKSAUDIO_DEVICE_ENTRY
PKSAUDIO_SUBDEVICE_ENTRY
GetListEntry(
IN PLIST_ENTRY Head,
IN ULONG Index)
{
PLIST_ENTRY Entry = Head->Flink;
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
PLIST_ENTRY SubEntry, Entry = Head->Flink;
DPRINT1("device index %u\n", Index);
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;
}
while(Index-- && Entry != Head)
Entry = Entry->Flink;
if (Entry == Head)
return NULL;
return (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
}
DPRINT1("Not Found index %u\n", Index);
DbgBreakPoint();
return NULL;
}
NTSTATUS
@ -69,7 +170,7 @@ SysAudioOpenVirtualDevice(
PSYSAUDIODEVEXT DeviceExtension)
{
PSYSAUDIO_CLIENT ClientInfo;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
PKSOBJECT_CREATE_ITEM CreateItem;
/* access the create item */
@ -99,9 +200,6 @@ SysAudioOpenVirtualDevice(
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
ASSERT(Entry != NULL);
/* increase usage count */
Entry->NumberOfClients++;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
}
@ -217,13 +315,12 @@ CreatePinWorkerRoutine(
ASSERT(WorkerContext->Entry->Pins);
ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
/* Fetch input format */
InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(WorkerContext->PinConnect + 1);
/* Let's try to create the audio irp pin */
Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
Status = KsoCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle, WorkerContext->Entry->ObjectClass);
if (!NT_SUCCESS(Status))
{
@ -260,7 +357,7 @@ CreatePinWorkerRoutine(
}
/* Retry with Mixer format */
Status = KsCreatePin(WorkerContext->Entry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
Status = KsoCreatePin(WorkerContext->Entry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle, WorkerContext->Entry->ObjectClass);
if (!NT_SUCCESS(Status))
{
/* This should not fail */
@ -432,7 +529,7 @@ HandleSysAudioFilterPinProperties(
{
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
ULONG BytesReturned;
PKSP_PIN Pin;
@ -519,7 +616,7 @@ HandleSysAudioFilterPinProperties(
NTSTATUS
ComputeCompatibleFormat(
IN PKSAUDIO_DEVICE_ENTRY Entry,
IN PKSAUDIO_SUBDEVICE_ENTRY Entry,
IN ULONG PinId,
IN PSYSAUDIODEVEXT DeviceExtension,
IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
@ -653,7 +750,7 @@ ComputeCompatibleFormat(
NTSTATUS
GetPinInstanceCount(
PKSAUDIO_DEVICE_ENTRY Entry,
PKSAUDIO_SUBDEVICE_ENTRY Entry,
PKSPIN_CINSTANCES PinInstances,
PKSPIN_CONNECT PinConnect)
{
@ -723,7 +820,7 @@ HandleSysAudioFilterPinCreation(
PDEVICE_OBJECT DeviceObject)
{
ULONG Length;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
KSPIN_CONNECT * PinConnect;
PIO_STACK_LOCATION IoStack;
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
@ -886,7 +983,7 @@ SysAudioHandleProperty(
PULONG Index;
PKSPROPERTY Property;
PSYSAUDIODEVEXT DeviceExtension;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
ULONG BytesReturned;
PKSOBJECT_CREATE_ITEM CreateItem;

View file

@ -11,13 +11,14 @@
const GUID GUID_DEVICE_INTERFACE_ARRIVAL = {0xCB3A4004L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}};
const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
#define IOCTL_KS_OBJECT_CLASS CTL_CODE(FILE_DEVICE_KS, 0x7, METHOD_NEITHER, FILE_ANY_ACCESS)
VOID
NTAPI
FilterPinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
QueryFilterRoutine(
IN PKSAUDIO_SUBDEVICE_ENTRY DeviceEntry)
{
KSPROPERTY PropertyRequest;
KSP_PIN PinRequest;
@ -27,15 +28,19 @@ FilterPinWorkerRoutine(
ULONG Count, Index;
NTSTATUS Status;
ULONG BytesReturned;
PSYSAUDIODEVEXT DeviceExtension;
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
DeviceEntry = Ctx->DeviceEntry;
ULONG NumWaveOutPin, NumWaveInPin;
DPRINT("Querying filter...\n");
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_OBJECT_CLASS, NULL, 0, &DeviceEntry->ObjectClass, sizeof(LPWSTR), &BytesReturned);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to query object class Status %x\n", Status);
return;
}
DPRINT("ObjectClass %S\n", DeviceEntry->ObjectClass);
PropertyRequest.Set = KSPROPSETID_Pin;
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
PropertyRequest.Id = KSPROPERTY_PIN_CTYPES;
@ -45,13 +50,13 @@ FilterPinWorkerRoutine(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to query number of pins Status %x\n", Status);
goto cleanup;
return;
}
if (!Count)
{
DPRINT1("Filter has no pins!\n");
goto cleanup;
return;
}
/* allocate pin array */
@ -60,12 +65,14 @@ FilterPinWorkerRoutine(
{
/* no memory */
DPRINT1("Failed to allocate memory Pins %u Block %x\n", Count, Count * sizeof(PIN_INFO));
goto cleanup;
return;
}
/* clear array */
RtlZeroMemory(DeviceEntry->Pins, sizeof(PIN_INFO) * Count);
DeviceEntry->NumberOfPins = Count;
NumWaveInPin = 0;
NumWaveOutPin = 0;
for(Index = 0; Index < Count; Index++)
{
/* get max instance count */
@ -97,20 +104,41 @@ FilterPinWorkerRoutine(
}
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
DeviceEntry->NumWaveOutPin++;
NumWaveOutPin++;
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
DeviceEntry->NumWaveInPin++;
NumWaveInPin++;
}
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, DeviceEntry->NumWaveInPin, DeviceEntry->NumWaveOutPin);
/* fetch device extension */
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
/* insert new audio device */
ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
/* increment audio device count */
InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, NumWaveInPin, NumWaveOutPin);
}
VOID
NTAPI
FilterPinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
PLIST_ENTRY ListEntry;
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
DeviceEntry = Ctx->DeviceEntry;
ListEntry = DeviceEntry->SubDeviceList.Flink;
while(ListEntry != &DeviceEntry->SubDeviceList)
{
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(ListEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
QueryFilterRoutine(SubDeviceEntry);
ListEntry = ListEntry->Flink;
}
/* free work item */
IoFreeWorkItem(Ctx->WorkItem);
@ -118,14 +146,6 @@ FilterPinWorkerRoutine(
ExFreePool(Ctx);
return;
cleanup:
ObDereferenceObject(DeviceEntry->FileObject);
ZwClose(DeviceEntry->Handle);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
IoFreeWorkItem(Ctx->WorkItem);
ExFreePool(Ctx);
}
NTSTATUS
@ -184,6 +204,7 @@ DeviceInterfaceChangeCallback(
NTSTATUS Status = STATUS_SUCCESS;
PSYSAUDIODEVEXT DeviceExtension;
PKSAUDIO_DEVICE_ENTRY DeviceEntry = NULL;
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
PIO_WORKITEM WorkItem = NULL;
PFILTER_WORKER_CONTEXT Ctx = NULL;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
@ -195,6 +216,7 @@ DeviceInterfaceChangeCallback(
if (IsEqualGUIDAligned(&Event->Event,
&GUID_DEVICE_INTERFACE_ARRIVAL))
{
/* a new device has arrived */
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
if (!DeviceEntry)
@ -226,7 +248,7 @@ DeviceInterfaceChangeCallback(
/* set device name */
DeviceEntry->DeviceName.Length = 0;
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 5 * sizeof(WCHAR);
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 10 * sizeof(WCHAR);
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
if (!DeviceEntry->DeviceName.Buffer)
@ -247,18 +269,42 @@ DeviceInterfaceChangeCallback(
goto cleanup;
}
Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwCreateFile failed with %x\n", Status);
goto cleanup;
}
/* FIXME Ros does not support device interface strings */
/* Workarround: repeatly call IoCreateFile untill ks wont find a create item which has no object header attached */
DPRINT("Successfully opened audio device %u handle %p file object %p device object %p\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->Handle, DeviceEntry->FileObject, DeviceEntry->FileObject->DeviceObject);
InitializeListHead(&DeviceEntry->SubDeviceList);
do
{
SubDeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_SUBDEVICE_ENTRY));
if (SubDeviceEntry)
{
RtlZeroMemory(SubDeviceEntry, sizeof(KSAUDIO_SUBDEVICE_ENTRY));
Status = OpenDevice(&DeviceEntry->DeviceName, &SubDeviceEntry->Handle, &SubDeviceEntry->FileObject);
if (NT_SUCCESS(Status))
{
InsertTailList(&DeviceEntry->SubDeviceList, &SubDeviceEntry->Entry);
DeviceEntry->NumSubDevices++;
/* increment audio device count */
InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
}
else
{
ExFreePool(SubDeviceEntry);
break;
}
}
}while(NT_SUCCESS(Status) && SubDeviceEntry != NULL);
DPRINT("Successfully opened audio device %u Device %S NumberOfSubDevices %u\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer, DeviceEntry->NumSubDevices);
Ctx->DeviceEntry = DeviceEntry;
Ctx->WorkItem = WorkItem;
/* fetch device extension */
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
/* insert new audio device */
ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
return Status;
}

View file

@ -74,7 +74,7 @@ Dispatch_fnClose(
PIRP Irp)
{
PSYSAUDIO_CLIENT Client;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
PIO_STACK_LOCATION IoStatus;
ULONG Index, SubIndex;
PSYSAUDIODEVEXT DeviceExtension;

View file

@ -34,8 +34,9 @@ SysAudio_Shutdown(
IN PIRP Irp)
{
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PKSAUDIO_SUBDEVICE_ENTRY SubDeviceEntry;
PSYSAUDIODEVEXT DeviceExtension;
PLIST_ENTRY Entry;
PLIST_ENTRY Entry, SubEntry;
DPRINT1("SysAudio_Shutdown called\n");
@ -48,9 +49,17 @@ SysAudio_Shutdown(
DPRINT1("Freeing item %wZ\n", &DeviceEntry->DeviceName);
RtlFreeUnicodeString(&DeviceEntry->DeviceName);
ZwClose(DeviceEntry->Handle);
ObDereferenceObject(DeviceEntry->FileObject);
ExFreePool(DeviceEntry->Pins);
while(!IsListEmpty(&DeviceEntry->SubDeviceList))
{
SubEntry = RemoveHeadList(&DeviceEntry->SubDeviceList);
SubDeviceEntry = (PKSAUDIO_SUBDEVICE_ENTRY)CONTAINING_RECORD(SubEntry, KSAUDIO_SUBDEVICE_ENTRY, Entry);
ZwClose(SubDeviceEntry->Handle);
ObDereferenceObject(SubDeviceEntry->FileObject);
ExFreePool(SubDeviceEntry->Pins);
ExFreePool(SubDeviceEntry);
}
ExFreePool(DeviceEntry);
}

View file

@ -7,8 +7,9 @@
#include <ks.h>
#include <ksmedia.h>
#include <math.h>
#define NDEBUG
#define YDEBUG
#include <debug.h>
#include <stdio.h>
typedef struct
{
@ -43,20 +44,27 @@ typedef struct
KSPIN_COMMUNICATION Communication; // pin type
}PIN_INFO;
typedef struct
{
LIST_ENTRY Entry; // linked list entry to KSAUDIO_DEVICE_ENTRY
HANDLE Handle; // handle to audio sub device
PFILE_OBJECT FileObject; // file objecto to audio sub device
ULONG NumberOfPins; // number of pins of audio device
PIN_INFO * Pins; // array of PIN_INFO
LPWSTR ObjectClass; // object class of sub device
}KSAUDIO_SUBDEVICE_ENTRY, *PKSAUDIO_SUBDEVICE_ENTRY;
typedef struct
{
LIST_ENTRY Entry; // device entry for KsAudioDeviceList
HANDLE Handle; // handle to audio device
PFILE_OBJECT FileObject; // file object for audio device
UNICODE_STRING DeviceName; // symbolic link of audio device
ULONG NumberOfClients; // number of clients referenced audio device
ULONG NumberOfPins; // number of pins of audio device
PIN_INFO * Pins; // array of PIN_INFO
ULONG NumWaveOutPin; // number of wave out pins
ULONG NumWaveInPin; // number of wave in pins
ULONG NumSubDevices; // number of subdevices
LIST_ENTRY SubDeviceList; // audio sub device list
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
@ -88,7 +96,7 @@ typedef struct
HANDLE Handle; // audio irp pin handle
PFILE_OBJECT FileObject; // audio irp pin file object
ULONG PinId; // pin id of device
PKSAUDIO_DEVICE_ENTRY AudioEntry; // pointer to audio device entry
PKSAUDIO_SUBDEVICE_ENTRY AudioEntry; // pointer to audio device entry
HANDLE hMixerPin; // handle to mixer pin
PFILE_OBJECT MixerFileObject; // mixer file object
@ -104,7 +112,7 @@ typedef struct
PIRP Irp;
BOOL CreateRealPin;
BOOL CreateMixerPin;
PKSAUDIO_DEVICE_ENTRY Entry;
PKSAUDIO_SUBDEVICE_ENTRY Entry;
KSPIN_CONNECT * PinConnect;
PDISPATCH_CONTEXT DispatchContext;
PSYSAUDIO_CLIENT AudioClient;
@ -148,7 +156,7 @@ OpenDevice(
IN PHANDLE HandleOut,
IN PFILE_OBJECT * FileObjectOut);
PKSAUDIO_DEVICE_ENTRY
PKSAUDIO_SUBDEVICE_ENTRY
GetListEntry(
IN PLIST_ENTRY Head,
IN ULONG Index);