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.

468 lines
11 KiB

  1. //***************************************************************************
  2. //
  3. // PQDE.CPP
  4. //
  5. // Module: HEALTHMON SERVER AGENT
  6. //
  7. // Purpose: CPolledQueryDataCollector class to do WMI instance collection.
  8. //
  9. // Copyright (c)1999 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "pqde.h"
  13. #include "system.h"
  14. extern CSystem* g_pSystem;
  15. //////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. CPolledQueryDataCollector::CPolledQueryDataCollector()
  20. {
  21. MY_OUTPUT(L"ENTER ***** CPolledQueryDataCollector...", 4);
  22. m_szQuery = NULL;
  23. m_deType = HM_PQDE;
  24. m_pEnumObjs = NULL;
  25. MY_OUTPUT(L"EXIT ***** CPolledQueryDataCollector...", 4);
  26. }
  27. CPolledQueryDataCollector::~CPolledQueryDataCollector()
  28. {
  29. MY_OUTPUT(L"ENTER ***** ~CPolledQueryDataCollector...", 4);
  30. if (m_szQuery)
  31. delete [] m_szQuery;
  32. EnumDone();
  33. MY_OUTPUT(L"EXIT ***** ~CPolledQueryDataCollector...", 4);
  34. }
  35. //
  36. // Load a single DataCollector, and everything under it.
  37. //
  38. HRESULT CPolledQueryDataCollector::LoadInstanceFromMOF(IWbemClassObject* pObj, CDataGroup *pParentDG, LPTSTR pszParentObjPath, BOOL bModifyPass/*FALSE*/)
  39. {
  40. HRESULT hRetRes = S_OK;
  41. int i, iSize;
  42. CThreshold* pThreshold;
  43. MY_OUTPUT(L"ENTER ***** CPolledQueryDataCollector::LoadInstanceFromMOF...", 4);
  44. iSize = m_thresholdList.size();
  45. for (i = 0; i < iSize ; i++)
  46. {
  47. MY_ASSERT(i<m_thresholdList.size());
  48. pThreshold = m_thresholdList[i];
  49. if (pThreshold->m_bValidLoad == FALSE)
  50. return WBEM_E_INVALID_OBJECT;
  51. // return S_OK;
  52. }
  53. if (m_szQuery)
  54. {
  55. delete [] m_szQuery;
  56. m_szQuery = NULL;
  57. }
  58. m_lNumInstancesCollected = 0;
  59. //
  60. // Call the base class to load the common properties. Then do the specific ones.
  61. //
  62. hRetRes = CDataCollector::LoadInstanceFromMOF(pObj, pParentDG, pszParentObjPath, bModifyPass);
  63. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) return hRetRes;
  64. // Get the GUID property
  65. hRetRes = GetStrProperty(pObj, L"Query", &m_szQuery);
  66. MY_HRESASSERT(hRetRes); if (hRetRes!=S_OK) goto error;
  67. MY_OUTPUT(L"EXIT ***** CPolledQueryDataCollector::LoadInstanceFromMOF...", 4);
  68. return S_OK;
  69. error:
  70. MY_ASSERT(FALSE);
  71. m_bValidLoad = FALSE;
  72. Cleanup(FALSE);
  73. return hRetRes;
  74. }
  75. BOOL CPolledQueryDataCollector::CollectInstance(void)
  76. {
  77. HRESULT hRes;
  78. BSTR Language;
  79. BSTR Query;
  80. IWbemClassObject *pObj = NULL;
  81. BOOL bRetValue = TRUE;
  82. SAFEARRAY *psaNames = NULL;
  83. BSTR PropName = NULL;
  84. int i, j, iSize, jSize;
  85. PNSTRUCT *ppn;
  86. INSTSTRUCT *pinst;
  87. INSTSTRUCT inst;
  88. CThreshold *pThreshold;
  89. IRSSTRUCT *pirs;
  90. ACTUALINSTSTRUCT *pActualInst;
  91. MY_OUTPUT(L"ENTER ***** CPolledQueryDataCollector::CollectInstance...", 1);
  92. m_lNumInstancesCollected = 0;
  93. if (m_pIWbemServices == NULL)
  94. {
  95. m_ulErrorCode = HMRES_BADWMI;
  96. GetLatestAgentError(HMRES_BADWMI, m_szErrorDescription);
  97. StoreStandardProperties();
  98. return FALSE;
  99. }
  100. //
  101. // We get an instance at a time, so we can set all to not needed first,
  102. // then go through them, do StoreValues... and delete what is not needed.
  103. //
  104. //
  105. // Mark each instance, so we can tell if we still need them.
  106. //
  107. iSize = m_pnList.size();
  108. for (i = 0; i < iSize ; i++)
  109. {
  110. MY_ASSERT(i<m_pnList.size());
  111. ppn = &m_pnList[i];
  112. jSize = ppn->instList.size();
  113. for (j = 0; j < jSize ; j++)
  114. {
  115. MY_ASSERT(j<ppn->instList.size());
  116. pinst = &ppn->instList[j];
  117. pinst->bNeeded = FALSE;
  118. }
  119. }
  120. // Also for all thresholds under this DataCollector
  121. iSize = m_thresholdList.size();
  122. for (i = 0; i < iSize; i++)
  123. {
  124. MY_ASSERT(i<m_thresholdList.size());
  125. pThreshold = m_thresholdList[i];
  126. jSize = pThreshold->m_irsList.size();
  127. for (j = 0; j < jSize; j++)
  128. {
  129. MY_ASSERT(j<pThreshold->m_irsList.size());
  130. pirs = &pThreshold->m_irsList[j];
  131. pirs->bNeeded = FALSE;
  132. }
  133. }
  134. iSize = m_actualInstList.size();
  135. for (i=0; i < iSize; i++)
  136. {
  137. MY_ASSERT(i<m_actualInstList.size());
  138. pActualInst = &m_actualInstList[i];
  139. pActualInst->bNeeded = FALSE;
  140. }
  141. //
  142. // Submit the query, then get all the instances
  143. //
  144. Language = SysAllocString(L"WQL");
  145. Query = SysAllocString(m_szQuery);
  146. // Issue query
  147. m_pEnumObjs = NULL;
  148. hRes = m_pIWbemServices->ExecQuery(Language, Query, WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, m_pContext, &m_pEnumObjs);
  149. SysFreeString(Query);
  150. SysFreeString(Language);
  151. if (hRes != S_OK)
  152. {
  153. m_ulErrorCode = hRes;
  154. GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
  155. StoreStandardProperties();
  156. bRetValue = FALSE;
  157. MY_HRESASSERT(hRes);
  158. MY_OUTPUT2(L"PQDC Unexpected Error: 0x%08x\n",hRes,4);
  159. MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
  160. MY_OUTPUT2(L"m_szQuery was=%s",m_szQuery,4);
  161. }
  162. else
  163. {
  164. m_bKeepCollectingSemiSync = TRUE;
  165. bRetValue = CollectInstanceSemiSync();
  166. }
  167. MY_OUTPUT(L"EXIT ***** CPolledQueryDataCollector::CollectInstance...", 1);
  168. return bRetValue;
  169. }
  170. BOOL CPolledQueryDataCollector::CollectInstanceSemiSync(void)
  171. {
  172. HRESULT hRes;
  173. IWbemClassObject *apObj[10];
  174. INSTSTRUCT inst;
  175. SAFEARRAY *psaNames = NULL;
  176. BSTR PropName = NULL;
  177. ULONG uReturned = 0;
  178. MY_OUTPUT(L"ENTER ***** CPolledQueryDataCollector::CollectInstanceSemiSync...", 1);
  179. MY_ASSERT(m_pEnumObjs);
  180. // We never want to block here, so we set it for zero second timeout,
  181. // and have it return immediatly what it has available.
  182. // Get up to 10 instances at a time.
  183. hRes = m_pEnumObjs->Next(0, 10, apObj, &uReturned);
  184. if (hRes == WBEM_S_TIMEDOUT)
  185. {
  186. // Get what is there
  187. if (!ProcessObjects(uReturned, apObj))
  188. {
  189. EnumDone();
  190. return FALSE;
  191. }
  192. return FALSE;
  193. }
  194. else if (hRes == WBEM_S_FALSE)
  195. {
  196. //
  197. // Means that we are done. The number returned was less than asked for.
  198. // But we still process what we did recieve to finish it off.
  199. // Add in a fake instance for the number of instances returned.
  200. //
  201. if (!ProcessObjects(uReturned, apObj))
  202. {
  203. EnumDone();
  204. return FALSE;
  205. }
  206. else
  207. {
  208. // NOTE: No instances returned is not an error!!!
  209. m_ulErrorCode = 0;
  210. StoreStandardProperties();
  211. EnumDone();
  212. //XXXWhy was this here??? m_lCurrState = HM_GOOD;
  213. return TRUE;
  214. }
  215. }
  216. else if (hRes == WBEM_S_NO_ERROR)
  217. {
  218. // Means that we have an instance, The number returned was what was requested
  219. }
  220. else
  221. {
  222. MY_HRESASSERT(hRes);
  223. MY_OUTPUT2(L"PQDC Unexpected Error Next: 0x%08x\n",hRes,4);
  224. MY_OUTPUT2(L"m_szGUID was=%s",m_szGUID,4);
  225. m_ulErrorCode = hRes;
  226. GetLatestWMIError(HMRES_ENUMFAIL, hRes, m_szErrorDescription);
  227. StoreStandardProperties();
  228. EnumDone();
  229. return FALSE;
  230. }
  231. if (apObj[0] == NULL)
  232. {
  233. //
  234. // NULL in this case can actually happen. An example is where the
  235. // threshold is to see if the SQL Server service is running. If it
  236. // is not even on the machine, then we would get an error looking
  237. // for its instance.
  238. //
  239. m_ulErrorCode = hRes;
  240. GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
  241. StoreStandardProperties();
  242. EnumDone();
  243. }
  244. else
  245. {
  246. MY_ASSERT(uReturned>=1);
  247. if (!ProcessObjects(uReturned, apObj))
  248. {
  249. EnumDone();
  250. return FALSE;
  251. }
  252. }
  253. MY_OUTPUT(L"EXIT ***** CPolledQueryDataCollector::CollectInstanceSemiSync...", 1);
  254. return FALSE;
  255. }
  256. BOOL CPolledQueryDataCollector::ProcessObjects(ULONG uReturned, IWbemClassObject **apObj)
  257. {
  258. HRESULT hRes;
  259. LPTSTR pszID;
  260. ULONG n;
  261. BOOL bRetValue = TRUE;
  262. for (n = 0; n < uReturned; n++)
  263. {
  264. if (g_pSystem->m_lNumInstancesAccepted <m_lNumInstancesCollected)
  265. {
  266. m_ulErrorCode = HMRES_TOOMANYINSTS;
  267. GetLatestAgentError(HMRES_TOOMANYINSTS, m_szErrorDescription);
  268. StoreStandardProperties();
  269. bRetValue = FALSE;
  270. break;
  271. }
  272. //
  273. // Figure out the key property name to identify instances with.
  274. //
  275. hRes = GetInstanceID(apObj[n], &pszID);
  276. if (hRes != S_OK)
  277. {
  278. m_ulErrorCode = hRes;
  279. GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
  280. StoreStandardProperties();
  281. bRetValue = FALSE;
  282. break;
  283. }
  284. //
  285. // Mark instances need to keep around, and add new ones
  286. //
  287. hRes = CheckInstanceExistance(apObj[n], pszID);
  288. if (hRes != S_OK)
  289. {
  290. delete [] pszID;
  291. m_ulErrorCode = hRes;
  292. GetLatestWMIError(HMRES_OBJECTNOTFOUND, hRes, m_szErrorDescription);
  293. StoreStandardProperties();
  294. bRetValue = FALSE;
  295. break;
  296. }
  297. //
  298. // Now store each property that we need to for this instance
  299. //
  300. m_lNumInstancesCollected++;
  301. StoreValues(apObj[n], pszID);
  302. delete [] pszID;
  303. }
  304. for (n = 0; n < uReturned; n++)
  305. {
  306. apObj[n]->Release();
  307. apObj[n] = NULL;
  308. }
  309. return bRetValue;
  310. }
  311. BOOL CPolledQueryDataCollector::EnumDone(void)
  312. {
  313. IRSSTRUCT *pirs;
  314. IWbemClassObject *pObj = NULL;
  315. BOOL bRetValue = TRUE;
  316. PNSTRUCT *ppn;
  317. INSTSTRUCT inst;
  318. INSTSTRUCT *pinst;
  319. int i, j, iSize, jSize;
  320. CThreshold *pThreshold;
  321. SAFEARRAY *psaNames = NULL;
  322. BSTR PropName = NULL;
  323. INSTLIST::iterator iaPINST;
  324. IRSLIST::iterator iaPIRS;
  325. ACTUALINSTLIST::iterator iaPAI;
  326. ACTUALINSTSTRUCT *pActualInst;
  327. CleanupSemiSync();
  328. //XXXAdd similar code to get rid of what is not needed in the m_instList
  329. //XXXOnce again take common code and place it in the base class!VVVVVVVVVVVVVVVVVVVVVVVVv
  330. //
  331. // Now loop through and get rid of instances that are no longer around
  332. //
  333. iSize = m_pnList.size();
  334. for (i = 0; i < iSize; i++)
  335. {
  336. MY_ASSERT(i<m_pnList.size());
  337. ppn = &m_pnList[i];
  338. iaPINST = ppn->instList.begin();
  339. jSize = ppn->instList.size();
  340. for (j = 0; j < jSize && iaPINST ; j++)
  341. {
  342. pinst = iaPINST;
  343. if (pinst->bNeeded == FALSE)
  344. {
  345. if (pinst->szInstanceID)
  346. delete [] pinst->szInstanceID;
  347. if (pinst->szCurrValue)
  348. delete [] pinst->szCurrValue;
  349. pinst->szCurrValue = NULL;
  350. iaPINST = ppn->instList.erase(iaPINST);
  351. }
  352. else
  353. {
  354. iaPINST++;
  355. }
  356. }
  357. }
  358. // Also for all thresholds under this DataCollector
  359. iSize = m_thresholdList.size();
  360. for (i = 0; i < iSize; i++)
  361. {
  362. MY_ASSERT(i<m_thresholdList.size());
  363. pThreshold = m_thresholdList[i];
  364. iaPIRS = pThreshold->m_irsList.begin();
  365. jSize = pThreshold->m_irsList.size();
  366. for (j = 0; j < jSize && iaPIRS ; j++)
  367. {
  368. pirs = iaPIRS;
  369. if (pirs->bNeeded == FALSE)
  370. {
  371. if (pirs->szInstanceID)
  372. delete [] pirs->szInstanceID;
  373. iaPIRS = pThreshold->m_irsList.erase(iaPIRS);
  374. }
  375. else
  376. {
  377. iaPIRS++;
  378. }
  379. }
  380. }
  381. iaPAI = m_actualInstList.begin();
  382. jSize = m_actualInstList.size();
  383. for (j = 0; j < jSize && iaPAI; j++)
  384. {
  385. pActualInst = iaPAI;
  386. if (pActualInst->bNeeded == FALSE)
  387. {
  388. if (pActualInst->szInstanceID)
  389. {
  390. delete [] pActualInst->szInstanceID;
  391. }
  392. if (pActualInst->pInst)
  393. {
  394. pActualInst->pInst->Release();
  395. pActualInst->pInst = NULL;
  396. }
  397. iaPAI = m_actualInstList.erase(iaPAI);
  398. }
  399. else
  400. {
  401. iaPAI++;
  402. }
  403. }
  404. //XXXOnce again take common code and place it in the base class!^^^^^^^^^^^^^^^^^^^^^^^^^
  405. return TRUE;
  406. }
  407. BOOL CPolledQueryDataCollector::CleanupSemiSync(void)
  408. {
  409. if (m_pEnumObjs)
  410. {
  411. m_pEnumObjs->Release();
  412. m_pEnumObjs = NULL;
  413. }
  414. m_bKeepCollectingSemiSync = FALSE;
  415. m_lCollectionTimeOutCount = 0;
  416. return TRUE;
  417. }