Leaked source code of windows server 2003
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.

505 lines
18 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  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. size_t cchSize = lstrlenW(pOrigClassMap->m_pszClassName)+1;
  96. pNewClassMap->m_pszClassName =
  97. new WCHAR[cchSize];
  98. if (pNewClassMap->m_pszClassName != NULL) {
  99. StringCchCopyW(pNewClassMap->m_pszClassName, cchSize, pOrigClassMap->m_pszClassName);
  100. pNewClassMap->m_bSingleton = pOrigClassMap->m_bSingleton;
  101. pNewClassMap->m_bCostly = pOrigClassMap->m_bCostly;
  102. pNewClassMap->m_dwObjectId = pOrigClassMap->m_dwObjectId;
  103. pNewClassMap->m_lRefCount = 1;
  104. pNewClassMap->m_dwNameHandle = pOrigClassMap->m_dwNameHandle;
  105. pNewClassMap->m_dwPerfTimeStampHandle = pOrigClassMap->m_dwPerfTimeStampHandle;
  106. pNewClassMap->m_dw100NsTimeStampHandle = pOrigClassMap->m_dw100NsTimeStampHandle;
  107. pNewClassMap->m_dwObjectTimeStampHandle = pOrigClassMap->m_dwObjectTimeStampHandle;
  108. pNewClassMap->m_dwPerfFrequencyHandle = pOrigClassMap->m_dwPerfFrequencyHandle;
  109. pNewClassMap->m_dw100NsFrequencyHandle = pOrigClassMap->m_dw100NsFrequencyHandle;
  110. pNewClassMap->m_dwObjectFrequencyHandle = pOrigClassMap->m_dwObjectFrequencyHandle;
  111. pNewClassMap->m_dwNumProps = pOrigClassMap->m_dwNumProps;
  112. pNewClassMap->m_pdwIDs = new PerfObjectId[pNewClassMap->m_dwNumProps];
  113. pNewClassMap->m_pdwHandles = new DWORD[pNewClassMap->m_dwNumProps];
  114. pNewClassMap->m_pdwTypes = new DWORD[pNewClassMap->m_dwNumProps];
  115. if ((pNewClassMap->m_pdwIDs != NULL) &&
  116. (pNewClassMap->m_pdwHandles != NULL) &&
  117. (pNewClassMap->m_pdwTypes != NULL)) {
  118. // copy each table to the new object
  119. for (i = 0; i < pNewClassMap->m_dwNumProps; i++) {
  120. pNewClassMap->m_pdwIDs[i] = pOrigClassMap->m_pdwIDs[i];
  121. pNewClassMap->m_pdwHandles[i] = pOrigClassMap->m_pdwHandles[i];
  122. pNewClassMap->m_pdwTypes[i] = pOrigClassMap->m_pdwTypes[i];
  123. }
  124. }
  125. else {
  126. delete pNewClassMap;
  127. pNewClassMap = NULL;
  128. }
  129. } else {
  130. delete pNewClassMap;
  131. pNewClassMap = NULL;
  132. }
  133. }
  134. }
  135. return pNewClassMap;
  136. }
  137. //***************************************************************************
  138. //
  139. // CClassMapInfo::Map()
  140. //
  141. // Maps the inbound class definition by:
  142. //
  143. // (1) Retrieving the perf object id from the class definition.
  144. // (2) Retrieving the property handles, perf ids, and types for each
  145. // property.
  146. //
  147. //
  148. //***************************************************************************
  149. // ok
  150. BOOL CClassMapInfo::Map(IWbemClassObject *pObj)
  151. {
  152. int nIndex = 0;
  153. IWbemObjectAccess *pAlias = 0;
  154. IWbemQualifierSet *pQSet = 0;
  155. HRESULT hRes;
  156. VARIANT vPropertyCount;
  157. VARIANT vClsName;
  158. VARIANT vPerfObjType;
  159. VARIANT vSingleton;
  160. VARIANT vCostly;
  161. VARIANT vCounter;
  162. VARIANT vCounterType;
  163. CBSTR cbPerfIndex(cszPerfIndex);
  164. CBSTR cbCountertype(cszCountertype);
  165. CBSTR cbPropertyCount(cszPropertyCount);
  166. CBSTR cbClassName(cszClassName);
  167. CBSTR cbSingleton(cszSingleton);
  168. CBSTR cbCostly(cszCostly);
  169. BOOL bReturn = TRUE;
  170. VariantInit(&vPropertyCount);
  171. VariantInit(&vClsName);
  172. VariantInit(&vPerfObjType);
  173. VariantInit(&vSingleton);
  174. VariantInit(&vCostly);
  175. VariantInit(&vCounter);
  176. VariantInit(&vCounterType);
  177. if( NULL == (BSTR)cbPerfIndex ||
  178. NULL == (BSTR)cbCountertype ||
  179. NULL == (BSTR)cbPropertyCount ||
  180. NULL == (BSTR)cbClassName ||
  181. NULL == (BSTR)cbSingleton ||
  182. NULL == (BSTR)cbCostly ){
  183. return FALSE;
  184. }
  185. // Copy the class definition.
  186. // ==========================
  187. m_pClassDef = pObj;
  188. //m_pClassDef->AddRef(); // this is unnecessary
  189. m_lRefCount++; // bump our ref count
  190. // Get the alternate interface so that we can look up handles.
  191. // ===========================================================
  192. hRes = pObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pAlias);
  193. if (hRes) {
  194. bReturn = FALSE;
  195. }
  196. // Determine the number of properties and allocate
  197. // arrays to hold the handles, perf ids, and types.
  198. // ================================================
  199. if (bReturn) {
  200. hRes = pObj->Get( cbPropertyCount, 0, &vPropertyCount, 0, 0);
  201. if (hRes == NO_ERROR) {
  202. m_dwNumProps = DWORD(V_UI4(&vPropertyCount));
  203. } else {
  204. bReturn = FALSE;
  205. }
  206. VariantClear(&vPropertyCount);
  207. }
  208. // allocate the table of the handles and id's
  209. if (bReturn) {
  210. m_pdwHandles = new DWORD[m_dwNumProps];
  211. assert (m_pdwHandles != NULL);
  212. m_pdwIDs = new PerfObjectId[m_dwNumProps];
  213. assert (m_pdwIDs != NULL);
  214. m_pdwTypes = new DWORD[m_dwNumProps];
  215. assert (m_pdwTypes != NULL);
  216. // check the memory allocations
  217. if ((m_pdwHandles == NULL) ||
  218. (m_pdwIDs == NULL) ||
  219. (m_pdwTypes == NULL)) {
  220. bReturn = FALSE;
  221. }
  222. }
  223. // Clone the class name.
  224. // =====================
  225. if (bReturn) {
  226. hRes = pObj->Get( cbClassName, 0, &vClsName, 0, 0);
  227. if ((hRes == NO_ERROR) && (vClsName.vt == VT_BSTR)) {
  228. m_pszClassName = Macro_CloneLPWSTR(V_BSTR(&vClsName));
  229. if (m_pszClassName == NULL) bReturn = FALSE;
  230. } else {
  231. bReturn = FALSE;
  232. }
  233. VariantClear (&vClsName);
  234. }
  235. // Get the perf object id for the class.
  236. // =====================================
  237. if (bReturn) {
  238. hRes = pObj->GetQualifierSet(&pQSet);
  239. if (hRes == NO_ERROR) {
  240. hRes = pQSet->Get(cbPerfIndex, 0, &vPerfObjType, 0);
  241. if (hRes == NO_ERROR) {
  242. m_dwObjectId = DWORD(V_UI4(&vPerfObjType));
  243. } else {
  244. bReturn = FALSE;
  245. }
  246. VariantClear(&vPerfObjType);
  247. hRes = pQSet->Get( cbSingleton, 0, &vSingleton, 0);
  248. if (hRes == 0) {
  249. m_bSingleton = TRUE;
  250. }
  251. VariantClear (&vSingleton);
  252. hRes = pQSet->Get( cbCostly, 0, &vCostly, 0);
  253. if ((hRes == 0) && (vCostly.vt == VT_BSTR)) {
  254. m_bCostly= TRUE;
  255. }
  256. VariantClear (&vCostly);
  257. pQSet->Release();
  258. } else {
  259. bReturn = FALSE;
  260. }
  261. }
  262. // Enumerate all the properties and get the object ids
  263. // and handles for each.
  264. // ===================================================
  265. hRes = pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  266. if (hRes == NO_ERROR) {
  267. // enumeration handle obtained so
  268. // continue and cache each property
  269. while (bReturn) {
  270. BSTR Name = 0;
  271. DWORD dwCtrId;
  272. DWORD dwCtrType;
  273. IWbemQualifierSet *pQSet = 0;
  274. LONG lType = 0;
  275. LONG lHandle = 0;
  276. hRes = pObj->Next(
  277. 0,
  278. &Name,
  279. 0,
  280. 0,
  281. 0
  282. );
  283. if (hRes == WBEM_S_NO_MORE_DATA) {
  284. break;
  285. }
  286. // Next, get the qualifier set for this property.
  287. // ==============================================
  288. hRes = pObj->GetPropertyQualifierSet(Name, &pQSet);
  289. if (hRes == NO_ERROR) {
  290. hRes = pQSet->Get(cbPerfIndex, 0, &vCounter, 0);
  291. if (hRes == S_OK) {
  292. dwCtrId = (DWORD)V_UI4(&vCounter);
  293. } else {
  294. // unable to read qualifier value
  295. dwCtrId = 0;
  296. }
  297. VariantClear (&vCounter);
  298. hRes = pQSet->Get(cbCountertype, 0, &vCounterType, 0);
  299. if (hRes == S_OK) {
  300. dwCtrType = (DWORD)V_UI4(&vCounterType);
  301. } else {
  302. // unable to read qualifier value
  303. dwCtrType = 0;
  304. }
  305. VariantClear (&vCounterType);
  306. // done with the qualifier set
  307. pQSet->Release();
  308. // Get the property handle and type.
  309. // =================================
  310. hRes = pAlias->GetPropertyHandle(Name, &lType, &lHandle);
  311. if (hRes == NO_ERROR && nIndex < (int)m_dwNumProps ) {
  312. // We now know the counter id, the property handle and its
  313. // type. That is all we really need at runtime to map
  314. // blobs into CIM object.
  315. // =======================================================
  316. m_pdwIDs[nIndex] = CM_MAKE_PerfObjectId (dwCtrId, dwCtrType);
  317. m_pdwHandles[nIndex] = (DWORD) lHandle;
  318. m_pdwTypes[nIndex] = (DWORD) lType;
  319. // this property was loaded successfully so
  320. // advance to the next index
  321. nIndex++;
  322. } else {
  323. // no property handle returned so skip it.
  324. }
  325. } else {
  326. // skip this object since it doesn't have
  327. // a qualifier set
  328. }
  329. // Free the name.
  330. // ==============
  331. SysFreeString(Name);
  332. }
  333. pObj->EndEnumeration();
  334. } else {
  335. // unable to get enumeration handle
  336. bReturn = FALSE;
  337. }
  338. // Get the handle of the 'name' property.
  339. // ======================================
  340. if (bReturn) {
  341. if (!m_bSingleton) {
  342. // only non-singleton classes have this property
  343. pAlias->GetPropertyHandle((LPWSTR)cszName, 0, (LONG *) &m_dwNameHandle);
  344. }
  345. // Get the handle of the "timestamp" properties
  346. pAlias->GetPropertyHandle((LPWSTR)cszTimestampPerfTime, 0, (LONG *) &m_dwPerfTimeStampHandle);
  347. pAlias->GetPropertyHandle((LPWSTR)cszFrequencyPerfTime, 0, (LONG *) &m_dwPerfFrequencyHandle);
  348. pAlias->GetPropertyHandle((LPWSTR)cszTimestampSys100Ns, 0, (LONG *) &m_dw100NsTimeStampHandle);
  349. pAlias->GetPropertyHandle((LPWSTR)cszFrequencySys100Ns, 0, (LONG *) &m_dw100NsFrequencyHandle);
  350. pAlias->GetPropertyHandle((LPWSTR)cszTimestampObject, 0, (LONG *) &m_dwObjectTimeStampHandle);
  351. pAlias->GetPropertyHandle((LPWSTR)cszFrequencyObject, 0, (LONG *) &m_dwObjectFrequencyHandle);
  352. // Cleanup.
  353. // ========
  354. SortHandles();
  355. }
  356. if (pAlias != NULL) pAlias->Release();
  357. return bReturn;
  358. }
  359. //***************************************************************************
  360. //
  361. // CClassMapInfo::SortHandles
  362. //
  363. // Sort the perf object ids for quick searching later in the GetPropHandle
  364. // method.
  365. //
  366. //***************************************************************************
  367. // ok
  368. void CClassMapInfo::SortHandles()
  369. {
  370. DWORD dwOuter;
  371. DWORD dwInner;
  372. DWORD dwTemp;
  373. PerfObjectId poiTemp;
  374. // Simple selection sort. The number of elements is so small
  375. // and this is only done once, so a quicksort / shellsort would be
  376. // overkill.
  377. // ===============================================================
  378. for (dwOuter = 0; dwOuter < m_dwNumProps - 1; dwOuter++)
  379. {
  380. for (dwInner = dwOuter + 1; dwInner < m_dwNumProps; dwInner++)
  381. {
  382. if (m_pdwIDs[dwInner] < m_pdwIDs[dwOuter])
  383. {
  384. poiTemp = m_pdwIDs[dwInner];
  385. m_pdwIDs[dwInner] = m_pdwIDs[dwOuter];
  386. m_pdwIDs[dwOuter] = poiTemp;
  387. dwTemp = m_pdwHandles[dwInner];
  388. m_pdwHandles[dwInner] = m_pdwHandles[dwOuter];
  389. m_pdwHandles[dwOuter] = dwTemp;
  390. dwTemp = m_pdwTypes[dwInner];
  391. m_pdwTypes[dwInner] = m_pdwTypes[dwOuter];
  392. m_pdwTypes[dwOuter] = dwTemp;
  393. }
  394. }
  395. }
  396. }
  397. //***************************************************************************
  398. //
  399. // CClassMapInfo::GetPropHandle
  400. //
  401. // Gets the property handle for a corresponding perf counter id.
  402. // Returns 0 if not found.
  403. //
  404. //***************************************************************************
  405. // ok
  406. LONG CClassMapInfo::GetPropHandle(PerfObjectId dwId)
  407. {
  408. // Binary search.
  409. // ==============
  410. LONG l;
  411. LONG u;
  412. LONG m;
  413. LONG lReturn = 0;
  414. if (m_dwNumProps > 0) {
  415. l = 0;
  416. u = m_dwNumProps - 1;
  417. while (l <= u)
  418. {
  419. m = (l + u) / 2;
  420. if (dwId < m_pdwIDs[m]) {
  421. u = m - 1;
  422. } else if (dwId > m_pdwIDs[m]) {
  423. l = m + 1;
  424. } else { // Hit!
  425. lReturn = m_pdwHandles[m];
  426. break;
  427. }
  428. }
  429. } else {
  430. // no entries so return 0;
  431. }
  432. return lReturn;
  433. }