758 lines
21 KiB
C++
758 lines
21 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mspterm.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implementations for the CBaseTerminal, CSingleFilterTerminal, and various
|
||
|
work item / worker thread classes.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
CBaseTerminal::CBaseTerminal()
|
||
|
: m_TerminalDirection(TD_CAPTURE)
|
||
|
, m_TerminalType(TT_STATIC)
|
||
|
, m_TerminalState(TS_NOTINUSE)
|
||
|
, m_TerminalClassID(CLSID_NULL)
|
||
|
, m_pFTM(NULL)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::CBaseTerminal() called"));
|
||
|
|
||
|
HRESULT hr = CoCreateFreeThreadedMarshaler(
|
||
|
GetControllingUnknown(), &m_pFTM);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::CBaseTerminal() - create ftm failed"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
CBaseTerminal::~CBaseTerminal()
|
||
|
{
|
||
|
if (NULL != m_pFTM)
|
||
|
{
|
||
|
m_pFTM->Release();
|
||
|
}
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::~CBaseTerminal() finished"));
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
//
|
||
|
// Dynamic terminals that support only one direction must override this to check
|
||
|
// if the direction is valid (although the terminal manager is supposed to
|
||
|
// ensure that the wrong direction is never passed). Dynamic terminal might want
|
||
|
// to override this for other reasons too (create filters now, etc.).
|
||
|
//
|
||
|
// Static terminals normally just call this in their CreateTerminal().
|
||
|
//
|
||
|
|
||
|
HRESULT CBaseTerminal::Initialize(
|
||
|
IN IID iidTerminalClass,
|
||
|
IN DWORD dwMediaType,
|
||
|
IN TERMINAL_DIRECTION Direction,
|
||
|
IN MSP_HANDLE htAddress
|
||
|
)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::Initialize - enter"));
|
||
|
|
||
|
//
|
||
|
// Check if the media type is supported by this terminal.
|
||
|
//
|
||
|
|
||
|
if ( ! MediaTypeSupported( (long) dwMediaType) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::Initialize - "
|
||
|
"media type not supported - returning E_INVALIDARG"));
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Save this configurarion.
|
||
|
//
|
||
|
|
||
|
m_dwMediaType = dwMediaType;
|
||
|
m_TerminalDirection = Direction;
|
||
|
m_TerminalClassID = iidTerminalClass;
|
||
|
m_htAddress = htAddress;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::Initialize - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_AddressHandle (
|
||
|
OUT MSP_HANDLE * phtAddress
|
||
|
)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_AddressHandle - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( phtAddress, sizeof(MSP_HANDLE) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_AddressHandle - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*phtAddress = m_htAddress;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_AddressHandle - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_Name(BSTR * pbsName)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_Name - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( pbsName, sizeof(BSTR) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_Name - "
|
||
|
"bad BSTR passed in - returning E_POINTER"));
|
||
|
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*pbsName = SysAllocString(m_szName);
|
||
|
|
||
|
if ( *pbsName == NULL )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_Name - "
|
||
|
"can't sysallocstring - returning E_OUTOFMEMORY"));
|
||
|
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_Name - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_State(TERMINAL_STATE * pVal)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_State - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( pVal, sizeof(TERMINAL_STATE) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_State - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*pVal = m_TerminalState;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_State - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_TerminalType(TERMINAL_TYPE * pVal)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_TerminalType - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( pVal, sizeof(TERMINAL_TYPE) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_TerminalType - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*pVal = m_TerminalType;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_TerminalType - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_TerminalClass(BSTR * pbsClassID)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_TerminalClass - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( pbsClassID, sizeof(BSTR) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_TerminalClass - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the CLSID to an OLE string.
|
||
|
//
|
||
|
|
||
|
LPOLESTR lposClass = NULL;
|
||
|
HRESULT hr = StringFromCLSID(m_TerminalClassID, &lposClass);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_TerminalClass (StringFromCLSID) - returning %8x", hr));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Put the string in a BSTR.
|
||
|
//
|
||
|
|
||
|
*pbsClassID = ::SysAllocString(lposClass);
|
||
|
|
||
|
//
|
||
|
// Free the OLE string.
|
||
|
//
|
||
|
|
||
|
::CoTaskMemFree(lposClass);
|
||
|
|
||
|
if (*pbsClassID == NULL)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_TerminalClass - returning E_OUTOFMEMORY"));
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_TerminalClass - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_Direction(
|
||
|
OUT TERMINAL_DIRECTION *pDirection
|
||
|
)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_Direction - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr( pDirection, sizeof(TERMINAL_DIRECTION) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_Direction - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*pDirection = m_TerminalDirection;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_Direction - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
// enters each of the internal filters into the filter graph
|
||
|
// connects the internal filters together (if applicable)
|
||
|
// and returns all the filters to be used as connection points
|
||
|
STDMETHODIMP CBaseTerminal::ConnectTerminal(
|
||
|
IN IGraphBuilder * pGraph,
|
||
|
IN DWORD dwTerminalDirection,
|
||
|
IN OUT DWORD * pdwNumPins,
|
||
|
OUT IPin ** ppPins
|
||
|
)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::ConnectTerminal - enter"));
|
||
|
|
||
|
//
|
||
|
// Check parameters.
|
||
|
//
|
||
|
|
||
|
if ( IsBadReadPtr(pGraph, sizeof(IGraphBuilder) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"bad graph pointer; exit E_POINTER"));
|
||
|
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr(pdwNumPins, sizeof(DWORD) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"bad numpins pointer; exit E_POINTER"));
|
||
|
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find out how many pins we expose. For most terminals this is
|
||
|
// straightforward but we pass in the graph pointer in case they
|
||
|
// need to do something funky to figure this out.
|
||
|
//
|
||
|
|
||
|
DWORD dwActualNumPins;
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = GetNumExposedPins(pGraph, &dwActualNumPins);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"GetNumExposedPins failed - exit 0x%08x", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If ppPins is NULL, just return the number of pins and don't try to
|
||
|
// connect the terminal.
|
||
|
//
|
||
|
|
||
|
if ( ppPins == NULL )
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::ConnectTerminal - "
|
||
|
"returned number of exposed pins - exit S_OK"));
|
||
|
|
||
|
*pdwNumPins = dwActualNumPins;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Otherwise, we have a pin return buffer. Check that the purported buffer
|
||
|
// size is big enough and that the buffer is actually writable to the size
|
||
|
// we need.
|
||
|
//
|
||
|
|
||
|
if ( *pdwNumPins < dwActualNumPins )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"not enough space to place pins; exit TAPI_E_NOTENOUGHMEMORY"));
|
||
|
|
||
|
*pdwNumPins = dwActualNumPins;
|
||
|
|
||
|
return TAPI_E_NOTENOUGHMEMORY;
|
||
|
}
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr(ppPins, dwActualNumPins * sizeof(IPin *) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"bad pins array pointer; exit E_POINTER"));
|
||
|
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if we're already connected, and if so, change our state to
|
||
|
// connected. Note that this makes sense for both core static terminals
|
||
|
// and dynamic terminals. Also note that we need to protect this with
|
||
|
// a critical section, but after this we can let go of the lock because
|
||
|
// anyone who subsequently enters the critical section will bail at this
|
||
|
// point.
|
||
|
//
|
||
|
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
//
|
||
|
// check if already connected
|
||
|
//
|
||
|
|
||
|
if (TS_INUSE == m_TerminalState)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"terminal already in use; exit TAPI_E_TERMINALINUSE"));
|
||
|
|
||
|
return TAPI_E_TERMINALINUSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Save important state.
|
||
|
//
|
||
|
|
||
|
m_pGraph = pGraph;
|
||
|
m_TerminalState = TS_INUSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
// add filters to the filter graph
|
||
|
hr = AddFiltersToGraph();
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"can't add filters to graph"));
|
||
|
goto disconnect_terminal;
|
||
|
}
|
||
|
|
||
|
// Give the terminal a chance to do any preconnection
|
||
|
hr = ConnectFilters();
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"can't do internal filter connection"));
|
||
|
goto disconnect_terminal;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the pins that this filter exposes. No need to pass in
|
||
|
// the filter graph because we already saved the graph pointer.
|
||
|
//
|
||
|
|
||
|
*pdwNumPins = dwActualNumPins;
|
||
|
hr = GetExposedPins(ppPins);
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::ConnectTerminal - "
|
||
|
"can't get exposed pins"));
|
||
|
goto disconnect_terminal;
|
||
|
}
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::ConnectTerminal success"));
|
||
|
return S_OK;
|
||
|
|
||
|
disconnect_terminal:
|
||
|
|
||
|
//
|
||
|
// best effort attempt to disconnect - ignore error code
|
||
|
//
|
||
|
|
||
|
DisconnectTerminal(pGraph, 0);
|
||
|
|
||
|
//
|
||
|
// Release our reference to the graph and set ourselves to notinuse state.
|
||
|
// DisconnectTerminal does this on success, but we need to make sure this
|
||
|
// cleanup happens even if DisconnectTerminal failed.
|
||
|
//
|
||
|
|
||
|
m_pGraph = NULL; // this releases the CComPtr
|
||
|
|
||
|
m_TerminalState = TS_NOTINUSE;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::ConnectTerminal - exit 0x%08x", hr));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CBaseTerminal::CompleteConnectTerminal(void)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::CompleteConnectTerminal - enter"));
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::CompleteConnectTerminal - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
// disconnects the internal filters from each other (if applicable)
|
||
|
// and removes them from the filter graph (thus breaking connections to
|
||
|
// the stream).
|
||
|
// Filter graph parameter is used for validation, to make sure the terminal
|
||
|
// is disconnected from the same graph that it was originally connected to.
|
||
|
|
||
|
|
||
|
STDMETHODIMP
|
||
|
CBaseTerminal::DisconnectTerminal(
|
||
|
IN IGraphBuilder * pGraph,
|
||
|
IN DWORD dwReserved
|
||
|
)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::DisconnectTerminal called"));
|
||
|
|
||
|
//
|
||
|
// If not in use, then there is nothing to be done.
|
||
|
//
|
||
|
|
||
|
if ( TS_INUSE != m_TerminalState )
|
||
|
{
|
||
|
_ASSERTE(m_pGraph == NULL);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::DisconnectTerminal success; not in use"));
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check that we are being disconnected from the correct graph.
|
||
|
//
|
||
|
if ( m_pGraph != pGraph )
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::DisconnectTerminal - "
|
||
|
"wrong graph; returning E_INVALIDARG"));
|
||
|
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Extra sanity check.
|
||
|
//
|
||
|
|
||
|
if ( m_pGraph == NULL )
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::DisconnectTerminal - "
|
||
|
"no graph; returning E_UNEXPECTED"));
|
||
|
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
//
|
||
|
// Remove filters from the graph
|
||
|
//
|
||
|
|
||
|
hr = RemoveFiltersFromGraph();
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::DisconnectTerminal - "
|
||
|
"remove filters from graph failed; returning 0x%08x", hr));
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Release our reference to the graph and set ourselves to notinuse state.
|
||
|
//
|
||
|
|
||
|
m_pGraph = NULL; // this releases the CComPtr
|
||
|
|
||
|
m_TerminalState = TS_NOTINUSE;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::DisconnectTerminal success"));
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
STDMETHODIMP CBaseTerminal::get_MediaType(long * plMediaType)
|
||
|
{
|
||
|
CLock lock(m_CritSec);
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_MediaType - enter"));
|
||
|
|
||
|
if ( MSPB_IsBadWritePtr(plMediaType, sizeof(long) ) )
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CBaseTerminal::get_MediaType - returning E_POINTER"));
|
||
|
return E_POINTER;
|
||
|
}
|
||
|
|
||
|
*plMediaType = (long) m_dwMediaType;
|
||
|
|
||
|
LOG((MSP_TRACE, "CBaseTerminal::get_MediaType - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
BOOL CBaseTerminal::MediaTypeSupported(long lMediaType)
|
||
|
{
|
||
|
return IsValidSingleMediaType( (DWORD) lMediaType,
|
||
|
GetSupportedMediaTypes() );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// CSingleFilterTerminal //
|
||
|
// //
|
||
|
// This is a base class for a terminal with a single filter and pin. The //
|
||
|
// terminal could be any direction or media type, and it could be static //
|
||
|
// or dynamic. //
|
||
|
// //
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
HRESULT CSingleFilterTerminal::GetNumExposedPins(
|
||
|
IN IGraphBuilder * pGraph,
|
||
|
OUT DWORD * pdwNumPins)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::GetNumExposedPins - enter"));
|
||
|
|
||
|
//
|
||
|
// We ignote pGraph because we don't need to do anything special to find
|
||
|
// out how many pins we have.
|
||
|
//
|
||
|
|
||
|
*pdwNumPins = 1;
|
||
|
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::GetNumExposedPins - exit S_OK"));
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
HRESULT CSingleFilterTerminal::GetExposedPins(
|
||
|
OUT IPin ** ppPins
|
||
|
)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::GetExposedPins - enter"));
|
||
|
|
||
|
_ASSERTE( ! MSPB_IsBadWritePtr(ppPins, 1 * sizeof(IPin *) ) );
|
||
|
|
||
|
//
|
||
|
// Return our single pin.
|
||
|
//
|
||
|
|
||
|
*ppPins = m_pIPin;
|
||
|
(*ppPins)->AddRef();
|
||
|
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::GetExposedPins - exit S_OK"));
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
// stops the rightmost render filter in the terminal
|
||
|
// (needed for dynamic filter graphs)
|
||
|
STDMETHODIMP CSingleFilterTerminal::RunRenderFilter(void)
|
||
|
{
|
||
|
// check that we're really a render filter
|
||
|
|
||
|
// tell our single filter to run
|
||
|
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
// stops the rightmost render filter in the terminal
|
||
|
// (needed for dynamic filter graphs)
|
||
|
STDMETHODIMP CSingleFilterTerminal::StopRenderFilter(void)
|
||
|
{
|
||
|
// check that we're really a render filter
|
||
|
|
||
|
// tell our single filter to stop
|
||
|
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
HRESULT
|
||
|
CSingleFilterTerminal::RemoveFiltersFromGraph(void)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::RemoveFiltersFromGraph - enter"));
|
||
|
|
||
|
if (m_pGraph == NULL)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CSingleFilterTerminal::RemoveFiltersFromGraph - "
|
||
|
"no graph; returning E_UNEXPECTED"));
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
if (m_pIFilter == NULL)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CSingleFilterTerminal::RemoveFiltersFromGraph - "
|
||
|
"no filter; returning E_UNEXPECTED"));
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Remove the filter from the graph. This also disconnects any connections
|
||
|
// the filter may have.
|
||
|
//
|
||
|
|
||
|
HRESULT hr = m_pGraph->RemoveFilter(m_pIFilter);
|
||
|
|
||
|
LOG((MSP_TRACE, "CSingleFilterTerminal::RemoveFiltersFromGraph - exit 0x%08x", hr));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
CSingleFilterStaticTerminal::CompareMoniker(
|
||
|
IMoniker *pMoniker
|
||
|
)
|
||
|
{
|
||
|
IMoniker *pReducedMoniker;
|
||
|
IMoniker *pReducedNewMoniker;
|
||
|
IBindCtx *pbc;
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = CreateBindCtx( 0, &pbc );
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CSingleFilterStaticTerminal::CompareMoniker - "
|
||
|
"unable to create bind context"));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = m_pMoniker->Reduce(pbc ,MKRREDUCE_ALL, NULL, &pReducedMoniker);
|
||
|
|
||
|
if (FAILED(hr) || !pReducedMoniker)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CSingleFilterStaticTerminal::CompareMoniker - "
|
||
|
"unable to reduce moniker"));
|
||
|
pbc->Release(); // release the bind context
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = pMoniker->Reduce(pbc ,MKRREDUCE_ALL, NULL, &pReducedNewMoniker);
|
||
|
|
||
|
if (FAILED(hr) || !pReducedNewMoniker)
|
||
|
{
|
||
|
LOG((MSP_ERROR, "CSingleFilterStaticTerminal::CompareMoniker - "
|
||
|
"unable to reduce moniker"));
|
||
|
pbc->Release(); // release the bind context
|
||
|
pReducedMoniker->Release(); // release the reduced moniker
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
pbc->Release(); // release the bind context
|
||
|
|
||
|
if (pReducedMoniker->IsEqual(pReducedNewMoniker) == S_OK)
|
||
|
{
|
||
|
LOG((MSP_TRACE, "CSingleFilterStaticTerminal::CompareMoniker - "
|
||
|
"exit - return S_OK"));
|
||
|
|
||
|
pReducedMoniker->Release(); // release the reduced monikers
|
||
|
pReducedNewMoniker->Release();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
pReducedMoniker->Release(); // release the reduced monikers
|
||
|
pReducedNewMoniker->Release();
|
||
|
|
||
|
LOG((MSP_TRACE, "CSingleFilterStaticTerminal::CompareMoniker - "
|
||
|
"exit - return S_FALSE"));
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
// eof
|