Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

758 lines
18 KiB

/*++
Copyright (C) Microsoft Corporation, 1997 - 1999
Module Name:
cpubfilt.cxx
Abstract:
This file contains the implementation of the PublisherFilter
for the ISensNetwork interface exposed by SENS.
Author:
Gopal Parupudi <GopalP>
[Notes:]
optional-notes
Revision History:
GopalP 1/26/1998 Start.
--*/
#include <precomp.hxx>
//
// Globals
//
LONG g_cFilterObj; // Count of active components
LONG g_cFilterLock; // Count of Server locks
//
// Constructors and Destructors
//
CImpISensNetworkFilter::CImpISensNetworkFilter(
void
) : m_cRef(1L), // Add a reference.
m_pConnectionMade_Enum(NULL),
m_pConnectionMadeNoQOC_Enum(NULL),
m_pConnectionLost_Enum(NULL),
m_pDestinationReachable_Enum(NULL),
m_pDestinationReachableNoQOC_Enum(NULL),
m_pConnectionMade_FiringControl(NULL),
m_pConnectionMadeNoQOC_FiringControl(NULL),
m_pConnectionLost_FiringControl(NULL),
m_pDestinationReachable_FiringControl(NULL),
m_pDestinationReachableNoQOC_FiringControl(NULL)
{
InterlockedIncrement(&g_cFilterObj);
}
CImpISensNetworkFilter::~CImpISensNetworkFilter(
void
)
{
InterlockedDecrement(&g_cFilterObj);
//
// Release all references that we added to IEnumEventObject pointers,
// if any.
//
if (m_pConnectionMade_Enum)
{
m_pConnectionMade_Enum->Release();
}
if (m_pConnectionMadeNoQOC_Enum)
{
m_pConnectionMadeNoQOC_Enum->Release();
}
if (m_pConnectionLost_Enum)
{
m_pConnectionLost_Enum->Release();
}
if (m_pDestinationReachable_Enum)
{
m_pDestinationReachable_Enum->Release();
}
if (m_pDestinationReachableNoQOC_Enum)
{
m_pDestinationReachableNoQOC_Enum->Release();
}
//
// Release all references that we added to IFiringControl pointers,
// if any (and there shouldn't be any).
//
if (m_pConnectionMade_FiringControl)
{
m_pConnectionMade_FiringControl->Release();
}
if (m_pConnectionMadeNoQOC_FiringControl)
{
m_pConnectionMadeNoQOC_FiringControl->Release();
}
if (m_pConnectionLost_FiringControl)
{
m_pConnectionLost_FiringControl->Release();
}
if (m_pDestinationReachable_FiringControl)
{
m_pDestinationReachable_FiringControl->Release();
}
if (m_pDestinationReachableNoQOC_FiringControl)
{
m_pDestinationReachableNoQOC_FiringControl->Release();
}
}
//
// Standard QueryInterface
//
STDMETHODIMP
CImpISensNetworkFilter::QueryInterface(
REFIID riid,
LPVOID *ppv
)
{
HRESULT hr;
DebugTraceGuid("CImpISensNetworkFilter:QueryInterface()", riid);
hr = S_OK;
*ppv = NULL;
// IUnknown
if (IsEqualIID(riid, IID_IUnknown))
{
*ppv = (ISensNetwork *) this;
}
else
// ISensNetwork
if (IsEqualIID(riid, IID_ISensNetwork))
{
*ppv = (ISensNetwork *) this;
}
else
// IPublisherFilter
if (IsEqualIID(riid, IID_IPublisherFilter))
{
*ppv = (IPublisherFilter *) this;
}
else
{
hr = E_NOINTERFACE;
}
if (NULL != *ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
}
return hr;
}
//
// IDispatch member function implementations. These are dummy implementations
// as EventSystem never calls them.
//
STDMETHODIMP
CImpISensNetworkFilter::GetTypeInfoCount(
UINT *pCountITypeInfo
)
{
return E_NOTIMPL;
}
STDMETHODIMP
CImpISensNetworkFilter::GetTypeInfo(
UINT iTypeInfo,
LCID lcid,
ITypeInfo **ppITypeInfo
)
{
return E_NOTIMPL;
}
STDMETHODIMP
CImpISensNetworkFilter::GetIDsOfNames(
REFIID riid,
LPOLESTR *arrNames,
UINT cNames,
LCID lcid,
DISPID *arrDispIDs)
{
return E_NOTIMPL;
}
STDMETHODIMP
CImpISensNetworkFilter::Invoke(
DISPID dispID,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pvarResult,
EXCEPINFO *pExecpInfo,
UINT *puArgErr
)
{
return E_NOTIMPL;
}
//
// Standard AddRef and Release
//
STDMETHODIMP_(ULONG)
CImpISensNetworkFilter::AddRef(
void
)
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG)
CImpISensNetworkFilter::Release(
void
)
{
LONG cRefT;
SensPrint(SENS_INFO, (SENS_STRING("\t| CImpISensNetworkFilter::Release(m_cRef = %d) called.\n"), m_cRef));
cRefT = InterlockedDecrement((PLONG) &m_cRef);
if (0 == m_cRef)
{
delete this;
}
return cRefT;
}
//
// ISensNetwork Implementation.
//
STDMETHODIMP
CImpISensNetworkFilter::ConnectionMade(
BSTR bstrConnection,
ULONG ulType,
LPSENS_QOCINFO lpQOCInfo
)
{
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
SensPrint(SENS_INFO, (SENS_STRING("CImpISensNetworkFilter::ConnectionMade() called\n\n")));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrConnection - %s\n"), bstrConnection));
SensPrint(SENS_INFO, (SENS_STRING(" ulType - 0x%x\n"), ulType));
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
HRESULT hr = S_OK;
ConnectionFilter filter(PROPERTY_CONNECTION_MADE_TYPE, ulType, hr);
if (SUCCEEDED(hr))
{
hr = FilterAndFire(
filter,
m_pConnectionMade_Enum,
m_pConnectionMade_FiringControl
);
}
// We're done with this IFiringControl object.
m_pConnectionMade_FiringControl->Release();
m_pConnectionMade_FiringControl = NULL;
return hr;
}
STDMETHODIMP
CImpISensNetworkFilter::ConnectionMadeNoQOCInfo(
BSTR bstrConnection,
ULONG ulType
)
{
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
SensPrint(SENS_INFO, (SENS_STRING("CImpISensNetworkFilter::ConnectionMadeNoQOCInfo() called\n\n")));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrConnection - %s\n"), bstrConnection));
SensPrint(SENS_INFO, (SENS_STRING(" ulType - 0x%x\n"), ulType));
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
HRESULT hr = S_OK;
ConnectionFilter filter(PROPERTY_CONNECTION_MADE_NOQOC_TYPE, ulType, hr);
if (SUCCEEDED(hr))
{
hr = FilterAndFire(
filter,
m_pConnectionMadeNoQOC_Enum,
m_pConnectionMadeNoQOC_FiringControl
);
}
// We're done with this IFiringControl object.
m_pConnectionMadeNoQOC_FiringControl->Release();
m_pConnectionMadeNoQOC_FiringControl = NULL;
return hr;
}
STDMETHODIMP
CImpISensNetworkFilter::ConnectionLost(
BSTR bstrConnection,
ULONG ulType
)
{
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
SensPrint(SENS_INFO, (SENS_STRING("CImpISensNetworkFilter::ConnectionLost() called\n\n")));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrConnection - %s\n"), bstrConnection));
SensPrint(SENS_INFO, (SENS_STRING(" ulType - 0x%x\n"), ulType));
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
HRESULT hr = S_OK;
ConnectionFilter filter(PROPERTY_CONNECTION_LOST_TYPE, ulType, hr);
if (SUCCEEDED(hr))
{
hr = FilterAndFire(
filter,
m_pConnectionLost_Enum,
m_pConnectionLost_FiringControl
);
}
// We're done with this IFiringControl object.
m_pConnectionLost_FiringControl->Release();
m_pConnectionLost_FiringControl = NULL;
return hr;
}
STDMETHODIMP
CImpISensNetworkFilter::DestinationReachable(
BSTR bstrDestination,
BSTR bstrConnection,
ULONG ulType,
LPSENS_QOCINFO lpQOCInfo
)
{
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
SensPrint(SENS_INFO, (SENS_STRING("CImpISensNetworkFilter::DestinationReachable() called\n\n")));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrDestination - %s\n"), bstrDestination));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrConnection - %s\n"), bstrConnection));
SensPrint(SENS_INFO, (SENS_STRING(" ulType - 0x%x\n"), ulType));
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
HRESULT hr = S_OK;
ReachabilityFilter filter(PROPERTY_DESTINATION, PROPERTY_DESTINATION_TYPE, bstrDestination, ulType, hr);
if (SUCCEEDED(hr))
{
hr = FilterAndFire(
filter,
m_pDestinationReachable_Enum,
m_pDestinationReachable_FiringControl
);
}
// We're done with this IFiringControl object.
m_pDestinationReachable_FiringControl->Release();
m_pDestinationReachable_FiringControl = NULL;
return hr;
}
STDMETHODIMP
CImpISensNetworkFilter::DestinationReachableNoQOCInfo(
BSTR bstrDestination,
BSTR bstrConnection,
ULONG ulType
)
{
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
SensPrint(SENS_INFO, (SENS_STRING("CImpISensNetworkFilter::DestinationReachableNoQOCInfo() called\n\n")));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrDestination - %s\n"), bstrDestination));
SensPrintW(SENS_INFO, (SENS_BSTR(" bstrConnection - %s\n"), bstrConnection));
SensPrint(SENS_INFO, (SENS_STRING(" ulType - 0x%x\n"), ulType));
SensPrint(SENS_INFO, (SENS_STRING("---------------------------------------------------------\n")));
HRESULT hr = S_OK;
ReachabilityFilter filter(PROPERTY_DESTINATION_NOQOC, PROPERTY_DESTINATION_NOQOC_TYPE, bstrDestination, ulType, hr);
if (SUCCEEDED(hr))
{
hr = FilterAndFire(
filter,
m_pDestinationReachableNoQOC_Enum,
m_pDestinationReachableNoQOC_FiringControl
);
}
// We're done with this IFiringControl object.
m_pDestinationReachableNoQOC_FiringControl->Release();
m_pDestinationReachableNoQOC_FiringControl = NULL;
return hr;
}
//
// IPublisherFilter Implementation.
//
STDMETHODIMP
CImpISensNetworkFilter::Initialize(
BSTR bstrMethodName,
IDispatch* dispUserDefined
)
{
HRESULT hr = E_INVALIDARG;
IEnumEventObject** ppEnum = NULL;
if (wcscmp(bstrMethodName, CONNECTION_MADE_METHOD) == 0)
{
ppEnum = &m_pConnectionMade_Enum;
}
else
if (wcscmp(bstrMethodName, CONNECTION_MADE_NOQOC_METHOD) == 0)
{
ppEnum = &m_pConnectionMadeNoQOC_Enum;
}
else
if (wcscmp(bstrMethodName, CONNECTION_LOST_METHOD) == 0)
{
ppEnum = &m_pConnectionLost_Enum;
}
else
if (wcscmp(bstrMethodName, DESTINATION_REACHABLE_METHOD) == 0)
{
ppEnum = &m_pDestinationReachable_Enum;
}
else
if (wcscmp(bstrMethodName, DESTINATION_REACHABLE_NOQOC_METHOD) == 0)
{
ppEnum = &m_pDestinationReachableNoQOC_Enum;
}
if (ppEnum != NULL)
{
IEventControl* control = NULL;
hr = dispUserDefined->QueryInterface(IID_IEventControl, (void**)&control);
if (FAILED(hr))
{
return hr;
}
IEventObjectCollection* collection = NULL;
hr = control->GetSubscriptions(bstrMethodName, NULL, NULL, &collection);
if (SUCCEEDED(hr))
{
hr = collection->get_NewEnum(ppEnum);
// Don't need the collection any more... just keep the enum
collection->Release();
}
control->Release();
}
return hr;
}
STDMETHODIMP
CImpISensNetworkFilter::PrepareToFire(
BSTR bstrMethodName,
IFiringControl* pIFiringControl
)
{
HRESULT hr = E_INVALIDARG;
IFiringControl** ppFiringControl = NULL;
if (wcscmp(bstrMethodName, CONNECTION_MADE_METHOD) == 0)
{
ppFiringControl = &m_pConnectionMade_FiringControl;
}
else
if (wcscmp(bstrMethodName, CONNECTION_MADE_NOQOC_METHOD) == 0)
{
ppFiringControl = &m_pConnectionMadeNoQOC_FiringControl;
}
else
if (wcscmp(bstrMethodName, CONNECTION_LOST_METHOD) == 0)
{
ppFiringControl = &m_pConnectionLost_FiringControl;
}
else
if (wcscmp(bstrMethodName, DESTINATION_REACHABLE_METHOD) == 0)
{
ppFiringControl = &m_pDestinationReachable_FiringControl;
}
else
if (wcscmp(bstrMethodName, DESTINATION_REACHABLE_NOQOC_METHOD) == 0)
{
ppFiringControl = &m_pDestinationReachableNoQOC_FiringControl;
}
if (ppFiringControl != NULL)
{
*ppFiringControl = pIFiringControl;
pIFiringControl->AddRef();
hr = S_OK;
}
return hr;
}
//
// Filter helper implementations.
//
//
// ConnectionFilter implementation.
//
ConnectionFilter::ConnectionFilter(
const wchar_t* connectionTypeProperty,
ULONG connectionType,
HRESULT& hr
) : m_connectionTypeProperty(SysAllocString(connectionTypeProperty)),
m_connectionType(connectionType)
{
if (m_connectionTypeProperty == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
hr = S_OK;
}
}
ConnectionFilter::~ConnectionFilter(
void
)
{
SysFreeString(m_connectionTypeProperty);
}
HRESULT
ConnectionFilter::CheckMatch(
IEventSubscription* pSubscription
) const
{
VARIANT value;
VariantInit(&value);
HRESULT hr = pSubscription->GetPublisherProperty(m_connectionTypeProperty, &value);
if (hr == S_FALSE)
{
// If the property isn't present, consider it a successful match.
hr = S_OK;
}
else
if (hr == S_OK)
{
// If the property is there, it must match the incoming parameter value.
ASSERT(value.vt == VT_UI4);
SensPrintW(SENS_INFO, (SENS_BSTR("\t| Property %s has value 0x%x\n"), m_connectionTypeProperty, value.ulVal));
hr = (m_connectionType == value.ulVal) ? S_OK : S_FALSE;
}
VariantClear(&value);
return hr;
}
//
// ReachabilityFilter implementation
//
ReachabilityFilter::ReachabilityFilter(
const wchar_t* destinationProperty,
const wchar_t* destinationTypeProperty,
BSTR destination,
ULONG destinationType,
HRESULT& hr
) : m_destinationProperty(SysAllocString(destinationProperty)),
m_destinationTypeProperty(SysAllocString(destinationTypeProperty)),
m_destination(destination),
m_destinationType(destinationType)
{
if (m_destinationProperty == NULL || m_destinationTypeProperty == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
hr = S_OK;
}
}
ReachabilityFilter::~ReachabilityFilter(
void
)
{
SysFreeString(m_destinationProperty);
SysFreeString(m_destinationTypeProperty);
}
HRESULT
ReachabilityFilter::CheckMatch(
IEventSubscription* pSubscription
) const
{
HRESULT hr;
// Check the destination property
VARIANT value;
VariantInit(&value);
hr = pSubscription->GetPublisherProperty(m_destinationProperty, &value);
if (hr == S_FALSE)
{
// If the property isn't present, consider it a successful match.
hr = S_OK;
SensPrintW(SENS_INFO, (SENS_BSTR("\t\t\t| Subscription (0x%x) has no %s Dest Property\n"), pSubscription, m_destinationProperty));
}
else
if (hr == S_OK)
{
// If the property is there, it must match the incoming parameter value.
ASSERT(value.vt == VT_BSTR);
SensPrintW(SENS_INFO, (SENS_BSTR("\t\t\t| Property %s has value %s\n"), m_destinationProperty, value.bstrVal));
hr = (wcscmp(m_destination, value.bstrVal) == 0) ? S_OK : S_FALSE;
}
VariantClear(&value);
if (hr == S_OK)
{
// If we have a match so far, check the destination type property
VARIANT value;
VariantInit(&value);
hr = pSubscription->GetPublisherProperty(m_destinationTypeProperty, &value);
if (hr == S_FALSE)
{
// If the property isn't present, consider it a successful match.
hr = S_OK;
SensPrintW(SENS_INFO, (SENS_BSTR("\t\t\t| Subscription (0x%x) has no %s Type Property\n"), pSubscription, m_destinationTypeProperty));
}
else
if (hr == S_OK)
{
// If the property is there, it must match the incoming parameter value.
ASSERT(value.vt == VT_UI4);
SensPrintW(SENS_INFO, (SENS_BSTR("\t\t\t| Property %s has value 0x%x\n"), m_destinationTypeProperty, value.ulVal));
hr = (m_destinationType == value.ulVal) ? S_OK : S_FALSE;
}
VariantClear(&value);
}
return hr;
}
//
// Generic filter and fire method.
//
HRESULT
FilterAndFire(
const Filter& filter,
IEnumEventObject* enumerator,
IFiringControl* firingControl
)
{
HRESULT hr;
IEventSubscription* pSubscription = NULL;
int i = 0;
//
// Reset the enum back to the start
//
hr = enumerator->Reset();
//
// Loop through all the candidate subscriptions and fire the ones
// that match the filter criteria.
//
for (;;)
{
ULONG cCount = 1;
hr = enumerator->Next(cCount, (IUnknown**)&pSubscription, &cCount);
if (hr != S_OK || cCount != 1)
{
break;
}
SensPrintA(SENS_INFO, ("\t\t\t| ****** Count for 0x%x is %d\n", enumerator, ++i));
hr = filter.CheckMatch(pSubscription);
if (hr == S_OK)
{
SensPrintA(SENS_INFO, ("\t\t\t| FilterAndFire(0x%x): CheckMatch() succeeded\n", enumerator));
firingControl->FireSubscription(pSubscription);
}
pSubscription->Release();
pSubscription = NULL;
}
//
// Cleanup, including any left-over stuff in case of premature exit from the loop.
//
if (pSubscription != NULL)
{
pSubscription->Release();
}
return S_OK;
}