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.

365 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. perfutil.c
  5. Abstract:
  6. This file implements the utility routines used for all perfmon
  7. interface dlls in the internet services group.
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 16-Nov-1995
  10. Pulled from perfmon interface common code.
  11. Environment:
  12. User Mode
  13. Project:
  14. Internet Servies Common Runtime functions
  15. Functions Exported:
  16. DWORD GetQueryType();
  17. BOOL IsNumberInUnicodeList();
  18. VOID MonBuildInstanceDefinition();
  19. Revision History:
  20. Sophia Chung (sophiac) 05-Nov-1996
  21. Added routine to support multiple instances
  22. --*/
  23. /************************************************************
  24. * Include Headers
  25. ************************************************************/
  26. #include <windows.h>
  27. #include <string.h>
  28. #include <winperf.h>
  29. #include <perfutil.h>
  30. /************************************************************
  31. * Global Data Definitions
  32. ************************************************************/
  33. WCHAR GLOBAL_STRING[] = L"Global";
  34. WCHAR FOREIGN_STRING[] = L"Foreign";
  35. WCHAR COSTLY_STRING[] = L"Costly";
  36. // test for delimiter, end of line and non-digit characters
  37. // used by IsNumberInUnicodeList routine
  38. //
  39. #define DIGIT 1
  40. #define DELIMITER 2
  41. #define INVALID 3
  42. #define EvalThisChar(c,d) ( \
  43. (c == d) ? DELIMITER : \
  44. (c == 0) ? DELIMITER : \
  45. (c < (WCHAR)'0') ? INVALID : \
  46. (c > (WCHAR)'9') ? INVALID : \
  47. DIGIT)
  48. #define ALIGN_ON_QWORD(x) \
  49. ((VOID *)(((ULONG_PTR)(x) + ((8)-1)) & ~((ULONG_PTR)(8)-1)))
  50. /************************************************************
  51. * Functions
  52. ************************************************************/
  53. DWORD
  54. GetQueryType (
  55. IN LPWSTR lpValue
  56. )
  57. /*++
  58. GetQueryType
  59. returns the type of query described in the lpValue string so that
  60. the appropriate processing method may be used
  61. Arguments
  62. IN lpValue
  63. string passed to PerfRegQuery Value for processing
  64. Return Value
  65. QUERY_GLOBAL
  66. if lpValue == 0 (null pointer)
  67. lpValue == pointer to Null string
  68. lpValue == pointer to "Global" string
  69. QUERY_FOREIGN
  70. if lpValue == pointer to "Foriegn" string
  71. QUERY_COSTLY
  72. if lpValue == pointer to "Costly" string
  73. otherwise:
  74. QUERY_ITEMS
  75. --*/
  76. {
  77. WCHAR *pwcArgChar, *pwcTypeChar;
  78. BOOL bFound;
  79. if (lpValue == 0) {
  80. return QUERY_GLOBAL;
  81. } else if (*lpValue == 0) {
  82. return QUERY_GLOBAL;
  83. }
  84. // check for "Global" request
  85. pwcArgChar = lpValue;
  86. pwcTypeChar = GLOBAL_STRING;
  87. bFound = TRUE; // assume found until contradicted
  88. // check to the length of the shortest string
  89. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  90. if (*pwcArgChar++ != *pwcTypeChar++) {
  91. bFound = FALSE; // no match
  92. break; // bail out now
  93. }
  94. }
  95. if (bFound) return QUERY_GLOBAL;
  96. // check for "Foreign" request
  97. pwcArgChar = lpValue;
  98. pwcTypeChar = FOREIGN_STRING;
  99. bFound = TRUE; // assume found until contradicted
  100. // check to the length of the shortest string
  101. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  102. if (*pwcArgChar++ != *pwcTypeChar++) {
  103. bFound = FALSE; // no match
  104. break; // bail out now
  105. }
  106. }
  107. if (bFound) return QUERY_FOREIGN;
  108. // check for "Costly" request
  109. pwcArgChar = lpValue;
  110. pwcTypeChar = COSTLY_STRING;
  111. bFound = TRUE; // assume found until contradicted
  112. // check to the length of the shortest string
  113. while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) {
  114. if (*pwcArgChar++ != *pwcTypeChar++) {
  115. bFound = FALSE; // no match
  116. break; // bail out now
  117. }
  118. }
  119. if (bFound) return QUERY_COSTLY;
  120. // if not Global and not Foreign and not Costly,
  121. // then it must be an item list
  122. return QUERY_ITEMS;
  123. }
  124. BOOL
  125. IsNumberInUnicodeList (
  126. IN DWORD dwNumber,
  127. IN LPWSTR lpwszUnicodeList
  128. )
  129. /*++
  130. IsNumberInUnicodeList
  131. Arguments:
  132. IN dwNumber
  133. DWORD number to find in list
  134. IN lpwszUnicodeList
  135. Null terminated, Space delimited list of decimal numbers
  136. Return Value:
  137. TRUE:
  138. dwNumber was found in the list of unicode number strings
  139. FALSE:
  140. dwNumber was not found in the list.
  141. --*/
  142. {
  143. DWORD dwThisNumber;
  144. WCHAR *pwcThisChar;
  145. BOOL bValidNumber;
  146. BOOL bNewItem;
  147. WCHAR wcDelimiter; // could be an argument to be more flexible
  148. if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not founde
  149. pwcThisChar = lpwszUnicodeList;
  150. dwThisNumber = 0;
  151. wcDelimiter = (WCHAR)' ';
  152. bValidNumber = FALSE;
  153. bNewItem = TRUE;
  154. while (TRUE) {
  155. switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  156. case DIGIT:
  157. // if this is the first digit after a delimiter, then
  158. // set flags to start computing the new number
  159. if (bNewItem) {
  160. bNewItem = FALSE;
  161. bValidNumber = TRUE;
  162. }
  163. if (bValidNumber) {
  164. dwThisNumber *= 10;
  165. dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  166. }
  167. break;
  168. case DELIMITER:
  169. // a delimter is either the delimiter character or the
  170. // end of the string ('\0') if when the delimiter has been
  171. // reached a valid number was found, then compare it to the
  172. // number from the argument list. if this is the end of the
  173. // string and no match was found, then return.
  174. //
  175. if (bValidNumber) {
  176. if (dwThisNumber == dwNumber) return TRUE;
  177. bValidNumber = FALSE;
  178. }
  179. if (*pwcThisChar == 0) {
  180. return FALSE;
  181. } else {
  182. bNewItem = TRUE;
  183. dwThisNumber = 0;
  184. }
  185. break;
  186. case INVALID:
  187. // if an invalid character was encountered, ignore all
  188. // characters up to the next delimiter and then start fresh.
  189. // the invalid number is not compared.
  190. bValidNumber = FALSE;
  191. break;
  192. default:
  193. break;
  194. }
  195. pwcThisChar++;
  196. }
  197. } // IsNumberInUnicodeList
  198. VOID
  199. MonBuildInstanceDefinition(
  200. OUT PERF_INSTANCE_DEFINITION *pBuffer,
  201. OUT PVOID *pBufferNext,
  202. IN DWORD ParentObjectTitleIndex,
  203. IN DWORD ParentObjectInstance,
  204. IN DWORD UniqueID,
  205. IN LPWSTR Name
  206. )
  207. /*++
  208. MonBuildInstanceDefinition
  209. Build an instance of an object
  210. Arguments:
  211. OUT pBuffer - pointer to buffer where instance is to
  212. be constructed
  213. OUT pBufferNext - pointer to a pointer which will contain
  214. next available location, DWORD aligned
  215. IN ParentObjectTitleIndex
  216. - Title Index of parent object type; 0 if
  217. no parent object
  218. IN ParentObjectInstance
  219. - Index into instances of parent object
  220. type, starting at 0, for this instances
  221. parent object instance
  222. IN UniqueID - a unique identifier which should be used
  223. instead of the Name for identifying
  224. this instance
  225. IN Name - Name of this instance
  226. Return Value:
  227. None.
  228. --*/
  229. {
  230. DWORD NameLength;
  231. LPWSTR pName;
  232. //
  233. // Include trailing null in name size
  234. //
  235. NameLength = (lstrlenW(Name) + 1) * sizeof(WCHAR);
  236. pBuffer->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
  237. DWORD_MULTIPLE(NameLength);
  238. pBuffer->ParentObjectTitleIndex = ParentObjectTitleIndex;
  239. pBuffer->ParentObjectInstance = ParentObjectInstance;
  240. pBuffer->UniqueID = UniqueID;
  241. pBuffer->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
  242. pBuffer->NameLength = NameLength;
  243. // copy name to name buffer
  244. pName = (LPWSTR)&pBuffer[1];
  245. RtlMoveMemory(pName,Name,NameLength);
  246. #if 0
  247. // allign on 8 byte boundary for new NT5 requirement
  248. pBuffer->ByteLength = QWORD_MULTIPLE(pBuffer->ByteLength);
  249. // update "next byte" pointer
  250. *pBufferNext = (PVOID) ((PCHAR) pBuffer + pBuffer->ByteLength);
  251. #endif
  252. // update "next byte" pointer
  253. *pBufferNext = (PVOID) ((PCHAR) pBuffer + pBuffer->ByteLength);
  254. // round up to put next buffer on a QUADWORD boundry
  255. *pBufferNext = ALIGN_ON_QWORD (*pBufferNext);
  256. // adjust length value to match new length
  257. pBuffer->ByteLength = (ULONG)((ULONG_PTR)*pBufferNext - (ULONG_PTR)pBuffer);
  258. return;
  259. }
  260. /************************ End of File ***********************/