/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel Streaming * FILE: drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp * PURPOSE: WavePci IRP Audio Pin * PROGRAMMER: Johannes Anderwald */ #include "private.hpp" #ifndef YDEBUG #define NDEBUG #endif #include class CPortPinWavePci : public IPortPinWavePci, public IServiceSink, public IPortWavePciStream { public: STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); STDMETHODIMP_(ULONG) AddRef() { InterlockedIncrement(&m_Ref); return m_Ref; } STDMETHODIMP_(ULONG) Release() { InterlockedDecrement(&m_Ref); if (!m_Ref) { delete this; return 0; } return m_Ref; } IMP_IPortPinWavePci; IMP_IServiceSink; IMP_IPortWavePciStream; CPortPinWavePci(IUnknown *OuterUnknown) {} virtual ~CPortPinWavePci(){} protected: friend NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); friend NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); friend NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); friend NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); IPortWavePci * m_Port; IPortFilterWavePci * m_Filter; KSPIN_DESCRIPTOR * m_KsPinDescriptor; PMINIPORTWAVEPCI m_Miniport; PSERVICEGROUP m_ServiceGroup; PDMACHANNEL m_DmaChannel; PMINIPORTWAVEPCISTREAM m_Stream; KSSTATE m_State; PKSDATAFORMAT m_Format; KSPIN_CONNECT * m_ConnectDetails; BOOL m_Capture; PDEVICE_OBJECT m_DeviceObject; IIrpQueue * m_IrpQueue; ULONG m_TotalPackets; KSAUDIO_POSITION m_Position; ULONG m_StopCount; BOOL m_bUsePrefetch; ULONG m_PrefetchOffset; SUBDEVICE_DESCRIPTOR m_Descriptor; KSALLOCATOR_FRAMING m_AllocatorFraming; LONG m_Ref; NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp); NTSTATUS NTAPI HandleKsStream(IN PIRP Irp); }; typedef struct { CPortPinWavePci *Pin; PIO_WORKITEM WorkItem; KSSTATE State; }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT; NTSTATUS NTAPI PinWavePciState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); NTSTATUS NTAPI PinWavePciDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); NTSTATUS NTAPI PinWavePciAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); NTSTATUS NTAPI PinWavePciAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); DEFINE_KSPROPERTY_CONNECTIONSET(PinWavePciConnectionSet, PinWavePciState, PinWavePciDataFormat, PinWavePciAllocatorFraming); DEFINE_KSPROPERTY_AUDIOSET(PinWavePciAudioSet, PinWavePciAudioPosition); KSPROPERTY_SET PinWavePciPropertySet[] = { { &KSPROPSETID_Connection, sizeof(PinWavePciConnectionSet) / sizeof(KSPROPERTY_ITEM), (const KSPROPERTY_ITEM*)&PinWavePciConnectionSet, 0, NULL }, { &KSPROPSETID_Audio, sizeof(PinWavePciAudioSet) / sizeof(KSPROPERTY_ITEM), (const KSPROPERTY_ITEM*)&PinWavePciAudioSet, 0, NULL } }; NTSTATUS NTAPI PinWavePciAllocatorFraming( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) { CPortPinWavePci *Pin; PSUBDEVICE_DESCRIPTOR Descriptor; // get sub device descriptor Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); // sanity check PC_ASSERT(Descriptor); PC_ASSERT(Descriptor->PortPin); PC_ASSERT_IRQL(DISPATCH_LEVEL); // cast to pin impl Pin = (CPortPinWavePci*)Descriptor->PortPin; if (Request->Flags & KSPROPERTY_TYPE_GET) { // copy pin framing RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING)); Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING); return STATUS_SUCCESS; } // not supported return STATUS_NOT_SUPPORTED; } NTSTATUS NTAPI PinWavePciAudioPosition( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) { CPortPinWavePci *Pin; PSUBDEVICE_DESCRIPTOR Descriptor; // get sub device descriptor Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); // sanity check PC_ASSERT(Descriptor); PC_ASSERT(Descriptor->PortPin); PC_ASSERT_IRQL(DISPATCH_LEVEL); // cast to pin impl Pin = (CPortPinWavePci*)Descriptor->PortPin; //sanity check PC_ASSERT(Pin->m_Stream); if (Request->Flags & KSPROPERTY_TYPE_GET) { // FIXME non multithreading-safe // copy audio position RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION)); DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset); Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION); return STATUS_SUCCESS; } // not supported return STATUS_NOT_SUPPORTED; } NTSTATUS NTAPI PinWavePciState( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) { NTSTATUS Status = STATUS_UNSUCCESSFUL; CPortPinWavePci *Pin; PSUBDEVICE_DESCRIPTOR Descriptor; PVOID FirstTag, LastTag; ULONG MappingsRevoked; PKSSTATE State = (PKSSTATE)Data; // get sub device descriptor Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); // sanity check PC_ASSERT(Descriptor); PC_ASSERT(Descriptor->PortPin); PC_ASSERT_IRQL(DISPATCH_LEVEL); // cast to pin impl Pin = (CPortPinWavePci*)Descriptor->PortPin; //sanity check PC_ASSERT(Pin->m_Stream); if (Request->Flags & KSPROPERTY_TYPE_SET) { // try set stream Status = Pin->m_Stream->SetState(*State); DPRINT("Setting state %u %x\n", *State, Status); if (NT_SUCCESS(Status)) { // store new state Pin->m_State = *State; if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP) { // FIXME // complete with successful state Pin->m_IrpQueue->CancelBuffers(); while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag)) { Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked); DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked); KeStallExecutionProcessor(10); } Pin->m_Position.PlayOffset = 0; Pin->m_Position.WriteOffset = 0; } else if (Pin->m_State == KSSTATE_STOP) { Pin->m_IrpQueue->CancelBuffers(); while(Pin->m_IrpQueue->GetAcquiredTagRange(&FirstTag, &LastTag)) { Status = Pin->m_Stream->RevokeMappings(FirstTag, LastTag, &MappingsRevoked); DPRINT("RevokeMappings Status %lx MappingsRevoked: %lu\n", Status, MappingsRevoked); KeStallExecutionProcessor(10); } Pin->m_Position.PlayOffset = 0; Pin->m_Position.WriteOffset = 0; } // store result Irp->IoStatus.Information = sizeof(KSSTATE); } // store result Irp->IoStatus.Information = sizeof(KSSTATE); return Status; } else if (Request->Flags & KSPROPERTY_TYPE_GET) { // get current stream state *State = Pin->m_State; // store result Irp->IoStatus.Information = sizeof(KSSTATE); return STATUS_SUCCESS; } // unsupported request return STATUS_NOT_SUPPORTED; } NTSTATUS NTAPI PinWavePciDataFormat( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) { NTSTATUS Status = STATUS_UNSUCCESSFUL; CPortPinWavePci *Pin; PSUBDEVICE_DESCRIPTOR Descriptor; PIO_STACK_LOCATION IoStack; // get current irp stack location IoStack = IoGetCurrentIrpStackLocation(Irp); // get sub device descriptor Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp); // sanity check PC_ASSERT(Descriptor); PC_ASSERT(Descriptor->PortPin); // cast to pin impl Pin = (CPortPinWavePci*)Descriptor->PortPin; //sanity check PC_ASSERT(Pin->m_Stream); PC_ASSERT(Pin->m_Format); if (Request->Flags & KSPROPERTY_TYPE_SET) { // try to change data format PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize); if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size) { // format is identical Irp->IoStatus.Information = DataFormat->FormatSize; return STATUS_SUCCESS; } // new change request PC_ASSERT(Pin->m_State == KSSTATE_STOP); // FIXME queue a work item when Irql != PASSIVE_LEVEL PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); // allocate new data format NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); if (!NewDataFormat) { // not enough memory return STATUS_NO_MEMORY; } // copy new data format RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize); // set new format Status = Pin->m_Stream->SetFormat(NewDataFormat); if (NT_SUCCESS(Status)) { // free old format FreeItem(Pin->m_Format, TAG_PORTCLASS); // store new format Pin->m_Format = NewDataFormat; Irp->IoStatus.Information = NewDataFormat->FormatSize; #if 0 PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); #endif } else { // failed to set format FreeItem(NewDataFormat, TAG_PORTCLASS); } // done return Status; } else if (Request->Flags & KSPROPERTY_TYPE_GET) { // get current data format PC_ASSERT(Pin->m_Format); if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength) { // buffer too small Irp->IoStatus.Information = Pin->m_Format->FormatSize; return STATUS_MORE_ENTRIES; } // copy data format RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize); // store result size Irp->IoStatus.Information = Pin->m_Format->FormatSize; // done return STATUS_SUCCESS; } // unsupported request return STATUS_NOT_SUPPORTED; } //================================================================================================================================== NTSTATUS NTAPI CPortPinWavePci::QueryInterface( IN REFIID refiid, OUT PVOID* Output) { //DPRINT("CPortPinWavePci::QueryInterface entered\n"); if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) || IsEqualGUIDAligned(refiid, IID_IUnknown)) { *Output = PVOID(PUNKNOWN((IIrpTarget*)this)); PUNKNOWN(*Output)->AddRef(); return STATUS_SUCCESS; } if (IsEqualGUIDAligned(refiid, IID_IServiceSink)) { *Output = PVOID(PSERVICESINK(this)); PUNKNOWN(*Output)->AddRef(); return STATUS_SUCCESS; } if (IsEqualGUIDAligned(refiid, IID_IPortWavePciStream)) { *Output = PVOID(PPORTWAVEPCISTREAM(this)); PUNKNOWN(*Output)->AddRef(); return STATUS_SUCCESS; } return STATUS_UNSUCCESSFUL; } NTSTATUS NTAPI CPortPinWavePci::GetMapping( IN PVOID Tag, OUT PPHYSICAL_ADDRESS PhysicalAddress, OUT PVOID *VirtualAddress, OUT PULONG ByteCount, OUT PULONG Flags) { PC_ASSERT_IRQL(DISPATCH_LEVEL); return m_IrpQueue->GetMappingWithTag(Tag, PhysicalAddress, VirtualAddress, ByteCount, Flags); } NTSTATUS NTAPI CPortPinWavePci::ReleaseMapping( IN PVOID Tag) { PC_ASSERT_IRQL(DISPATCH_LEVEL); return m_IrpQueue->ReleaseMappingWithTag(Tag); } NTSTATUS NTAPI CPortPinWavePci::TerminatePacket() { UNIMPLEMENTED; PC_ASSERT_IRQL(DISPATCH_LEVEL); return STATUS_SUCCESS; } VOID NTAPI CPortPinWavePci::RequestService() { PC_ASSERT_IRQL(DISPATCH_LEVEL); if (m_State == KSSTATE_RUN) { m_Stream->Service(); //TODO //generate events } } //================================================================================================================================== NTSTATUS NTAPI CPortPinWavePci::NewIrpTarget( OUT struct IIrpTarget **OutTarget, IN PCWSTR Name, IN PUNKNOWN Unknown, IN POOL_TYPE PoolType, IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN KSOBJECT_CREATE *CreateObject) { UNIMPLEMENTED; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } NTSTATUS NTAPI CPortPinWavePci::HandleKsProperty( IN PIRP Irp) { //PKSPROPERTY Property; NTSTATUS Status; //UNICODE_STRING GuidString; PIO_STACK_LOCATION IoStack; //DPRINT("IPortPinWave_HandleKsProperty entered\n"); IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY) { //DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } Status = PcHandlePropertyWithTable(Irp, m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor); if (Status == STATUS_NOT_FOUND) { //Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; #if 0 RtlStringFromGUID(Property->Set, &GuidString); //DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); RtlFreeUnicodeString(&GuidString); #endif } if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; } NTSTATUS NTAPI CPortPinWavePci::HandleKsStream( IN PIRP Irp) { NTSTATUS Status; ULONG Data = 0; BOOLEAN bFailed; InterlockedIncrement((PLONG)&m_TotalPackets); DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData()); bFailed = m_IrpQueue->HasLastMappingFailed(); Status = m_IrpQueue->AddMapping(Irp, &Data); if (NT_SUCCESS(Status)) { if (m_Capture) m_Position.WriteOffset += Data; else m_Position.PlayOffset += Data; if (bFailed) { // notify stream of new mapping m_Stream->MappingAvailable(); } return STATUS_PENDING; } return Status; } NTSTATUS NTAPI CPortPinWavePci::DeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) { return HandleKsProperty(Irp); } else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) { return HandleKsStream(Irp); } UNIMPLEMENTED; Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } NTSTATUS NTAPI CPortPinWavePci::Read( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } NTSTATUS NTAPI CPortPinWavePci::Write( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } NTSTATUS NTAPI CPortPinWavePci::Flush( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } NTSTATUS NTAPI CPortPinWavePci::Close( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status; 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) { // remove member from service group 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_State != 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(); // stream is now freed m_Stream = NULL; } if (m_Filter) { // disconnect pin from filter m_Filter->FreePin((PPORTPINWAVEPCI)this); // release filter reference m_Filter->Release(); // pin is done with filter m_Filter = NULL; } if (m_Port) { // release reference to port driver m_Port->Release(); // work is done for port m_Port = NULL; } // successfully complete irp Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS NTAPI CPortPinWavePci::QuerySecurity( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } NTSTATUS NTAPI CPortPinWavePci::SetSecurity( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); } BOOLEAN NTAPI CPortPinWavePci::FastDeviceIoControl( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer, IN ULONG InputBufferLength, OUT PVOID OutputBuffer, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK StatusBlock, IN PDEVICE_OBJECT DeviceObject) { return FALSE; } BOOLEAN NTAPI CPortPinWavePci::FastRead( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK StatusBlock, IN PDEVICE_OBJECT DeviceObject) { return FALSE; } BOOLEAN NTAPI CPortPinWavePci::FastWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK StatusBlock, IN PDEVICE_OBJECT DeviceObject) { return FALSE; } NTSTATUS NTAPI CPortPinWavePci::Init( IN PPORTWAVEPCI Port, IN PPORTFILTERWAVEPCI Filter, IN KSPIN_CONNECT * ConnectDetails, IN KSPIN_DESCRIPTOR * KsPinDescriptor, IN PDEVICE_OBJECT DeviceObject) { NTSTATUS Status; PKSDATAFORMAT DataFormat; BOOLEAN Capture; ISubdevice * Subdevice = NULL; PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL; // check if it is a source / sink pin if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) { // sink pin Capture = FALSE; } else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT) { // source pin Capture = TRUE; } else { DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow); DbgBreakPoint(); 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, NULL, NonPagedPool, PPORTWAVEPCISTREAM(this), ConnectDetails->PinId, Capture, m_Format, &m_DmaChannel, &m_ServiceGroup); DPRINT("IPortPinWavePci_fnInit Status %x\n", Status); if (!NT_SUCCESS(Status)) { // free references Port->Release(); Filter->Release(); // 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; } // get allocator requirements for pin 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)) { // 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; } // initialize irp queue Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE); if (!NT_SUCCESS(Status)) { // this should never happen ASSERT(0); } // get subdevice interface Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice); if (!NT_SUCCESS(Status)) { // this function should never fail ASSERT(0); } // get subdevice descriptor Status = Subdevice->GetDescriptor(&SubDeviceDescriptor); if (!NT_SUCCESS(Status)) { // this function should never fail ASSERT(0); } // release subdevice Subdevice->Release(); /* set up subdevice descriptor */ RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR)); m_Descriptor.FilterPropertySet = PinWavePciPropertySet; m_Descriptor.FilterPropertySetCount = sizeof(PinWavePciPropertySet) / sizeof(KSPROPERTY_SET); m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream; m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor; m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport; m_Descriptor.PortPin = (PVOID)this; if (m_ServiceGroup) { Status = m_ServiceGroup->AddMember(PSERVICESINK(this)); 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; } } return STATUS_SUCCESS; } PVOID NTAPI CPortPinWavePci::GetIrpStream() { return (PVOID)m_IrpQueue; } PMINIPORT NTAPI CPortPinWavePci::GetMiniport() { return (PMINIPORT)m_Miniport; } NTSTATUS NewPortPinWavePci( OUT IPortPinWavePci ** OutPin) { CPortPinWavePci * This; This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWavePci(NULL); if (!This) return STATUS_INSUFFICIENT_RESOURCES; This->AddRef(); // store result *OutPin = (IPortPinWavePci*)This; return STATUS_SUCCESS; }