mirror of
https://github.com/reactos/reactos.git
synced 2024-07-28 15:19:09 +00:00
- 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:
parent
d74f376c18
commit
89797da903
|
@ -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 =
|
||||
|
|
|
@ -608,6 +608,7 @@ PcCreateItemDispatch(
|
|||
}
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,19 +616,10 @@ 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))
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -145,17 +241,19 @@ DeviceInterfaceChangeCallback(
|
|||
NTSTATUS
|
||||
SysAudioRegisterNotifications(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
SYSAUDIODEVEXT *DeviceExtension)
|
||||
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))
|
||||
|
|
|
@ -133,7 +133,7 @@ SysAudio_InstallDevice(
|
|||
}
|
||||
|
||||
Status = SysAudioRegisterNotifications(DriverObject,
|
||||
DeviceExtension);
|
||||
DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to register device notifications\n");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
@ -89,7 +94,7 @@ SysAudioRegisterDeviceInterfaces(
|
|||
NTSTATUS
|
||||
SysAudioRegisterNotifications(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
SYSAUDIODEVEXT *DeviceExtension);
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
NTSTATUS
|
||||
SysAudioHandleProperty(
|
||||
|
@ -105,4 +110,9 @@ NTSTATUS
|
|||
CreateDispatcher(
|
||||
IN PIRP Irp);
|
||||
|
||||
ULONG
|
||||
GetDeviceCount(
|
||||
PSYSAUDIODEVEXT DeviceExtension,
|
||||
BOOL WaveIn);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue