From 89797da90332c7b16a1fe86ae0ca94e7cea7f4a4 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Fri, 27 Feb 2009 11:22:16 +0000 Subject: [PATCH] - Complete missing irp - Handle all properties of KSPROPSETID - Initialize filter properties in a deferred routine - Add more error checks svn path=/trunk/; revision=39782 --- .../audio/backpln/portcls/pin_wavecyclic.c | 12 +- .../wdm/audio/backpln/portcls/port_topology.c | 1 + reactos/drivers/wdm/audio/sysaudio/control.c | 511 ++++++++++-------- reactos/drivers/wdm/audio/sysaudio/deviface.c | 114 +++- reactos/drivers/wdm/audio/sysaudio/main.c | 2 +- reactos/drivers/wdm/audio/sysaudio/sysaudio.h | 14 +- 6 files changed, 420 insertions(+), 234 deletions(-) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c index d7e2243cc11..a8de9e3185a 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c @@ -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 = diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c index 4ba0ae9d78b..0596eb8325f 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c @@ -608,6 +608,7 @@ PcCreateItemDispatch( } Irp->IoStatus.Information = 0; Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } diff --git a/reactos/drivers/wdm/audio/sysaudio/control.c b/reactos/drivers/wdm/audio/sysaudio/control.c index 449c56bd209..82f01464d88 100644 --- a/reactos/drivers/wdm/audio/sysaudio/control.c +++ b/reactos/drivers/wdm/audio/sysaudio/control.c @@ -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); } } diff --git a/reactos/drivers/wdm/audio/sysaudio/deviface.c b/reactos/drivers/wdm/audio/sysaudio/deviface.c index 509f6763ebc..72d653c451e 100644 --- a/reactos/drivers/wdm/audio/sysaudio/deviface.c +++ b/reactos/drivers/wdm/audio/sysaudio/deviface.c @@ -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)) diff --git a/reactos/drivers/wdm/audio/sysaudio/main.c b/reactos/drivers/wdm/audio/sysaudio/main.c index c1017a4b58e..a61bf080c74 100644 --- a/reactos/drivers/wdm/audio/sysaudio/main.c +++ b/reactos/drivers/wdm/audio/sysaudio/main.c @@ -133,7 +133,7 @@ SysAudio_InstallDevice( } Status = SysAudioRegisterNotifications(DriverObject, - DeviceExtension); + DeviceObject); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to register device notifications\n"); diff --git a/reactos/drivers/wdm/audio/sysaudio/sysaudio.h b/reactos/drivers/wdm/audio/sysaudio/sysaudio.h index 870b42dc9f8..e4bc6fb0c0d 100644 --- a/reactos/drivers/wdm/audio/sysaudio/sysaudio.h +++ b/reactos/drivers/wdm/audio/sysaudio/sysaudio.h @@ -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