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.

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