781 lines
17 KiB
C++
781 lines
17 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1997-2000 Microsoft Corporation All Rights Reserved
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
minwave.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementation of wavecyclic miniport.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <msvad.h>
|
||
|
#include <common.h>
|
||
|
#include "pcmex.h"
|
||
|
#include "minwave.h"
|
||
|
#include "wavtable.h"
|
||
|
|
||
|
#pragma code_seg("PAGE")
|
||
|
|
||
|
//=============================================================================
|
||
|
// CMiniportWaveCyclic
|
||
|
//=============================================================================
|
||
|
|
||
|
//=============================================================================
|
||
|
NTSTATUS
|
||
|
CreateMiniportWaveCyclicMSVAD
|
||
|
(
|
||
|
OUT PUNKNOWN * Unknown,
|
||
|
IN REFCLSID,
|
||
|
IN PUNKNOWN UnknownOuter OPTIONAL,
|
||
|
IN POOL_TYPE PoolType
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Create the wavecyclic miniport.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Unknown -
|
||
|
|
||
|
RefClsId -
|
||
|
|
||
|
UnknownOuter -
|
||
|
|
||
|
PoolType -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(Unknown);
|
||
|
|
||
|
STD_CREATE_BODY(CMiniportWaveCyclic, Unknown, UnknownOuter, PoolType);
|
||
|
}
|
||
|
|
||
|
//=============================================================================
|
||
|
CMiniportWaveCyclic::~CMiniportWaveCyclic
|
||
|
(
|
||
|
void
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Destructor for wavecyclic miniport
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclic::~CMiniportWaveCyclic]"));
|
||
|
} // ~CMiniportWaveCyclic
|
||
|
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclic::DataRangeIntersection
|
||
|
(
|
||
|
IN ULONG PinId,
|
||
|
IN PKSDATARANGE ClientDataRange,
|
||
|
IN PKSDATARANGE MyDataRange,
|
||
|
IN ULONG OutputBufferLength,
|
||
|
OUT PVOID ResultantFormat,
|
||
|
OUT PULONG ResultantFormatLength
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The DataRangeIntersection function determines the highest quality
|
||
|
intersection of two data ranges.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
PinId - Pin for which data intersection is being determined.
|
||
|
|
||
|
ClientDataRange - Pointer to KSDATARANGE structure which contains the data
|
||
|
range submitted by client in the data range intersection
|
||
|
property request.
|
||
|
|
||
|
MyDataRange - Pin's data range to be compared with client's data
|
||
|
range. In this case we actually ignore our own data
|
||
|
range, because we know that we only support one range.
|
||
|
|
||
|
OutputBufferLength - Size of the buffer pointed to by the resultant format
|
||
|
parameter.
|
||
|
|
||
|
ResultantFormat - Pointer to value where the resultant format should be
|
||
|
returned.
|
||
|
|
||
|
ResultantFormatLength - Actual length of the resultant format placed in
|
||
|
ResultantFormat. This should be less than or equal
|
||
|
to OutputBufferLength.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
// This code is the same as AC97 sample intersection handler.
|
||
|
//
|
||
|
|
||
|
// Check the size of output buffer. Note that we are returning
|
||
|
// WAVEFORMATPCMEX.
|
||
|
//
|
||
|
if (!OutputBufferLength)
|
||
|
{
|
||
|
*ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
|
||
|
return STATUS_BUFFER_OVERFLOW;
|
||
|
}
|
||
|
|
||
|
if (OutputBufferLength < (sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX)))
|
||
|
{
|
||
|
return STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
// Fill in the structure the datarange structure.
|
||
|
//
|
||
|
RtlCopyMemory(ResultantFormat, MyDataRange, sizeof(KSDATAFORMAT));
|
||
|
|
||
|
// Modify the size of the data format structure to fit the WAVEFORMATPCMEX
|
||
|
// structure.
|
||
|
//
|
||
|
((PKSDATAFORMAT)ResultantFormat)->FormatSize =
|
||
|
sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
|
||
|
|
||
|
// Append the WAVEFORMATPCMEX structure
|
||
|
//
|
||
|
PWAVEFORMATPCMEX pWfxExt =
|
||
|
(PWAVEFORMATPCMEX)((PKSDATAFORMAT)ResultantFormat + 1);
|
||
|
|
||
|
pWfxExt->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||
|
pWfxExt->Format.nChannels =
|
||
|
(WORD)((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumChannels;
|
||
|
pWfxExt->Format.nSamplesPerSec =
|
||
|
((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumSampleFrequency;
|
||
|
pWfxExt->Format.wBitsPerSample = (WORD)
|
||
|
((PKSDATARANGE_AUDIO) ClientDataRange)->MaximumBitsPerSample;
|
||
|
pWfxExt->Format.nBlockAlign =
|
||
|
(pWfxExt->Format.wBitsPerSample * pWfxExt->Format.nChannels) / 8;
|
||
|
pWfxExt->Format.nAvgBytesPerSec =
|
||
|
pWfxExt->Format.nSamplesPerSec * pWfxExt->Format.nBlockAlign;
|
||
|
pWfxExt->Format.cbSize = 22;
|
||
|
pWfxExt->Samples.wValidBitsPerSample = pWfxExt->Format.wBitsPerSample;
|
||
|
pWfxExt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||
|
|
||
|
// This should be set to wave port's channel config
|
||
|
// MSVAD ds3dhw implements this properly.
|
||
|
//
|
||
|
pWfxExt->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
|
||
|
|
||
|
// Now overwrite also the sample size in the ksdataformat structure.
|
||
|
((PKSDATAFORMAT)ResultantFormat)->SampleSize = pWfxExt->Format.nBlockAlign;
|
||
|
|
||
|
// That we will return.
|
||
|
//
|
||
|
*ResultantFormatLength = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATPCMEX);
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
} // DataRangeIntersection
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclic::GetDescription
|
||
|
(
|
||
|
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The GetDescription function gets a pointer to a filter description.
|
||
|
It provides a location to deposit a pointer in miniport's description
|
||
|
structure. This is the placeholder for the FromNode or ToNode fields in
|
||
|
connections which describe connections to the filter's pins.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFilterDescriptor - Pointer to the filter description.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(OutFilterDescriptor);
|
||
|
|
||
|
return
|
||
|
CMiniportWaveCyclicMSVAD::GetDescription(OutFilterDescriptor);
|
||
|
} // GetDescription
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclic::Init
|
||
|
(
|
||
|
IN PUNKNOWN UnknownAdapter_,
|
||
|
IN PRESOURCELIST ResourceList_,
|
||
|
IN PPORTWAVECYCLIC Port_
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The Init function initializes the miniport. Callers of this function
|
||
|
should run at IRQL PASSIVE_LEVEL
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
UnknownAdapter - A pointer to the Iuknown interface of the adapter object.
|
||
|
|
||
|
ResourceList - Pointer to the resource list to be supplied to the miniport
|
||
|
during initialization. The port driver is free to examine the
|
||
|
contents of the ResourceList. The port driver will not be
|
||
|
modify the ResourceList contents.
|
||
|
|
||
|
Port - Pointer to the topology port object that is linked with this miniport.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(UnknownAdapter_);
|
||
|
ASSERT(Port_);
|
||
|
|
||
|
NTSTATUS ntStatus;
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclic::Init]"));
|
||
|
|
||
|
m_MaxOutputStreams = MAX_OUTPUT_STREAMS;
|
||
|
m_MaxInputStreams = MAX_INPUT_STREAMS;
|
||
|
m_MaxTotalStreams = MAX_TOTAL_STREAMS;
|
||
|
|
||
|
m_MinChannels = MIN_CHANNELS;
|
||
|
m_MaxChannelsPcm = MAX_CHANNELS_PCM;
|
||
|
|
||
|
m_MinBitsPerSamplePcm = MIN_BITS_PER_SAMPLE_PCM;
|
||
|
m_MaxBitsPerSamplePcm = MAX_BITS_PER_SAMPLE_PCM;
|
||
|
m_MinSampleRatePcm = MIN_SAMPLE_RATE;
|
||
|
m_MaxSampleRatePcm = MAX_SAMPLE_RATE;
|
||
|
|
||
|
ntStatus =
|
||
|
CMiniportWaveCyclicMSVAD::Init
|
||
|
(
|
||
|
UnknownAdapter_,
|
||
|
ResourceList_,
|
||
|
Port_
|
||
|
);
|
||
|
if (NT_SUCCESS(ntStatus))
|
||
|
{
|
||
|
// Set filter descriptor.
|
||
|
m_FilterDescriptor = &MiniportFilterDescriptor;
|
||
|
|
||
|
m_fCaptureAllocated = FALSE;
|
||
|
m_fRenderAllocated = FALSE;
|
||
|
}
|
||
|
|
||
|
return ntStatus;
|
||
|
} // Init
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclic::NewStream
|
||
|
(
|
||
|
OUT PMINIPORTWAVECYCLICSTREAM * OutStream,
|
||
|
IN PUNKNOWN OuterUnknown,
|
||
|
IN POOL_TYPE PoolType,
|
||
|
IN ULONG Pin,
|
||
|
IN BOOLEAN Capture,
|
||
|
IN PKSDATAFORMAT DataFormat,
|
||
|
OUT PDMACHANNEL * OutDmaChannel,
|
||
|
OUT PSERVICEGROUP * OutServiceGroup
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
The NewStream function creates a new instance of a logical stream
|
||
|
associated with a specified physical channel. Callers of NewStream should
|
||
|
run at IRQL PASSIVE_LEVEL.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutStream -
|
||
|
|
||
|
OuterUnknown -
|
||
|
|
||
|
PoolType -
|
||
|
|
||
|
Pin -
|
||
|
|
||
|
Capture -
|
||
|
|
||
|
DataFormat -
|
||
|
|
||
|
OutDmaChannel -
|
||
|
|
||
|
OutServiceGroup -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(OutStream);
|
||
|
ASSERT(DataFormat);
|
||
|
ASSERT(OutDmaChannel);
|
||
|
ASSERT(OutServiceGroup);
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclic::NewStream]"));
|
||
|
|
||
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
PCMiniportWaveCyclicStream stream = NULL;
|
||
|
|
||
|
// Check if we have enough streams.
|
||
|
if (Capture)
|
||
|
{
|
||
|
if (m_fCaptureAllocated)
|
||
|
{
|
||
|
DPF(D_TERSE, ("[Only one capture stream supported]"));
|
||
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (m_fRenderAllocated)
|
||
|
{
|
||
|
DPF(D_TERSE, ("[Only one render stream supported]"));
|
||
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Determine if the format is valid.
|
||
|
//
|
||
|
if (NT_SUCCESS(ntStatus))
|
||
|
{
|
||
|
ntStatus = ValidateFormat(DataFormat);
|
||
|
}
|
||
|
|
||
|
// Instantiate a stream. Stream must be in
|
||
|
// NonPagedPool because of file saving.
|
||
|
//
|
||
|
if (NT_SUCCESS(ntStatus))
|
||
|
{
|
||
|
stream = new (NonPagedPool, MSVAD_POOLTAG)
|
||
|
CMiniportWaveCyclicStream(OuterUnknown);
|
||
|
|
||
|
if (stream)
|
||
|
{
|
||
|
stream->AddRef();
|
||
|
|
||
|
ntStatus =
|
||
|
stream->Init
|
||
|
(
|
||
|
this,
|
||
|
Pin,
|
||
|
Capture,
|
||
|
DataFormat
|
||
|
);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS(ntStatus))
|
||
|
{
|
||
|
if (Capture)
|
||
|
{
|
||
|
m_fCaptureAllocated = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_fRenderAllocated = TRUE;
|
||
|
}
|
||
|
|
||
|
*OutStream = PMINIPORTWAVECYCLICSTREAM(stream);
|
||
|
(*OutStream)->AddRef();
|
||
|
|
||
|
*OutDmaChannel = PDMACHANNEL(stream);
|
||
|
(*OutDmaChannel)->AddRef();
|
||
|
|
||
|
*OutServiceGroup = m_ServiceGroup;
|
||
|
(*OutServiceGroup)->AddRef();
|
||
|
|
||
|
// The stream, the DMA channel, and the service group have
|
||
|
// references now for the caller. The caller expects these
|
||
|
// references to be there.
|
||
|
}
|
||
|
|
||
|
// This is our private reference to the stream. The caller has
|
||
|
// its own, so we can release in any case.
|
||
|
//
|
||
|
if (stream)
|
||
|
{
|
||
|
stream->Release();
|
||
|
}
|
||
|
|
||
|
return ntStatus;
|
||
|
} // NewStream
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclic::NonDelegatingQueryInterface
|
||
|
(
|
||
|
IN REFIID Interface,
|
||
|
OUT PVOID * Object
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
QueryInterface
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Interface - GUID
|
||
|
|
||
|
Object - interface pointer to be returned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(Object);
|
||
|
|
||
|
if (IsEqualGUIDAligned(Interface, IID_IUnknown))
|
||
|
{
|
||
|
*Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this)));
|
||
|
}
|
||
|
else if (IsEqualGUIDAligned(Interface, IID_IMiniport))
|
||
|
{
|
||
|
*Object = PVOID(PMINIPORT(this));
|
||
|
}
|
||
|
else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveCyclic))
|
||
|
{
|
||
|
*Object = PVOID(PMINIPORTWAVECYCLIC(this));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*Object = NULL;
|
||
|
}
|
||
|
|
||
|
if (*Object)
|
||
|
{
|
||
|
// We reference the interface for the caller.
|
||
|
|
||
|
PUNKNOWN(*Object)->AddRef();
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
} // NonDelegatingQueryInterface
|
||
|
|
||
|
//=============================================================================
|
||
|
NTSTATUS
|
||
|
CMiniportWaveCyclic::ValidateFormat
|
||
|
(
|
||
|
IN PKSDATAFORMAT pDataFormat
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Validates that the given dataformat is valid. This is for supporting
|
||
|
WAVEFORMATEXTENSIBLE.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pDataFormat - The dataformat for validation.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(pDataFormat);
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::ValidateFormat]"));
|
||
|
|
||
|
NTSTATUS ntStatus;
|
||
|
PWAVEFORMATEX pwfx;
|
||
|
|
||
|
// Let the default Validator handle the request.
|
||
|
//
|
||
|
ntStatus = CMiniportWaveCyclicMSVAD::ValidateFormat(pDataFormat);
|
||
|
if (NT_SUCCESS(ntStatus))
|
||
|
{
|
||
|
return ntStatus;
|
||
|
}
|
||
|
|
||
|
// If the format is not known check for WAVEFORMATEXTENSIBLE.
|
||
|
//
|
||
|
pwfx = GetWaveFormatEx(pDataFormat);
|
||
|
if (pwfx)
|
||
|
{
|
||
|
if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat))
|
||
|
{
|
||
|
USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat);
|
||
|
|
||
|
switch (wfxID)
|
||
|
{
|
||
|
// This is for WAVE_FORMAT_EXTENSIBLE support.
|
||
|
//
|
||
|
case WAVE_FORMAT_EXTENSIBLE:
|
||
|
{
|
||
|
PWAVEFORMATEXTENSIBLE pwfxExt =
|
||
|
(PWAVEFORMATEXTENSIBLE) pwfx;
|
||
|
|
||
|
ntStatus = ValidateWfxExt(pwfxExt);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
default:
|
||
|
DPF(D_TERSE, ("Invalid format EXTRACT_WAVEFORMATEX_ID!"));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ntStatus;
|
||
|
} // ValidateFormat
|
||
|
|
||
|
//=============================================================================
|
||
|
NTSTATUS
|
||
|
CMiniportWaveCyclic::ValidateWfxExt
|
||
|
(
|
||
|
IN PWAVEFORMATEXTENSIBLE pWfxExt
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a waveformatextensible, verifies that the format is in device
|
||
|
datarange.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pWfxExt - wave format extensible structure
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclic::ValidateWfxExtPcm]"));
|
||
|
|
||
|
// First verify that the subformat is OK
|
||
|
//
|
||
|
if (pWfxExt)
|
||
|
{
|
||
|
if(IsEqualGUIDAligned(pWfxExt->SubFormat, KSDATAFORMAT_SUBTYPE_PCM))
|
||
|
{
|
||
|
PWAVEFORMATEX pWfx = (PWAVEFORMATEX) pWfxExt;
|
||
|
|
||
|
if
|
||
|
(
|
||
|
pWfx->cbSize ==
|
||
|
sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)
|
||
|
)
|
||
|
{
|
||
|
// Do any channel specific stuff here.
|
||
|
//
|
||
|
|
||
|
return CMiniportWaveCyclicMSVAD::ValidatePcm(pWfx);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DPF(D_TERSE, ("Invalid PCM format"));
|
||
|
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
} // ValidateWfxExtPcm
|
||
|
|
||
|
//=============================================================================
|
||
|
// CMiniportWaveStreamCyclicSimple
|
||
|
//=============================================================================
|
||
|
|
||
|
//=============================================================================
|
||
|
CMiniportWaveCyclicStream::~CMiniportWaveCyclicStream
|
||
|
(
|
||
|
void
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Destructor for wavecyclicstream
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
DPF_ENTER(("[CMiniportWaveCyclicStream::~CMiniportWaveCyclicStream]"));
|
||
|
|
||
|
if (NULL != m_pMiniportLocal)
|
||
|
{
|
||
|
if (m_fCapture)
|
||
|
{
|
||
|
m_pMiniportLocal->m_fCaptureAllocated = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pMiniportLocal->m_fRenderAllocated = FALSE;
|
||
|
}
|
||
|
}
|
||
|
} // ~CMiniportWaveCyclicStream
|
||
|
|
||
|
//=============================================================================
|
||
|
NTSTATUS
|
||
|
CMiniportWaveCyclicStream::Init
|
||
|
(
|
||
|
IN PCMiniportWaveCyclic Miniport_,
|
||
|
IN ULONG Pin_,
|
||
|
IN BOOLEAN Capture_,
|
||
|
IN PKSDATAFORMAT DataFormat_
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initializes the stream object. Allocate a DMA buffer, timer and DPC
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Miniport_ -
|
||
|
|
||
|
Pin_ -
|
||
|
|
||
|
Capture_ -
|
||
|
|
||
|
DataFormat -
|
||
|
|
||
|
DmaChannel_ -
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
m_pMiniportLocal = Miniport_;
|
||
|
|
||
|
return
|
||
|
CMiniportWaveCyclicStreamMSVAD::Init
|
||
|
(
|
||
|
Miniport_,
|
||
|
Pin_,
|
||
|
Capture_,
|
||
|
DataFormat_
|
||
|
);
|
||
|
} // Init
|
||
|
|
||
|
//=============================================================================
|
||
|
STDMETHODIMP_(NTSTATUS)
|
||
|
CMiniportWaveCyclicStream::NonDelegatingQueryInterface
|
||
|
(
|
||
|
IN REFIID Interface,
|
||
|
OUT PVOID * Object
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
QueryInterface
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Interface - GUID
|
||
|
|
||
|
Object - interface pointer to be returned
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PAGED_CODE();
|
||
|
|
||
|
ASSERT(Object);
|
||
|
|
||
|
if (IsEqualGUIDAligned(Interface, IID_IUnknown))
|
||
|
{
|
||
|
*Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
|
||
|
}
|
||
|
else if (IsEqualGUIDAligned(Interface, IID_IMiniportWaveCyclicStream))
|
||
|
{
|
||
|
*Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this));
|
||
|
}
|
||
|
else if (IsEqualGUIDAligned(Interface, IID_IDmaChannel))
|
||
|
{
|
||
|
*Object = PVOID(PDMACHANNEL(this));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*Object = NULL;
|
||
|
}
|
||
|
|
||
|
if (*Object)
|
||
|
{
|
||
|
PUNKNOWN(*Object)->AddRef();
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
} // NonDelegatingQueryInterface
|
||
|
#pragma code_seg()
|
||
|
|