Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

608 lines
14 KiB

  1. //***************************************************************************
  2. //
  3. // PMDE.CPP
  4. //
  5. // Module: HEALTHMON SERVER AGENT
  6. //
  7. // Purpose: CPolledMethodDataCollector class to do WMI instance collection.
  8. //
  9. // Copyright (c)1999 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "pmde.h"
  13. //////////////////////////////////////////////////////////////////////
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CPolledMethodDataCollector::CPolledMethodDataCollector()
  18. {
  19. MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector...", 4);
  20. //
  21. // XXX
  22. //
  23. #ifdef SAVE
  24. m_pHMEventSink = NULL;
  25. #endif
  26. m_szObjectPath = NULL;
  27. m_szMethodName = NULL;
  28. m_deType = HM_PMDE;
  29. m_lNumInstancesCollected = 0;
  30. m_pCallResult = NULL;
  31. MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector...", 4);
  32. }
  33. CPolledMethodDataCollector::~CPolledMethodDataCollector()
  34. {
  35. int iSize;
  36. int i;
  37. PARSTRUCT *pparameter;
  38. MY_OUTPUT(L"ENTER ***** ~CPolledMethodDataCollector...", 4);
  39. if (m_szObjectPath)
  40. delete [] m_szObjectPath;
  41. if (m_szMethodName)
  42. delete [] m_szMethodName;
  43. iSize = m_parameterList.size();
  44. for (i=0; i<iSize ;i++)
  45. {
  46. MY_ASSERT(i<m_parameterList.size());
  47. pparameter = &m_parameterList[i];
  48. if (pparameter->szName)
  49. {
  50. delete [] pparameter->szName;
  51. }
  52. if (pparameter->szValue)
  53. {
  54. delete [] pparameter->szValue;
  55. }
  56. }
  57. EnumDone();
  58. MY_OUTPUT(L"EXIT ***** ~CPolledMethodDataCollector...", 4);
  59. }
  60. //
  61. // Load a single DataCollector, and everything under it.
  62. //
  63. HRESULT CPolledMethodDataCollector::LoadInstanceFromMOF(IWbemClassObject* pObj, CDataGroup *pParentDG, LPTSTR pszParentObjPath, BOOL bModifyPass/*FALSE*/)
  64. {
  65. BOOL bRetValue = TRUE;
  66. VARIANT v;
  67. VARIANT vValue;
  68. IUnknown* vUnknown;
  69. IWbemClassObject* pCO;
  70. long iLBound, iUBound;
  71. long lType;
  72. PARSTRUCT par;
  73. int iSize;
  74. long i;
  75. PARSTRUCT *pparameter;
  76. HRESULT hRetRes = S_OK;
  77. VariantInit(&v);
  78. VariantInit(&vValue);
  79. CThreshold* pThreshold;
  80. MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::LoadInstanceFromMOF...", 4);
  81. iSize = m_thresholdList.size();
  82. for (i = 0; i < iSize ; i++)
  83. {
  84. MY_ASSERT(i<m_thresholdList.size());
  85. pThreshold = m_thresholdList[i];
  86. if (pThreshold->m_bValidLoad == FALSE)
  87. return WBEM_E_INVALID_OBJECT;
  88. }
  89. if (m_szObjectPath)
  90. {
  91. delete [] m_szObjectPath;
  92. m_szObjectPath = NULL;
  93. }
  94. if (m_szMethodName)
  95. {
  96. delete [] m_szMethodName;
  97. m_szMethodName = NULL;
  98. }
  99. m_lNumInstancesCollected = 0;
  100. iSize = m_parameterList.size();
  101. for (i=0; i<iSize ;i++)
  102. {
  103. MY_ASSERT(i<m_parameterList.size());
  104. pparameter = &m_parameterList[i];
  105. if (pparameter->szName)
  106. {
  107. delete [] pparameter->szName;
  108. }
  109. if (pparameter->szValue)
  110. {
  111. delete [] pparameter->szValue;
  112. }
  113. }
  114. m_parameterList.clear();
  115. //
  116. // Call the base class to load the common properties. Then do the specific ones.
  117. //
  118. hRetRes = CDataCollector::LoadInstanceFromMOF(pObj, pParentDG, pszParentObjPath, bModifyPass);
  119. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) return hRetRes;
  120. hRetRes = GetStrProperty(pObj, L"ObjectPath", &m_szObjectPath);
  121. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  122. hRetRes = GetStrProperty(pObj, L"MethodName", &m_szMethodName);
  123. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  124. //
  125. // Get the IN parameters from the Arguments property.
  126. //
  127. VariantInit(&v);
  128. if ((hRetRes = pObj->Get(L"Arguments", 0L, &v, NULL, NULL)) == S_OK)
  129. {
  130. if (V_VT(&v)==VT_NULL)
  131. {
  132. // MY_ASSERT(FALSE);
  133. }
  134. else
  135. {
  136. MY_ASSERT(V_VT(&v)==(VT_UNKNOWN|VT_ARRAY));
  137. SafeArrayGetLBound(v.parray, 1, &iLBound);
  138. SafeArrayGetUBound(v.parray, 1, &iUBound);
  139. if ((iUBound - iLBound + 1) == 0)
  140. {
  141. MY_ASSERT(FALSE);
  142. }
  143. else
  144. {
  145. for (i = iLBound; i <= iUBound; i++)
  146. {
  147. par.szName = NULL;
  148. par.szValue = NULL;
  149. VariantInit(&vValue);
  150. vUnknown = NULL;
  151. hRetRes = SafeArrayGetElement(v.parray, &i, &vUnknown);
  152. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  153. pCO = (IWbemClassObject *)vUnknown;
  154. hRetRes = GetStrProperty(pCO, L"Name", &par.szName);
  155. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  156. hRetRes = GetUint32Property(pCO, L"Type", &lType);
  157. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  158. par.lType = lType;
  159. hRetRes = GetStrProperty(pCO, L"Value", &par.szValue);
  160. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  161. m_parameterList.push_back(par);
  162. VariantClear(&vValue);
  163. vUnknown->Release();
  164. }
  165. }
  166. }
  167. }
  168. else
  169. {
  170. MY_HRESASSERT(hRetRes);
  171. return hRetRes;
  172. }
  173. VariantClear(&v);
  174. MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::LoadInstanceFromMOF...", 4);
  175. return S_OK;
  176. error:
  177. MY_ASSERT(FALSE);
  178. VariantClear(&v);
  179. m_bValidLoad = FALSE;
  180. Cleanup(FALSE);
  181. if (m_szObjectPath)
  182. {
  183. delete [] m_szObjectPath;
  184. m_szObjectPath = NULL;
  185. }
  186. if (m_szMethodName)
  187. {
  188. delete [] m_szMethodName;
  189. m_szMethodName = NULL;
  190. }
  191. iSize = m_parameterList.size();
  192. for (i=0; i<iSize ;i++)
  193. {
  194. MY_ASSERT(i<m_parameterList.size());
  195. pparameter = &m_parameterList[i];
  196. if (pparameter->szName)
  197. {
  198. delete [] pparameter->szName;
  199. }
  200. if (pparameter->szValue)
  201. {
  202. delete [] pparameter->szValue;
  203. }
  204. }
  205. return hRetRes;
  206. }
  207. BOOL CPolledMethodDataCollector::CollectInstance(void)
  208. {
  209. BOOL bRetValue = TRUE;
  210. int iSize;
  211. int i;
  212. PARSTRUCT *pparameter;
  213. HRESULT hRetRes = S_OK;
  214. VARIANT var;
  215. SAFEARRAY* psa = NULL;
  216. IWbemClassObject *pObj = NULL;
  217. IWbemClassObject *pClass = NULL;
  218. IWbemClassObject *pOutInst = NULL;
  219. IWbemClassObject *pInClass = NULL;
  220. IWbemClassObject *pInInst = NULL;
  221. BSTR ClassPath = NULL;
  222. BSTR MethodName = NULL;
  223. INSTSTRUCT inst;
  224. VariantInit(&var);
  225. MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::CollectInstance...", 1);
  226. m_lNumInstancesCollected = 0;
  227. if (m_pIWbemServices == NULL)
  228. {
  229. m_ulErrorCode = HMRES_BADWMI;
  230. GetLatestAgentError(HMRES_BADWMI, m_szErrorDescription);
  231. StoreStandardProperties();
  232. return FALSE;
  233. }
  234. //
  235. // We get an instance at a time, so we can set all to not needed first,
  236. // then go through them, do StoreValues... and delete what is not needed.
  237. //
  238. //
  239. // Mark each instance, so we can tell if we still need them.
  240. //
  241. #ifdef SAVE
  242. iSize = m_pnList.size();
  243. for (i = 0; i < iSize ; i++)
  244. {
  245. MY_ASSERT(i<m_pnList.size());
  246. ppn = &m_pnList[i];
  247. jSize = ppn->instList.size();
  248. for (j = 0; j < jSize ; j++)
  249. {
  250. MY_ASSERT(j<ppn->instList.size());
  251. pinst = &ppn->instList[j];
  252. pinst->bNeeded = FALSE;
  253. }
  254. }
  255. #endif
  256. ClassPath = SysAllocString(m_szObjectPath);
  257. MY_ASSERT(ClassPath); if (!ClassPath) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
  258. MethodName = SysAllocString(m_szMethodName);
  259. MY_ASSERT(MethodName); if (!MethodName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
  260. hRetRes = m_pIWbemServices->GetObject(ClassPath, 0, NULL, &pClass, NULL);
  261. if (FAILED(hRetRes) || pClass == NULL)
  262. {
  263. m_lCurrState = HM_WARNING;
  264. }
  265. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK || pClass == NULL) goto error;
  266. // Get the input-argument class object and create an instance.
  267. hRetRes = pClass->GetMethod(MethodName, 0, &pInClass, NULL);
  268. if (FAILED(hRetRes) || pClass == NULL)
  269. {
  270. m_lCurrState = HM_WARNING;
  271. }
  272. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK || pInClass == NULL) goto error;
  273. hRetRes = pInClass->SpawnInstance(0, &pInInst);
  274. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  275. //
  276. // Set the IN parameters - they are actually properties on the instance we pass in.
  277. // We will do error checking to make sure that there is one by that name, by seeing
  278. // if the Put fails.
  279. //
  280. iSize = m_parameterList.size();
  281. for (i=0; i<iSize ;i++)
  282. {
  283. MY_ASSERT(i<m_parameterList.size());
  284. pparameter = &m_parameterList[i];
  285. VariantInit(&var);
  286. if (pparameter->lType == CIM_SINT8 ||
  287. pparameter->lType == CIM_SINT16 ||
  288. pparameter->lType == CIM_CHAR16)
  289. {
  290. V_VT(&var) = VT_I2;
  291. V_I2(&var) = _wtol(pparameter->szValue);
  292. }
  293. else if (pparameter->lType == CIM_SINT32 ||
  294. pparameter->lType == CIM_UINT16 ||
  295. pparameter->lType == CIM_UINT32)
  296. {
  297. V_VT(&var) = VT_I4;
  298. V_I4(&var) = _wtol(pparameter->szValue);
  299. }
  300. else if (pparameter->lType == CIM_REAL32)
  301. {
  302. V_VT(&var) = VT_R4;
  303. V_R4(&var) = wcstod(pparameter->szValue, NULL);
  304. }
  305. else if (pparameter->lType == CIM_BOOLEAN)
  306. {
  307. V_VT(&var) = VT_BOOL;
  308. V_BOOL(&var) = (BOOL) _wtol(pparameter->szValue);
  309. }
  310. else if (pparameter->lType == CIM_SINT64 ||
  311. pparameter->lType == CIM_UINT64 ||
  312. //XXX pparameter->lType == CIM_REF ||
  313. pparameter->lType == CIM_STRING ||
  314. pparameter->lType == CIM_DATETIME)
  315. {
  316. V_VT(&var) = VT_BSTR;
  317. V_BSTR(&var) = SysAllocString(pparameter->szValue);
  318. }
  319. else if (pparameter->lType == CIM_REAL64)
  320. {
  321. V_VT(&var) = VT_R8;
  322. V_R8(&var) = wcstod(pparameter->szValue, NULL);
  323. }
  324. else if (pparameter->lType == CIM_UINT8)
  325. {
  326. V_VT(&var) = VT_UI1;
  327. V_UI1(&var) = (unsigned char) _wtoi(pparameter->szValue);
  328. }
  329. else
  330. {
  331. MY_ASSERT(FALSE);
  332. }
  333. hRetRes = pInInst->Put(pparameter->szName, 0, &var, 0);
  334. MY_HRESASSERT(hRetRes);
  335. VariantClear(&var);
  336. if (psa != NULL)
  337. {
  338. SafeArrayDestroy(psa);
  339. psa = NULL;
  340. }
  341. }
  342. //
  343. // Call the method.
  344. //
  345. hRetRes = m_pIWbemServices->ExecMethod(ClassPath, MethodName, WBEM_FLAG_RETURN_IMMEDIATELY, m_pContext, pInInst, &pOutInst, &m_pCallResult);
  346. if (hRetRes != S_OK)
  347. {
  348. MY_HRESASSERT(hRetRes);
  349. MY_OUTPUT2(L"PMDE - ExecMethod Error: 0x%08x",hRetRes,4);
  350. MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
  351. m_ulErrorCode = hRetRes;
  352. GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRetRes, m_szErrorDescription);
  353. StoreStandardProperties();
  354. bRetValue = FALSE;
  355. }
  356. else
  357. {
  358. m_bKeepCollectingSemiSync = TRUE;
  359. bRetValue = CollectInstanceSemiSync();
  360. }
  361. //
  362. // Free up resources.
  363. //
  364. SysFreeString(ClassPath);
  365. ClassPath = NULL;
  366. SysFreeString(MethodName);
  367. MethodName = NULL;
  368. pClass->Release();
  369. pClass = NULL;
  370. pInInst->Release();
  371. pInInst = NULL;
  372. pInClass->Release();
  373. pInClass = NULL;
  374. MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::CollectInstance...", 1);
  375. return bRetValue;
  376. error:
  377. MY_ASSERT(FALSE);
  378. if (ClassPath)
  379. SysFreeString(ClassPath);
  380. if (MethodName)
  381. SysFreeString(MethodName);
  382. if (pClass)
  383. pClass->Release();
  384. if (pInInst)
  385. pInInst->Release();
  386. if (pInClass)
  387. pInClass->Release();
  388. if (psa != NULL)
  389. SafeArrayDestroy(psa);
  390. m_bValidLoad = FALSE;
  391. Cleanup(FALSE);
  392. return hRetRes;
  393. }
  394. BOOL CPolledMethodDataCollector::CollectInstanceSemiSync(void)
  395. {
  396. HRESULT hRetRes = S_OK;
  397. IWbemClassObject *pObj = NULL;
  398. PNSTRUCT *ppn;
  399. INSTSTRUCT inst;
  400. CThreshold *pThreshold;
  401. long lStatus;
  402. ULONG uReturned = 0;
  403. int i, iSize;
  404. InstIDSTRUCT InstID;
  405. MY_OUTPUT(L"ENTER ***** CPolledMethodDataCollector::CollectInstanceSemiSync...", 1);
  406. MY_ASSERT(m_pCallResult);
  407. lStatus = 0;
  408. //
  409. // Keep trying until we get WBEM_S_NO_ERROR. Then we know the GetObject call has completed.
  410. // hRes will contain the result of the origional GetObject call if needed.
  411. //
  412. hRetRes = m_pCallResult->GetCallStatus(0, &lStatus);
  413. if (hRetRes == WBEM_S_TIMEDOUT)
  414. {
  415. return FALSE;
  416. }
  417. else if (hRetRes == WBEM_S_NO_ERROR)
  418. {
  419. // Means that we have an instance
  420. }
  421. else
  422. {
  423. MY_HRESASSERT(hRetRes);
  424. MY_OUTPUT2(L"PMDE - GetCallStatus Error: 0x%08x",hRetRes,4);
  425. MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
  426. MY_OUTPUT2(L"ClassPath was=%s",m_szObjectPath,4);
  427. MY_OUTPUT2(L"MethodName was=%s",m_szMethodName,4);
  428. m_ulErrorCode = 0;
  429. EnumDone();
  430. return FALSE;
  431. }
  432. //
  433. // This may mean that the call completed, and the object was not found (e.g. bad path).
  434. //
  435. if (lStatus != 0)
  436. {
  437. m_lCurrState = HM_WARNING;
  438. m_ulErrorCode = 0;
  439. EnumDone();
  440. return FALSE;
  441. }
  442. //
  443. // Get the Object finaly.
  444. //
  445. hRetRes = m_pCallResult->GetResultObject(0, &pObj);
  446. if (pObj == NULL)
  447. {
  448. //
  449. // NULL in this case can actually happen. An example is where the
  450. // threshold is to see if the SQL Server service is running. If it
  451. // is not even on the machine, then we would get an error looking
  452. // for its instance.
  453. //
  454. m_lCurrState = HM_WARNING;
  455. EnumDone();
  456. }
  457. else
  458. {
  459. EnumDone();
  460. //
  461. // Figure out the key property name to identify instances with.
  462. //
  463. iSize = m_instIDList.size();
  464. if (iSize == 0)
  465. {
  466. // There is no key property returned!!!
  467. InstID.szInstanceIDPropertyName = new TCHAR[7];
  468. MY_ASSERT(InstID.szInstanceIDPropertyName); if (!InstID.szInstanceIDPropertyName) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
  469. wcscpy(InstID.szInstanceIDPropertyName , L"Method");
  470. m_instIDList.push_back(InstID);
  471. // Add an instance to each property name
  472. iSize = m_pnList.size();
  473. for (i=0; i < iSize ; i++)
  474. {
  475. MY_ASSERT(i<m_pnList.size());
  476. ppn = &m_pnList[i];
  477. inst.szInstanceID = new TCHAR[2];
  478. MY_ASSERT(inst.szInstanceID); if (!inst.szInstanceID) {hRetRes = WBEM_E_OUT_OF_MEMORY; goto error;}
  479. wcscpy(inst.szInstanceID, L"");
  480. inst.szCurrValue = NULL;
  481. ResetInst(&inst, ppn->type);
  482. inst.bNull = FALSE;
  483. inst.bNeeded = TRUE;
  484. ppn->instList.push_back(inst);
  485. }
  486. //Also add instance for all thresholds under this DataCollector
  487. iSize = m_thresholdList.size();
  488. for (i=0; i < iSize ; i++)
  489. {
  490. MY_ASSERT(i<m_thresholdList.size());
  491. pThreshold = m_thresholdList[i];
  492. hRetRes = pThreshold->AddInstance(L"");
  493. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  494. }
  495. }
  496. MY_ASSERT(m_instIDList.size());
  497. //
  498. // Check the list of actual instances that the Data Collector is collecting.
  499. // We keep around the latest one(s) for the DataCollector.
  500. //
  501. CheckActualInstanceExistance(pObj, L"");
  502. m_lNumInstancesCollected = 1;
  503. StoreValues(pObj, L"");
  504. pObj->Release();
  505. pObj = NULL;
  506. //
  507. // Means that we are done.
  508. // Won't ever get here the first time
  509. // Add in a fake instance for the number of instances returned.
  510. //
  511. m_lCurrState = HM_GOOD;
  512. m_ulErrorCode = 0;
  513. StoreStandardProperties();
  514. }
  515. MY_OUTPUT(L"EXIT ***** CPolledMethodDataCollector::CollectInstanceSemiSync...", 1);
  516. return TRUE;
  517. error:
  518. MY_ASSERT(FALSE);
  519. if (pObj)
  520. pObj->Release();
  521. m_bValidLoad = FALSE;
  522. Cleanup(FALSE);
  523. return FALSE;
  524. }
  525. BOOL CPolledMethodDataCollector::CleanupSemiSync(void)
  526. {
  527. if (m_pCallResult)
  528. {
  529. m_pCallResult->Release();
  530. m_pCallResult = NULL;
  531. }
  532. m_bKeepCollectingSemiSync = FALSE;
  533. m_lCollectionTimeOutCount = 0;
  534. return TRUE;
  535. }
  536. BOOL CPolledMethodDataCollector::EnumDone(void)
  537. {
  538. CleanupSemiSync();
  539. return TRUE;
  540. }