windows-nt/Source/XPSP1/NT/admin/hmonitor/hmagent/consumer.cpp
2020-09-26 16:20:57 +08:00

491 lines
11 KiB
C++

// Consumer.cpp: implementation of the CConsumer class.
//
// Copyright (c)1999-20000 Microsoft Corporation, All Rights Reserved
//////////////////////////////////////////////////////////////////////
#define HM_AGENT_INTERVAL 1000
#include <atlbase.h>
#include "hmagent.h"
#include "system.h"
#include "Consumer.h"
#include <process.h>
#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;
}