From 2d8cd02bb566654b39e8b97aeda642bf7d15d4c2 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sun, 2 Aug 2009 18:20:39 +0000 Subject: [PATCH] [PORTCLS] - Fix lots of COM object leaks - IPortWaveCyclic & IPortTopology drivers now shutdown cleanly - Implement freeing of all registered physical connections and release of the registered power management interface [SYSAUDIO] - Close handles to audio filters svn path=/trunk/; revision=42344 --- .../audio/backpln/portcls/filter_topology.c | 68 ++++++------------- .../audio/backpln/portcls/filter_wavecyclic.c | 45 +++++------- .../drivers/wdm/audio/backpln/portcls/irp.c | 33 ++++++++- .../audio/backpln/portcls/pin_wavecyclic.c | 18 +++-- .../wdm/audio/backpln/portcls/port_topology.c | 19 ++++-- .../audio/backpln/portcls/port_wavecyclic.c | 34 ++++++---- reactos/drivers/wdm/audio/sysaudio/main.c | 11 ++- 7 files changed, 125 insertions(+), 103 deletions(-) diff --git a/reactos/drivers/wdm/audio/backpln/portcls/filter_topology.c b/reactos/drivers/wdm/audio/backpln/portcls/filter_topology.c index 8f6badecbd6..c2b34921060 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/filter_topology.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/filter_topology.c @@ -16,6 +16,7 @@ typedef struct IPortTopology* Port; SUBDEVICE_DESCRIPTOR * Descriptor; + ISubdevice *SubDevice; }IPortFilterTopologyImpl; @@ -112,24 +113,12 @@ IPortFilterTopology_fnDeviceIoControl( 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); + return PcPropertyHandler(Irp, This->Descriptor); } /* @@ -181,18 +170,21 @@ IPortFilterTopology_fnClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - //PMINIPORTTOPOLOGY Miniport; - //IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface; + NTSTATUS Status = STATUS_SUCCESS; + IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl *)iface; - /* release reference to port */ - //This->Port->lpVtbl->Release(This->Port); + /* FIXME handle DirectSound */ - /* get the miniport driver */ - //Miniport = GetTopologyMiniport(This->Port); - /* release miniport driver */ - //Miniport->lpVtbl->Release(Miniport); + if (This->ref == 1) + { + /* release reference to port */ + This->SubDevice->lpVtbl->Release(This->SubDevice); - Irp->IoStatus.Status = STATUS_SUCCESS; + /* time to shutdown the audio system */ + Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice); + } + + Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -244,9 +236,6 @@ IPortFilterTopology_fnFastDeviceIoControl( { ULONG Index; PKSPROPERTY Property; - NTSTATUS Status; - ISubdevice * SubDevice = NULL; - PSUBDEVICE_DESCRIPTOR Descriptor = NULL; IPortFilterTopologyImpl * This = (IPortFilterTopologyImpl*)iface; Property = (PKSPROPERTY)InputBuffer; @@ -254,28 +243,14 @@ IPortFilterTopology_fnFastDeviceIoControl( if (InputBufferLength < sizeof(KSPROPERTY)) return FALSE; - - /* get private interface */ - Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice); - if (!NT_SUCCESS(Status)) - return FALSE; - - /* get descriptor */ - Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor); - if (!NT_SUCCESS(Status)) + for(Index = 0; Index < This->Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++) { - SubDevice->lpVtbl->Release(SubDevice); - return FALSE; - } - - for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++) - { - if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set)) + if (IsEqualGUIDAligned(&Property->Set, This->Descriptor->FilterPropertySet.Properties[Index].Set)) { FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock, 1, - &Descriptor->FilterPropertySet.Properties[Index], - Descriptor, SubDevice); + &This->Descriptor->FilterPropertySet.Properties[Index], + This->Descriptor, This->SubDevice); } } return TRUE; @@ -342,8 +317,8 @@ IPortFilterTopology_fnInit( /* get the subdevice descriptor */ Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor); - /* release subdevice interface */ - ISubDevice->lpVtbl->Release(ISubDevice); + /* store subdevice interface */ + This->SubDevice = ISubDevice; if (!NT_SUCCESS(Status)) return STATUS_UNSUCCESSFUL; @@ -351,9 +326,6 @@ IPortFilterTopology_fnInit( /* save descriptor */ This->Descriptor = Descriptor; - /* increment reference count */ - Port->lpVtbl->AddRef(Port); - /* store port object */ This->Port = Port; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c index 4abf7ca8859..77903736974 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/filter_wavecyclic.c @@ -17,6 +17,7 @@ typedef struct IPortWaveCyclic* Port; IPortPinWaveCyclic ** Pins; SUBDEVICE_DESCRIPTOR * Descriptor; + ISubdevice * SubDevice; }IPortFilterWaveCyclicImpl; @@ -161,24 +162,12 @@ IPortFilterWaveCyclic_fnDeviceIoControl( IN PIRP Irp) { PIO_STACK_LOCATION IoStack; - ISubdevice *SubDevice = NULL; - SUBDEVICE_DESCRIPTOR * Descriptor; - NTSTATUS Status; IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)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); + return PcPropertyHandler(Irp, This->Descriptor); } /* @@ -231,7 +220,7 @@ IPortFilterWaveCyclic_fnClose( IN PIRP Irp) { ULONG Index; - //PMINIPORTWAVECYCLIC Miniport; + NTSTATUS Status = STATUS_SUCCESS; IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl *)iface; for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++) @@ -240,16 +229,18 @@ IPortFilterWaveCyclic_fnClose( ASSERT(This->Pins[Index] == NULL); } - /* release reference to port */ - //This->Port->lpVtbl->Release(This->Port); + DPRINT("IPortFilterWaveCyclic_fnClose ref %u\n", This->ref); - /* get the miniport driver */ - //Miniport = GetWaveCyclicMiniport(This->Port); - /* release miniport driver */ - //Miniport->lpVtbl->Release(Miniport); + if (This->ref == 1) + { + /* release reference to port */ + This->SubDevice->lpVtbl->Release(This->SubDevice); + /* time to shutdown the audio system */ + Status = This->SubDevice->lpVtbl->ReleaseChildren(This->SubDevice); + } - Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -358,18 +349,16 @@ IPortFilterWaveCyclic_fnInit( NTSTATUS Status; IPortFilterWaveCyclicImpl * This = (IPortFilterWaveCyclicImpl*)iface; - This->Port = Port; - /* get our private interface */ - Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice); + 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); + /* store subdevice interface */ + This->SubDevice = ISubDevice; if (!NT_SUCCESS(Status)) return STATUS_UNSUCCESSFUL; @@ -383,8 +372,8 @@ IPortFilterWaveCyclic_fnInit( if (!This->Pins) return STATUS_UNSUCCESSFUL; - /* increment reference count */ - Port->lpVtbl->AddRef(Port); + /* store port driver */ + This->Port = Port; return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/irp.c b/reactos/drivers/wdm/audio/backpln/portcls/irp.c index d731e25cb5f..a2111cb1abe 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/irp.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/irp.c @@ -194,10 +194,39 @@ PortClsShutdown( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + PPCLASS_DEVICE_EXTENSION DeviceExtension; + PLIST_ENTRY Entry; + PPHYSICAL_CONNECTION Connection; DPRINT("PortClsShutdown called\n"); - //DbgBreakPoint(); - /* TODO */ + /* get device extension */ + DeviceExtension = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + while(!IsListEmpty(&DeviceExtension->PhysicalConnectionList)) + { + /* get connection entry */ + Entry = RemoveHeadList(&DeviceExtension->PhysicalConnectionList); + Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry); + + if (Connection->FromSubDevice) + { + /* release subdevice */ + Connection->FromSubDevice->lpVtbl->Release(Connection->FromSubDevice); + } + + if (Connection->ToSubDevice) + { + /* release subdevice */ + Connection->ToSubDevice->lpVtbl->Release(Connection->ToSubDevice); + } + FreeItem(Connection, TAG_PORTCLASS); + } + + if (DeviceExtension->AdapterPowerManagement) + { + /* release adapter power management */ + DPRINT1("Power %u\n", DeviceExtension->AdapterPowerManagement->lpVtbl->Release(DeviceExtension->AdapterPowerManagement)); + } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c index 1f919b0839c..86162cfe177 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c @@ -777,6 +777,12 @@ CloseStreamRoutine( /* free work item ctx */ FreeItem(Ctx, TAG_PORTCLASS); + /* release reference to port driver */ + This->Port->lpVtbl->Release(This->Port); + + /* release reference to filter instance */ + This->Filter->lpVtbl->Release(This->Filter); + if (This->Stream) { Stream = This->Stream; @@ -1013,11 +1019,6 @@ IPortPinWaveCyclic_fnInit( IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; - Port->lpVtbl->AddRef(Port); - Filter->lpVtbl->AddRef(Filter); - - This->Port = Port; - This->Filter = Filter; This->KsPinDescriptor = KsPinDescriptor; This->ConnectDetails = ConnectDetails; This->Miniport = GetWaveCyclicMiniport(Port); @@ -1115,11 +1116,18 @@ IPortPinWaveCyclic_fnInit( return Status; } + Port->lpVtbl->AddRef(Port); + Filter->lpVtbl->AddRef(Filter); + + This->Port = Port; + This->Filter = Filter; + //This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format); DPRINT1("Setting state to acquire %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_ACQUIRE)); DPRINT1("Setting state to pause %x\n", This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE)); This->State = KSSTATE_PAUSE; + //This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay); return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c index 58cb6e61813..c98a8185d3b 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_topology.c @@ -124,7 +124,6 @@ IPortTopology_fnAddRef( IPortTopology* iface) { IPortTopologyImpl * This = (IPortTopologyImpl*)iface; - return InterlockedIncrement(&This->ref); } @@ -136,6 +135,7 @@ IPortTopology_fnRelease( IPortTopologyImpl * This = (IPortTopologyImpl*)iface; InterlockedDecrement(&This->ref); + DPRINT("Reference Count %u\n", This->ref); if (This->ref == 0) { @@ -208,9 +208,7 @@ IPortTopology_fnInit( This->pDeviceObject = DeviceObject; This->bInitialized = TRUE; - /* increment reference on miniport adapter */ - Miniport->lpVtbl->AddRef(Miniport); - + /* now initialize the miniport driver */ Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface); if (!NT_SUCCESS(Status)) { @@ -394,10 +392,17 @@ NTAPI ISubDevice_fnReleaseChildren( IN ISubdevice *iface) { - //IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice); + IPortTopologyImpl * This = (IPortTopologyImpl*)CONTAINING_RECORD(iface, IPortTopologyImpl, lpVtblSubDevice); - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; + DPRINT1("ISubDevice_fnReleaseChildren with ref %u\n", This->ref); + + /* release the filter */ + This->Filter->lpVtbl->Release(This->Filter); + + /* release the miniport */ + DPRINT("Refs %u %u\n", This->pMiniport->lpVtbl->Release(This->pMiniport), This->ref); + + return STATUS_SUCCESS; } static diff --git a/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c b/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c index eef0193c301..80df4011de7 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c +++ b/reactos/drivers/wdm/audio/backpln/portcls/port_wavecyclic.c @@ -266,12 +266,6 @@ IPortWaveCyclic_fnRelease( if (This->ref == 0) { - if (This->pPinCount) - This->pPinCount->lpVtbl->Release(This->pPinCount); - - if (This->pPowerNotify) - This->pPowerNotify->lpVtbl->Release(This->pPowerNotify); - FreeItem(This, TAG_PORTCLASS); return 0; } @@ -343,9 +337,6 @@ IPortWaveCyclic_fnInit( This->bInitialized = TRUE; This->pResourceList = ResourceList; - /* increment reference on miniport adapter */ - Miniport->lpVtbl->AddRef(Miniport); - Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface); if (!NT_SUCCESS(Status)) { @@ -644,10 +635,29 @@ NTAPI ISubDevice_fnReleaseChildren( IN ISubdevice *iface) { - //IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice); + IPortWaveCyclicImpl * This = (IPortWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortWaveCyclicImpl, lpVtblSubDevice); - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; + DPRINT("ISubDevice_fnReleaseChildren ref %u\n", This->ref); + + /* release the filter */ + This->Filter->lpVtbl->Release(This->Filter); + + if (This->pPinCount) + { + /* release pincount interface */ + This->pPinCount->lpVtbl->Release(This->pPinCount); + } + + if (This->pPowerNotify) + { + /* release power notify interface */ + This->pPowerNotify->lpVtbl->Release(This->pPowerNotify); + } + + /* now release the miniport */ + This->pMiniport->lpVtbl->Release(This->pMiniport); + + return STATUS_SUCCESS; } static diff --git a/reactos/drivers/wdm/audio/sysaudio/main.c b/reactos/drivers/wdm/audio/sysaudio/main.c index 6cdf2527cf8..d1134c88360 100644 --- a/reactos/drivers/wdm/audio/sysaudio/main.c +++ b/reactos/drivers/wdm/audio/sysaudio/main.c @@ -47,8 +47,17 @@ SysAudio_Shutdown( DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry); DPRINT1("Freeing item %wZ\n", &DeviceEntry->DeviceName); - RtlFreeUnicodeString(&DeviceEntry->DeviceName); + /* dereference audio device file object */ + ObDereferenceObject(DeviceEntry->FileObject); + + /* close audio device handle */ + ZwClose(DeviceEntry->Handle); + /* free device string */ + RtlFreeUnicodeString(&DeviceEntry->DeviceName); + /* free pins */ + ExFreePool(DeviceEntry->Pins); + /* free audio device entry */ ExFreePool(DeviceEntry); }