- Complete missing irp

- Handle all properties of KSPROPSETID
- Initialize filter properties in a deferred routine
- Add more error checks

svn path=/trunk/; revision=39782
This commit is contained in:
Johannes Anderwald 2009-02-27 11:22:16 +00:00
parent d74f376c18
commit 89797da903
6 changed files with 420 additions and 234 deletions

View file

@ -813,15 +813,16 @@ IPortPinWaveCyclic_fnGetCycleCount(
}
/*
* @unimplemented
* @implemented
*/
ULONG
NTAPI
IPortPinWaveCyclic_fnGetDeviceBufferSize(
IN IPortPinWaveCyclic* iface)
{
UNIMPLEMENTED;
return 0;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
return This->CommonBufferSize;
}
/*
@ -845,8 +846,9 @@ NTAPI
IPortPinWaveCyclic_fnGetMiniport(
IN IPortPinWaveCyclic* iface)
{
UNIMPLEMENTED;
return NULL;
IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
return (PMINIPORT)This->Miniport;
}
static IPortPinWaveCyclicVtbl vt_IPortPinWaveCyclic =

View file

@ -608,6 +608,7 @@ PcCreateItemDispatch(
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -308,6 +308,295 @@ CreatePinWorkerRoutine(
ExFreePool(WorkerContext);
}
NTSTATUS
HandleSysAudioFilterPinProperties(
PIRP Irp,
PKSPROPERTY Property,
PSYSAUDIODEVEXT DeviceExtension)
{
PIO_STACK_LOCATION IoStack;
NTSTATUS Status;
PKSAUDIO_DEVICE_ENTRY Entry;
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);
}
}
NTSTATUS
HandleSysAudioFilterPinCreation(
PIRP Irp,
PKSPROPERTY Property,
PSYSAUDIODEVEXT DeviceExtension,
PDEVICE_OBJECT DeviceObject)
{
ULONG Length, BytesReturned;
PKSAUDIO_DEVICE_ENTRY Entry;
KSPIN_CONNECT * PinConnect;
PIO_STACK_LOCATION IoStack;
PSYSAUDIO_INSTANCE_INFO InstanceInfo;
PSYSAUDIO_CLIENT ClientInfo;
PKSOBJECT_CREATE_ITEM CreateItem;
KSP_PIN PinRequest;
NTSTATUS Status;
KSPIN_CINSTANCES PinInstances;
PIO_WORKITEM WorkItem;
PFILE_OBJECT FileObject;
PPIN_WORKER_CONTEXT WorkerContext;
PDISPATCH_CONTEXT DispatchContext;
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 client context */
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
if (!ClientInfo || !ClientInfo->NumDevices || !ClientInfo->Devs ||
ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId != InstanceInfo->DeviceNumber)
{
/* we have a problem */
KeBugCheckEx(0, 0, 0, 0, 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);
}
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);
}
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
{
/* pin already exists */
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
if (Entry->Pins[PinConnect->PinId].References > 1)
{
/* 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);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
}
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* create worker context */
WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
if (!WorkerContext)
{
/* invalid parameters */
IoFreeWorkItem(WorkItem);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* create worker context */
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
if (!DispatchContext)
{
/* invalid parameters */
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* prepare context */
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
{
/* re-using pin */
PinRequest.Property.Set = KSPROPSETID_Connection;
PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
/* get pin file object */
Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get pin file object with %x\n", Status);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, Status, 0);
}
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))
{
DPRINT1("Failed to set format with Status %x\n", Status);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, Status, 0);
}
}
else
{
/* create the real pin */
WorkerContext->CreateRealPin = TRUE;
}
/* set up context */
WorkerContext->DispatchContext = DispatchContext;
WorkerContext->Entry = Entry;
WorkerContext->Irp = Irp;
WorkerContext->PinConnect = PinConnect;
WorkerContext->AudioClient = ClientInfo;
DPRINT("Queing Irp %p\n", Irp);
/* queue the work item */
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)WorkerContext);
/* mark irp as pending */
return STATUS_PENDING;
}
NTSTATUS
SysAudioHandleProperty(
@ -327,24 +616,15 @@ SysAudioHandleProperty(
ULONG Count, BytesReturned;
PKSOBJECT_CREATE_ITEM CreateItem;
UNICODE_STRING GuidString;
ULONG Length;
KSPIN_CONNECT * PinConnect;
KSP_PIN PinRequest;
KSPIN_CINSTANCES PinInstances;
PPIN_WORKER_CONTEXT WorkerContext;
PDISPATCH_CONTEXT DispatchContext;
PIO_WORKITEM WorkItem;
PFILE_OBJECT FileObject;
/* access the create item */
CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
{
/* buffer must be atleast of sizeof KSPROPERTY */
/* buffer must be at least of sizeof KSPROPERTY */
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY));
}
@ -353,33 +633,7 @@ SysAudioHandleProperty(
if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Pin))
{
/* ros specific request */
if (Property->Id == KSPROPERTY_PIN_DATARANGES)
{
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_PIN))
{
/* too small buffer */
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY) + sizeof(ULONG));
}
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, ((KSP_PIN*)Property)->Reserved);
if (!Entry)
{
/* too small buffer */
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY,
(PVOID)IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
IoStack->Parameters.DeviceIoControl.InputBufferLength,
Irp->UserBuffer,
IoStack->Parameters.DeviceIoControl.OutputBufferLength,
&BytesReturned);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesReturned;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
return HandleSysAudioFilterPinProperties(Irp, Property, DeviceExtension);
}
else if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Sysaudio))
{
@ -428,6 +682,7 @@ SysAudioHandleProperty(
/* too small buffer */
return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
}
*((PULONG)Irp->UserBuffer) = DeviceExtension->NumberOfKsAudioDevices;
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
}
@ -504,187 +759,7 @@ SysAudioHandleProperty(
{
/* ros specific pin creation request */
DPRINT1("Initiating create request\n");
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);
}
/* get input parameter */
InstanceInfo = (PSYSAUDIO_INSTANCE_INFO)Property;
if (DeviceExtension->NumberOfKsAudioDevices <= InstanceInfo->DeviceNumber)
{
/* invalid parameters */
return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
}
/* get client context */
ClientInfo = (PSYSAUDIO_CLIENT)CreateItem->Context;
ASSERT(ClientInfo);
ASSERT(ClientInfo->NumDevices >= 1);
ASSERT(ClientInfo->Devs != NULL);
ASSERT(ClientInfo->Devs[ClientInfo->NumDevices-1].DeviceId == InstanceInfo->DeviceNumber);
/* get sysaudio entry */
Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, InstanceInfo->DeviceNumber);
ASSERT(Entry != NULL);
if (!Entry->Pins)
{
PropertyRequest.Set = KSPROPSETID_Pin;
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
PropertyRequest.Id = KSPROPERTY_PIN_CTYPES;
/* query for num of pins */
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PropertyRequest, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
{
DPRINT("Property Request KSPROPERTY_PIN_CTYPES failed with %x\n", Status);
return SetIrpIoStatus(Irp, Status, 0);
}
DPRINT("KSPROPERTY_TYPE_GET num pins %d\n", Count);
Entry->Pins = ExAllocatePool(NonPagedPool, Count * sizeof(PIN_INFO));
if (!Entry->Pins)
{
/* invalid parameters */
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* clear array */
RtlZeroMemory(Entry->Pins, sizeof(PIN_INFO) * Count);
Entry->NumberOfPins = Count;
}
/* 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);
}
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);
}
DPRINT("PinInstances Current %u Max %u\n", PinInstances.CurrentCount, PinInstances.PossibleCount);
Entry->Pins[PinConnect->PinId].MaxPinInstanceCount = PinInstances.PossibleCount;
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* create worker context */
WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
if (!WorkerContext)
{
/* invalid parameters */
IoFreeWorkItem(WorkItem);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* create worker context */
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
if (!DispatchContext)
{
/* invalid parameters */
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* prepare context */
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
if (PinInstances.CurrentCount == PinInstances.PossibleCount)
{
/* pin already exists */
ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL);
if (Entry->Pins[PinConnect->PinId].References > 1)
{
/* 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);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
}
/* re-using pin */
PropertyRequest.Set = KSPROPSETID_Connection;
PropertyRequest.Flags = KSPROPERTY_TYPE_SET;
PropertyRequest.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
/* get pin file object */
Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle,
GENERIC_READ | GENERIC_WRITE,
IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get pin file object with %x\n", Status);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, Status, 0);
}
Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO);
Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PropertyRequest, sizeof(KSPROPERTY),
(PVOID)(PinConnect + 1), Length, &BytesReturned);
ObDereferenceObject(FileObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to set format with Status %x\n", Status);
IoFreeWorkItem(WorkItem);
ExFreePool(WorkerContext);
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, Status, 0);
}
}
else
{
/* create the real pin */
WorkerContext->CreateRealPin = TRUE;
}
/* set up context */
WorkerContext->DispatchContext = DispatchContext;
WorkerContext->Entry = Entry;
WorkerContext->Irp = Irp;
WorkerContext->PinConnect = PinConnect;
WorkerContext->AudioClient = ClientInfo;
DPRINT("Queing Irp %p\n", Irp);
/* queue the work item */
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)WorkerContext);
/* mark irp as pending */
return STATUS_PENDING;
return HandleSysAudioFilterPinCreation(Irp, Property, DeviceExtension, DeviceObject);
}
}

View file

@ -21,6 +21,93 @@ const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {
const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}};
VOID
NTAPI
FilterPinWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
KSPROPERTY PropertyRequest;
KSP_PIN PinRequest;
KSPIN_DATAFLOW DataFlow;
KSPIN_COMMUNICATION Communication;
KSPIN_CINSTANCES PinInstances;
ULONG Count, Index;
NTSTATUS Status;
ULONG BytesReturned;
PKSAUDIO_DEVICE_ENTRY DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)Context;
DPRINT1("Querying filter...\n");
PropertyRequest.Set = KSPROPSETID_Pin;
PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
PropertyRequest.Id = KSPROPERTY_PIN_CTYPES;
/* query for num of pins */
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PropertyRequest, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned);
if (!NT_SUCCESS(Status))
{
return;
}
if (!Count)
return;
/* allocate pin array */
DeviceEntry->Pins = ExAllocatePool(NonPagedPool, Count * sizeof(PIN_INFO));
if (!DeviceEntry->Pins)
{
/* no memory */
return;
}
/* clear array */
RtlZeroMemory(DeviceEntry->Pins, sizeof(PIN_INFO) * Count);
DeviceEntry->NumberOfPins = Count;
for(Index = 0; Index < Count; Index++)
{
/* get max instance count */
PinRequest.PinId = Index;
PinRequest.Property.Set = KSPROPSETID_Pin;
PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
if (NT_SUCCESS(Status))
{
DeviceEntry->Pins[Index].MaxPinInstanceCount = PinInstances.PossibleCount;
}
/* get dataflow direction */
PinRequest.Property.Id = KSPROPERTY_PIN_DATAFLOW;
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
if (NT_SUCCESS(Status))
{
DeviceEntry->Pins[Index].DataFlow = DataFlow;
}
/* get irp flow direction */
PinRequest.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
Status = KsSynchronousIoControlDevice(DeviceEntry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
if (NT_SUCCESS(Status))
{
DeviceEntry->Pins[Index].Communication = Communication;
}
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_IN)
DeviceEntry->NumWaveOutPin++;
if (Communication == KSPIN_COMMUNICATION_SINK && DataFlow == KSPIN_DATAFLOW_OUT)
DeviceEntry->NumWaveInPin++;
}
DPRINT1("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, DeviceEntry->NumWaveInPin, DeviceEntry->NumWaveOutPin);
}
NTSTATUS
NTAPI
@ -29,8 +116,11 @@ DeviceInterfaceChangeCallback(
IN PVOID Context)
{
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
SYSAUDIODEVEXT *DeviceExtension = (SYSAUDIODEVEXT*)Context;
NTSTATUS Status = STATUS_SUCCESS;
PSYSAUDIODEVEXT DeviceExtension;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
@ -44,7 +134,7 @@ DeviceInterfaceChangeCallback(
HANDLE NodeHandle;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
PIO_WORKITEM WorkItem;
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
if (!DeviceEntry)
@ -116,10 +206,16 @@ DeviceInterfaceChangeCallback(
DeviceEntry->Handle = NodeHandle;
DeviceEntry->FileObject = FileObject;
InsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry);
DPRINT1("Successfully opened audio device %u handle %p file object %p device object %p\n", DeviceExtension->KsAudioDeviceList, NodeHandle, FileObject, FileObject->DeviceObject);
DeviceExtension->NumberOfKsAudioDevices++;
DPRINT1("Successfully opened audio device handle %p file object %p device object %p\n", NodeHandle, FileObject, FileObject->DeviceObject);
WorkItem = IoAllocateWorkItem(DeviceObject);
if (WorkItem)
{
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)DeviceEntry);
}
InsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry);
return Status;
}
else if (IsEqualGUIDAligned(&Event->Event,
@ -144,18 +240,20 @@ DeviceInterfaceChangeCallback(
NTSTATUS
SysAudioRegisterNotifications(
IN PDRIVER_OBJECT DriverObject,
SYSAUDIODEVEXT *DeviceExtension)
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PSYSAUDIODEVEXT DeviceExtension;
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)&KS_CATEGORY_AUDIO,
DriverObject,
DeviceInterfaceChangeCallback,
(PVOID)DeviceExtension,
(PVOID)DeviceObject,
(PVOID*)&DeviceExtension->KsAudioNotificationEntry);
if (!NT_SUCCESS(Status))
@ -168,7 +266,7 @@ SysAudioRegisterNotifications(
(PVOID)&DMOCATEGORY_ACOUSTIC_ECHO_CANCEL,
DriverObject,
DeviceInterfaceChangeCallback,
(PVOID)DeviceExtension,
(PVOID)DeviceObject,
(PVOID*)&DeviceExtension->EchoCancelNotificationEntry);
if (!NT_SUCCESS(Status))

View file

@ -133,7 +133,7 @@ SysAudio_InstallDevice(
}
Status = SysAudioRegisterNotifications(DriverObject,
DeviceExtension);
DeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to register device notifications\n");

View file

@ -29,6 +29,8 @@ typedef struct
ULONG MaxPinInstanceCount;
HANDLE PinHandle;
ULONG References;
KSPIN_DATAFLOW DataFlow;
KSPIN_COMMUNICATION Communication;
}PIN_INFO;
@ -43,6 +45,9 @@ typedef struct
ULONG NumberOfPins;
PIN_INFO * Pins;
ULONG NumWaveOutPin;
ULONG NumWaveInPin;
}KSAUDIO_DEVICE_ENTRY, *PKSAUDIO_DEVICE_ENTRY;
@ -88,8 +93,8 @@ SysAudioRegisterDeviceInterfaces(
NTSTATUS
SysAudioRegisterNotifications(
IN PDRIVER_OBJECT DriverObject,
SYSAUDIODEVEXT *DeviceExtension);
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject);
NTSTATUS
SysAudioHandleProperty(
@ -105,4 +110,9 @@ NTSTATUS
CreateDispatcher(
IN PIRP Irp);
ULONG
GetDeviceCount(
PSYSAUDIODEVEXT DeviceExtension,
BOOL WaveIn);
#endif