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.

489 lines
17 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1998-1999 by Microsoft Corp.
  4. //
  5. // CLASSMAP.CPP
  6. //
  7. // Mapped NT5 Perf Counter Provider
  8. //
  9. // raymcc 02-Dec-97 Created.
  10. // raymcc 20-Feb-98 Updated to use new initializer.
  11. // bobw 8-Jub-98 optimized for use with NT Perf counters
  12. //
  13. //***************************************************************************
  14. #include <wpheader.h>
  15. #include "oahelp.inl"
  16. //***************************************************************************
  17. //
  18. // CClassMapInfo::CClassMapInfo()
  19. //
  20. // The objective of the map is to have one instance for each CIM class.
  21. // Internally, a map of perf object ids to CIM property handles is maintained
  22. // for the class.
  23. //
  24. // Later, when instances are requested, the blob is retrieved from
  25. // HKEY_PERFORMANCE_DATA, and the object IDs in the blob are used to
  26. // look up the property handles, which are then used to populate instances.
  27. //
  28. // Property names are never really used except in the mapping phase.
  29. //
  30. //***************************************************************************
  31. // ok
  32. CClassMapInfo::CClassMapInfo()
  33. {
  34. m_pClassDef = 0; // The CIM class definition
  35. m_pszClassName = 0; // The UNICODE class name
  36. m_dwObjectId = 0; // Perf object Id
  37. m_bSingleton = FALSE;
  38. m_bCostly = FALSE;
  39. m_dwNumProps = 0; // Number of props in class, size
  40. // of the following arrays
  41. m_lRefCount = 0; // nothing mapped yet
  42. // These are pointers to parallel arrays, all of the same
  43. // size (m_dwNumProps)
  44. // ============================================================
  45. m_pdwIDs = 0; // IDs of properties
  46. m_pdwHandles = 0; // Handles to properties
  47. m_pdwTypes = 0; // Types of properties
  48. m_dwNameHandle = 0; // The 'Name' property
  49. m_dwPerfTimeStampHandle = 0; // the Perf time TimeStamp property
  50. m_dw100NsTimeStampHandle = 0; // the 100 Ns Perf TimeStamp property
  51. m_dwObjectTimeStampHandle = 0; // the Object TimeStamp property
  52. m_dwPerfFrequencyHandle = 0; // the Perf time frequency property
  53. m_dw100NsFrequencyHandle = 0; // the 100 Ns Perf frequency property
  54. m_dwObjectFrequencyHandle = 0; // the Object frequency property
  55. }
  56. //***************************************************************************
  57. //
  58. // CClassMapInfo::~CClassMapInfo
  59. //
  60. //***************************************************************************
  61. // ok
  62. CClassMapInfo::~CClassMapInfo()
  63. {
  64. // this can be destructed only if it's the last item referencing it.
  65. // if there's another reference to this class, it should have been
  66. // released before the destructor was called.
  67. assert (m_lRefCount <= 1);
  68. if (m_pClassDef)
  69. m_pClassDef->Release();
  70. if (m_pszClassName != NULL) { delete [] m_pszClassName; m_pszClassName = NULL;}
  71. if (m_pdwIDs != NULL) { delete [] m_pdwIDs; m_pdwIDs = NULL; }
  72. if (m_pdwHandles != NULL) { delete [] m_pdwHandles; m_pdwHandles = NULL; }
  73. if (m_pdwTypes != NULL) { delete [] m_pdwTypes; m_pdwTypes = NULL; }
  74. }
  75. //***************************************************************************
  76. //
  77. // CClassMapInfo::Copy(CClassMapInfo *pClassMap)
  78. //
  79. // allocates an new Class Map entry and copies the data from the
  80. // class map passed into it and returns a pointer to the duplicate entry
  81. //
  82. //
  83. //***************************************************************************
  84. // ok
  85. CClassMapInfo * CClassMapInfo::CreateDuplicate()
  86. {
  87. CClassMapInfo *pOrigClassMap = this;
  88. CClassMapInfo *pNewClassMap = NULL;
  89. DWORD i;
  90. pNewClassMap = new CClassMapInfo;
  91. if (pNewClassMap != NULL) {
  92. pNewClassMap->m_pClassDef = pOrigClassMap->m_pClassDef;
  93. pNewClassMap->m_pClassDef->AddRef();
  94. if (pOrigClassMap->m_pszClassName != NULL) {
  95. pNewClassMap->m_pszClassName =
  96. new WCHAR[lstrlenW(pOrigClassMap->m_pszClassName)+1];
  97. if (pNewClassMap->m_pszClassName != NULL) {
  98. lstrcpyW (pNewClassMap->m_pszClassName, pOrigClassMap->m_pszClassName);
  99. pNewClassMap->m_bSingleton = pOrigClassMap->m_bSingleton;
  100. pNewClassMap->m_bCostly = pOrigClassMap->m_bCostly;
  101. pNewClassMap->m_dwObjectId = pOrigClassMap->m_dwObjectId;
  102. pNewClassMap->m_lRefCount = 1;
  103. pNewClassMap->m_dwNameHandle = pOrigClassMap->m_dwNameHandle;
  104. pNewClassMap->m_dwPerfTimeStampHandle = pOrigClassMap->m_dwPerfTimeStampHandle;
  105. pNewClassMap->m_dw100NsTimeStampHandle = pOrigClassMap->m_dw100NsTimeStampHandle;
  106. pNewClassMap->m_dwObjectTimeStampHandle = pOrigClassMap->m_dwObjectTimeStampHandle;
  107. pNewClassMap->m_dwPerfFrequencyHandle = pOrigClassMap->m_dwPerfFrequencyHandle;
  108. pNewClassMap->m_dw100NsFrequencyHandle = pOrigClassMap->m_dw100NsFrequencyHandle;
  109. pNewClassMap->m_dwObjectFrequencyHandle = pOrigClassMap->m_dwObjectFrequencyHandle;
  110. pNewClassMap->m_dwNumProps = pOrigClassMap->m_dwNumProps;
  111. pNewClassMap->m_pdwIDs = new PerfObjectId[pNewClassMap->m_dwNumProps];
  112. pNewClassMap->m_pdwHandles = new DWORD[pNewClassMap->m_dwNumProps];
  113. pNewClassMap->m_pdwTypes = new DWORD[pNewClassMap->m_dwNumProps];
  114. if ((pNewClassMap->m_pdwIDs != NULL) &&
  115. (pNewClassMap->m_pdwHandles != NULL) &&
  116. (pNewClassMap->m_pdwTypes != NULL)) {
  117. // copy each table to the new object
  118. for (i = 0; i < pNewClassMap->m_dwNumProps; i++) {
  119. pNewClassMap->m_pdwIDs[i] = pOrigClassMap->m_pdwIDs[i];
  120. pNewClassMap->m_pdwHandles[i] = pOrigClassMap->m_pdwHandles[i];
  121. pNewClassMap->m_pdwTypes[i] = pOrigClassMap->m_pdwTypes[i];
  122. }
  123. }
  124. else {
  125. delete pNewClassMap;
  126. pNewClassMap = NULL;
  127. }
  128. } else {
  129. delete pNewClassMap;
  130. pNewClassMap = NULL;
  131. }
  132. }
  133. }
  134. return pNewClassMap;
  135. }
  136. //***************************************************************************
  137. //
  138. // CClassMapInfo::Map()
  139. //
  140. // Maps the inbound class definition by:
  141. //
  142. // (1) Retrieving the perf object id from the class definition.
  143. // (2) Retrieving the property handles, perf ids, and types for each
  144. // property.
  145. //
  146. //
  147. //***************************************************************************
  148. // ok
  149. BOOL CClassMapInfo::Map(IWbemClassObject *pObj)
  150. {
  151. int nIndex = 0;
  152. IWbemObjectAccess *pAlias = 0;
  153. IWbemQualifierSet *pQSet = 0;
  154. HRESULT hRes;
  155. VARIANT vPropertyCount;
  156. VARIANT vClsName;
  157. VARIANT vPerfObjType;
  158. VARIANT vSingleton;
  159. VARIANT vCostly;
  160. VARIANT vCounter;
  161. VARIANT vCounterType;
  162. CBSTR cbPerfIndex(cszPerfIndex);
  163. CBSTR cbCountertype(cszCountertype);
  164. BOOL bReturn = TRUE;
  165. VariantInit(&vPropertyCount);
  166. VariantInit(&vClsName);
  167. VariantInit(&vPerfObjType);
  168. VariantInit(&vSingleton);
  169. VariantInit(&vCostly);
  170. VariantInit(&vCounter);
  171. VariantInit(&vCounterType);
  172. // Copy the class definition.
  173. // ==========================
  174. m_pClassDef = pObj;
  175. //m_pClassDef->AddRef(); // this is unnecessary
  176. m_lRefCount++; // bump our ref count
  177. // Get the alternate interface so that we can look up handles.
  178. // ===========================================================
  179. hRes = pObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pAlias);
  180. if (hRes) {
  181. bReturn = FALSE;
  182. }
  183. // Determine the number of properties and allocate
  184. // arrays to hold the handles, perf ids, and types.
  185. // ================================================
  186. if (bReturn) {
  187. hRes = pObj->Get(CBSTR(cszPropertyCount), 0, &vPropertyCount, 0, 0);
  188. if (hRes == NO_ERROR) {
  189. m_dwNumProps = DWORD(V_UI4(&vPropertyCount));
  190. } else {
  191. bReturn = FALSE;
  192. }
  193. VariantClear(&vPropertyCount);
  194. }
  195. // allocate the table of the handles and id's
  196. if (bReturn) {
  197. m_pdwHandles = new DWORD[m_dwNumProps];
  198. assert (m_pdwHandles != NULL);
  199. m_pdwIDs = new PerfObjectId[m_dwNumProps];
  200. assert (m_pdwIDs != NULL);
  201. m_pdwTypes = new DWORD[m_dwNumProps];
  202. assert (m_pdwTypes != NULL);
  203. // check the memory allocations
  204. if ((m_pdwHandles == NULL) ||
  205. (m_pdwIDs == NULL) ||
  206. (m_pdwTypes == NULL)) {
  207. bReturn = FALSE;
  208. }
  209. }
  210. // Clone the class name.
  211. // =====================
  212. if (bReturn) {
  213. hRes = pObj->Get(CBSTR(cszClassName), 0, &vClsName, 0, 0);
  214. if ((hRes == NO_ERROR) && (vClsName.vt == VT_BSTR)) {
  215. m_pszClassName = Macro_CloneLPWSTR(V_BSTR(&vClsName));
  216. if (m_pszClassName == NULL) bReturn = FALSE;
  217. } else {
  218. bReturn = FALSE;
  219. }
  220. VariantClear (&vClsName);
  221. }
  222. // Get the perf object id for the class.
  223. // =====================================
  224. if (bReturn) {
  225. hRes = pObj->GetQualifierSet(&pQSet);
  226. if (hRes == NO_ERROR) {
  227. hRes = pQSet->Get(cbPerfIndex, 0, &vPerfObjType, 0);
  228. if (hRes == NO_ERROR) {
  229. m_dwObjectId = DWORD(V_UI4(&vPerfObjType));
  230. } else {
  231. bReturn = FALSE;
  232. }
  233. VariantClear(&vPerfObjType);
  234. hRes = pQSet->Get(CBSTR(cszSingleton), 0, &vSingleton, 0);
  235. if (hRes == 0) {
  236. m_bSingleton = TRUE;
  237. }
  238. VariantClear (&vSingleton);
  239. hRes = pQSet->Get(CBSTR(cszCostly), 0, &vCostly, 0);
  240. if ((hRes == 0) && (vCostly.vt == VT_BSTR)) {
  241. m_bCostly= TRUE;
  242. }
  243. VariantClear (&vCostly);
  244. pQSet->Release();
  245. } else {
  246. bReturn = FALSE;
  247. }
  248. }
  249. // Enumerate all the properties and get the object ids
  250. // and handles for each.
  251. // ===================================================
  252. hRes = pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  253. if (hRes == NO_ERROR) {
  254. // enumeration handle obtained so
  255. // continue and cache each property
  256. while (bReturn) {
  257. BSTR Name = 0;
  258. DWORD dwCtrId;
  259. DWORD dwCtrType;
  260. IWbemQualifierSet *pQSet = 0;
  261. LONG lType = 0;
  262. LONG lHandle = 0;
  263. hRes = pObj->Next(
  264. 0,
  265. &Name,
  266. 0,
  267. 0,
  268. 0
  269. );
  270. if (hRes == WBEM_S_NO_MORE_DATA) {
  271. break;
  272. }
  273. // Next, get the qualifier set for this property.
  274. // ==============================================
  275. hRes = pObj->GetPropertyQualifierSet(Name, &pQSet);
  276. if (hRes == NO_ERROR) {
  277. hRes = pQSet->Get(cbPerfIndex, 0, &vCounter, 0);
  278. if (hRes == S_OK) {
  279. dwCtrId = (DWORD)V_UI4(&vCounter);
  280. } else {
  281. // unable to read qualifier value
  282. dwCtrId = 0;
  283. }
  284. VariantClear (&vCounter);
  285. hRes = pQSet->Get(cbCountertype, 0, &vCounterType, 0);
  286. if (hRes == S_OK) {
  287. dwCtrType = (DWORD)V_UI4(&vCounterType);
  288. } else {
  289. // unable to read qualifier value
  290. dwCtrType = 0;
  291. }
  292. VariantClear (&vCounterType);
  293. // done with the qualifier set
  294. pQSet->Release();
  295. // Get the property handle and type.
  296. // =================================
  297. hRes = pAlias->GetPropertyHandle(Name, &lType, &lHandle);
  298. if (hRes == NO_ERROR) {
  299. // We now know the counter id, the property handle and its
  300. // type. That is all we really need at runtime to map
  301. // blobs into CIM object.
  302. // =======================================================
  303. m_pdwIDs[nIndex] = CM_MAKE_PerfObjectId (dwCtrId, dwCtrType);
  304. m_pdwHandles[nIndex] = (DWORD) lHandle;
  305. m_pdwTypes[nIndex] = (DWORD) lType;
  306. // this property was loaded successfully so
  307. // advance to the next index
  308. nIndex++;
  309. } else {
  310. // no property handle returned so skip it.
  311. }
  312. } else {
  313. // skip this object since it doesn't have
  314. // a qualifier set
  315. }
  316. // Free the name.
  317. // ==============
  318. SysFreeString(Name);
  319. }
  320. pObj->EndEnumeration();
  321. } else {
  322. // unable to get enumeration handle
  323. bReturn = FALSE;
  324. }
  325. // Get the handle of the 'name' property.
  326. // ======================================
  327. if (bReturn) {
  328. if (!m_bSingleton) {
  329. // only non-singleton classes have this property
  330. pAlias->GetPropertyHandle((LPWSTR)cszName, 0, (LONG *) &m_dwNameHandle);
  331. }
  332. // Get the handle of the "timestamp" properties
  333. pAlias->GetPropertyHandle((LPWSTR)cszTimestampPerfTime, 0, (LONG *) &m_dwPerfTimeStampHandle);
  334. pAlias->GetPropertyHandle((LPWSTR)cszFrequencyPerfTime, 0, (LONG *) &m_dwPerfFrequencyHandle);
  335. pAlias->GetPropertyHandle((LPWSTR)cszTimestampSys100Ns, 0, (LONG *) &m_dw100NsTimeStampHandle);
  336. pAlias->GetPropertyHandle((LPWSTR)cszFrequencySys100Ns, 0, (LONG *) &m_dw100NsFrequencyHandle);
  337. pAlias->GetPropertyHandle((LPWSTR)cszTimestampObject, 0, (LONG *) &m_dwObjectTimeStampHandle);
  338. pAlias->GetPropertyHandle((LPWSTR)cszFrequencyObject, 0, (LONG *) &m_dwObjectFrequencyHandle);
  339. // Cleanup.
  340. // ========
  341. SortHandles();
  342. }
  343. if (pAlias != NULL) pAlias->Release();
  344. return bReturn;
  345. }
  346. //***************************************************************************
  347. //
  348. // CClassMapInfo::SortHandles
  349. //
  350. // Sort the perf object ids for quick searching later in the GetPropHandle
  351. // method.
  352. //
  353. //***************************************************************************
  354. // ok
  355. void CClassMapInfo::SortHandles()
  356. {
  357. DWORD dwOuter;
  358. DWORD dwInner;
  359. DWORD dwTemp;
  360. PerfObjectId poiTemp;
  361. // Simple selection sort. The number of elements is so small
  362. // and this is only done once, so a quicksort / shellsort would be
  363. // overkill.
  364. // ===============================================================
  365. for (dwOuter = 0; dwOuter < m_dwNumProps - 1; dwOuter++)
  366. {
  367. for (dwInner = dwOuter + 1; dwInner < m_dwNumProps; dwInner++)
  368. {
  369. if (m_pdwIDs[dwInner] < m_pdwIDs[dwOuter])
  370. {
  371. poiTemp = m_pdwIDs[dwInner];
  372. m_pdwIDs[dwInner] = m_pdwIDs[dwOuter];
  373. m_pdwIDs[dwOuter] = poiTemp;
  374. dwTemp = m_pdwHandles[dwInner];
  375. m_pdwHandles[dwInner] = m_pdwHandles[dwOuter];
  376. m_pdwHandles[dwOuter] = dwTemp;
  377. dwTemp = m_pdwTypes[dwInner];
  378. m_pdwTypes[dwInner] = m_pdwTypes[dwOuter];
  379. m_pdwTypes[dwOuter] = dwTemp;
  380. }
  381. }
  382. }
  383. }
  384. //***************************************************************************
  385. //
  386. // CClassMapInfo::GetPropHandle
  387. //
  388. // Gets the property handle for a corresponding perf counter id.
  389. // Returns 0 if not found.
  390. //
  391. //***************************************************************************
  392. // ok
  393. LONG CClassMapInfo::GetPropHandle(PerfObjectId dwId)
  394. {
  395. // Binary search.
  396. // ==============
  397. LONG l;
  398. LONG u;
  399. LONG m;
  400. LONG lReturn = 0;
  401. if (m_dwNumProps > 0) {
  402. l = 0;
  403. u = m_dwNumProps - 1;
  404. while (l <= u)
  405. {
  406. m = (l + u) / 2;
  407. if (dwId < m_pdwIDs[m]) {
  408. u = m - 1;
  409. } else if (dwId > m_pdwIDs[m]) {
  410. l = m + 1;
  411. } else { // Hit!
  412. lReturn = m_pdwHandles[m];
  413. break;
  414. }
  415. }
  416. } else {
  417. // no entries so return 0;
  418. }
  419. return lReturn;
  420. }