[PORTCLS]

- Fix check if the pin can be instantiated another time
- Remove hack to close old
- Add function FreePin to remove its old reference
- Fix memory leaks / reference leaks in WavePci pin implementation
- Fix memory / reference leaks in WavePci Close implementation

svn path=/trunk/; revision=49238
This commit is contained in:
Johannes Anderwald 2010-10-23 12:10:56 +00:00
parent cd63ffe6c2
commit 4b5747df27
6 changed files with 244 additions and 89 deletions

View file

@ -327,7 +327,7 @@ CPortFilterWaveCyclic::Init(
NTSTATUS NTSTATUS
NTAPI NTAPI
CPortFilterWaveCyclic::FreePin( CPortFilterWaveCyclic::FreePin(
IN struct IPortPinWaveCyclic* Pin) IN PPORTPINWAVECYCLIC Pin)
{ {
ULONG Index; ULONG Index;

View file

@ -96,13 +96,14 @@ CPortFilterWavePci::NewIrpTarget(
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount) if (m_Pins[ConnectDetails->PinId] &&
(m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
{ {
// release existing instance // no available instance
PC_ASSERT(0); return STATUS_UNSUCCESSFUL;
m_Pins[ConnectDetails->PinId]->Close(DeviceObject, NULL);
} }
// now create the pin // now create the pin
Status = NewPortPinWavePci(&Pin); Status = NewPortPinWavePci(&Pin);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -305,6 +306,26 @@ CPortFilterWavePci::Init(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS
NTAPI
CPortFilterWavePci::FreePin(
IN struct IPortPinWavePci* Pin)
{
ULONG Index;
for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
{
if (m_Pins[Index] == Pin)
{
m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
m_Pins[Index] = NULL;
return STATUS_SUCCESS;
}
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS NTSTATUS
NewPortFilterWavePci( NewPortFilterWavePci(
OUT IPortFilterWavePci ** OutFilter) OUT IPortFilterWavePci ** OutFilter)

View file

@ -599,6 +599,8 @@ DECLARE_INTERFACE_(IIrpStreamVirtual, IIrpStream)
#undef INTERFACE #undef INTERFACE
#define INTERFACE IPortFilterWavePci #define INTERFACE IPortFilterWavePci
struct IPortPinWavePci;
DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget) DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget)
{ {
DEFINE_ABSTRACT_UNKNOWN() DEFINE_ABSTRACT_UNKNOWN()
@ -607,6 +609,9 @@ DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget)
STDMETHOD_(NTSTATUS, Init)(THIS_ STDMETHOD_(NTSTATUS, Init)(THIS_
IN PPORTWAVEPCI Port)PURE; IN PPORTWAVEPCI Port)PURE;
STDMETHOD_(NTSTATUS, FreePin)(THIS_
IN struct IPortPinWavePci* Pin)PURE;
}; };
typedef IPortFilterWavePci *PPORTFILTERWAVEPCI; typedef IPortFilterWavePci *PPORTFILTERWAVEPCI;
@ -614,7 +619,10 @@ typedef IPortFilterWavePci *PPORTFILTERWAVEPCI;
#define IMP_IPortFilterPci \ #define IMP_IPortFilterPci \
IMP_IIrpTarget; \ IMP_IIrpTarget; \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \ STDMETHODIMP_(NTSTATUS) Init(THIS_ \
IN PPORTWAVEPCI Port) IN PPORTWAVEPCI Port); \
STDMETHODIMP_(NTSTATUS) FreePin(THIS_ \
IN struct IPortPinWavePci* Pin)
/***************************************************************************** /*****************************************************************************
* IPortPinWavePci * IPortPinWavePci

View file

@ -960,27 +960,29 @@ CPortPinWaveCyclic::Close(
{ {
// free format // free format
FreeItem(m_Format, TAG_PORTCLASS); FreeItem(m_Format, TAG_PORTCLASS);
// format is freed
m_Format = NULL; m_Format = NULL;
} }
if (m_IrpQueue) if (m_IrpQueue)
{ {
// fixme cancel irps // cancel remaining irps
m_IrpQueue->CancelBuffers();
// release irp queue
m_IrpQueue->Release(); m_IrpQueue->Release();
}
// queue is freed
if (m_Port) m_IrpQueue = NULL;
{
// release reference to port driver
m_Port->Release();
m_Port = NULL;
} }
if (m_ServiceGroup) if (m_ServiceGroup)
{ {
// remove member from service group // remove member from service group
m_ServiceGroup->RemoveMember(PSERVICESINK(this)); m_ServiceGroup->RemoveMember(PSERVICESINK(this));
// do not release service group, it is released by the miniport object
m_ServiceGroup = NULL; m_ServiceGroup = NULL;
} }
@ -999,22 +1001,37 @@ CPortPinWaveCyclic::Close(
// set state to stop // set state to stop
m_State = KSSTATE_STOP; m_State = KSSTATE_STOP;
DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql()); DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
// release stream // release stream
m_Stream->Release(); m_Stream->Release();
// stream is now freed
m_Stream = NULL;
} }
if (m_Filter) if (m_Filter)
{ {
// release reference to filter instance // disconnect pin from filter
m_Filter->FreePin((PPORTPINWAVECYCLIC)this); m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
// release filter reference
m_Filter->Release(); m_Filter->Release();
// pin is done with filter
m_Filter = NULL; m_Filter = NULL;
} }
if (m_Port)
{
// release reference to port driver
m_Port->Release();
// work is done for port
m_Port = NULL;
}
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);

View file

@ -62,8 +62,6 @@ protected:
KSAUDIO_POSITION m_Position; KSAUDIO_POSITION m_Position;
ULONG m_StopCount; ULONG m_StopCount;
ULONG m_Delay;
BOOL m_bUsePrefetch; BOOL m_bUsePrefetch;
ULONG m_PrefetchOffset; ULONG m_PrefetchOffset;
SUBDEVICE_DESCRIPTOR m_Descriptor; SUBDEVICE_DESCRIPTOR m_Descriptor;
@ -637,41 +635,85 @@ CPortPinWavePci::Close(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
ISubdevice *SubDevice;
NTSTATUS Status; NTSTATUS Status;
PSUBDEVICE_DESCRIPTOR Descriptor;
if (m_Format)
{
// free format
FreeItem(m_Format, TAG_PORTCLASS);
// format is freed
m_Format = NULL;
}
if (m_IrpQueue)
{
// cancel remaining irps
m_IrpQueue->CancelBuffers();
// release irp queue
m_IrpQueue->Release();
// queue is freed
m_IrpQueue = NULL;
}
if (m_ServiceGroup) if (m_ServiceGroup)
{ {
// remove member from service group
m_ServiceGroup->RemoveMember(PSERVICESINK(this)); m_ServiceGroup->RemoveMember(PSERVICESINK(this));
// do not release service group, it is released by the miniport object
m_ServiceGroup = NULL;
} }
if (m_Stream) if (m_Stream)
{ {
if (m_State != KSSTATE_STOP) if (m_State != KSSTATE_STOP)
{ {
m_Stream->SetState(KSSTATE_STOP); // stop stream
Status = m_Stream->SetState(KSSTATE_STOP);
if (!NT_SUCCESS(Status))
{
DPRINT("Warning: failed to stop stream with %x\n", Status);
PC_ASSERT(0);
}
} }
// set state to stop
m_State = KSSTATE_STOP;
DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
// release stream
m_Stream->Release(); m_Stream->Release();
// stream is now freed
m_Stream = NULL;
} }
Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice); if (m_Filter)
if (NT_SUCCESS(Status))
{ {
Status = SubDevice->GetDescriptor(&Descriptor); // disconnect pin from filter
if (NT_SUCCESS(Status)) m_Filter->FreePin((PPORTPINWAVEPCI)this);
{
Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--; // release filter reference
} m_Filter->Release();
SubDevice->Release();
// pin is done with filter
m_Filter = NULL;
} }
if (m_Format) if (m_Port)
{ {
FreeItem(m_Format, TAG_PORTCLASS); // release reference to port driver
m_Format = NULL; m_Port->Release();
// work is done for port
m_Port = NULL;
} }
// successfully complete irp
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
@ -756,33 +798,18 @@ CPortPinWavePci::Init(
NTSTATUS Status; NTSTATUS Status;
PKSDATAFORMAT DataFormat; PKSDATAFORMAT DataFormat;
BOOLEAN Capture; BOOLEAN Capture;
ISubdevice * Subdevice = NULL;
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
Port->AddRef(); // check if it is a source / sink pin
Filter->AddRef();
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_Miniport = GetWavePciMiniport(Port);
m_DeviceObject = DeviceObject;
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
DPRINT("IPortPinWavePci_fnInit entered\n");
m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
return STATUS_INSUFFICIENT_RESOURCES;
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
{ {
// sink pin
Capture = FALSE; Capture = FALSE;
} }
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT) else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
{ {
// source pin
Capture = TRUE; Capture = TRUE;
} }
else else
@ -792,6 +819,45 @@ CPortPinWavePci::Init(
while(TRUE); while(TRUE);
} }
// add port / filter reference
Port->AddRef();
Filter->AddRef();
// initialize pin
m_Port = Port;
m_Filter = Filter;
m_KsPinDescriptor = KsPinDescriptor;
m_ConnectDetails = ConnectDetails;
m_Miniport = GetWavePciMiniport(Port);
m_DeviceObject = DeviceObject;
m_State = KSSTATE_STOP;
m_Capture = Capture;
DPRINT("IPortPinWavePci_fnInit entered\n");
// get dataformat
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
// allocate data format
m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
if (!m_Format)
{
// release references
m_Port->Release();
m_Filter->Release();
// no dangling pointers
Port = NULL;
Filter = NULL;
// failed to allocate data format
return STATUS_INSUFFICIENT_RESOURCES;
}
// copy data format
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
// allocate new stream
Status = m_Miniport->NewStream(&m_Stream, Status = m_Miniport->NewStream(&m_Stream,
NULL, NULL,
NonPagedPool, NonPagedPool,
@ -805,47 +871,81 @@ CPortPinWavePci::Init(
DPRINT("IPortPinWavePci_fnInit Status %x\n", Status); DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return Status;
if (m_ServiceGroup)
{ {
Status = m_ServiceGroup->AddMember(PSERVICESINK(this)); // free references
if (!NT_SUCCESS(Status)) Port->Release();
{ Filter->Release();
DPRINT("Failed to add pin to service group\n");
return Status; // free data format
} FreeItem(m_Format, TAG_PORTCLASS);
// no dangling pointers
m_Port = NULL;
m_Filter = NULL;
m_Format = NULL;
// failed to allocate stream
return Status;
} }
// delay of 10 milisec // get allocator requirements for pin
m_Delay = Int32x32To64(10, -10000);
Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming); Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
if (NT_SUCCESS(Status))
{
DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
}
// allocate new irp queue
Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("GetAllocatorFraming failed with %x\n", Status); // free references
Port->Release();
Filter->Release();
m_Stream->Release();
// free data format
FreeItem(m_Format, TAG_PORTCLASS);
// no dangling pointers
m_Port = NULL;
m_Filter = NULL;
m_Format = NULL;
m_Stream = NULL;
// failed to allocate irp queue
return Status;
} }
DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n", // initialize irp queue
m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment); Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
if (!NT_SUCCESS(Status))
{
// this should never happen
ASSERT(0);
}
ISubdevice * Subdevice = NULL;
// get subdevice interface // get subdevice interface
Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice); Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return Status; {
// this function should never fail
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL; ASSERT(0);
}
// get subdevice descriptor
Status = Subdevice->GetDescriptor(&SubDeviceDescriptor); Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
// failed to get descriptor // this function should never fail
Subdevice->Release(); ASSERT(0);
return Status;
} }
// release subdevice
Subdevice->Release();
/* set up subdevice descriptor */ /* set up subdevice descriptor */
RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR)); RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
m_Descriptor.FilterPropertySet = PinWavePciPropertySet; m_Descriptor.FilterPropertySet = PinWavePciPropertySet;
@ -855,21 +955,30 @@ CPortPinWavePci::Init(
m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport; m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
m_Descriptor.PortPin = (PVOID)this; m_Descriptor.PortPin = (PVOID)this;
if (m_ServiceGroup)
Status = NewIrpQueue(&m_IrpQueue);
if (!NT_SUCCESS(Status))
return Status;
Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
if (!NT_SUCCESS(Status))
{ {
DPRINT("IrpQueue_Init failed with %x\n", Status); Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
return Status; if (!NT_SUCCESS(Status))
{
// free references
m_Stream->Release();
Port->Release();
Filter->Release();
// free data format
FreeItem(m_Format, TAG_PORTCLASS);
// no dangling pointers
m_Stream = NULL;
m_Port = NULL;
m_Filter = NULL;
m_Format = NULL;
// failed to add to service group
return Status;
}
} }
m_State = KSSTATE_STOP;
m_Capture = Capture;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -275,12 +275,12 @@ CPortWaveCyclic::Init(
} }
// create the subdevice descriptor // create the subdevice descriptor
Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor, Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
4, 4,
InterfaceGuids, InterfaceGuids,
0, 0,
NULL, NULL,
2, 2,
WaveCyclicPropertySet, WaveCyclicPropertySet,
0, 0,
0, 0,