// Consumer.cpp: implementation of the CConsumer class. // // Copyright (c)1999-20000 Microsoft Corporation, All Rights Reserved ////////////////////////////////////////////////////////////////////// #define HM_AGENT_INTERVAL 1000 #include #include "hmagent.h" #include "system.h" #include "Consumer.h" #include #include "global.h" extern CSystem* g_pSystem; extern HANDLE g_hConfigLock; extern HANDLE g_hThrdDie; extern HANDLE g_hThrdDead; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CConsumer::CConsumer() { // one and only instance of Consumer. MY_OUTPUT(L"ENTER CConsumer::CConsumer()", 1); m_cRef = 1; m_uThrdId = 0; m_hUpdateThrdFn = NULL; // Set the polling interval. Default to 1 sec. if the value is invalid m_lAgentInterval = HM_AGENT_INTERVAL; // If this ever fails, the agent will not be able to do any work if( (m_hUpdateThrdFn = (HANDLE)_beginthreadex(NULL, 0, Update, this, 0, &m_uThrdId)) ==0) { OutputDebugString(L"_beginthreadex FAILED! HM agent inactive\n"); } MY_ASSERT(m_hUpdateThrdFn); } CConsumer::~CConsumer() { MY_OUTPUT(L"CConsumer::~CConsumer", 1); if(!SetEvent(g_hThrdDie)) { DWORD dwErr = GetLastError(); MY_OUTPUT(L"SetEvent for CConsumer failed with error ",dwErr); } // *** At this point, WBEM already terminated our thread. } // Static thread fuction to update data point. unsigned int __stdcall CConsumer::Update(void *pv) { CConsumer* pThis = (CConsumer*)pv; BOOL bRet = FALSE; while(1) { if (WAIT_OBJECT_0 == WaitForSingleObject(g_hThrdDie, pThis->m_lAgentInterval)) { MY_OUTPUT(L"CConsumer::Update()-Told to die!", 1); SetEvent(g_hThrdDead); break; } if (WaitForSingleObject(g_hConfigLock, HM_ASYNC_TIMEOUT) != WAIT_OBJECT_0) { continue; } if (!g_pSystem) { ReleaseMutex(g_hConfigLock); continue; } bRet = g_pSystem->OnAgentInterval(); ReleaseMutex(g_hConfigLock); } _endthreadex(0); return 0; } ////////////////////////////////////////////////////////////////////// // IUnknown Implementation ////////////////////////////////////////////////////////////////////// STDMETHODIMP CConsumer::QueryInterface(REFIID riid, LPVOID* ppv) { *ppv = NULL; if (riid == IID_IUnknown || riid == IID_IWbemUnboundObjectSink) { *ppv = this; AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CConsumer::AddRef(void) { return InterlockedIncrement((long*)&m_cRef); } STDMETHODIMP_(ULONG) CConsumer::Release(void) { return InterlockedDecrement((long*)&m_cRef); } ////////////////////////////////////////////////////////////////////// // IWbemUnboundObjectSink Implementation ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // IndicateToConsumer: Consumes following HealthMon events : // Timer Event, Threshold modification event(HMDataPoint), // and Category update event(HMStaticCatStatus). STDMETHODIMP CConsumer::IndicateToConsumer(IWbemClassObject* pLogicalConsumer, LONG lNumObjects, IWbemClassObject** ppObjects) { MY_OUTPUT(L"ENTER CConsumer::IndicateToConsumer()", 1); HRESULT hRes = S_OK; // WBEM may deliver multiple events for (long i = 0; i < lNumObjects; i++) { hRes = ProcessEvent(ppObjects[i]); if (FAILED(hRes)) { MY_OUTPUT2(L"CConsumer::IndicateToConsumer() Failed tp process event: 0x%08x\n",hRes,4); } } // end for loop if (hRes == WBEM_E_NOT_FOUND) // ok, otherwise CIMOM will reque this event { hRes = S_OK; } MY_OUTPUT(L"EXIT CConsumer::IndicateToConsumer()", 1); return hRes; } ////////////////////////////////////////////////////////////////////// // CConsumer Implementation ////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // ProcessEvent: Processes CIMOM events // HRESULT CConsumer::ProcessEvent(IWbemClassObject* pClass) { VARIANT vDispatch; MY_OUTPUT(L"CConsumer::ProcessEvent()", 1); // // Decide if it is a Timer, Creation, Modification, Deletion or some type of event. // VariantInit(&vDispatch); HRESULT hRes = pClass->Get(L"TargetInstance", 0L, &vDispatch, 0, 0); switch (hRes) { case WBEM_E_NOT_FOUND: { // Timer Event hRes = S_OK; VariantClear(&vDispatch); break; } case WBEM_S_NO_ERROR: { IWbemClassObject* pTargetInstance = NULL; hRes = GetWbemClassObject(&pTargetInstance, &vDispatch); MY_HRESASSERT(hRes); if (SUCCEEDED(hRes)) { hRes = ProcessModEvent(pClass, pTargetInstance); } if (pTargetInstance) { pTargetInstance->Release(); } VariantClear(&vDispatch); break; } default: { MY_HRESASSERT(hRes); MY_OUTPUT2(L"CConsumer::ProcessEvent()-Unexpected Error: 0x%08x\n",hRes,4); break; } } // end switch return hRes; } ///////////////////////////////////////////////////////////////////////////// // ProcessModEvent: Processes the inst. modification events // HRESULT CConsumer::ProcessModEvent(IWbemClassObject* pClass, IWbemClassObject* pInst) { TCHAR szParent[HM_MAX_PATH]; TCHAR szChild[HM_MAX_PATH]; CComVariant vInstClassName; CComVariant vOperationClassName; CComVariant vParent; CComVariant vChild; HRESULT hRes = S_OK; TCHAR *pszInstName = NULL; TCHAR *pszOperationName = NULL; BOOL bMod = FALSE; DWORD dwErr = 0; MY_OUTPUT(L"CConsumer::ProcessModEvent()", 1); // So we don't step on our toes. dwErr = WaitForSingleObject(g_hConfigLock, HM_ASYNC_TIMEOUT); if(dwErr != WAIT_OBJECT_0) { if(dwErr = WAIT_TIMEOUT) { TRACE_MUTEX(L"TIMEOUT MUTEX"); return WBEM_S_TIMEDOUT; } else { MY_OUTPUT(L"WaitForSingleObject on Mutex failed",4); return WBEM_E_FAILED; } } if (!g_pSystem) { ReleaseMutex(g_hConfigLock); return hRes; } hRes = pInst->Get(L"__CLASS", 0L, &vInstClassName, 0L, 0L); if (FAILED(hRes)) { MY_HRESASSERT(hRes); MY_OUTPUT(L"CConsumer::ValidateModEvent()-Unexpected Error!", 4); ReleaseMutex(g_hConfigLock); return hRes; } hRes = pClass->Get(L"__CLASS", 0L, &vOperationClassName, 0L, 0L); if (FAILED(hRes)) { MY_HRESASSERT(hRes); MY_OUTPUT(L"CConsumer::ValidateModEvent()-Unexpected Error!", 4); ReleaseMutex(g_hConfigLock); return hRes; } pszInstName = V_BSTR(&vInstClassName); pszOperationName = V_BSTR(&vOperationClassName); MY_ASSERT(wcslen(pszInstName) > HM_PREFIX_LEN); if(wcscmp(pszOperationName, HM_MOD_CLASS_NAME)==0) { bMod = TRUE; } else { bMod = FALSE; } try { if (!wcscmp(L"SystemConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModSystem(pInst); } else { //XXXSend out a CRITICAL MESSAGE, Tell them they need to re-install the agent MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"DataGroupConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModDataGroup(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"PolledGetObjectDataCollectorConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModDataCollector(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"PolledMethodDataCollectorConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModDataCollector(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"PolledQueryDataCollectorConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModDataCollector(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"EventQueryDataCollectorConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModDataCollector(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"ThresholdConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModThreshold(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"ActionConfiguration", pszInstName+HM_PREFIX_LEN)) { if (bMod) { hRes = g_pSystem->ModAction(pInst); } else if (!wcscmp(L"__InstanceCreationEvent", pszOperationName)) { hRes = g_pSystem->CreateAction(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"ConfigurationActionAssociation", pszInstName+HM_PREFIX_LEN)) { if (bMod) { g_pSystem->ModActionAssociation(pInst); } else if (!wcscmp(L"__InstanceCreationEvent", pszOperationName)) { g_pSystem->CreateActionAssociation(pInst); } else if (!wcscmp(L"__InstanceDeletionEvent", pszOperationName)) { //XXX g_pSystem->DeleteActionAssociation(pInst); } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else if (!wcscmp(L"ConfigurationAssociation", pszInstName+HM_PREFIX_LEN)) { if (!wcscmp(L"__InstanceCreationEvent", pszOperationName)) { hRes = pInst->Get(L"ParentPath", 0L, &vParent, 0L, 0L); if (FAILED(hRes)) { MY_HRESASSERT(hRes); } else { hRes = pInst->Get(L"ChildPath", 0L, &vChild, 0L, 0L); if (FAILED(hRes)) { MY_HRESASSERT(hRes); } else { wcscpy(szParent, V_BSTR(&vParent)); wcscpy(szChild, V_BSTR(&vChild)); if (wcsstr(szParent, L"MicrosoftHM_SystemConfiguration") && wcsstr(szChild, L"MicrosoftHM_DataGroupConfiguration")) { hRes = g_pSystem->CreateSystemDataGroupAssociation(pInst); } else if (wcsstr(szParent, L"MicrosoftHM_DataGroupConfiguration") && wcsstr(szChild, L"MicrosoftHM_DataGroupConfiguration")) { hRes = g_pSystem->CreateDataGroupDataGroupAssociation(pInst); } else if (wcsstr(szParent, L"MicrosoftHM_DataGroupConfiguration") && (wcsstr(szChild, L"MicrosoftHM_DataCollectorConfiguration") || wcsstr(szChild, L"MicrosoftHM_PolledGetObjectDataCollectorConfiguration") || wcsstr(szChild, L"MicrosoftHM_PolledMethodDataCollectorConfiguration") || wcsstr(szChild, L"MicrosoftHM_PolledQueryDataCollectorConfiguration") || wcsstr(szChild, L"MicrosoftHM_EventQueryDataCollectorConfiguration") )) { hRes = g_pSystem->CreateDataGroupDataCollectorAssociation(pInst); } else if ((wcsstr(szParent, L"MicrosoftHM_DataCollectorConfiguration") || wcsstr(szParent, L"MicrosoftHM_PolledGetObjectDataCollectorConfiguration") || wcsstr(szParent, L"MicrosoftHM_PolledMethodDataCollectorConfiguration") || wcsstr(szParent, L"MicrosoftHM_PolledQueryDataCollectorConfiguration") || wcsstr(szParent, L"MicrosoftHM_EventQueryDataCollectorConfiguration") ) && wcsstr(szChild, L"MicrosoftHM_ThresholdConfiguration")) { hRes = g_pSystem->CreateDataCollectorThresholdAssociation(pInst); } } } } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } else { MY_ASSERT(FALSE); hRes = S_FALSE; } } catch (...) { MY_ASSERT(FALSE); hRes = S_FALSE; } ReleaseMutex(g_hConfigLock); MY_OUTPUT(L"EXIT CConsumer::ProcessModEvent()", 1); return hRes; }