Windows NT 4.0 source code leak
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.

443 lines
11 KiB

4 years ago
  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 routine that constructs the
  7. common parts of a PERF_INSTANCE_DEFINITION (see winperf.h)
  8. Created:
  9. Russ Blake 07/30/92
  10. Revision History:
  11. --*/
  12. //
  13. // include files
  14. //
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <string.h>
  20. #include <winperf.h>
  21. #include "perfctr.h" // error message definition
  22. #include "perfmsg.h"
  23. #include "perfutil.h"
  24. #define INITIAL_SIZE 1024L
  25. #define EXTEND_SIZE 1024L
  26. //
  27. // Global data definitions.
  28. //
  29. PRTL_HEAP_INFORMATION pInfoBuffer = NULL;
  30. ULONG ulInfoBufferSize = 0;
  31. HANDLE hEventLog = NULL; // event log handle for reporting events
  32. // initialized in Open... routines
  33. DWORD dwLogUsers = 0; // count of functions using event log
  34. DWORD MESSAGE_LEVEL = 0;
  35. WCHAR GLOBAL_STRING[] = L"Global";
  36. WCHAR FOREIGN_STRING[] = L"Foreign";
  37. WCHAR COSTLY_STRING[] = L"Costly";
  38. WCHAR NULL_STRING[] = L"\0"; // pointer to null string
  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 < '0') ? INVALID : \
  49. (c > '9') ? INVALID : \
  50. DIGIT)
  51. BOOL
  52. MonBuildInstanceDefinition(
  53. PERF_INSTANCE_DEFINITION *pBuffer,
  54. PVOID *pBufferNext,
  55. DWORD ParentObjectTitleIndex,
  56. DWORD ParentObjectInstance,
  57. DWORD UniqueID,
  58. PUNICODE_STRING Name
  59. )
  60. /*++
  61. MonBuildInstanceDefinition - Build an instance of an object
  62. Inputs:
  63. pBuffer - pointer to buffer where instance is to
  64. be constructed
  65. pBufferNext - pointer to a pointer which will contain
  66. next available location, DWORD aligned
  67. ParentObjectTitleIndex
  68. - Title Index of parent object type; 0 if
  69. no parent object
  70. ParentObjectInstance
  71. - Index into instances of parent object
  72. type, starting at 0, for this instances
  73. parent object instance
  74. UniqueID - a unique identifier which should be used
  75. instead of the Name for identifying
  76. this instance
  77. Name - Name of this instance
  78. --*/
  79. {
  80. DWORD NameLength;
  81. WCHAR *pName;
  82. //
  83. // Include trailing null in name size
  84. //
  85. NameLength = Name->Length;
  86. if ( !NameLength ||
  87. Name->Buffer[(NameLength/sizeof(WCHAR))-1] != UNICODE_NULL ) {
  88. NameLength += sizeof(WCHAR);
  89. }
  90. pBuffer->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
  91. DWORD_MULTIPLE(NameLength);
  92. pBuffer->ParentObjectTitleIndex = ParentObjectTitleIndex;
  93. pBuffer->ParentObjectInstance = ParentObjectInstance;
  94. pBuffer->UniqueID = UniqueID;
  95. pBuffer->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
  96. pBuffer->NameLength = NameLength;
  97. pName = (PWCHAR)&pBuffer[1];
  98. RtlMoveMemory(pName,Name->Buffer,Name->Length);
  99. // Always null terminated. Space for this reserved above.
  100. pName[(NameLength/sizeof(WCHAR))-1] = UNICODE_NULL;
  101. *pBufferNext = (PVOID) ((PCHAR) pBuffer + pBuffer->ByteLength);
  102. return 0;
  103. }
  104. HANDLE
  105. MonOpenEventLog (
  106. )
  107. /*++
  108. Routine Description:
  109. Reads the level of event logging from the registry and opens the
  110. channel to the event logger for subsequent event log entries.
  111. Arguments:
  112. None
  113. Return Value:
  114. Handle to the event log for reporting events.
  115. NULL if open not successful.
  116. --*/
  117. {
  118. HKEY hAppKey;
  119. TCHAR LogLevelKeyName[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
  120. TCHAR LogLevelValueName[] = "EventLogLevel";
  121. LONG lStatus;
  122. DWORD dwLogLevel;
  123. DWORD dwValueType;
  124. DWORD dwValueSize;
  125. // if global value of the logging level not initialized or is disabled,
  126. // check the registry to see if it should be updated.
  127. if (!MESSAGE_LEVEL) {
  128. lStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  129. LogLevelKeyName,
  130. 0,
  131. KEY_READ,
  132. &hAppKey);
  133. dwValueSize = sizeof (dwLogLevel);
  134. if (lStatus == ERROR_SUCCESS) {
  135. lStatus = RegQueryValueEx (hAppKey,
  136. LogLevelValueName,
  137. (LPDWORD)NULL,
  138. &dwValueType,
  139. (LPBYTE)&dwLogLevel,
  140. &dwValueSize);
  141. if (lStatus == ERROR_SUCCESS) {
  142. MESSAGE_LEVEL = dwLogLevel;
  143. } else {
  144. MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  145. }
  146. RegCloseKey (hAppKey);
  147. } else {
  148. MESSAGE_LEVEL = MESSAGE_LEVEL_DEFAULT;
  149. }
  150. }
  151. if (hEventLog == NULL){
  152. hEventLog = RegisterEventSource (
  153. (LPTSTR)NULL, // Use Local Machine
  154. APP_NAME); // event log app name to find in registry
  155. if (hEventLog != NULL) {
  156. REPORT_INFORMATION (UTIL_LOG_OPEN, LOG_DEBUG);
  157. }
  158. }
  159. if (hEventLog != NULL) {
  160. dwLogUsers++; // increment count of perfctr log users
  161. }
  162. return (hEventLog);
  163. }
  164. VOID
  165. MonCloseEventLog (
  166. )
  167. /*++
  168. Routine Description:
  169. Closes the handle to the event logger if this is the last caller
  170. Arguments:
  171. None
  172. Return Value:
  173. None
  174. --*/
  175. {
  176. if (hEventLog) {
  177. if (dwLogUsers)
  178. dwLogUsers--;
  179. if (dwLogUsers <= 0) { // and if we're the last, then close up log
  180. REPORT_INFORMATION (UTIL_CLOSING_LOG, LOG_DEBUG);
  181. DeregisterEventSource (hEventLog);
  182. hEventLog = 0;
  183. }
  184. }
  185. }
  186. DWORD
  187. GetQueryType (
  188. IN LPWSTR lpValue
  189. )
  190. /*++
  191. GetQueryType
  192. returns the type of query described in the lpValue string so that
  193. the appropriate processing method may be used
  194. Arguments
  195. IN lpValue
  196. string passed to PerfRegQuery Value for processing
  197. Return Value
  198. QUERY_GLOBAL
  199. if lpValue == 0 (null pointer)
  200. lpValue == pointer to Null string
  201. lpValue == pointer to "Global" string
  202. QUERY_FOREIGN
  203. if lpValue == pointer to "Foriegn" string
  204. QUERY_COSTLY
  205. if lpValue == pointer to "Costly" string
  206. otherwise:
  207. QUERY_ITEMS
  208. --*/
  209. {
  210. WCHAR *pwcArgChar, *pwcTypeChar;
  211. BOOL bFound;
  212. if (lpValue == 0) {
  213. return QUERY_GLOBAL;
  214. } else if (*lpValue == 0) {
  215. return QUERY_GLOBAL;
  216. }
  217. // check for "Global" request
  218. pwcArgChar = lpValue;
  219. pwcTypeChar = GLOBAL_STRING;
  220. bFound = TRUE; // assume found until contradicted
  221. // check to the length of the shortest string
  222. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  223. if (*pwcArgChar++ != *pwcTypeChar++) {
  224. bFound = FALSE; // no match
  225. break; // bail out now
  226. }
  227. }
  228. if (bFound) return QUERY_GLOBAL;
  229. // check for "Foreign" request
  230. pwcArgChar = lpValue;
  231. pwcTypeChar = FOREIGN_STRING;
  232. bFound = TRUE; // assume found until contradicted
  233. // check to the length of the shortest string
  234. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  235. if (*pwcArgChar++ != *pwcTypeChar++) {
  236. bFound = FALSE; // no match
  237. break; // bail out now
  238. }
  239. }
  240. if (bFound) return QUERY_FOREIGN;
  241. // check for "Costly" request
  242. pwcArgChar = lpValue;
  243. pwcTypeChar = COSTLY_STRING;
  244. bFound = TRUE; // assume found until contradicted
  245. // check to the length of the shortest string
  246. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  247. if (*pwcArgChar++ != *pwcTypeChar++) {
  248. bFound = FALSE; // no match
  249. break; // bail out now
  250. }
  251. }
  252. if (bFound) return QUERY_COSTLY;
  253. // if not Global and not Foreign and not Costly,
  254. // then it must be an item list
  255. return QUERY_ITEMS;
  256. }
  257. BOOL
  258. IsNumberInUnicodeList (
  259. IN DWORD dwNumber,
  260. IN LPWSTR lpwszUnicodeList
  261. )
  262. /*++
  263. IsNumberInUnicodeList
  264. Arguments:
  265. IN dwNumber
  266. DWORD number to find in list
  267. IN lpwszUnicodeList
  268. Null terminated, Space delimited list of decimal numbers
  269. Return Value:
  270. TRUE:
  271. dwNumber was found in the list of unicode number strings
  272. FALSE:
  273. dwNumber was not found in the list.
  274. --*/
  275. {
  276. DWORD dwThisNumber;
  277. WCHAR *pwcThisChar;
  278. BOOL bValidNumber;
  279. BOOL bNewItem;
  280. BOOL bReturnValue;
  281. WCHAR wcDelimiter; // could be an argument to be more flexible
  282. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  283. pwcThisChar = lpwszUnicodeList;
  284. dwThisNumber = 0;
  285. wcDelimiter = (WCHAR)' ';
  286. bValidNumber = FALSE;
  287. bNewItem = TRUE;
  288. while (TRUE) {
  289. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  290. case DIGIT:
  291. // if this is the first digit after a delimiter, then
  292. // set flags to start computing the new number
  293. if (bNewItem) {
  294. bNewItem = FALSE;
  295. bValidNumber = TRUE;
  296. }
  297. if (bValidNumber) {
  298. dwThisNumber *= 10;
  299. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  300. }
  301. break;
  302. case DELIMITER:
  303. // a delimter is either the delimiter character or the
  304. // end of the string ('\0') if when the delimiter has been
  305. // reached a valid number was found, then compare it to the
  306. // number from the argument list. if this is the end of the
  307. // string and no match was found, then return.
  308. //
  309. if (bValidNumber) {
  310. if (dwThisNumber == dwNumber) return TRUE;
  311. bValidNumber = FALSE;
  312. }
  313. if (*pwcThisChar == 0) {
  314. return FALSE;
  315. } else {
  316. bNewItem = TRUE;
  317. dwThisNumber = 0;
  318. }
  319. break;
  320. case INVALID:
  321. // if an invalid character was encountered, ignore all
  322. // characters up to the next delimiter and then start fresh.
  323. // the invalid number is not compared.
  324. bValidNumber = FALSE;
  325. break;
  326. default:
  327. break;
  328. }
  329. pwcThisChar++;
  330. }
  331. } // IsNumberInUnicodeList