//****************************************************************************** // // Copyright (c) 1999-2000, Microsoft Corporation, All rights reserved // //***************************************************************************** #include "precomp.h" #include #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 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); }