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.

490 lines
11 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. perfutil.c
  5. Abstract:
  6. This file implements the utility routines used to construct the
  7. common parts of a PERF_INSTANCE_DEFINITION (see winperf.h) and
  8. perform event logging functions.
  9. Created:
  10. Russ Blake 07/30/92
  11. Revision History:
  12. --*/
  13. //
  14. // include files
  15. //
  16. #include "debug.h"
  17. #include <windows.h>
  18. #include <string.h>
  19. #include <winperf.h>
  20. #include "winsctrs.h" // error message definition
  21. #include "perfmsg.h"
  22. #include "perfutil.h"
  23. #include "winsevnt.h"
  24. //
  25. // Global data definitions.
  26. //
  27. DWORD MESSAGE_LEVEL = 0;
  28. WCHAR GLOBAL_STRING[] = L"Global";
  29. WCHAR FOREIGN_STRING[] = L"Foreign";
  30. WCHAR COSTLY_STRING[] = L"Costly";
  31. WCHAR NULL_STRING[] = L"\0"; // pointer to null string
  32. HANDLE hEventLog;
  33. DWORD dwLogUsers;
  34. #define WINSCTRS_LOG_KEY \
  35. TEXT("System\\CurrentControlSet\\Services\\EventLog\\Application\\WinsCtrs")
  36. HKEY LogRoot;
  37. #define WINS_LOG_FILE_NAME TEXT("%SystemRoot%\\System32\\winsevnt.dll")
  38. #define WINS_MSGFILE_SKEY TEXT("EventMessageFile")
  39. // test for delimiter, end of line and non-digit characters
  40. // used by IsNumberInUnicodeList routine
  41. //
  42. #define DIGIT 1
  43. #define DELIMITER 2
  44. #define INVALID 3
  45. #define EvalThisChar(c,d) ( \
  46. (c == d) ? DELIMITER : \
  47. (c == 0) ? DELIMITER : \
  48. (c < (WCHAR)'0') ? INVALID : \
  49. (c > (WCHAR)'9') ? INVALID : \
  50. DIGIT)
  51. TCHAR WinsMsgFileSKey[] = WINS_MSGFILE_SKEY;
  52. DWORD
  53. GetQueryType (
  54. IN LPWSTR lpValue
  55. )
  56. /*++
  57. GetQueryType
  58. Returns the type of query described in the lpValue string so that
  59. the appropriate processing method may be used
  60. Arguments
  61. IN lpValue
  62. string passed to PerfRegQuery Value for processing
  63. Return Value
  64. QUERY_GLOBAL
  65. if lpValue == 0 (null pointer)
  66. lpValue == pointer to Null string
  67. lpValue == pointer to "Global" string
  68. QUERY_FOREIGN
  69. if lpValue == pointer to "Foriegn" string
  70. QUERY_COSTLY
  71. if lpValue == pointer to "Costly" string
  72. otherwise:
  73. QUERY_ITEMS
  74. --*/
  75. {
  76. WCHAR *pwcArgChar, *pwcTypeChar;
  77. BOOL bFound;
  78. if (lpValue == 0) {
  79. return QUERY_GLOBAL;
  80. } else if (*lpValue == 0) {
  81. return QUERY_GLOBAL;
  82. }
  83. // check for "Global" request
  84. pwcArgChar = lpValue;
  85. pwcTypeChar = GLOBAL_STRING;
  86. bFound = TRUE; // assume found until contradicted
  87. // check to the length of the shortest string
  88. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  89. if (*pwcArgChar++ != *pwcTypeChar++) {
  90. bFound = FALSE; // no match
  91. break; // bail out now
  92. }
  93. }
  94. if (bFound) return QUERY_GLOBAL;
  95. // check for "Foreign" request
  96. pwcArgChar = lpValue;
  97. pwcTypeChar = FOREIGN_STRING;
  98. bFound = TRUE; // assume found until contradicted
  99. // check to the length of the shortest string
  100. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  101. if (*pwcArgChar++ != *pwcTypeChar++) {
  102. bFound = FALSE; // no match
  103. break; // bail out now
  104. }
  105. }
  106. if (bFound) return QUERY_FOREIGN;
  107. // check for "Costly" request
  108. pwcArgChar = lpValue;
  109. pwcTypeChar = COSTLY_STRING;
  110. bFound = TRUE; // assume found until contradicted
  111. // check to the length of the shortest string
  112. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  113. if (*pwcArgChar++ != *pwcTypeChar++) {
  114. bFound = FALSE; // no match
  115. break; // bail out now
  116. }
  117. }
  118. if (bFound) return QUERY_COSTLY;
  119. // if not Global and not Foreign and not Costly,
  120. // then it must be an item list
  121. return QUERY_ITEMS;
  122. }
  123. BOOL
  124. IsNumberInUnicodeList (
  125. IN DWORD dwNumber,
  126. IN LPWSTR lpwszUnicodeList
  127. )
  128. /*++
  129. IsNumberInUnicodeList
  130. Arguments:
  131. IN dwNumber
  132. DWORD number to find in list
  133. IN lpwszUnicodeList
  134. Null terminated, Space delimited list of decimal numbers
  135. Return Value:
  136. TRUE:
  137. dwNumber was found in the list of unicode number strings
  138. FALSE:
  139. dwNumber was not found in the list.
  140. --*/
  141. {
  142. DWORD dwThisNumber;
  143. WCHAR *pwcThisChar;
  144. BOOL bValidNumber;
  145. BOOL bNewItem;
  146. WCHAR wcDelimiter; // could be an argument to be more flexible
  147. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  148. pwcThisChar = lpwszUnicodeList;
  149. dwThisNumber = 0;
  150. wcDelimiter = (WCHAR)' ';
  151. bValidNumber = FALSE;
  152. bNewItem = TRUE;
  153. while (TRUE) {
  154. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  155. case DIGIT:
  156. // if this is the first digit after a delimiter, then
  157. // set flags to start computing the new number
  158. if (bNewItem) {
  159. bNewItem = FALSE;
  160. bValidNumber = TRUE;
  161. }
  162. if (bValidNumber) {
  163. dwThisNumber *= 10;
  164. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  165. }
  166. break;
  167. case DELIMITER:
  168. // a delimter is either the delimiter character or the
  169. // end of the string ('\0') if when the delimiter has been
  170. // reached a valid number was found, then compare it to the
  171. // number from the argument list. if this is the end of the
  172. // string and no match was found, then return.
  173. //
  174. if (bValidNumber) {
  175. if (dwThisNumber == dwNumber) return TRUE;
  176. bValidNumber = FALSE;
  177. }
  178. if (*pwcThisChar == 0) {
  179. return FALSE;
  180. } else {
  181. bNewItem = TRUE;
  182. dwThisNumber = 0;
  183. }
  184. break;
  185. case INVALID:
  186. // if an invalid character was encountered, ignore all
  187. // characters up to the next delimiter and then start fresh.
  188. // the invalid number is not compared.
  189. bValidNumber = FALSE;
  190. break;
  191. default:
  192. break;
  193. }
  194. pwcThisChar++;
  195. }
  196. } // IsNumberInUnicodeList
  197. HANDLE
  198. MonOpenEventLog (
  199. )
  200. /*++
  201. Routine Description:
  202. Reads the level of event logging from the registry and opens the
  203. channel to the event logger for subsequent event log entries.
  204. Arguments:
  205. None
  206. Return Value:
  207. Handle to the event log for reporting events.
  208. NULL if open not successful.
  209. --*/
  210. {
  211. HKEY hAppKey;
  212. TCHAR LogLevelValueName[] = TEXT("EventLogLevel");
  213. LONG lStatus;
  214. DWORD dwLogLevel;
  215. DWORD dwValueType;
  216. DWORD dwValueSize;
  217. // if global value of the logging level not initialized or is disabled,
  218. // check the registry to see if it should be updated.
  219. if (!MESSAGE_LEVEL) {
  220. lStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  221. WINSCTRS_LOG_KEY,
  222. 0,
  223. KEY_READ,
  224. &hAppKey);
  225. dwValueSize = sizeof (dwLogLevel);
  226. if (lStatus == ERROR_SUCCESS) {
  227. lStatus = RegQueryValueEx (hAppKey,
  228. LogLevelValueName,
  229. (LPDWORD)NULL,
  230. &dwValueType,
  231. (LPBYTE)&dwLogLevel,
  232. &dwValueSize);
  233. if (lStatus == ERROR_SUCCESS) {
  234. MESSAGE_LEVEL = dwLogLevel;
  235. } else {
  236. MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  237. }
  238. RegCloseKey (hAppKey);
  239. } else {
  240. MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  241. }
  242. }
  243. if (hEventLog == NULL){
  244. hEventLog = RegisterEventSource (
  245. (LPTSTR)NULL, // Use Local Machine
  246. APP_NAME); // event log app name to find in registry
  247. if (hEventLog == NULL) {
  248. REPORT_ERROR (WINS_EVT_LOG_OPEN_ERR, LOG_USER);
  249. }
  250. }
  251. if (hEventLog != NULL) {
  252. dwLogUsers++; // increment count of perfctr log users
  253. }
  254. return (hEventLog);
  255. }
  256. VOID
  257. MonCloseEventLog (
  258. )
  259. /*++
  260. Routine Description:
  261. Closes the handle to the event logger if this is the last caller
  262. Arguments:
  263. None
  264. Return Value:
  265. None
  266. --*/
  267. {
  268. if (hEventLog) {
  269. if (dwLogUsers)
  270. dwLogUsers--;
  271. if (dwLogUsers <= 0) { // and if we're the last, then close up log
  272. REPORT_INFORMATION (WINS_EVT_LOG_CLOSE, LOG_DEBUG);
  273. DeregisterEventSource (hEventLog);
  274. hEventLog = 0;
  275. }
  276. }
  277. }
  278. LONG
  279. AddSrcToReg(
  280. VOID
  281. )
  282. /*++
  283. Routine Description:
  284. This function open (or creates) a log file for registering events
  285. Arguments:
  286. None
  287. Externals Used:
  288. None
  289. Return Value:
  290. Error Handling:
  291. Called by:
  292. Side Effects:
  293. Comments:
  294. None
  295. --*/
  296. {
  297. LONG RetVal = ERROR_SUCCESS;
  298. DWORD NewKeyInd;
  299. TCHAR Buff[160];
  300. DWORD dwData;
  301. RetVal = RegCreateKeyEx(
  302. HKEY_LOCAL_MACHINE, //predefined key value
  303. WINSCTRS_LOG_KEY, //subkey for WINS
  304. 0, //must be zero (reserved)
  305. TEXT("Class"), //class -- may change in future
  306. REG_OPTION_NON_VOLATILE, //non-volatile information
  307. KEY_ALL_ACCESS, //we desire all access to the keyo
  308. NULL, //let key have default sec. attributes
  309. &LogRoot, //handle to key
  310. &NewKeyInd //is it a new key (out arg) -- not
  311. //looked at
  312. );
  313. if (RetVal != ERROR_SUCCESS)
  314. {
  315. return(RetVal);
  316. }
  317. /*
  318. Set the event id message file name
  319. */
  320. lstrcpy(Buff, WINS_LOG_FILE_NAME);
  321. /*
  322. Add the Event-ID message-file name to the subkey
  323. */
  324. RetVal = RegSetValueEx(
  325. LogRoot, //key handle
  326. WinsMsgFileSKey, //value name
  327. 0, //must be zero
  328. REG_EXPAND_SZ, //value type
  329. (LPBYTE)Buff,
  330. (lstrlen(Buff) + 1) * sizeof(TCHAR) //length of value data
  331. );
  332. if (RetVal != ERROR_SUCCESS)
  333. {
  334. return(RetVal);
  335. }
  336. /*
  337. Set the supported data types flags
  338. */
  339. dwData = EVENTLOG_ERROR_TYPE |
  340. EVENTLOG_WARNING_TYPE |
  341. EVENTLOG_INFORMATION_TYPE;
  342. RetVal = RegSetValueEx (
  343. LogRoot, //subkey handle
  344. TEXT("TypesSupported"), //value name
  345. 0, //must be zero
  346. REG_DWORD, //value type
  347. (LPBYTE)&dwData, //Address of value data
  348. sizeof(DWORD) //length of value data
  349. );
  350. if (RetVal != ERROR_SUCCESS)
  351. {
  352. return(RetVal);
  353. }
  354. /*
  355. * Done with the key. Close it
  356. */
  357. RetVal = RegCloseKey(LogRoot);
  358. if (RetVal != ERROR_SUCCESS)
  359. {
  360. return(RetVal);
  361. }
  362. return(RetVal);
  363. }