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.

496 lines
14 KiB

  1. /*----------------------------------------------------------------------------
  2. PerfUtil.cpp
  3. Contains general functions used by pbsmon.dll
  4. Copyright (c) 1997-1998 Microsoft Corporation
  5. All rights reserved.
  6. Authors:
  7. t-geetat Geeta Tarachandani
  8. History:
  9. 6/12/97 t-geetat Created
  10. --------------------------------------------------------------------------*/
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <assert.h>
  15. #include "Loaddata.h"
  16. #include "CpsSym.h"
  17. #define DIGIT 1
  18. #define DELIMITER 2
  19. #define INVALID 3
  20. #define EvalThisChar(c,d) ( \
  21. (c == d) ? DELIMITER : \
  22. (c == 0) ? DELIMITER : \
  23. (c < (WCHAR)'0') ? INVALID : \
  24. (c > (WCHAR)'9') ? INVALID : \
  25. DIGIT)
  26. void InitializeDataDef( void )
  27. //----------------------------------------------------------------------------
  28. //
  29. // Function: InitializeDataDef
  30. //
  31. // Synopsis: Initializes the data-structure g_CpsMonDataDef to pass to the
  32. // performance monitoring application
  33. //
  34. // Arguments: None
  35. //
  36. // Returns: void
  37. //
  38. // History: 06/03/97 t-geetat Created
  39. //
  40. //----------------------------------------------------------------------------
  41. {
  42. CPSMON_COUNTERS Ctr; // This is a dummy variable, just to get offsets
  43. CPSMON_DATA_DEFINITION CpsMonDataDef = {
  44. // CPS_OBJECT_TYPE
  45. { sizeof( CPSMON_DATA_DEFINITION ) + sizeof( CPSMON_COUNTERS ),// ??
  46. sizeof( CPSMON_DATA_DEFINITION ),
  47. sizeof( PERF_OBJECT_TYPE ),
  48. OBJECT_CPS_SERVER,
  49. 0,
  50. OBJECT_CPS_SERVER,
  51. 0,
  52. PERF_DETAIL_NOVICE,
  53. NUM_OF_INFO_COUNTERS,
  54. 0, // total hits is the default counter
  55. -1, // num instances
  56. 0, // unicode instance names
  57. {0,0},
  58. {0,0}
  59. },
  60. ////////////////////
  61. // Raw Counters //
  62. ////////////////////
  63. // Counter 0 -- TOTAL HITS
  64. { sizeof(PERF_COUNTER_DEFINITION),
  65. COUNTER_TOTAL_HITS,
  66. 0,
  67. COUNTER_TOTAL_HITS,
  68. 0,
  69. -3, // Scale = 10^-3 = .001
  70. PERF_DETAIL_NOVICE,
  71. PERF_COUNTER_RAWCOUNT,
  72. sizeof(DWORD),
  73. (DWORD)((LPBYTE)&(Ctr.m_dwTotalHits) - (LPBYTE)&Ctr)
  74. },
  75. // Counter 1 -- NO UPGRADES
  76. { sizeof(PERF_COUNTER_DEFINITION),
  77. COUNTER_NO_UPGRADE,
  78. 0,
  79. COUNTER_NO_UPGRADE,
  80. 0,
  81. -3, // Scale = 10^-3
  82. PERF_DETAIL_NOVICE,
  83. PERF_COUNTER_RAWCOUNT,
  84. sizeof(DWORD),
  85. (DWORD)((LPBYTE)&(Ctr.m_dwNoUpgrade) - (LPBYTE)&Ctr)
  86. },
  87. // Counter 2 -- DELTA UPGRADES
  88. { sizeof(PERF_COUNTER_DEFINITION),
  89. COUNTER_DELTA_UPGRADE,
  90. 0,
  91. COUNTER_DELTA_UPGRADE,
  92. 0,
  93. -3,
  94. PERF_DETAIL_NOVICE,
  95. PERF_COUNTER_RAWCOUNT,
  96. sizeof(DWORD),
  97. (DWORD)((LPBYTE)&(Ctr.m_dwDeltaUpgrade) - (LPBYTE)&Ctr)
  98. },
  99. // Counter 3 -- FULL UPGRADE
  100. { sizeof(PERF_COUNTER_DEFINITION),
  101. COUNTER_FULL_UPGRADE,
  102. 0,
  103. COUNTER_FULL_UPGRADE,
  104. 0,
  105. -3,
  106. PERF_DETAIL_NOVICE,
  107. PERF_COUNTER_RAWCOUNT,
  108. sizeof(DWORD),
  109. (DWORD)((LPBYTE)&(Ctr.m_dwFullUpgrade) - (LPBYTE)&Ctr)
  110. },
  111. // Counter 4 -- ERROR HITS
  112. { sizeof(PERF_COUNTER_DEFINITION),
  113. COUNTER_ERRORS,
  114. 0,
  115. COUNTER_ERRORS,
  116. 0,
  117. -3,
  118. PERF_DETAIL_NOVICE,
  119. PERF_COUNTER_RAWCOUNT,
  120. sizeof(DWORD),
  121. (DWORD)((LPBYTE)&(Ctr.m_dwErrors) - (LPBYTE)&Ctr)
  122. },
  123. /////////////////////
  124. // Rate Counters //
  125. /////////////////////
  126. // Counter 5 -- TOTAL HITS/SEC
  127. { sizeof(PERF_COUNTER_DEFINITION),
  128. COUNTER_TOTAL_HITS_PER_SEC,
  129. 0,
  130. COUNTER_TOTAL_HITS_PER_SEC,
  131. 0,
  132. 0, // Scale = 10^0
  133. PERF_DETAIL_NOVICE,
  134. PERF_COUNTER_COUNTER,
  135. sizeof(DWORD),
  136. (DWORD)((LPBYTE)&(Ctr.m_dwTotalHitsPerSec) - (LPBYTE)&Ctr)
  137. },
  138. // Counter 6 -- NO UPGRADE/SEC
  139. { sizeof(PERF_COUNTER_DEFINITION),
  140. COUNTER_NO_UPGRADE_PER_SEC,
  141. 0,
  142. COUNTER_NO_UPGRADE_PER_SEC,
  143. 0,
  144. 0, // Scale = 10^0
  145. PERF_DETAIL_NOVICE,
  146. PERF_COUNTER_COUNTER,
  147. sizeof(DWORD),
  148. (DWORD)((LPBYTE)&(Ctr.m_dwNoUpgradePerSec) - (LPBYTE)&Ctr)
  149. },
  150. // Counter 7 -- DELTA UPGRADE/SEC
  151. { sizeof(PERF_COUNTER_DEFINITION),
  152. COUNTER_DELTA_UPGRADE_PER_SEC,
  153. 0,
  154. COUNTER_DELTA_UPGRADE_PER_SEC,
  155. 0,
  156. 0,
  157. PERF_DETAIL_NOVICE,
  158. PERF_COUNTER_COUNTER,
  159. sizeof(DWORD),
  160. (DWORD)((LPBYTE)&(Ctr.m_dwDeltaUpgradePerSec) - (LPBYTE)&Ctr)
  161. },
  162. // Counter 8 -- FULL UPGRADE/SEC
  163. { sizeof(PERF_COUNTER_DEFINITION),
  164. COUNTER_FULL_UPGRADE_PER_SEC,
  165. 0,
  166. COUNTER_FULL_UPGRADE_PER_SEC,
  167. 0,
  168. 0,
  169. PERF_DETAIL_NOVICE,
  170. PERF_COUNTER_COUNTER,
  171. sizeof(DWORD),
  172. (DWORD)((LPBYTE)&(Ctr.m_dwFullUpgradePerSec) - (LPBYTE)&Ctr)
  173. },
  174. // Counter 9 -- ERRORS/SEC
  175. { sizeof(PERF_COUNTER_DEFINITION),
  176. COUNTER_ERRORS_PER_SEC,
  177. 0,
  178. COUNTER_ERRORS_PER_SEC,
  179. 0,
  180. 0,
  181. PERF_DETAIL_NOVICE,
  182. PERF_COUNTER_COUNTER,
  183. sizeof(DWORD),
  184. (DWORD)((LPBYTE)&(Ctr.m_dwErrorsPerSec) - (LPBYTE)&Ctr)
  185. }
  186. };
  187. memmove( &g_CpsMonDataDef, &CpsMonDataDef, sizeof(CPSMON_DATA_DEFINITION) );
  188. }
  189. BOOL UpdateDataDefFromRegistry( void )
  190. //----------------------------------------------------------------------------
  191. //
  192. // Function: UpdateDataDefFromRegistry
  193. //
  194. // Synopsis: Gets counter and help index base values from registry as follows :
  195. // 1) Open key to registry entry
  196. // 2) Read First Counter and First Help values
  197. // 3) Update static data strucutures g_CpsMonDataDef by adding base to
  198. // offset value in structure.
  199. //
  200. // Arguments: None
  201. //
  202. // Returns: TRUE if succeeds, FALSE otherwise
  203. //
  204. // History: 06/03/97 t-geetat Created
  205. //
  206. //----------------------------------------------------------------------------
  207. {
  208. HKEY hKeyDriverPerf;
  209. BOOL status;
  210. DWORD type;
  211. DWORD size;
  212. DWORD dwFirstCounter;
  213. DWORD dwFirstHelp;
  214. PERF_COUNTER_DEFINITION *pctr;
  215. DWORD i;
  216. status = RegOpenKeyEx (
  217. HKEY_LOCAL_MACHINE,
  218. "SYSTEM\\CurrentControlSet\\Services\\PBServerMonitor\\Performance",
  219. 0L,
  220. KEY_READ,
  221. &hKeyDriverPerf);
  222. if (status != ERROR_SUCCESS) {
  223. // this is fatal, if we can't get the base values of the
  224. // counter or help names, then the names won't be available
  225. // to the requesting application so there's not much
  226. // point in continuing.
  227. return FALSE;
  228. }
  229. size = sizeof (DWORD);
  230. status = RegQueryValueEx(
  231. hKeyDriverPerf,
  232. "First Counter",
  233. 0L,
  234. &type,
  235. (LPBYTE)&dwFirstCounter,
  236. &size);
  237. if (status != ERROR_SUCCESS) {
  238. // this is fatal, if we can't get the base values of the
  239. // counter or help names, then the names won't be available
  240. // to the requesting application so there's not much
  241. // point in continuing.
  242. return FALSE;
  243. }
  244. size = sizeof (DWORD);
  245. status = RegQueryValueEx(
  246. hKeyDriverPerf,
  247. "First Help",
  248. 0L,
  249. &type,
  250. (LPBYTE)&dwFirstHelp,
  251. &size);
  252. if (status != ERROR_SUCCESS) {
  253. // this is fatal, if we can't get the base values of the
  254. // counter or help names, then the names won't be available
  255. // to the requesting application so there's not much
  256. // point in continuing.
  257. return FALSE;
  258. }
  259. // Object
  260. g_CpsMonDataDef.m_CpsMonObjectType.ObjectNameTitleIndex += dwFirstCounter;
  261. g_CpsMonDataDef.m_CpsMonObjectType.ObjectHelpTitleIndex += dwFirstHelp;
  262. // All counters
  263. pctr = &g_CpsMonDataDef.m_CpsMonTotalHits;
  264. for( i=0; i<NUM_OF_INFO_COUNTERS; i++ )
  265. {
  266. pctr->CounterNameTitleIndex += dwFirstCounter;
  267. pctr->CounterHelpTitleIndex += dwFirstHelp;
  268. pctr ++;
  269. }
  270. RegCloseKey (hKeyDriverPerf); // close key to registry
  271. return TRUE;
  272. }
  273. DWORD GetQueryType ( IN LPWSTR lpValue )
  274. /***************************************************************************
  275. GetQueryType
  276. returns the type of query described in the lpValue string so that
  277. the appropriate processing method may be used
  278. Arguments
  279. IN lpValue
  280. string passed to PerfRegQuery Value for processing
  281. Return Value
  282. QUERY_GLOBAL
  283. if lpValue == 0 (null pointer)
  284. lpValue == pointer to Null string
  285. lpValue == pointer to "Global" string
  286. QUERY_FOREIGN
  287. if lpValue == pointer to "Foriegn" string
  288. QUERY_COSTLY
  289. if lpValue == pointer to "Costly" string
  290. otherwise:
  291. QUERY_ITEMS
  292. Source :- Perfmon-DLL samples by Bob Watson ( MSDN )
  293. ***********************************************************************************/
  294. {
  295. WCHAR GLOBAL_STRING[] = L"Global";
  296. WCHAR FOREIGN_STRING[] = L"Foreign";
  297. WCHAR COSTLY_STRING[] = L"Costly";
  298. WCHAR NULL_STRING[] = L"\0"; // pointer to null string
  299. WCHAR *pwcArgChar, *pwcTypeChar;
  300. BOOL bFound;
  301. if (lpValue == 0) {
  302. return QUERY_GLOBAL;
  303. } else if (*lpValue == 0) {
  304. return QUERY_GLOBAL;
  305. }
  306. // check for "Global" request
  307. pwcArgChar = lpValue;
  308. pwcTypeChar = GLOBAL_STRING;
  309. bFound = TRUE; // assume found until contradicted
  310. // check to the length of the shortest string
  311. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  312. if (*pwcArgChar++ != *pwcTypeChar++) {
  313. bFound = FALSE; // no match
  314. break; // bail out now
  315. }
  316. }
  317. if (bFound) return QUERY_GLOBAL;
  318. // check for "Foreign" request
  319. pwcArgChar = lpValue;
  320. pwcTypeChar = FOREIGN_STRING;
  321. bFound = TRUE; // assume found until contradicted
  322. // check to the length of the shortest string
  323. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  324. if (*pwcArgChar++ != *pwcTypeChar++) {
  325. bFound = FALSE; // no match
  326. break; // bail out now
  327. }
  328. }
  329. if (bFound) return QUERY_FOREIGN;
  330. // check for "Costly" request
  331. pwcArgChar = lpValue;
  332. pwcTypeChar = COSTLY_STRING;
  333. bFound = TRUE; // assume found until contradicted
  334. // check to the length of the shortest string
  335. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  336. if (*pwcArgChar++ != *pwcTypeChar++) {
  337. bFound = FALSE; // no match
  338. break; // bail out now
  339. }
  340. }
  341. if (bFound) return QUERY_COSTLY;
  342. // if not Global and not Foreign and not Costly,
  343. // then it must be an item list
  344. return QUERY_ITEMS;
  345. }
  346. BOOL IsNumberInUnicodeList (
  347. IN DWORD dwNumber,
  348. IN LPWSTR lpwszUnicodeList
  349. )
  350. /**********************************************************************************
  351. IsNumberInUnicodeList
  352. Arguments:
  353. IN dwNumber
  354. DWORD number to find in list
  355. IN lpwszUnicodeList
  356. Null terminated, Space delimited list of decimal numbers
  357. Return Value:
  358. TRUE:
  359. dwNumber was found in the list of unicode number strings
  360. FALSE:
  361. dwNumber was not found in the list.
  362. Source :- Perfmon-DLL samples by Bob Watson ( MSDN )
  363. **************************************************************************************/
  364. {
  365. DWORD dwThisNumber;
  366. WCHAR *pwcThisChar;
  367. BOOL bValidNumber;
  368. BOOL bNewItem;
  369. WCHAR wcDelimiter; // could be an argument to be more flexible
  370. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  371. pwcThisChar = lpwszUnicodeList;
  372. dwThisNumber = 0;
  373. wcDelimiter = (WCHAR)' ';
  374. bValidNumber = FALSE;
  375. bNewItem = TRUE;
  376. while (TRUE) {
  377. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  378. case DIGIT:
  379. // if this is the first digit after a delimiter, then
  380. // set flags to start computing the new number
  381. if (bNewItem) {
  382. bNewItem = FALSE;
  383. bValidNumber = TRUE;
  384. }
  385. if (bValidNumber) {
  386. dwThisNumber *= 10;
  387. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  388. }
  389. break;
  390. case DELIMITER:
  391. // a delimter is either the delimiter character or the
  392. // end of the string ('\0') if when the delimiter has been
  393. // reached a valid number was found, then compare it to the
  394. // number from the argument list. if this is the end of the
  395. // string and no match was found, then return.
  396. //
  397. if (bValidNumber) {
  398. if (dwThisNumber == dwNumber) return TRUE;
  399. bValidNumber = FALSE;
  400. }
  401. if (*pwcThisChar == 0) {
  402. return FALSE;
  403. } else {
  404. bNewItem = TRUE;
  405. dwThisNumber = 0;
  406. }
  407. break;
  408. case INVALID:
  409. // if an invalid character was encountered, ignore all
  410. // characters up to the next delimiter and then start fresh.
  411. // the invalid number is not compared.
  412. bValidNumber = FALSE;
  413. break;
  414. default:
  415. break;
  416. }
  417. pwcThisChar++;
  418. }
  419. } // IsNumberInUnicodeList