mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 03:27:31 +00:00
403 lines
10 KiB
C++
403 lines
10 KiB
C++
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS BDA Proxy
|
|
* FILE: dll/directx/bdaplgin/pincontrol.cpp
|
|
* PURPOSE: ClassFactory interface
|
|
*
|
|
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifndef _MSC_VER
|
|
const GUID KSPROPSETID_BdaPinControl = {0x0ded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}};
|
|
const GUID IID_IBDA_PinControl = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}};
|
|
const GUID IID_IPin = {0x56a86891, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
|
|
#endif
|
|
|
|
|
|
class CBDAPinControl : public IBDA_PinControl
|
|
{
|
|
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;
|
|
}
|
|
// IBDA_PinControl methods
|
|
HRESULT STDMETHODCALLTYPE GetPinID(ULONG *pulPinID);
|
|
HRESULT STDMETHODCALLTYPE GetPinType(ULONG *pulPinType);
|
|
HRESULT STDMETHODCALLTYPE RegistrationContext(ULONG *pulRegistrationCtx);
|
|
|
|
|
|
CBDAPinControl(HANDLE hFile, IBDA_NetworkProvider * pProvider, IPin * pConnectedPin, ULONG RegistrationCtx) : m_Ref(0), m_Handle(hFile), m_pProvider(pProvider), m_pConnectedPin(pConnectedPin), m_RegistrationCtx(RegistrationCtx){};
|
|
virtual ~CBDAPinControl()
|
|
{
|
|
//m_pConnectedPin->Release();
|
|
//m_pProvider->Release();
|
|
};
|
|
|
|
protected:
|
|
LONG m_Ref;
|
|
HANDLE m_Handle;
|
|
IBDA_NetworkProvider * m_pProvider;
|
|
IPin * m_pConnectedPin;
|
|
ULONG m_RegistrationCtx;
|
|
};
|
|
|
|
HRESULT
|
|
STDMETHODCALLTYPE
|
|
CBDAPinControl::QueryInterface(
|
|
IN REFIID refiid,
|
|
OUT PVOID* Output)
|
|
{
|
|
*Output = NULL;
|
|
if (IsEqualGUID(refiid, IID_IUnknown))
|
|
{
|
|
*Output = PVOID(this);
|
|
reinterpret_cast<IUnknown*>(*Output)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
if (IsEqualGUID(refiid, IID_IBDA_PinControl))
|
|
{
|
|
*Output = (IBDA_PinControl*)(this);
|
|
reinterpret_cast<IBDA_PinControl*>(*Output)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
DebugBreak();
|
|
return E_NOINTERFACE;
|
|
}
|
|
//-------------------------------------------------------------------
|
|
// IBDA_PinControl methods
|
|
//
|
|
HRESULT
|
|
STDMETHODCALLTYPE
|
|
CBDAPinControl::GetPinID(ULONG *pulPinID)
|
|
{
|
|
KSPROPERTY Property;
|
|
ULONG BytesReturned;
|
|
HRESULT hr;
|
|
|
|
// setup request
|
|
Property.Set = KSPROPSETID_BdaPinControl;
|
|
Property.Id = KSPROPERTY_BDA_PIN_ID;
|
|
Property.Flags = KSPROPERTY_TYPE_GET;
|
|
|
|
// perform request
|
|
hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinID, sizeof(ULONG), &BytesReturned);
|
|
|
|
#ifdef BDAPLGIN_TRACE
|
|
WCHAR Buffer[100];
|
|
swprintf(Buffer, L"CBDAPinControl::GetPinID: hr %lx pulPinID %lu BytesReturned %lx\n", hr, *pulPinID, BytesReturned);
|
|
OutputDebugStringW(Buffer);
|
|
#endif
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
STDMETHODCALLTYPE
|
|
CBDAPinControl::GetPinType(ULONG *pulPinType)
|
|
{
|
|
KSPROPERTY Property;
|
|
ULONG BytesReturned;
|
|
HRESULT hr;
|
|
|
|
// setup request
|
|
Property.Set = KSPROPSETID_BdaPinControl;
|
|
Property.Id = KSPROPERTY_BDA_PIN_TYPE;
|
|
Property.Flags = KSPROPERTY_TYPE_GET;
|
|
|
|
// perform request
|
|
hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinType, sizeof(ULONG), &BytesReturned);
|
|
|
|
#ifdef BDAPLGIN_TRACE
|
|
WCHAR Buffer[100];
|
|
swprintf(Buffer, L"CBDAPinControl::GetPinType: hr %lx pulPinType %lu BytesReturned %lx\n", hr, *pulPinType, BytesReturned);
|
|
OutputDebugStringW(Buffer);
|
|
#endif
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
STDMETHODCALLTYPE
|
|
CBDAPinControl::RegistrationContext(ULONG *pulRegistrationCtx)
|
|
{
|
|
#ifdef BDAPLGIN_TRACE
|
|
OutputDebugStringW(L"CBDAPinControl::RegistrationContext\n");
|
|
#endif
|
|
|
|
if (!pulRegistrationCtx)
|
|
{
|
|
// invalid argument
|
|
return E_POINTER;
|
|
}
|
|
|
|
if (m_RegistrationCtx)
|
|
{
|
|
// is registered
|
|
*pulRegistrationCtx = m_RegistrationCtx;
|
|
return NOERROR;
|
|
}
|
|
|
|
//pin not registered
|
|
return E_FAIL;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
HRESULT
|
|
GetNetworkProviderFromGraph(
|
|
IFilterGraph * pGraph,
|
|
IBDA_NetworkProvider ** pOutNetworkProvider)
|
|
{
|
|
IEnumFilters *pEnumFilters = NULL;
|
|
IBaseFilter * ppFilter[1];
|
|
IBDA_NetworkProvider * pNetworkProvider = NULL;
|
|
HRESULT hr;
|
|
|
|
// get IEnumFilters interface
|
|
hr = pGraph->EnumFilters(&pEnumFilters);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//clean up
|
|
*pOutNetworkProvider = NULL;
|
|
return hr;
|
|
}
|
|
|
|
while(pEnumFilters->Next(1, ppFilter, NULL) == S_OK)
|
|
{
|
|
// check if that filter supports the IBDA_NetworkProvider interface
|
|
hr = ppFilter[0]->QueryInterface(IID_IBDA_NetworkProvider, (void**)&pNetworkProvider);
|
|
|
|
// release IBaseFilter
|
|
ppFilter[0]->Release();
|
|
|
|
if (SUCCEEDED(hr))
|
|
break;
|
|
}
|
|
|
|
// release IEnumFilters interface
|
|
pEnumFilters->Release();
|
|
|
|
//store result
|
|
*pOutNetworkProvider = pNetworkProvider;
|
|
|
|
if (pNetworkProvider)
|
|
return S_OK;
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT
|
|
CBDAPinControl_RealConstructor(
|
|
HANDLE hPin,
|
|
IBDA_NetworkProvider *pNetworkProvider,
|
|
IPin * pConnectedPin,
|
|
ULONG RegistrationCtx,
|
|
IUnknown * pUnkOuter,
|
|
REFIID riid,
|
|
LPVOID * ppv)
|
|
{
|
|
CBDAPinControl * handler = new CBDAPinControl(hPin, pNetworkProvider, pConnectedPin, RegistrationCtx);
|
|
|
|
#ifdef BDAPLGIN_TRACE
|
|
OutputDebugStringW(L"CBDAPinControl_fnConstructor\n");
|
|
#endif
|
|
|
|
if (!handler)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (FAILED(handler->QueryInterface(riid, ppv)))
|
|
{
|
|
/* not supported */
|
|
delete handler;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
CBDAPinControl_fnConstructor(
|
|
IUnknown * pUnkOuter,
|
|
REFIID riid,
|
|
LPVOID * ppv)
|
|
{
|
|
IPin * pConnectedPin = NULL;
|
|
IBDA_NetworkProvider * pNetworkProvider = NULL;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HRESULT hr;
|
|
IKsObject * pObject = NULL;
|
|
IPin * pPin = NULL;
|
|
IUnknown * pUnknown = NULL;
|
|
PIN_INFO PinInfo;
|
|
FILTER_INFO FilterInfo;
|
|
ULONG RegistrationCtx = 0;
|
|
|
|
if (!pUnkOuter)
|
|
return E_POINTER;
|
|
|
|
OutputDebugStringW(L"CBDAPinControl_fnConstructor\n");
|
|
//DebugBreak();
|
|
|
|
// query for IKsObject interface
|
|
hr = pUnkOuter->QueryInterface(IID_IKsObject, (void**)&pObject);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// query for IPin interface
|
|
hr = pObject->QueryInterface(IID_IPin, (void**)&pPin);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//clean up
|
|
pObject->Release();
|
|
return hr;
|
|
}
|
|
|
|
// get pin info
|
|
hr = pPin->QueryPinInfo(&PinInfo);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
//clean up
|
|
pObject->Release();
|
|
pPin->Release();
|
|
return hr;
|
|
}
|
|
|
|
if (!PinInfo.pFilter)
|
|
{
|
|
//clean up
|
|
pObject->Release();
|
|
pPin->Release();
|
|
return hr;
|
|
}
|
|
|
|
// sanity checks
|
|
assert(PinInfo.pFilter != NULL);
|
|
|
|
// query filter info
|
|
hr = PinInfo.pFilter->QueryFilterInfo(&FilterInfo);
|
|
|
|
// sanity check
|
|
assert(FilterInfo.pGraph != NULL);
|
|
|
|
// get network provider interface
|
|
hr = GetNetworkProviderFromGraph(FilterInfo.pGraph, &pNetworkProvider);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (PinInfo.dir == PINDIR_OUTPUT)
|
|
{
|
|
// get connected pin handle
|
|
hr = pPin->ConnectedTo(&pConnectedPin);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// get file handle
|
|
hFile = pObject->KsGetObjectHandle();
|
|
if (hFile)
|
|
{
|
|
hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, pConnectedPin, 0, pUnkOuter, riid, ppv);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// set to null to prevent releasing
|
|
pNetworkProvider = NULL;
|
|
pConnectedPin = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// expected file handle
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// get IUnknown from base filter
|
|
hr = PinInfo.pFilter->QueryInterface(IID_IUnknown, (void**)&pUnknown);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// register device filter
|
|
OutputDebugStringW(L"CBDAPinControl_fnConstructor registering device filter with network provider\n");
|
|
hr = pNetworkProvider->RegisterDeviceFilter(pUnknown, &RegistrationCtx);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// get file handle
|
|
hFile = pObject->KsGetObjectHandle();
|
|
if (hFile)
|
|
{
|
|
hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, NULL, RegistrationCtx, pUnkOuter, riid, ppv);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// set to null to prevent releasing
|
|
pNetworkProvider = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// expected file handle
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WCHAR Buffer[100];
|
|
swprintf(Buffer, L"CBDAPinControl_fnConstructor failed to register filter with %lx\n", hr);
|
|
OutputDebugStringW(Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// release IFilterGraph interface
|
|
FilterInfo.pGraph->Release();
|
|
|
|
// release IBaseFilter interface
|
|
PinInfo.pFilter->Release();
|
|
|
|
// release IPin
|
|
pPin->Release();
|
|
|
|
// release IKsObject
|
|
pObject->Release();
|
|
|
|
|
|
if (pNetworkProvider)
|
|
{
|
|
// release network provider
|
|
pNetworkProvider->Release();
|
|
}
|
|
|
|
if (pConnectedPin)
|
|
{
|
|
// release connected pin
|
|
pConnectedPin->Release();
|
|
}
|
|
|
|
if (pUnknown)
|
|
{
|
|
// release filter
|
|
pUnknown->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|