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.

306 lines
8.2 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. //***************************************************************************
  8. //
  9. // CLASSMAP.CPP
  10. //
  11. // Mapped NT5 Perf Counter Provider
  12. //
  13. // raymcc 02-Dec-97 Created.
  14. // raymcc 20-Feb-98 Updated to use new initializer.
  15. //
  16. //***************************************************************************
  17. #include "precomp.h"
  18. #include <stdio.h>
  19. #include <wbemidl.h>
  20. #include <wbemint.h>
  21. #include "flexarry.h"
  22. #include "ntperf.h"
  23. #include "oahelp.inl"
  24. //***************************************************************************
  25. //
  26. // CClassMapInfo::CClassMapInfo()
  27. //
  28. // The objective of the map is to have one instance for each CIM class.
  29. // Internally, a map of perf object ids to CIM property handles is maintained
  30. // for the class.
  31. //
  32. // Later, when instances are requested, the blob is retrieved from
  33. // HKEY_PERFORMANCE_DATA, and the object IDs in the blob are used to
  34. // look up the property handles, which are then used to populate instances.
  35. //
  36. // Property names are never really used except in the mapping phase.
  37. //
  38. //***************************************************************************
  39. // ok
  40. CClassMapInfo::CClassMapInfo()
  41. {
  42. m_pClassDef = 0; // The CIM class definition
  43. m_pszClassName = 0; // The UNICODE class name
  44. m_dwObjectId = 0; // Perf object Id
  45. m_bSingleton = FALSE;
  46. m_dwNumProps = 0; // Number of props in class, size
  47. // of the following arrays
  48. // These are pointers to parallel DWORD arrays, all of the same
  49. // size (m_dwNumProps)
  50. // ============================================================
  51. m_pdwIDs = 0; // IDs of properties
  52. m_pdwHandles = 0; // Handles to properties
  53. m_pdwTypes = 0; // Types of properties
  54. m_dwNameHandle = 0; // The 'Name' property
  55. }
  56. //***************************************************************************
  57. //
  58. // CClassMapInfo::~CClassMapInfo
  59. //
  60. //***************************************************************************
  61. // ok
  62. CClassMapInfo::~CClassMapInfo()
  63. {
  64. if (m_pClassDef)
  65. m_pClassDef->Release();
  66. delete [] m_pszClassName;
  67. delete [] m_pdwIDs;
  68. delete [] m_pdwHandles;
  69. delete [] m_pdwTypes;
  70. }
  71. //***************************************************************************
  72. //
  73. // CClassMapInfo::Map()
  74. //
  75. // Maps the inbound class definition by:
  76. //
  77. // (1) Retrieving the perf object id from the class definition.
  78. // (2) Retrieving the property handles, perf ids, and types for each
  79. // property.
  80. //
  81. //
  82. //***************************************************************************
  83. // ok
  84. BOOL CClassMapInfo::Map(IWbemClassObject *pObj)
  85. {
  86. HRESULT hRes;
  87. // Copy the class definition.
  88. // ==========================
  89. m_pClassDef = pObj;
  90. m_pClassDef->AddRef();
  91. // Get the alternate interface so that we can look up handles.
  92. // ===========================================================
  93. IWbemObjectAccess *pAlias = 0;
  94. pObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pAlias);
  95. // Determine the number of properties and allocate
  96. // arrays to hold the handles, perf ids, and types.
  97. // ================================================
  98. CVARIANT v;
  99. pObj->Get(CBSTR(L"__PROPERTY_COUNT"), 0, v, 0, 0);
  100. m_dwNumProps = DWORD(v.GetLONG());
  101. m_pdwHandles = new DWORD[m_dwNumProps];
  102. m_pdwIDs = new DWORD[m_dwNumProps];
  103. m_pdwTypes = new DWORD[m_dwNumProps];
  104. // Clone the class name.
  105. // =====================
  106. CVARIANT vClsName;
  107. pObj->Get(CBSTR(L"__CLASS"), 0, vClsName, 0, 0);
  108. m_pszClassName = Macro_CloneLPWSTR(vClsName.GetStr());
  109. // Get the perf object id for the class.
  110. // =====================================
  111. IWbemQualifierSet *pQSet = 0;
  112. CVARIANT vPerfObjType;
  113. pObj->GetQualifierSet(&pQSet);
  114. pQSet->Get(CBSTR(L"PerfIndex"), 0, vPerfObjType, 0);
  115. m_dwObjectId = DWORD(vPerfObjType.GetLONG());
  116. CVARIANT vSingleton;
  117. hRes = pQSet->Get(CBSTR(L"Singleton"), 0, vSingleton, 0);
  118. if (hRes == 0)
  119. m_bSingleton = TRUE;
  120. pQSet->Release();
  121. // Enumerate all the properties and get the object ids
  122. // and handles for each.
  123. // ===================================================
  124. pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  125. int nIndex = 0;
  126. while (1)
  127. {
  128. BSTR Name = 0;
  129. hRes = pObj->Next(
  130. 0,
  131. &Name,
  132. 0,
  133. 0,
  134. 0
  135. );
  136. if (hRes == WBEM_S_NO_MORE_DATA)
  137. break;
  138. // Next, get the qualifier set for this property.
  139. // ==============================================
  140. IWbemQualifierSet *pQSet = 0;
  141. pObj->GetPropertyQualifierSet(Name, &pQSet);
  142. CVARIANT vCounter;
  143. hRes = pQSet->Get(CBSTR(L"PerfIndex"), 0, &vCounter, 0);
  144. pQSet->Release();
  145. if (hRes)
  146. vCounter.SetLONG(0);
  147. // Get the property handle and type.
  148. // =================================
  149. LONG lType = 0;
  150. LONG lHandle = 0;
  151. pAlias->GetPropertyHandle(Name, &lType, &lHandle);
  152. FILE *f = fopen("log", "at");
  153. fprintf(f, "Prop <%S> Handle = 0x%X PerfIx=%d\n", Name, lHandle, vCounter.GetLONG());
  154. fclose(f);
  155. // We now know the counter id, the property handle and its
  156. // type. That is all we really need at runtime to map
  157. // blobs into CIM object.
  158. // =======================================================
  159. m_pdwIDs[nIndex] = (DWORD) vCounter.GetLONG();
  160. m_pdwHandles[nIndex] = (DWORD) lHandle;
  161. m_pdwTypes[nIndex] = (DWORD) lType;
  162. // Free the name.
  163. // ==============
  164. SysFreeString(Name);
  165. nIndex++;
  166. }
  167. // Get the handle of the 'name' property.
  168. // ======================================
  169. pAlias->GetPropertyHandle(L"Name", 0, (LONG *) &m_dwNameHandle);
  170. // Cleanup.
  171. // ========
  172. SortHandles();
  173. pObj->EndEnumeration();
  174. pAlias->Release();
  175. return TRUE;
  176. }
  177. //***************************************************************************
  178. //
  179. // CClassMapInfo::SortHandles
  180. //
  181. // Sort the perf object ids for quick searching later in the GetPropHandle
  182. // method.
  183. //
  184. //***************************************************************************
  185. void CClassMapInfo::SortHandles()
  186. {
  187. // Simple selection sort. The number of elements is so small
  188. // and this is only done once, so a quicksort / shellsort would be
  189. // overkill.
  190. // ===============================================================
  191. for (DWORD dwOuter = 0; dwOuter < m_dwNumProps - 1; dwOuter++)
  192. {
  193. for (DWORD dwInner = dwOuter + 1; dwInner < m_dwNumProps; dwInner++)
  194. {
  195. if (m_pdwIDs[dwInner] < m_pdwIDs[dwOuter])
  196. {
  197. DWORD dwTemp = m_pdwIDs[dwInner];
  198. m_pdwIDs[dwInner] = m_pdwIDs[dwOuter];
  199. m_pdwIDs[dwOuter] = dwTemp;
  200. dwTemp = m_pdwHandles[dwInner];
  201. m_pdwHandles[dwInner] = m_pdwHandles[dwOuter];
  202. m_pdwHandles[dwOuter] = dwTemp;
  203. dwTemp = m_pdwTypes[dwInner];
  204. m_pdwTypes[dwInner] = m_pdwTypes[dwOuter];
  205. m_pdwTypes[dwOuter] = dwTemp;
  206. }
  207. }
  208. }
  209. }
  210. //***************************************************************************
  211. //
  212. // CClassMapInfo::GetPropHandle
  213. //
  214. // Gets the property handle for a corresponding perf counter id.
  215. // Returns 0 if not found.
  216. //
  217. //***************************************************************************
  218. LONG CClassMapInfo::GetPropHandle(DWORD dwId)
  219. {
  220. // Binary search.
  221. // ==============
  222. DWORD l = 0, u = m_dwNumProps - 1;
  223. DWORD m;
  224. while (l <= u)
  225. {
  226. m = (l + u) / 2;
  227. if (dwId < m_pdwIDs[m])
  228. u = m - 1;
  229. else if (dwId > m_pdwIDs[m])
  230. l = m + 1;
  231. else // Hit!
  232. return m_pdwHandles[m];
  233. }
  234. return 0;
  235. }