From 7fc6b68491ebbf838ef666efed32ded6fafd10ea Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Tue, 2 Mar 2010 20:18:29 +0000 Subject: [PATCH] [BDAPLGIN] - Set output variable to null to fixup lazy callers [KSPROXY] - Enumerate input / output pins and their names - Start implementing input / output pin - Implement IEnumPins interface for CKsProxy filter [MSDVBNP] - Fix a bug (IEnumPins::Next should increase reference count on pin) - Fix a bug (IPin::QueryFilterInfo should increase reference count on parent filter) - Reference leakage is now fixed svn path=/trunk/; revision=45768 --- reactos/dll/directx/bdaplgin/bdaplgin.cpp | 1 - .../dll/directx/bdaplgin/devicecontrol.cpp | 8 +- reactos/dll/directx/bdaplgin/pincontrol.cpp | 4 +- reactos/dll/directx/ksproxy/enumpins.cpp | 179 +++++++++++++ reactos/dll/directx/ksproxy/input_pin.cpp | 239 +++++++++++++++++ reactos/dll/directx/ksproxy/ksproxy.rbuild | 3 + reactos/dll/directx/ksproxy/output_pin.cpp | 242 ++++++++++++++++++ reactos/dll/directx/ksproxy/precomp.h | 27 ++ reactos/dll/directx/ksproxy/proxy.cpp | 227 +++++++++++++++- .../dll/directx/msdvbnp/enum_mediatypes.cpp | 2 +- reactos/dll/directx/msdvbnp/enumpins.cpp | 4 +- .../dll/directx/msdvbnp/networkprovider.cpp | 2 +- reactos/dll/directx/msdvbnp/pin.cpp | 5 +- reactos/dll/directx/msdvbnp/scanningtuner.cpp | 2 +- 14 files changed, 929 insertions(+), 16 deletions(-) create mode 100644 reactos/dll/directx/ksproxy/enumpins.cpp create mode 100644 reactos/dll/directx/ksproxy/input_pin.cpp create mode 100644 reactos/dll/directx/ksproxy/output_pin.cpp diff --git a/reactos/dll/directx/bdaplgin/bdaplgin.cpp b/reactos/dll/directx/bdaplgin/bdaplgin.cpp index ddc22972c36..39ddb8a2ccb 100644 --- a/reactos/dll/directx/bdaplgin/bdaplgin.cpp +++ b/reactos/dll/directx/bdaplgin/bdaplgin.cpp @@ -12,7 +12,6 @@ const GUID CBDADeviceControl_GUID = {STATIC_KSMETHODSETID_BdaChangeSync}; const GUID CBDAPinControl_GUID = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}}; - static INTERFACE_TABLE InterfaceTable[] = { {&CBDADeviceControl_GUID, CBDADeviceControl_fnConstructor}, diff --git a/reactos/dll/directx/bdaplgin/devicecontrol.cpp b/reactos/dll/directx/bdaplgin/devicecontrol.cpp index d44367f126e..661eba547a0 100644 --- a/reactos/dll/directx/bdaplgin/devicecontrol.cpp +++ b/reactos/dll/directx/bdaplgin/devicecontrol.cpp @@ -498,6 +498,10 @@ CBDADeviceControl_fnConstructor( IBaseFilter *pFilter = NULL; HANDLE hFile; +#ifdef BDAPLGIN_TRACE + OutputDebugStringW(L"CBDADeviceControl_fnConstructor\n"); +#endif + //DebugBreak(); // sanity check @@ -540,10 +544,6 @@ CBDADeviceControl_fnConstructor( // construct device control CBDADeviceControl * handler = new CBDADeviceControl(pUnkOuter, pFilter, hFile); -#ifdef BDAPLGIN_TRACE - OutputDebugStringW(L"CBDADeviceControl_fnConstructor\n"); -#endif - if (!handler) return E_OUTOFMEMORY; diff --git a/reactos/dll/directx/bdaplgin/pincontrol.cpp b/reactos/dll/directx/bdaplgin/pincontrol.cpp index 74e2398eb49..a5b99128b16 100644 --- a/reactos/dll/directx/bdaplgin/pincontrol.cpp +++ b/reactos/dll/directx/bdaplgin/pincontrol.cpp @@ -59,6 +59,7 @@ CBDAPinControl::QueryInterface( IN REFIID refiid, OUT PVOID* Output) { + *Output = NULL; if (IsEqualGUID(refiid, IID_IUnknown)) { *Output = PVOID(this); @@ -77,7 +78,6 @@ CBDAPinControl::QueryInterface( LPOLESTR lpstr; StringFromCLSID(refiid, &lpstr); swprintf(Buffer, L"CBDAPinControl::QueryInterface: NoInterface for %s", lpstr); - DebugBreak(); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); #endif @@ -290,6 +290,8 @@ CBDAPinControl_fnConstructor( OutputDebugStringW(L"CBDAPinControl_fnConstructor"); #endif + DebugBreak(); + if (!handler) return E_OUTOFMEMORY; diff --git a/reactos/dll/directx/ksproxy/enumpins.cpp b/reactos/dll/directx/ksproxy/enumpins.cpp new file mode 100644 index 00000000000..5d71d5355d2 --- /dev/null +++ b/reactos/dll/directx/ksproxy/enumpins.cpp @@ -0,0 +1,179 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Network Provider for MPEG2 based networks + * FILE: dll/directx/msdvbnp/enumpins.cpp + * PURPOSE: IEnumPins interface + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +class CEnumPins : public IEnumPins +{ +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; + } + + + HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched); + HRESULT STDMETHODCALLTYPE Skip(ULONG cPins); + HRESULT STDMETHODCALLTYPE Reset(); + HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum); + + CEnumPins(std::vector Pins) : m_Ref(0), m_Pins(Pins), m_Index(0){}; + virtual ~CEnumPins(){}; + +protected: + LONG m_Ref; + std::vector m_Pins; + ULONG m_Index; +}; + +HRESULT +STDMETHODCALLTYPE +CEnumPins::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + *Output = NULL; + if (IsEqualGUID(refiid, IID_IUnknown)) + { + *Output = PVOID(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + if (IsEqualGUID(refiid, IID_IEnumPins)) + { + *Output = (IEnumPins*)(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + + WCHAR Buffer[MAX_PATH]; + LPOLESTR lpstr; + StringFromCLSID(refiid, &lpstr); + swprintf(Buffer, L"CEnumPins::QueryInterface: NoInterface for %s\n", lpstr); + OutputDebugStringW(Buffer); + CoTaskMemFree(lpstr); + + return E_NOINTERFACE; +} + +HRESULT +STDMETHODCALLTYPE +CEnumPins::Next( + ULONG cPins, + IPin **ppPins, + ULONG *pcFetched) +{ + ULONG i = 0; + + if (!ppPins) + return E_POINTER; + + if (cPins > 1 && !pcFetched) + return E_INVALIDARG; + + WCHAR Buffer[MAX_PATH]; + swprintf(Buffer, L"CEnumPins::Next: this %p m_Index %lx cPins %u\n", this, m_Index, cPins); + OutputDebugStringW(Buffer); + + while(i < cPins) + { + if (m_Index + i >= m_Pins.size()) + break; + + ppPins[i] = m_Pins[m_Index + i]; + m_Pins[m_Index + i]->AddRef(); + + i++; + } + + if (pcFetched) + { + *pcFetched = i; + } + + m_Index += i; + OutputDebugStringW(L"CEnumPins::Next: done\n"); + if (i < cPins) + return S_FALSE; + else + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CEnumPins::Skip( + ULONG cPins) +{ + if (cPins + m_Index >= m_Pins.size()) + { + return S_FALSE; + } + + m_Index += cPins; + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CEnumPins::Reset() +{ + m_Index = 0; + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CEnumPins::Clone( + IEnumPins **ppEnum) +{ + OutputDebugStringW(L"CEnumPins::Clone : NotImplemented\n"); + return E_NOTIMPL; +} + +HRESULT +WINAPI +CEnumPins_fnConstructor( + std::vector Pins, + REFIID riid, + LPVOID * ppv) +{ + CEnumPins * handler = new CEnumPins(Pins); + +#ifdef MSDVBNP_TRACE + WCHAR Buffer[MAX_PATH]; + LPOLESTR lpstr; + StringFromCLSID(riid, &lpstr); + swprintf(Buffer, L"CEnumPins_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown); + OutputDebugStringW(Buffer); +#endif + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return NOERROR; +} \ No newline at end of file diff --git a/reactos/dll/directx/ksproxy/input_pin.cpp b/reactos/dll/directx/ksproxy/input_pin.cpp new file mode 100644 index 00000000000..03a97bad932 --- /dev/null +++ b/reactos/dll/directx/ksproxy/input_pin.cpp @@ -0,0 +1,239 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy + * FILE: dll/directx/ksproxy/input_cpp.cpp + * PURPOSE: InputPin of Proxy Filter + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +class CInputPin : public IPin +/* + public IQualityControl, + public IKsObject, + public IKsPinEx, + public IKsPinPipe, + public ISpecifyPropertyPages, + public IStreamBuilder, + public IKsPropertySet, + public IKsPinFactory, + public IKsControl, + public IKsAggregateControl +*/ +{ +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; + } + + //IPin methods + HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE Disconnect(); + HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); + HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); + HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); + HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); + HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); + HRESULT STDMETHODCALLTYPE EndOfStream(); + HRESULT STDMETHODCALLTYPE BeginFlush(); + HRESULT STDMETHODCALLTYPE EndFlush(); + HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + + CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName){}; + virtual ~CInputPin(){}; + +protected: + LONG m_Ref; + IBaseFilter * m_ParentFilter; + LPCWSTR m_PinName; +}; + +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + *Output = NULL; + if (IsEqualGUID(refiid, IID_IUnknown) || + IsEqualGUID(refiid, IID_IPin)) + { + *Output = PVOID(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + + WCHAR Buffer[MAX_PATH]; + LPOLESTR lpstr; + StringFromCLSID(refiid, &lpstr); + swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr); + OutputDebugStringW(Buffer); + CoTaskMemFree(lpstr); + + return E_NOINTERFACE; +} + +//------------------------------------------------------------------- +// IPin interface +// +HRESULT +STDMETHODCALLTYPE +CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"CInputPin::Connect called\n"); + return E_NOTIMPL; +} + +HRESULT +STDMETHODCALLTYPE +CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"CInputPin::ReceiveConnection called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::Disconnect( void) +{ + OutputDebugStringW(L"CInputPin::Disconnect called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::ConnectedTo(IPin **pPin) +{ + OutputDebugStringW(L"CInputPin::ConnectedTo called\n"); + return VFW_E_NOT_CONNECTED; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"CInputPin::ConnectionMediaType called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryPinInfo(PIN_INFO *pInfo) +{ + wcscpy(pInfo->achName, m_PinName); + pInfo->dir = PINDIR_INPUT; + pInfo->pFilter = m_ParentFilter; + m_ParentFilter->AddRef(); + + return S_OK; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryDirection(PIN_DIRECTION *pPinDir) +{ + if (pPinDir) + { + *pPinDir = PINDIR_INPUT; + return S_OK; + } + + return E_POINTER; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryId(LPWSTR *Id) +{ + *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); + if (!*Id) + return E_OUTOFMEMORY; + + wcscpy(*Id, m_PinName); + return S_OK; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryAccept(const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"CInputPin::QueryAccept called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) +{ + OutputDebugStringW(L"CInputPin::EnumMediaTypes called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) +{ + OutputDebugStringW(L"CInputPin::QueryInternalConnections called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::EndOfStream( void) +{ + OutputDebugStringW(L"CInputPin::EndOfStream called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::BeginFlush( void) +{ + OutputDebugStringW(L"CInputPin::BeginFlush called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::EndFlush( void) +{ + OutputDebugStringW(L"CInputPin::EndFlush called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + OutputDebugStringW(L"CInputPin::NewSegment called\n"); + return E_NOTIMPL; +} + +HRESULT +WINAPI +CInputPin_Constructor( + IBaseFilter * ParentFilter, + LPCWSTR PinName, + REFIID riid, + LPVOID * ppv) +{ + CInputPin * handler = new CInputPin(ParentFilter, PinName); + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return S_OK; +} diff --git a/reactos/dll/directx/ksproxy/ksproxy.rbuild b/reactos/dll/directx/ksproxy/ksproxy.rbuild index 76eb3aa8b20..4a4123061ca 100644 --- a/reactos/dll/directx/ksproxy/ksproxy.rbuild +++ b/reactos/dll/directx/ksproxy/ksproxy.rbuild @@ -26,9 +26,12 @@ cvpconfig.cpp cvpvbiconfig.cpp datatype.cpp + enumpins.cpp + input_pin.cpp interface.cpp ksproxy.cpp ksproxy.rc + output_pin.cpp proxy.cpp qualityforward.cpp diff --git a/reactos/dll/directx/ksproxy/output_pin.cpp b/reactos/dll/directx/ksproxy/output_pin.cpp new file mode 100644 index 00000000000..ba7b31bb131 --- /dev/null +++ b/reactos/dll/directx/ksproxy/output_pin.cpp @@ -0,0 +1,242 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy + * FILE: dll/directx/ksproxy/input_cpp.cpp + * PURPOSE: InputPin of Proxy Filter + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ +#include "precomp.h" + +class COutputPin : public IPin +/* + public IQualityControl, + public IKsObject, + public IKsPinEx, + public IKsPinPipe, + public ISpecifyPropertyPages, + public IStreamBuilder, + public IKsPropertySet, + public IKsPinFactory, + public IKsControl, + public IKsAggregateControl + public IMediaSeeking, + public IAMStreamConfig, + public IMemAllocatorNotifyCallbackTemp +*/ +{ +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; + } + + //IPin methods + HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE Disconnect(); + HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin); + HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); + HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); + HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); + HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); + HRESULT STDMETHODCALLTYPE EndOfStream(); + HRESULT STDMETHODCALLTYPE BeginFlush(); + HRESULT STDMETHODCALLTYPE EndFlush(); + HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + + COutputPin(IBaseFilter * ParentFilter, LPCWSTR PinName) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName){}; + virtual ~COutputPin(){}; + +protected: + LONG m_Ref; + IBaseFilter * m_ParentFilter; + LPCWSTR m_PinName; +}; + +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryInterface( + IN REFIID refiid, + OUT PVOID* Output) +{ + *Output = NULL; + if (IsEqualGUID(refiid, IID_IUnknown) || + IsEqualGUID(refiid, IID_IPin)) + { + *Output = PVOID(this); + reinterpret_cast(*Output)->AddRef(); + return NOERROR; + } + + WCHAR Buffer[MAX_PATH]; + LPOLESTR lpstr; + StringFromCLSID(refiid, &lpstr); + swprintf(Buffer, L"COutputPin::QueryInterface: NoInterface for %s\n", lpstr); + OutputDebugStringW(Buffer); + CoTaskMemFree(lpstr); + + return E_NOINTERFACE; +} + +//------------------------------------------------------------------- +// IPin interface +// +HRESULT +STDMETHODCALLTYPE +COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"COutputPin::Connect called\n"); + return E_NOTIMPL; +} + +HRESULT +STDMETHODCALLTYPE +COutputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"COutputPin::ReceiveConnection called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::Disconnect( void) +{ + OutputDebugStringW(L"COutputPin::Disconnect called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::ConnectedTo(IPin **pPin) +{ + OutputDebugStringW(L"COutputPin::ConnectedTo called\n"); + return VFW_E_NOT_CONNECTED; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"COutputPin::ConnectionMediaType called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryPinInfo(PIN_INFO *pInfo) +{ + wcscpy(pInfo->achName, m_PinName); + pInfo->dir = PINDIR_OUTPUT; + pInfo->pFilter = m_ParentFilter; + m_ParentFilter->AddRef(); + + return S_OK; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryDirection(PIN_DIRECTION *pPinDir) +{ + if (pPinDir) + { + *pPinDir = PINDIR_OUTPUT; + return S_OK; + } + + return E_POINTER; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryId(LPWSTR *Id) +{ + *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR)); + if (!*Id) + return E_OUTOFMEMORY; + + wcscpy(*Id, m_PinName); + return S_OK; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryAccept(const AM_MEDIA_TYPE *pmt) +{ + OutputDebugStringW(L"COutputPin::QueryAccept called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) +{ + OutputDebugStringW(L"COutputPin::EnumMediaTypes called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) +{ + OutputDebugStringW(L"COutputPin::QueryInternalConnections called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::EndOfStream( void) +{ + OutputDebugStringW(L"COutputPin::EndOfStream called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::BeginFlush( void) +{ + OutputDebugStringW(L"COutputPin::BeginFlush called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::EndFlush( void) +{ + OutputDebugStringW(L"COutputPin::EndFlush called\n"); + return E_NOTIMPL; +} +HRESULT +STDMETHODCALLTYPE +COutputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + OutputDebugStringW(L"COutputPin::NewSegment called\n"); + return E_NOTIMPL; +} + +HRESULT +WINAPI +COutputPin_Constructor( + IBaseFilter * ParentFilter, + LPCWSTR PinName, + REFIID riid, + LPVOID * ppv) +{ + COutputPin * handler = new COutputPin(ParentFilter, PinName); + + if (!handler) + return E_OUTOFMEMORY; + + if (FAILED(handler->QueryInterface(riid, ppv))) + { + /* not supported */ + delete handler; + return E_NOINTERFACE; + } + + return S_OK; +} diff --git a/reactos/dll/directx/ksproxy/precomp.h b/reactos/dll/directx/ksproxy/precomp.h index ceef173034d..6ddcd6e647a 100644 --- a/reactos/dll/directx/ksproxy/precomp.h +++ b/reactos/dll/directx/ksproxy/precomp.h @@ -97,3 +97,30 @@ CKsProxy_Constructor( IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); + +/* input_pin.cpp */ +HRESULT +WINAPI +CInputPin_Constructor( + IBaseFilter * ParentFilter, + LPCWSTR PinName, + REFIID riid, + LPVOID * ppv); + +/* output_pin.cpp */ +HRESULT +WINAPI +COutputPin_Constructor( + IBaseFilter * ParentFilter, + LPCWSTR PinName, + REFIID riid, + LPVOID * ppv); + +/* enumpins.cpp */ +HRESULT +WINAPI +CEnumPins_fnConstructor( + std::vector Pins, + REFIID riid, + LPVOID * ppv) +; \ No newline at end of file diff --git a/reactos/dll/directx/ksproxy/proxy.cpp b/reactos/dll/directx/ksproxy/proxy.cpp index 23b013fafea..f9713895167 100644 --- a/reactos/dll/directx/ksproxy/proxy.cpp +++ b/reactos/dll/directx/ksproxy/proxy.cpp @@ -36,6 +36,7 @@ class CKsProxy : public IBaseFilter, { public: typedef std::vectorProxyPluginVector; + typedef std::vector PinVector; STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); @@ -81,7 +82,7 @@ public: // IKsObject HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); - CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(0) {}; + CKsProxy() : m_Ref(0), m_pGraph(0), m_ReferenceClock(0), m_FilterState(State_Stopped), m_hDevice(0), m_Plugins(), m_Pins() {}; virtual ~CKsProxy() { if (m_hDevice) @@ -90,7 +91,11 @@ public: HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); - + HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins); + HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances); + HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow); + HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName); + HRESULT STDMETHODCALLTYPE CreatePins(); protected: LONG m_Ref; IFilterGraph *m_pGraph; @@ -98,6 +103,7 @@ protected: FILTER_STATE m_FilterState; HANDLE m_hDevice; ProxyPluginVector m_Plugins; + PinVector m_Pins; }; HRESULT @@ -291,6 +297,206 @@ CKsProxy::LoadProxyPlugins( return S_OK; } +HRESULT +STDMETHODCALLTYPE +CKsProxy::GetNumberOfPins( + PULONG NumPins) +{ + KSPROPERTY Property; + ULONG BytesReturned; + + // setup request + Property.Set = KSPROPSETID_Pin; + Property.Id = KSPROPERTY_PIN_CTYPES; + Property.Flags = KSPROPERTY_TYPE_GET; + + return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned); +} + +HRESULT +STDMETHODCALLTYPE +CKsProxy::GetPinInstanceCount( + ULONG PinId, + PKSPIN_CINSTANCES Instances) +{ + KSP_PIN Property; + ULONG BytesReturned; + + // setup request + Property.Property.Set = KSPROPSETID_Pin; + Property.Property.Id = KSPROPERTY_PIN_CINSTANCES; + Property.Property.Flags = KSPROPERTY_TYPE_GET; + Property.PinId = PinId; + Property.Reserved = 0; + + return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned); +} + +HRESULT +STDMETHODCALLTYPE +CKsProxy::GetPinDataflow( + ULONG PinId, + KSPIN_DATAFLOW * DataFlow) +{ + KSP_PIN Property; + ULONG BytesReturned; + + // setup request + Property.Property.Set = KSPROPSETID_Pin; + Property.Property.Id = KSPROPERTY_PIN_DATAFLOW; + Property.Property.Flags = KSPROPERTY_TYPE_GET; + Property.PinId = PinId; + Property.Reserved = 0; + + return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); +} + +HRESULT +STDMETHODCALLTYPE +CKsProxy::GetPinName( + ULONG PinId, + KSPIN_DATAFLOW DataFlow, + ULONG PinCount, + LPWSTR * OutPinName) +{ + KSP_PIN Property; + LPWSTR PinName; + ULONG BytesReturned; + HRESULT hr; + WCHAR Buffer[100]; + + // setup request + Property.Property.Set = KSPROPSETID_Pin; + Property.Property.Id = KSPROPERTY_PIN_NAME; + Property.Property.Flags = KSPROPERTY_TYPE_GET; + Property.PinId = PinId; + Property.Reserved = 0; + + // #1 try get it from pin directly + hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + + if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA)) + { + // allocate pin name + PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned); + if (!PinName) + return E_OUTOFMEMORY; + + // retry with allocated buffer + hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned); + if (SUCCEEDED(hr)) + { + *OutPinName = PinName; + return hr; + } + + //free buffer + CoTaskMemFree(PinName); + } + + // + // TODO: retrieve pin name from topology node + // + + if (DataFlow == KSPIN_DATAFLOW_IN) + { + swprintf(Buffer, L"Input%lu", PinCount); + } + else + { + swprintf(Buffer, L"Output%lu", PinCount); + } + + // allocate pin name + PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR)); + if (!PinName) + return E_OUTOFMEMORY; + + // copy pin name + wcscpy(PinName, Buffer); + + // store result + *OutPinName = PinName; + // done + return S_OK; +} + +HRESULT +STDMETHODCALLTYPE +CKsProxy::CreatePins() +{ + ULONG NumPins, Index; + KSPIN_CINSTANCES Instances; + KSPIN_DATAFLOW DataFlow; + HRESULT hr; + WCHAR Buffer[100]; + LPWSTR PinName; + IPin * pPin; + ULONG InputPin = 0; + ULONG OutputPin = 0; + + // get number of pins + hr = GetNumberOfPins(&NumPins); + if (FAILED(hr)) + return hr; + + for(Index = 0; Index < NumPins; Index++) + { + // query current instance count + hr = GetPinInstanceCount(Index, &Instances); + if (FAILED(hr)) + continue; + + if (Instances.CurrentCount == Instances.PossibleCount) + { + // already maximum reached for this pin + continue; + } + + // get direction of pin + hr = GetPinDataflow(Index, &DataFlow); + if (FAILED(hr)) + continue; + + if (DataFlow == KSPIN_DATAFLOW_IN) + hr = GetPinName(Index, DataFlow, InputPin, &PinName); + else + hr = GetPinName(Index, DataFlow, OutputPin, &PinName); + + if (FAILED(hr)) + continue; + + // construct the pins + if (DataFlow == KSPIN_DATAFLOW_IN) + { + hr = CInputPin_Constructor((IBaseFilter*)this, PinName, IID_IPin, (void**)&pPin); + if (FAILED(hr)) + { + CoTaskMemFree(PinName); + continue; + } + InputPin++; + } + else + { + hr = COutputPin_Constructor((IBaseFilter*)this, PinName, IID_IPin, (void**)&pPin); + if (FAILED(hr)) + { + CoTaskMemFree(PinName); + continue; + } + OutputPin++; + } + + // store pins + m_Pins.push_back(pPin); + + swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName); + OutputDebugStringW(Buffer); + } + + return S_OK; +} HRESULT STDMETHODCALLTYPE @@ -336,6 +542,19 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) // load all proxy plugins hr = LoadProxyPlugins(pGuid, NumGuids); + if (FAILED(hr)) + { + CloseHandle(m_hDevice); + m_hDevice = NULL; + return hr; + } + + // free sets + CoTaskMemFree(pGuid); + + // now create the input / output pins + hr = CreatePins(); + CloseHandle(m_hDevice); m_hDevice = NULL; @@ -438,8 +657,8 @@ STDMETHODCALLTYPE CKsProxy::EnumPins( IEnumPins **ppEnum) { - OutputDebugStringW(L"CKsProxy::EnumPins : NotImplemented\n"); - return E_NOTIMPL; + OutputDebugStringW(L"CKsProxy::EnumPins\n"); + return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum); } HRESULT diff --git a/reactos/dll/directx/msdvbnp/enum_mediatypes.cpp b/reactos/dll/directx/msdvbnp/enum_mediatypes.cpp index f1497ab737e..6cd887f358c 100644 --- a/reactos/dll/directx/msdvbnp/enum_mediatypes.cpp +++ b/reactos/dll/directx/msdvbnp/enum_mediatypes.cpp @@ -23,7 +23,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - //delete this; + delete this; return 0; } return m_Ref; diff --git a/reactos/dll/directx/msdvbnp/enumpins.cpp b/reactos/dll/directx/msdvbnp/enumpins.cpp index 3887be48a1f..567705907b7 100644 --- a/reactos/dll/directx/msdvbnp/enumpins.cpp +++ b/reactos/dll/directx/msdvbnp/enumpins.cpp @@ -23,7 +23,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - //delete this; + delete this; return 0; } return m_Ref; @@ -95,6 +95,8 @@ CEnumPins::Next( break; ppPins[i] = m_Pins[m_Index + i]; + m_Pins[m_Index + i]->AddRef(); + i++; } diff --git a/reactos/dll/directx/msdvbnp/networkprovider.cpp b/reactos/dll/directx/msdvbnp/networkprovider.cpp index 926a7516196..c69c2336e48 100644 --- a/reactos/dll/directx/msdvbnp/networkprovider.cpp +++ b/reactos/dll/directx/msdvbnp/networkprovider.cpp @@ -25,7 +25,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - //delete this; + delete this; return 0; } return m_Ref; diff --git a/reactos/dll/directx/msdvbnp/pin.cpp b/reactos/dll/directx/msdvbnp/pin.cpp index 52ce7ecb943..288a312dcc1 100644 --- a/reactos/dll/directx/msdvbnp/pin.cpp +++ b/reactos/dll/directx/msdvbnp/pin.cpp @@ -26,7 +26,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - //delete this; + delete this; return 0; } return m_Ref; @@ -137,6 +137,7 @@ CPin::QueryPinInfo(PIN_INFO *pInfo) wcscpy(pInfo->achName, PIN_ID); pInfo->dir = PINDIR_OUTPUT; pInfo->pFilter = m_ParentFilter; + m_ParentFilter->AddRef(); return S_OK; } @@ -182,7 +183,7 @@ CPin::EnumMediaTypes(IEnumMediaTypes **ppEnum) } MediaType->majortype = KSDATAFORMAT_TYPE_BDA_ANTENNA; - MediaType->subtype = GUID_NULL; + MediaType->subtype = MEDIASUBTYPE_None; MediaType->formattype = GUID_NULL; MediaType->bFixedSizeSamples = true; MediaType->bTemporalCompression = false; diff --git a/reactos/dll/directx/msdvbnp/scanningtuner.cpp b/reactos/dll/directx/msdvbnp/scanningtuner.cpp index bcedd51c239..0c9b7782d2b 100644 --- a/reactos/dll/directx/msdvbnp/scanningtuner.cpp +++ b/reactos/dll/directx/msdvbnp/scanningtuner.cpp @@ -23,7 +23,7 @@ public: InterlockedDecrement(&m_Ref); if (!m_Ref) { - //delete this; + delete this; return 0; } return m_Ref;