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.
 
 
 
 
 
 

495 lines
12 KiB

//******************************************************************************
//
// Copyright (c) 1999-2000, Microsoft Corporation, All rights reserved
//
//*****************************************************************************
#include "precomp.h"
#include <stdio.h>
#include "ess.h"
#include "moniprov.h"
CMonitorProvider::CMonitorProvider(CLifeControl* pControl) : TUnkBase(pControl),
m_pNamespace(NULL), m_pSink(NULL), m_pAssertClass(NULL), m_pRetractClass(NULL), m_pGoingUpClass(NULL), m_pGoingDownClass(NULL), m_pErrorClass( NULL )
{
}
CMonitorProvider::~CMonitorProvider()
{
Shutdown();
if(m_pNamespace)
m_pNamespace->Release();
if(m_pSink)
m_pSink->Release();
if( m_pAssertClass )
{
m_pAssertClass->Release();
}
if ( m_pRetractClass )
{
m_pRetractClass->Release();
}
if ( m_pGoingUpClass )
{
m_pGoingUpClass->Release();
}
if ( m_pGoingDownClass )
{
m_pGoingDownClass->Release();
}
if ( m_pErrorClass )
{
m_pErrorClass->Release();
}
}
HRESULT CMonitorProvider::Shutdown()
{
CInCritSec ics(&m_cs);
for(TIterator it = m_mapMonitors.begin(); it != m_mapMonitors.end(); it++)
{
delete it->second;
}
m_mapMonitors.clear();
return WBEM_S_NO_ERROR;
}
HRESULT CMonitorProvider::SetNamespace(CEssNamespace* pNamespace)
{
m_pNamespace = pNamespace;
m_pNamespace->AddRef();
//
// Retrieve system classes from the namespace
//
if(FAILED(m_pNamespace->GetClass(ASSERT_EVENT_CLASS, &m_pAssertClass)))
return WBEM_E_CRITICAL_ERROR;
if(FAILED(m_pNamespace->GetClass(RETRACT_EVENT_CLASS, &m_pRetractClass)))
return WBEM_E_CRITICAL_ERROR;
if(FAILED(m_pNamespace->GetClass(GOINGUP_EVENT_CLASS, &m_pGoingUpClass)))
return WBEM_E_CRITICAL_ERROR;
if(FAILED(m_pNamespace->GetClass(GOINGDOWN_EVENT_CLASS, &m_pGoingDownClass)))
return WBEM_E_CRITICAL_ERROR;
if(FAILED(m_pNamespace->GetClass(MONITORERROR_EVENT_CLASS, &m_pErrorClass)))
return WBEM_E_CRITICAL_ERROR;
//
// Retrieve handle values
//
m_pAssertClass->GetPropertyHandleEx(MONITORNAME_EVENT_PROPNAME,
0, NULL, &m_lNameHandle);
m_pAssertClass->GetPropertyHandleEx(MONITOROBJECT_EVENT_PROPNAME,
0, NULL, &m_lObjectHandle);
m_pAssertClass->GetPropertyHandleEx(MONITORCOUNT_EVENT_PROPNAME,
0, NULL, &m_lCountHandle);
m_pAssertClass->GetPropertyHandleEx(MONITORNEW_EVENT_PROPNAME,
0, NULL, &m_lNewHandle);
return S_OK;
}
STDMETHODIMP CMonitorProvider::ProvideEvents(IWbemObjectSink* pSink,
long lFlags)
{
return pSink->QueryInterface(IID_IWbemEventSink, (void**)&m_pSink);
}
HRESULT CMonitorProvider::AddMonitor(LPCWSTR wszName, LPCWSTR wszQuery,
long lFlags, IWbemContext* pContext)
{
HRESULT hres;
CMonitor* pMonitor = new CMonitor;
if(pMonitor == NULL)
return WBEM_E_OUT_OF_MEMORY;
CFiringMonitorCallback* pCallback =
new CFiringMonitorCallback(this, wszName);
if(pCallback == NULL || pCallback->GetName() == NULL)
return WBEM_E_OUT_OF_MEMORY;
pCallback->AddRef();
CTemplateReleaseMe<CFiringMonitorCallback> rm1(pCallback);
hres = pCallback->Initialize();
if(FAILED(hres))
{
delete pMonitor;
return hres;
}
hres = pMonitor->Construct(m_pNamespace, pCallback, wszQuery);
if(FAILED(hres))
{
delete pMonitor;
return hres;
}
//
// Attempt to start the monitor. TBD: consider monitor's guard
//
hres = pMonitor->Start(pContext);
if(FAILED(hres))
{
//
// Could not start monitor --- depending on whether strong validation
// is required, remove the monitor or keep it inactive
//
if(lFlags & WBEM_FLAG_STRONG_VALIDATION)
{
delete pMonitor;
return hres;
}
}
//
// Add the monitor to the list, active or not
//
{
CInCritSec ics(&m_cs);
m_mapMonitors[wszName] = pMonitor;
}
return hres;
}
HRESULT CMonitorProvider::RemoveMonitor(LPCWSTR wszName, IWbemContext* pContext)
{
CInCritSec ics(&m_cs);
TIterator it = m_mapMonitors.find(wszName);
if(it == m_mapMonitors.end())
return WBEM_S_FALSE;
it->second->Stop(pContext);
delete it->second;
m_mapMonitors.erase(it);
return WBEM_S_NO_ERROR;
}
// static
HRESULT CMonitorProvider::GetMonitorInfo(IWbemClassObject* pMonitorObj,
BSTR* pstrKey, BSTR* pstrQuery, long* plFlags)
{
HRESULT hres;
if(pstrKey)
{
//
// Extract the relpath to use as the key
//
VARIANT v;
hres = pMonitorObj->Get(MONITOR_NAME_PROPNAME, 0, &v, NULL, NULL);
if(FAILED(hres))
{
ERRORTRACE((LOG_ESS, "Monitor without a path? Not valid\n"));
return hres;
}
if(V_VT(&v) != VT_BSTR)
return WBEM_E_CRITICAL_ERROR;
*pstrKey = V_BSTR(&v);
}
if(pstrQuery)
{
//
// Check query type
//
VARIANT vType;
VariantInit(&vType);
CClearMe cm1(&vType);
hres = pMonitorObj->Get(MONITOR_QUERYLANG_PROPNAME, 0, &vType, NULL,
NULL);
if(FAILED(hres))
{
ERRORTRACE((LOG_ESS, "Monitor without a query type? Not valid\n"));
return hres;
}
if(V_VT(&vType) != VT_BSTR)
{
ERRORTRACE((LOG_ESS, "Monitor without a query type? Not valid\n"));
return WBEM_E_INVALID_OBJECT;
}
if(wbem_wcsicmp(V_BSTR(&vType), L"WQL"))
{
ERRORTRACE((LOG_ESS, "Monitor with invalid query type %S is "
"rejected\n", V_BSTR(&vType)));
return hres;
}
//
// Extract the query
//
VARIANT v;
hres = pMonitorObj->Get(MONITOR_QUERY_PROPNAME, 0, &v, NULL, NULL);
if(FAILED(hres))
{
ERRORTRACE((LOG_ESS, "Monitor without a name? Not valid\n"));
return hres;
}
if(V_VT(&v) != VT_BSTR)
return hres;
*pstrQuery = V_BSTR(&v);
}
if(plFlags)
{
//
// TBD: no flags for now
//
*plFlags = 0;
}
return WBEM_S_NO_ERROR;
}
HRESULT CMonitorProvider::ConstructAssert(LPCWSTR wszName, _IWmiObject* pObj,
bool bEvent,
DWORD dwTotalCount, _IWmiObject** ppEvent)
{
HRESULT hres;
hres = GetInstance(m_pAssertClass, wszName, dwTotalCount, ppEvent);
if(FAILED(hres))
return hres;
hres = SetObject(*ppEvent, pObj, bEvent);
if(FAILED(hres))
(*ppEvent)->Release();
return hres;
}
HRESULT CMonitorProvider::ConstructRetract(LPCWSTR wszName, _IWmiObject* pObj, bool bEvent,
DWORD dwTotalCount, _IWmiObject** ppEvent)
{
HRESULT hres;
hres = GetInstance(m_pRetractClass, wszName, dwTotalCount, ppEvent);
if(FAILED(hres))
return hres;
hres = SetObject(*ppEvent, pObj, bEvent);
if(FAILED(hres))
(*ppEvent)->Release();
return hres;
}
HRESULT CMonitorProvider::ConstructGoingUp(LPCWSTR wszName, DWORD dwNumMatching,
_IWmiObject** ppEvent)
{
return GetInstance(m_pGoingUpClass, wszName, dwNumMatching, ppEvent);
}
HRESULT CMonitorProvider::ConstructGoingDown(LPCWSTR wszName, DWORD dwNumMatching,
_IWmiObject** ppEvent)
{
return GetInstance(m_pGoingDownClass, wszName, dwNumMatching, ppEvent);
}
HRESULT CMonitorProvider::ConstructError(LPCWSTR wszName, HRESULT hresError,
IWbemClassObject* pErrorObj,
_IWmiObject** ppEvent)
{
return GetInstance(m_pErrorClass, wszName, 0, ppEvent);
}
HRESULT CMonitorProvider::GetInstance(_IWmiObject* pClass, LPCWSTR wszName, DWORD dwCount,
_IWmiObject** ppEvent)
{
if(pClass == NULL)
return WBEM_E_CRITICAL_ERROR;
HRESULT hres;
IWbemClassObject* pEvent = NULL;
hres = pClass->SpawnInstance(0, &pEvent);
if(FAILED(hres))
return hres;
pEvent->QueryInterface(IID__IWmiObject, (void**)ppEvent);
pEvent->Release();
hres = (*ppEvent)->SetPropByHandle(m_lCountHandle, 0, sizeof(DWORD),
&dwCount);
if(FAILED(hres))
{
(*ppEvent)->Release();
return hres;
}
hres = (*ppEvent)->SetPropByHandle(m_lNameHandle, 0,
wcslen(wszName)*2+2, (LPVOID)wszName);
if(FAILED(hres))
{
(*ppEvent)->Release();
return hres;
}
return WBEM_S_NO_ERROR;
}
HRESULT CMonitorProvider::SetObject(_IWmiObject* pEvent, _IWmiObject* pObj,
bool bFromEvent)
{
HRESULT hres;
hres = pEvent->SetPropByHandle(m_lObjectHandle, 0, sizeof(_IWmiObject*),
&pObj);
if(FAILED(hres))
return hres;
short bNew = (bFromEvent?-1:0);
hres = pEvent->SetPropByHandle(m_lNewHandle, 0, sizeof(short), &bNew);
if(FAILED(hres))
return hres;
return WBEM_S_NO_ERROR;
}
CFiringMonitorCallback::CFiringMonitorCallback(CMonitorProvider* pProvider,
LPCWSTR wszName)
: m_pProvider(pProvider), m_wsName(wszName), m_pSink(NULL), m_lRef(0)
{
if(m_pProvider)
m_pProvider->AddRef();
}
CFiringMonitorCallback::~CFiringMonitorCallback()
{
if(m_pProvider)
m_pProvider->Release();
if(m_pSink)
m_pSink->Release();
}
ULONG STDMETHODCALLTYPE CFiringMonitorCallback::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
ULONG STDMETHODCALLTYPE CFiringMonitorCallback::Release()
{
long lRef = InterlockedIncrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
HRESULT CFiringMonitorCallback::Initialize()
{
//
// Get us a restricted sink for our key. TBD
//
m_pSink = m_pProvider->GetSink();
m_pSink->AddRef();
return S_OK;
}
bool CFiringMonitorCallback::CheckSink()
{
return (m_pSink && (m_pSink->IsActive() == WBEM_S_NO_ERROR));
}
HRESULT CFiringMonitorCallback::FireEvent(_IWmiObject* pEvent)
{
return m_pSink->Indicate(1, (IWbemClassObject**)&pEvent);
}
HRESULT CFiringMonitorCallback::Assert(_IWmiObject* pObj, LPCWSTR wszPath,
bool bEvent, DWORD dwTotalCount)
{
if(!CheckSink())
return WBEM_S_FALSE;
HRESULT hres;
_IWmiObject* pEvent = NULL;
hres = m_pProvider->ConstructAssert(m_wsName, pObj, bEvent, dwTotalCount, &pEvent);
if(FAILED(hres))
return hres;
CReleaseMe rm(pEvent);
return FireEvent(pEvent);
}
HRESULT CFiringMonitorCallback::Retract(_IWmiObject* pObj, LPCWSTR wszPath,
bool bEvent, DWORD dwTotalCount)
{
if(!CheckSink())
return WBEM_S_FALSE;
HRESULT hres;
_IWmiObject* pEvent = NULL;
hres = m_pProvider->ConstructRetract(m_wsName, pObj, bEvent, dwTotalCount, &pEvent);
if(FAILED(hres))
return hres;
CReleaseMe rm(pEvent);
return FireEvent(pEvent);
}
HRESULT CFiringMonitorCallback::GoingUp(DWORD dwNumMatching)
{
if(!CheckSink())
return WBEM_S_FALSE;
HRESULT hres;
_IWmiObject* pEvent = NULL;
hres = m_pProvider->ConstructGoingUp(m_wsName, dwNumMatching, &pEvent);
if(FAILED(hres))
return hres;
CReleaseMe rm(pEvent);
return FireEvent(pEvent);
}
HRESULT CFiringMonitorCallback::GoingDown(DWORD dwNumMatching)
{
if(!CheckSink())
return WBEM_S_FALSE;
HRESULT hres;
_IWmiObject* pEvent = NULL;
hres = m_pProvider->ConstructGoingDown(m_wsName, dwNumMatching, &pEvent);
if(FAILED(hres))
return hres;
CReleaseMe rm(pEvent);
return FireEvent(pEvent);
}
HRESULT CFiringMonitorCallback::Error(HRESULT hresError,
IWbemClassObject* pErrorObj)
{
if(!CheckSink())
return WBEM_S_FALSE;
HRESULT hres;
_IWmiObject* pEvent = NULL;
hres = m_pProvider->ConstructError(m_wsName, hresError, pErrorObj, &pEvent);
if(FAILED(hres))
return hres;
CReleaseMe rm(pEvent);
return FireEvent(pEvent);
}