491 lines
11 KiB
C++
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;
|
||
|
}
|