802 lines
18 KiB
C++
802 lines
18 KiB
C++
//***************************************************************************
|
|
//
|
|
// PGDE.CPP
|
|
//
|
|
// Module: HEALTHMON SERVER AGENT
|
|
//
|
|
// Purpose: CPolledGetObjectDataCollector class to do WMI instance collection.
|
|
//
|
|
// Copyright (c)1999 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "pgde.h"
|
|
#include "system.h"
|
|
extern CSystem* g_pSystem;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CPolledGetObjectDataCollector::CPolledGetObjectDataCollector()
|
|
{
|
|
MY_OUTPUT(L"ENTER ***** CPolledGetObjectDataCollector...", 1);
|
|
|
|
m_pRefresher = NULL;
|
|
m_pConfigureRefresher = NULL;
|
|
m_pEnum = NULL;
|
|
m_pObjAccess = NULL;
|
|
m_lId = 0;
|
|
m_szObjectPath = NULL;
|
|
m_deType = HM_PGDE;
|
|
m_lNumInstancesCollected = 0;
|
|
m_pEnumObjs = NULL;
|
|
m_pCallResult = NULL;
|
|
|
|
MY_OUTPUT(L"EXIT ***** CPolledGetObjectDataCollector...", 1);
|
|
}
|
|
|
|
CPolledGetObjectDataCollector::~CPolledGetObjectDataCollector()
|
|
{
|
|
MY_OUTPUT(L"ENTER ***** ~CPolledGetObjectDataCollector...", 1);
|
|
|
|
if (m_szObjectPath)
|
|
{
|
|
delete [] m_szObjectPath;
|
|
}
|
|
|
|
if (m_pRefresher != NULL)
|
|
{
|
|
m_pRefresher->Release();
|
|
m_pRefresher = NULL;
|
|
}
|
|
|
|
if (m_pConfigureRefresher != NULL)
|
|
{
|
|
m_pConfigureRefresher->Release();
|
|
m_pConfigureRefresher = NULL;
|
|
}
|
|
|
|
if (m_pEnum != NULL)
|
|
{
|
|
m_pEnum->Release();
|
|
m_pEnum = NULL;
|
|
}
|
|
|
|
if (m_pObjAccess != NULL)
|
|
{
|
|
m_pObjAccess->Release();
|
|
m_pObjAccess = NULL;
|
|
}
|
|
|
|
EnumDone();
|
|
|
|
MY_OUTPUT(L"EXIT ***** ~CPolledGetObjectDataCollector...", 1);
|
|
}
|
|
|
|
//
|
|
// Load a single DataCollector, and everything under it.
|
|
//
|
|
HRESULT CPolledGetObjectDataCollector::LoadInstanceFromMOF(IWbemClassObject* pObj, CDataGroup *pParentDG, LPTSTR pszParentObjPath, BOOL bModifyPass/*FALSE*/)
|
|
{
|
|
HRESULT hRes;
|
|
IWbemClassObject* pConfigObj = NULL;
|
|
BOOL bRetValue = TRUE;
|
|
HRESULT hRetRes = S_OK;
|
|
int i, iSize;
|
|
CThreshold* pThreshold;
|
|
|
|
MY_OUTPUT(L"ENTER ***** CPolledGetObjectDataCollector::LoadInstanceFromMOF...", 4);
|
|
iSize = m_thresholdList.size();
|
|
for (i = 0; i < iSize ; i++)
|
|
{
|
|
MY_ASSERT(i<m_thresholdList.size());
|
|
pThreshold = m_thresholdList[i];
|
|
if (pThreshold->m_bValidLoad == FALSE)
|
|
return WBEM_E_INVALID_OBJECT;
|
|
// return S_OK;
|
|
}
|
|
|
|
if (m_szObjectPath)
|
|
{
|
|
delete [] m_szObjectPath;
|
|
m_szObjectPath = NULL;
|
|
}
|
|
m_lNumInstancesCollected = 0;
|
|
|
|
//
|
|
// Call the base class to load the common properties. Then do the specific ones.
|
|
//
|
|
hRetRes = CDataCollector::LoadInstanceFromMOF(pObj, pParentDG, pszParentObjPath, bModifyPass);
|
|
MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) return hRetRes;
|
|
|
|
// Get the GUID property
|
|
hRetRes = GetStrProperty(pObj, L"ObjectPath", &m_szObjectPath);
|
|
MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
|
|
|
|
// Decide if the path sets us up for multiple instances
|
|
if (wcschr(m_szObjectPath, L'='))
|
|
{
|
|
m_bMultiInstance = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_bMultiInstance = TRUE;
|
|
}
|
|
|
|
//
|
|
// Check to see if the High Performance interfaces are supported
|
|
// Otherwise we just revert to less efficient WMI interfaces
|
|
//
|
|
hRes = E_UNEXPECTED;
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
m_pRefresher = NULL;
|
|
bRetValue = FALSE;
|
|
}
|
|
|
|
if (bModifyPass)
|
|
{
|
|
}
|
|
|
|
MY_OUTPUT(L"EXIT ***** CPolledGetObjectDataCollector::LoadInstanceFromMOF...", 4);
|
|
return S_OK;
|
|
|
|
error:
|
|
MY_ASSERT(FALSE);
|
|
m_bValidLoad = FALSE;
|
|
Cleanup(FALSE);
|
|
return hRetRes;
|
|
}
|
|
|
|
//
|
|
// Get the instance out of WMI, and store all the properties we care about.
|
|
// Also calculate statistics for them.
|
|
//
|
|
BOOL CPolledGetObjectDataCollector::CollectInstance(void)
|
|
{
|
|
BSTR bstrName = NULL;
|
|
TCHAR szTemp[1024];
|
|
HRESULT hRes;
|
|
IWbemClassObject *pObj = NULL;
|
|
BOOL bRetValue = TRUE;
|
|
PNSTRUCT *ppn;
|
|
INSTSTRUCT inst;
|
|
INSTSTRUCT *pinst;
|
|
int i, j, iSize, jSize;
|
|
SAFEARRAY *psaNames = NULL;
|
|
BSTR PropName = NULL;
|
|
CThreshold *pThreshold;
|
|
IRSSTRUCT *pirs;
|
|
ACTUALINSTSTRUCT *pActualInst;
|
|
|
|
MY_OUTPUT(L"ENTER ***** CPolledGetObjectDataCollector::CollectInstance...", 1);
|
|
|
|
m_lNumInstancesCollected = 0;
|
|
|
|
if (m_pIWbemServices == NULL)
|
|
{
|
|
//XXX m_lCurrState = HM_CRITICAL;
|
|
MY_ASSERT(FALSE);
|
|
m_ulErrorCode = HMRES_BADWMI;
|
|
GetLatestAgentError(HMRES_BADWMI, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// First we can tell if this is going to be single instance, or multi-instance
|
|
//
|
|
//XXXCould split this out into four functions that call from here.
|
|
if (m_bMultiInstance==TRUE)
|
|
{
|
|
//XXXNeed to change this to be asyncronous???
|
|
//
|
|
// MULTI-INSTANCE CASE
|
|
//
|
|
|
|
//
|
|
// Check to see if the High Performance interfaces are supported
|
|
//
|
|
if (m_pRefresher!=NULL)
|
|
{
|
|
// Ask for the refresh
|
|
#ifdef SAVE
|
|
hRes = m_pRefresher->Refresh(0L);
|
|
if (FAILED(hRes))
|
|
{
|
|
}
|
|
#endif
|
|
|
|
// Now get the instance
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We get an instance at a time, so we can set all to not needed first,
|
|
// then go through them, do StoreValues... and delete what is not needed.
|
|
//
|
|
|
|
//
|
|
// Mark each instance, so we can tell if we still need them.
|
|
//
|
|
iSize = m_pnList.size();
|
|
for (i = 0; i < iSize ; i++)
|
|
{
|
|
MY_ASSERT(i<m_pnList.size());
|
|
ppn = &m_pnList[i];
|
|
jSize = ppn->instList.size();
|
|
for (j = 0; j < jSize ; j++)
|
|
{
|
|
MY_ASSERT(j<ppn->instList.size());
|
|
pinst = &ppn->instList[j];
|
|
pinst->bNeeded = FALSE;
|
|
}
|
|
}
|
|
|
|
// Also for all thresholds under this DataCollector
|
|
iSize = m_thresholdList.size();
|
|
for (i = 0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_thresholdList.size());
|
|
pThreshold = m_thresholdList[i];
|
|
jSize = pThreshold->m_irsList.size();
|
|
for (j = 0; j < jSize; j++)
|
|
{
|
|
MY_ASSERT(j<pThreshold->m_irsList.size());
|
|
pirs = &pThreshold->m_irsList[j];
|
|
pirs->bNeeded = FALSE;
|
|
}
|
|
}
|
|
|
|
iSize = m_actualInstList.size();
|
|
for (i=0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_actualInstList.size());
|
|
pActualInst = &m_actualInstList[i];
|
|
pActualInst->bNeeded = FALSE;
|
|
}
|
|
|
|
//
|
|
// Enumerate through the instances
|
|
//
|
|
bstrName = SysAllocString(m_szObjectPath);
|
|
m_pEnumObjs = NULL;
|
|
hRes = m_pIWbemServices->CreateInstanceEnum(bstrName,
|
|
WBEM_FLAG_SHALLOW|WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
|
|
&m_pEnumObjs);
|
|
if (hRes != S_OK)
|
|
{
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
bRetValue = FALSE;
|
|
MY_HRESASSERT(hRes);
|
|
MY_OUTPUT2(L"PGDE-Unexpected Error: 0x%08x",hRes,4);
|
|
MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
|
|
MY_OUTPUT2(L"bstrName was=%s",bstrName,4);
|
|
MY_OUTPUT2(L"CreateInstanceEnum(%s)",m_szObjectPath,4);
|
|
}
|
|
else
|
|
{
|
|
m_bKeepCollectingSemiSync = TRUE;
|
|
bRetValue = CollectInstanceSemiSync();
|
|
}
|
|
SysFreeString(bstrName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
//XXX
|
|
//XXX
|
|
//XXX
|
|
//We should just always use the multi-instance code, and delete this code.
|
|
//The multi-instance code will still work in the single instance case!!!!!
|
|
//XXX
|
|
//XXX
|
|
//XXX
|
|
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
//
|
|
// SINGLE INSTANCE CASE
|
|
//
|
|
|
|
//
|
|
// Check to see if the High Performance interfaces are supported
|
|
//
|
|
if (m_pRefresher!=NULL)
|
|
{
|
|
// Ask for the refresh
|
|
#ifdef SAVE
|
|
hRes = m_pRefresher->Refresh(0L);
|
|
if (FAILED(hRes))
|
|
{
|
|
}
|
|
#endif
|
|
|
|
// Now get the instances
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Mark each instance, so we can tell if we still need them.
|
|
//
|
|
iSize = m_pnList.size();
|
|
for (i = 0; i < iSize ; i++)
|
|
{
|
|
MY_ASSERT(i<m_pnList.size());
|
|
ppn = &m_pnList[i];
|
|
jSize = ppn->instList.size();
|
|
for (j = 0; j < jSize ; j++)
|
|
{
|
|
MY_ASSERT(j<ppn->instList.size());
|
|
pinst = &ppn->instList[j];
|
|
pinst->bNeeded = FALSE;
|
|
}
|
|
}
|
|
|
|
// Also for all thresholds under this DataCollector
|
|
iSize = m_thresholdList.size();
|
|
for (i = 0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_thresholdList.size());
|
|
pThreshold = m_thresholdList[i];
|
|
jSize = pThreshold->m_irsList.size();
|
|
for (j = 0; j < jSize; j++)
|
|
{
|
|
MY_ASSERT(j<pThreshold->m_irsList.size());
|
|
pirs = &pThreshold->m_irsList[j];
|
|
pirs->bNeeded = FALSE;
|
|
}
|
|
}
|
|
|
|
iSize = m_actualInstList.size();
|
|
for (i=0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_actualInstList.size());
|
|
pActualInst = &m_actualInstList[i];
|
|
pActualInst->bNeeded = FALSE;
|
|
}
|
|
|
|
//
|
|
// This is the single instance, NON-HighPerformance case
|
|
//
|
|
swprintf(szTemp, L"%s", m_szObjectPath);
|
|
hRes = GetWbemObjectInstSemiSync(&m_pIWbemServices, szTemp, m_pContext, &m_pCallResult);
|
|
if (hRes != S_OK || m_pCallResult == NULL)
|
|
{
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
bRetValue = FALSE;
|
|
MY_HRESASSERT(hRes);
|
|
MY_OUTPUT2(L"PGDE-Unexpected Error: 0x%08x",hRes,4);
|
|
MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
|
|
MY_OUTPUT2(L"CreateWbemObjectInstSemiSync(%s)",m_szObjectPath,4);
|
|
}
|
|
else
|
|
{
|
|
m_bKeepCollectingSemiSync = TRUE;
|
|
bRetValue = CollectInstanceSemiSync();
|
|
}
|
|
}
|
|
}
|
|
|
|
MY_OUTPUT(L"EXIT ***** CPolledGetObjectDataCollector::CollectInstance...", 1);
|
|
return bRetValue;
|
|
}
|
|
|
|
BOOL CPolledGetObjectDataCollector::CollectInstanceSemiSync(void)
|
|
{
|
|
LPTSTR pszID = NULL;
|
|
HRESULT hRes;
|
|
IWbemClassObject *pObj;
|
|
IWbemClassObject *apObj[10];
|
|
INSTSTRUCT inst;
|
|
long lStatus;
|
|
ULONG uReturned = 0;
|
|
|
|
MY_OUTPUT(L"ENTER ***** CPolledGetObjectDataCollector::CollectInstanceSemiSync...", 1);
|
|
|
|
if (m_bMultiInstance==TRUE)
|
|
{
|
|
MY_ASSERT(m_pEnumObjs);
|
|
// We never want to block here, so we set it for zero second timeout,
|
|
// and have it return immediatly what it has available.
|
|
hRes = m_pEnumObjs->Next(0, 10, apObj, &uReturned);
|
|
|
|
if (hRes == WBEM_S_TIMEDOUT)
|
|
{
|
|
// Didn't get full list of instances yet.
|
|
if (!ProcessObjects(uReturned, apObj))
|
|
{
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
else if (hRes == WBEM_S_FALSE)
|
|
{
|
|
//
|
|
// Means that we are done. The number returned was less than asked for.
|
|
// But we still process what we did recieve to finish it off.
|
|
// Add in a fake instance for the number of instances returned.
|
|
//
|
|
if (!ProcessObjects(uReturned, apObj))
|
|
{
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_ulErrorCode = 0;
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
//XXXWhy was this here??? m_lCurrState = HM_GOOD;
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if (hRes == WBEM_S_NO_ERROR)
|
|
{
|
|
// Means that we have an instance, The number returned was what was requested
|
|
}
|
|
else
|
|
{
|
|
MY_HRESASSERT(hRes);
|
|
MY_OUTPUT2(L"PGDE-Unexpected Error MultiInstance Next(): 0x%08x",hRes,4);
|
|
MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
|
|
MY_OUTPUT2(L"ObjectPath was=%s",m_szObjectPath,4);
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_ENUMFAIL, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
|
|
if (apObj[0] == NULL)
|
|
{
|
|
//
|
|
// NULL in this case can actually happen. An example is where the
|
|
// threshold is to see if the SQL Server service is running. If it
|
|
// is not even on the machine, then we would get an error looking
|
|
// for its instance.
|
|
//
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
}
|
|
else
|
|
{
|
|
MY_ASSERT(uReturned>=1);
|
|
if (!ProcessObjects(uReturned, apObj))
|
|
{
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
// else
|
|
// {
|
|
// m_ulErrorCode = 0;
|
|
// }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MY_ASSERT(m_pCallResult);
|
|
lStatus = 0;
|
|
//
|
|
// Keep trying until we get WBEM_S_NO_ERROR. Then we know the GetObject call has completed.
|
|
// hRes will contain the result of the origional GetObject call if needed.
|
|
//
|
|
hRes = m_pCallResult->GetCallStatus(0, &lStatus);
|
|
if (hRes == WBEM_S_TIMEDOUT)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else if (hRes == WBEM_S_NO_ERROR)
|
|
{
|
|
// Means that we are done.
|
|
// HOWEVER, we don't know if we ever retrieved any instances!
|
|
// This is different from the multi-instance case, because we do
|
|
// ask for a single specific instance, and will know below if it is there!
|
|
}
|
|
else
|
|
{
|
|
MY_HRESASSERT(hRes);
|
|
MY_OUTPUT2(L"PGDE-Unexpected Error SingleInstance GetCallStatus: 0x%08x",hRes,4);
|
|
MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
|
|
MY_OUTPUT2(L"ObjectPath was=%s",m_szObjectPath,4);
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// This may mean that the call completed, and the object was not found (e.g. bad path).
|
|
//
|
|
if (lStatus != 0)
|
|
{
|
|
MY_HRESASSERT(lStatus);
|
|
m_ulErrorCode = lStatus;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, lStatus, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the Object finaly.
|
|
//
|
|
hRes = m_pCallResult->GetResultObject(0, &pObj);
|
|
if (pObj == NULL)
|
|
{
|
|
MY_ASSERT(FALSE);
|
|
//
|
|
// NULL in this case can actually happen. An example is where the
|
|
// threshold is to see if the SQL Server service is running. If it
|
|
// is not even on the machine, then we would get an error looking
|
|
// for its instance.
|
|
//
|
|
m_lCurrState = HM_WARNING;
|
|
m_ulErrorCode = 0;
|
|
EnumDone();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Figure out the key property name to identify instances with.
|
|
//
|
|
hRes = GetInstanceID(pObj, &pszID);
|
|
if (hRes != S_OK)
|
|
{
|
|
pObj->Release();
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Mark instances need to keep around, and add new ones
|
|
//
|
|
hRes = CheckInstanceExistance(pObj, pszID);
|
|
if (hRes != S_OK)
|
|
{
|
|
delete [] pszID;
|
|
pObj->Release();
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
EnumDone();
|
|
return FALSE;
|
|
}
|
|
|
|
m_lNumInstancesCollected = 1;
|
|
StoreValues(pObj, pszID);
|
|
delete [] pszID;
|
|
pObj->Release();
|
|
pObj = NULL;
|
|
|
|
//
|
|
// We are done.
|
|
// Add in a fake instance for the number of instances returned.
|
|
//
|
|
m_ulErrorCode = 0;
|
|
StoreStandardProperties();
|
|
m_lCurrState = HM_GOOD;
|
|
EnumDone();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
MY_OUTPUT(L"EXIT ***** CPolledGetObjectDataCollector::CollectInstanceSemiSync...", 1);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CPolledGetObjectDataCollector::ProcessObjects(ULONG uReturned, IWbemClassObject **apObj)
|
|
{
|
|
HRESULT hRes;
|
|
LPTSTR pszID;
|
|
ULONG n;
|
|
BOOL bRetValue = TRUE;
|
|
|
|
for (n = 0; n < uReturned; n++)
|
|
{
|
|
if (g_pSystem->m_lNumInstancesAccepted <m_lNumInstancesCollected)
|
|
{
|
|
m_ulErrorCode = HMRES_TOOMANYINSTS;
|
|
GetLatestAgentError(HMRES_TOOMANYINSTS, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
bRetValue = FALSE;
|
|
break;
|
|
}
|
|
//Why does the above cause ASSERT on 1151 of Threshold.cpp???
|
|
//
|
|
// Figure out the key property name to identify instances with.
|
|
//
|
|
hRes = GetInstanceID(apObj[n], &pszID);
|
|
if (hRes != S_OK)
|
|
{
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
bRetValue = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Special case to throw out the "_Total" instance in the multi-instance case
|
|
//
|
|
if (!_wcsicmp(pszID, L"_total"))
|
|
{
|
|
delete [] pszID;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Mark instances need to keep around, and add new ones
|
|
//
|
|
hRes = CheckInstanceExistance(apObj[n], pszID);
|
|
if (hRes != S_OK)
|
|
{
|
|
delete [] pszID;
|
|
m_ulErrorCode = hRes;
|
|
GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
|
|
StoreStandardProperties();
|
|
bRetValue = FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Now store each property that we need to for this instance
|
|
//
|
|
m_lNumInstancesCollected++;
|
|
StoreValues(apObj[n], pszID);
|
|
|
|
delete [] pszID;
|
|
}
|
|
|
|
for (n = 0; n < uReturned; n++)
|
|
{
|
|
apObj[n]->Release();
|
|
apObj[n] = NULL;
|
|
}
|
|
return bRetValue;
|
|
}
|
|
|
|
//XXXIs EnumDone needed in all cases, if so place it in the base class
|
|
BOOL CPolledGetObjectDataCollector::EnumDone(void)
|
|
{
|
|
IRSSTRUCT *pirs;
|
|
IWbemClassObject *pObj = NULL;
|
|
BOOL bRetValue = TRUE;
|
|
PNSTRUCT *ppn;
|
|
INSTSTRUCT inst;
|
|
INSTSTRUCT *pinst;
|
|
int i, j, iSize, jSize;
|
|
CThreshold *pThreshold;
|
|
SAFEARRAY *psaNames = NULL;
|
|
BSTR PropName = NULL;
|
|
INSTLIST::iterator iaPINST;
|
|
IRSLIST::iterator iaPIRS;
|
|
ACTUALINSTLIST::iterator iaPAI;
|
|
ACTUALINSTSTRUCT *pActualInst;
|
|
|
|
CleanupSemiSync();
|
|
|
|
//XXXAdd similar code to get rid of what is not needed in the m_instList
|
|
//XXXOnce again take common code and place it in the base class!VVVVVVVVVVVVVVVVVVVVVVVVv
|
|
//
|
|
// Now loop through and get rid of instances that are no longer around
|
|
//
|
|
iSize = m_pnList.size();
|
|
for (i = 0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_pnList.size());
|
|
ppn = &m_pnList[i];
|
|
iaPINST = ppn->instList.begin();
|
|
jSize = ppn->instList.size();
|
|
for (j = 0; j < jSize && iaPINST ; j++)
|
|
{
|
|
pinst = iaPINST;
|
|
if (pinst->bNeeded == FALSE)
|
|
{
|
|
if (pinst->szInstanceID)
|
|
delete [] pinst->szInstanceID;
|
|
if (pinst->szCurrValue)
|
|
delete [] pinst->szCurrValue;
|
|
pinst->szCurrValue = NULL;
|
|
iaPINST = ppn->instList.erase(iaPINST);
|
|
}
|
|
else
|
|
{
|
|
iaPINST++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also for all thresholds under this DataCollector
|
|
iSize = m_thresholdList.size();
|
|
for (i = 0; i < iSize; i++)
|
|
{
|
|
MY_ASSERT(i<m_thresholdList.size());
|
|
pThreshold = m_thresholdList[i];
|
|
iaPIRS = pThreshold->m_irsList.begin();
|
|
jSize = pThreshold->m_irsList.size();
|
|
for (j = 0; j < jSize && iaPIRS ; j++)
|
|
{
|
|
pirs = iaPIRS;
|
|
if (pirs->bNeeded == FALSE)
|
|
{
|
|
if (pirs->szInstanceID)
|
|
delete [] pirs->szInstanceID;
|
|
iaPIRS = pThreshold->m_irsList.erase(iaPIRS);
|
|
}
|
|
else
|
|
{
|
|
iaPIRS++;
|
|
}
|
|
}
|
|
}
|
|
|
|
iaPAI = m_actualInstList.begin();
|
|
jSize = m_actualInstList.size();
|
|
for (j = 0; j < jSize && iaPAI; j++)
|
|
{
|
|
pActualInst = iaPAI;
|
|
if (pActualInst->bNeeded == FALSE)
|
|
{
|
|
if (pActualInst->szInstanceID)
|
|
{
|
|
delete [] pActualInst->szInstanceID;
|
|
}
|
|
if (pActualInst->pInst)
|
|
{
|
|
pActualInst->pInst->Release();
|
|
pActualInst->pInst = NULL;
|
|
}
|
|
iaPAI = m_actualInstList.erase(iaPAI);
|
|
}
|
|
else
|
|
{
|
|
iaPAI++;
|
|
}
|
|
}
|
|
//XXXOnce again take common code and place it in the base class!^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CPolledGetObjectDataCollector::CleanupSemiSync(void)
|
|
{
|
|
if (m_bMultiInstance==TRUE)
|
|
{
|
|
if (m_pEnumObjs)
|
|
{
|
|
m_pEnumObjs->Release();
|
|
m_pEnumObjs = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_pCallResult)
|
|
{
|
|
m_pCallResult->Release();
|
|
m_pCallResult = NULL;
|
|
}
|
|
}
|
|
|
|
m_bKeepCollectingSemiSync = FALSE;
|
|
m_lCollectionTimeOutCount = 0;
|
|
|
|
return TRUE;
|
|
}
|