|
|
//***************************************************************************
//
// PMDE.CPP
//
// Module: HEALTHMON SERVER AGENT
//
// Purpose: CPolledMethodDataCollector class to do WMI instance collection.
//
// Copyright (c)1999 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include "pmde.h"
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPolledMethodDataCollector::CPolledMethodDataCollector() { MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector...", 4);
//
// XXX
//
#ifdef SAVE
m_pHMEventSink = NULL; #endif
m_szObjectPath = NULL; m_szMethodName = NULL; m_deType = HM_PMDE; m_lNumInstancesCollected = 0; m_pCallResult = NULL;
MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector...", 4); }
CPolledMethodDataCollector::~CPolledMethodDataCollector() { int iSize; int i; PARSTRUCT *pparameter;
MY_OUTPUT(L"ENTER ***** ~CPolledMethodDataCollector...", 4);
if (m_szObjectPath) delete [] m_szObjectPath; if (m_szMethodName) delete [] m_szMethodName;
iSize = m_parameterList.size(); for (i=0; i<iSize ;i++) { MY_ASSERT(i<m_parameterList.size()); pparameter = &m_parameterList[i]; if (pparameter->szName) { delete [] pparameter->szName; }
if (pparameter->szValue) { delete [] pparameter->szValue; } }
EnumDone();
MY_OUTPUT(L"EXIT ***** ~CPolledMethodDataCollector...", 4); }
//
// Load a single DataCollector, and everything under it.
//
HRESULT CPolledMethodDataCollector::LoadInstanceFromMOF(IWbemClassObject* pObj, CDataGroup *pParentDG, LPTSTR pszParentObjPath, BOOL bModifyPass/*FALSE*/) { BOOL bRetValue = TRUE; VARIANT v; VARIANT vValue; IUnknown* vUnknown; IWbemClassObject* pCO; long iLBound, iUBound; long lType; PARSTRUCT par; int iSize; long i; PARSTRUCT *pparameter; HRESULT hRetRes = S_OK; VariantInit(&v); VariantInit(&vValue); CThreshold* pThreshold;
MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::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; }
if (m_szObjectPath) { delete [] m_szObjectPath; m_szObjectPath = NULL; } if (m_szMethodName) { delete [] m_szMethodName; m_szMethodName = NULL; } m_lNumInstancesCollected = 0;
iSize = m_parameterList.size(); for (i=0; i<iSize ;i++) { MY_ASSERT(i<m_parameterList.size()); pparameter = &m_parameterList[i];
if (pparameter->szName) { delete [] pparameter->szName; }
if (pparameter->szValue) { delete [] pparameter->szValue; } } m_parameterList.clear();
//
// 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;
hRetRes = GetStrProperty(pObj, L"ObjectPath", &m_szObjectPath); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetStrProperty(pObj, L"MethodName", &m_szMethodName); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Get the IN parameters from the Arguments property.
//
VariantInit(&v); if ((hRetRes = pObj->Get(L"Arguments", 0L, &v, NULL, NULL)) == S_OK) { if (V_VT(&v)==VT_NULL) { // MY_ASSERT(FALSE);
} else { MY_ASSERT(V_VT(&v)==(VT_UNKNOWN|VT_ARRAY)); SafeArrayGetLBound(v.parray, 1, &iLBound); SafeArrayGetUBound(v.parray, 1, &iUBound); if ((iUBound - iLBound + 1) == 0) { MY_ASSERT(FALSE); } else { for (i = iLBound; i <= iUBound; i++) { par.szName = NULL; par.szValue = NULL; VariantInit(&vValue); vUnknown = NULL; hRetRes = SafeArrayGetElement(v.parray, &i, &vUnknown); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; pCO = (IWbemClassObject *)vUnknown;
hRetRes = GetStrProperty(pCO, L"Name", &par.szName); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
hRetRes = GetUint32Property(pCO, L"Type", &lType); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; par.lType = lType;
hRetRes = GetStrProperty(pCO, L"Value", &par.szValue); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
m_parameterList.push_back(par);
VariantClear(&vValue);
vUnknown->Release(); } } } } else { MY_HRESASSERT(hRetRes); return hRetRes; } VariantClear(&v);
MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::LoadInstanceFromMOF...", 4); return S_OK;
error: MY_ASSERT(FALSE); VariantClear(&v); m_bValidLoad = FALSE; Cleanup(FALSE); if (m_szObjectPath) { delete [] m_szObjectPath; m_szObjectPath = NULL; } if (m_szMethodName) { delete [] m_szMethodName; m_szMethodName = NULL; }
iSize = m_parameterList.size(); for (i=0; i<iSize ;i++) { MY_ASSERT(i<m_parameterList.size()); pparameter = &m_parameterList[i]; if (pparameter->szName) { delete [] pparameter->szName; }
if (pparameter->szValue) { delete [] pparameter->szValue; } } return hRetRes; }
BOOL CPolledMethodDataCollector::CollectInstance(void) { BOOL bRetValue = TRUE; int iSize; int i; PARSTRUCT *pparameter; HRESULT hRetRes = S_OK; VARIANT var; SAFEARRAY* psa = NULL; IWbemClassObject *pObj = NULL; IWbemClassObject *pClass = NULL; IWbemClassObject *pOutInst = NULL; IWbemClassObject *pInClass = NULL; IWbemClassObject *pInInst = NULL; BSTR ClassPath = NULL; BSTR MethodName = NULL; INSTSTRUCT inst; VariantInit(&var);
MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::CollectInstance...", 1);
m_lNumInstancesCollected = 0;
if (m_pIWbemServices == NULL) { m_ulErrorCode = HMRES_BADWMI; GetLatestAgentError(HMRES_BADWMI, m_szErrorDescription); StoreStandardProperties(); return FALSE; }
//
// 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.
//
#ifdef SAVE
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; } } #endif
ClassPath = SysAllocString(m_szObjectPath); MY_ASSERT(ClassPath); if (!ClassPath) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} MethodName = SysAllocString(m_szMethodName); MY_ASSERT(MethodName); if (!MethodName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
hRetRes = m_pIWbemServices->GetObject(ClassPath, 0, NULL, &pClass, NULL); if (FAILED(hRetRes) || pClass == NULL) { m_lCurrState = HM_WARNING; } MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK || pClass == NULL) goto error;
// Get the input-argument class object and create an instance.
hRetRes = pClass->GetMethod(MethodName, 0, &pInClass, NULL); if (FAILED(hRetRes) || pClass == NULL) { m_lCurrState = HM_WARNING; } MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK || pInClass == NULL) goto error;
hRetRes = pInClass->SpawnInstance(0, &pInInst); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
//
// Set the IN parameters - they are actually properties on the instance we pass in.
// We will do error checking to make sure that there is one by that name, by seeing
// if the Put fails.
//
iSize = m_parameterList.size(); for (i=0; i<iSize ;i++) { MY_ASSERT(i<m_parameterList.size()); pparameter = &m_parameterList[i]; VariantInit(&var);
if (pparameter->lType == CIM_SINT8 || pparameter->lType == CIM_SINT16 || pparameter->lType == CIM_CHAR16) { V_VT(&var) = VT_I2; V_I2(&var) = _wtol(pparameter->szValue); } else if (pparameter->lType == CIM_SINT32 || pparameter->lType == CIM_UINT16 || pparameter->lType == CIM_UINT32) { V_VT(&var) = VT_I4; V_I4(&var) = _wtol(pparameter->szValue); } else if (pparameter->lType == CIM_REAL32) { V_VT(&var) = VT_R4; V_R4(&var) = wcstod(pparameter->szValue, NULL); } else if (pparameter->lType == CIM_BOOLEAN) { V_VT(&var) = VT_BOOL; V_BOOL(&var) = (BOOL) _wtol(pparameter->szValue); } else if (pparameter->lType == CIM_SINT64 || pparameter->lType == CIM_UINT64 || //XXX pparameter->lType == CIM_REF ||
pparameter->lType == CIM_STRING || pparameter->lType == CIM_DATETIME) { V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(pparameter->szValue); } else if (pparameter->lType == CIM_REAL64) { V_VT(&var) = VT_R8; V_R8(&var) = wcstod(pparameter->szValue, NULL); } else if (pparameter->lType == CIM_UINT8) { V_VT(&var) = VT_UI1; V_UI1(&var) = (unsigned char) _wtoi(pparameter->szValue); } else { MY_ASSERT(FALSE); }
hRetRes = pInInst->Put(pparameter->szName, 0, &var, 0); MY_HRESASSERT(hRetRes); VariantClear(&var); if (psa != NULL) { SafeArrayDestroy(psa); psa = NULL; } }
//
// Call the method.
//
hRetRes = m_pIWbemServices->ExecMethod(ClassPath, MethodName, WBEM_FLAG_RETURN_IMMEDIATELY, m_pContext, pInInst, &pOutInst, &m_pCallResult); if (hRetRes != S_OK) { MY_HRESASSERT(hRetRes); MY_OUTPUT2(L"PMDE - ExecMethod Error: 0x%08x",hRetRes,4); MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4); m_ulErrorCode = hRetRes; GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRetRes, m_szErrorDescription); StoreStandardProperties(); bRetValue = FALSE; } else { m_bKeepCollectingSemiSync = TRUE; bRetValue = CollectInstanceSemiSync(); }
//
// Free up resources.
//
SysFreeString(ClassPath); ClassPath = NULL; SysFreeString(MethodName); MethodName = NULL; pClass->Release(); pClass = NULL; pInInst->Release(); pInInst = NULL; pInClass->Release(); pInClass = NULL;
MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::CollectInstance...", 1); return bRetValue;
error: MY_ASSERT(FALSE); if (ClassPath) SysFreeString(ClassPath); if (MethodName) SysFreeString(MethodName); if (pClass) pClass->Release(); if (pInInst) pInInst->Release(); if (pInClass) pInClass->Release(); if (psa != NULL) SafeArrayDestroy(psa); m_bValidLoad = FALSE; Cleanup(FALSE); return hRetRes; }
BOOL CPolledMethodDataCollector::CollectInstanceSemiSync(void) { HRESULT hRetRes = S_OK; IWbemClassObject *pObj = NULL; PNSTRUCT *ppn; INSTSTRUCT inst; CThreshold *pThreshold; long lStatus; ULONG uReturned = 0; int i, iSize; InstIDSTRUCT InstID;
MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::CollectInstanceSemiSync...", 1);
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.
//
hRetRes = m_pCallResult->GetCallStatus(0, &lStatus); if (hRetRes == WBEM_S_TIMEDOUT) { return FALSE; } else if (hRetRes == WBEM_S_NO_ERROR) { // Means that we have an instance
} else { MY_HRESASSERT(hRetRes); MY_OUTPUT2(L"PMDE - GetCallStatus Error: 0x%08x",hRetRes,4); MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4); MY_OUTPUT2(L"ClassPath was=%s",m_szObjectPath,4); MY_OUTPUT2(L"MethodName was=%s",m_szMethodName,4); m_ulErrorCode = 0; EnumDone(); return FALSE; }
//
// This may mean that the call completed, and the object was not found (e.g. bad path).
//
if (lStatus != 0) { m_lCurrState = HM_WARNING; m_ulErrorCode = 0; EnumDone(); return FALSE; }
//
// Get the Object finaly.
//
hRetRes = m_pCallResult->GetResultObject(0, &pObj); if (pObj == 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_lCurrState = HM_WARNING; EnumDone(); } else { EnumDone();
//
// Figure out the key property name to identify instances with.
//
iSize = m_instIDList.size(); if (iSize == 0) { // There is no key property returned!!!
InstID.szInstanceIDPropertyName = new TCHAR[7]; MY_ASSERT(InstID.szInstanceIDPropertyName); if (!InstID.szInstanceIDPropertyName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} wcscpy(InstID.szInstanceIDPropertyName , L"Method"); m_instIDList.push_back(InstID); // Add an instance to each property name
iSize = m_pnList.size(); for (i=0; i < iSize ; i++) { MY_ASSERT(i<m_pnList.size()); ppn = &m_pnList[i]; inst.szInstanceID = new TCHAR[2]; MY_ASSERT(inst.szInstanceID); if (!inst.szInstanceID) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;} wcscpy(inst.szInstanceID, L""); inst.szCurrValue = NULL; ResetInst(&inst, ppn->type); inst.bNull = FALSE; inst.bNeeded = TRUE; ppn->instList.push_back(inst); } //Also add instance 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]; hRetRes = pThreshold->AddInstance(L""); MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error; } } MY_ASSERT(m_instIDList.size());
//
// Check the list of actual instances that the Data Collector is collecting.
// We keep around the latest one(s) for the DataCollector.
//
CheckActualInstanceExistance(pObj, L"");
m_lNumInstancesCollected = 1; StoreValues(pObj, L""); pObj->Release(); pObj = NULL;
//
// Means that we are done.
// Won't ever get here the first time
// Add in a fake instance for the number of instances returned.
//
m_lCurrState = HM_GOOD; m_ulErrorCode = 0; StoreStandardProperties(); }
MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::CollectInstanceSemiSync...", 1); return TRUE;
error: MY_ASSERT(FALSE); if (pObj) pObj->Release(); m_bValidLoad = FALSE; Cleanup(FALSE); return FALSE; }
BOOL CPolledMethodDataCollector::CleanupSemiSync(void) { if (m_pCallResult) { m_pCallResult->Release(); m_pCallResult = NULL; }
m_bKeepCollectingSemiSync = FALSE; m_lCollectionTimeOutCount = 0;
return TRUE; }
BOOL CPolledMethodDataCollector::EnumDone(void) { CleanupSemiSync();
return TRUE; }
|