collect.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include "pch.h"
  2. extern CPerfShare gPerfShare;
  3. extern PSHARE_HEADER gpHeader;
  4. extern BOOL gbInitialized;
  5. BOOL HandleNonCases(LPWSTR lpRequestType,
  6. LPVOID *lppData,
  7. LPDWORD lpcbTotalBytes,
  8. LPDWORD lpcObjectTypes,
  9. PBOOL bMask)
  10. {
  11. DWORD dwQueryType, dwIndex;
  12. BOOL bFound;
  13. //
  14. // Make sure we initialized ok.
  15. //
  16. if ((NULL == gpHeader) || !gbInitialized)
  17. {
  18. *lpcbTotalBytes = (DWORD) 0;
  19. *lpcObjectTypes = (DWORD) 0;
  20. return(TRUE);
  21. }
  22. //
  23. // See if this is a non-NT data request.
  24. //
  25. dwQueryType = GetQueryType(lpRequestType);
  26. if (QUERY_FOREIGN == dwQueryType)
  27. {
  28. *lpcbTotalBytes = (DWORD) 0;
  29. *lpcObjectTypes = (DWORD) 0;
  30. return(TRUE);
  31. }
  32. //
  33. // Make sure we're requesting one of our objects.
  34. //
  35. ZeroMemory(bMask, sizeof(BOOL) * MAX_PERF_OBJECTS);
  36. bFound = FALSE;
  37. if (QUERY_ITEMS == dwQueryType)
  38. {
  39. for(dwIndex = 0; dwIndex < gdwNumberOfPerfObjects; dwIndex++)
  40. {
  41. if ((IsNumberInUnicodeList(gPerfObject[dwIndex].mPerfId,
  42. lpRequestType)) && (gPerfObject[dwIndex].mdwCounters > 0))
  43. {
  44. bMask[dwIndex] = TRUE;
  45. bFound = TRUE;
  46. }
  47. }
  48. if (!bFound)
  49. {
  50. *lpcbTotalBytes = (DWORD) 0;
  51. *lpcObjectTypes = (DWORD) 0;
  52. return(TRUE);
  53. }
  54. } else
  55. {
  56. for(dwIndex = 0; dwIndex < gdwNumberOfPerfObjects; dwIndex++)
  57. bMask[dwIndex] = TRUE;
  58. }
  59. return(FALSE);
  60. }
  61. DWORD ComputeSpaceNeeded(PBOOL bMask)
  62. {
  63. DWORD dwIndex, dwLoop, dwTemp, dwSpaceNeeded[MAX_PERF_OBJECTS];
  64. PSHARE_INSTANCE pInstance;
  65. //
  66. // Go through all the instances and see how much they're taking
  67. // up. We keep totals for each object type.
  68. //
  69. ZeroMemory(dwSpaceNeeded, sizeof(DWORD) * MAX_PERF_OBJECTS);
  70. pInstance = (PSHARE_INSTANCE) (gpHeader + 1);
  71. for(dwLoop = gpHeader->dwInstanceHeader; dwLoop != DWORD_NULL;
  72. dwLoop = pInstance[dwLoop].dwNextInList)
  73. {
  74. for(dwIndex = 0; dwIndex < gdwNumberOfPerfObjects; dwIndex++)
  75. {
  76. if (gPerfObject[dwIndex].mdwFirstCounter ==
  77. pInstance[dwLoop].dwFirstCounter)
  78. {
  79. if (0 < (dwTemp = wcslen(pInstance[dwLoop].wszInstanceName)))
  80. dwTemp = (dwTemp + 1) * sizeof(WCHAR);
  81. dwSpaceNeeded[dwIndex] += (sizeof(PERF_INSTANCE_DEFINITION) +
  82. DWORD_MULTIPLE(dwTemp) +
  83. sizeof(PERF_COUNTER_BLOCK) +
  84. pInstance[dwLoop].dwDataSize);
  85. break;
  86. }
  87. }
  88. }
  89. //
  90. // We have running totals for each object. Now tack on the object
  91. // and counter specific data.
  92. //
  93. for(dwIndex = dwTemp = 0; dwIndex < gdwNumberOfPerfObjects; dwIndex++)
  94. {
  95. // if (dwSpaceNeeded[dwIndex] > 0)
  96. if (bMask[dwIndex])
  97. {
  98. dwTemp += (dwSpaceNeeded[dwIndex] +
  99. sizeof(PERF_OBJECT_TYPE) +
  100. sizeof(PERF_COUNTER_DEFINITION) *
  101. gPerfObject[dwIndex].mdwCounters);
  102. if (!dwSpaceNeeded[dwIndex])
  103. {
  104. dwTemp += sizeof(PERF_INSTANCE_DEFINITION) +
  105. sizeof(PERF_COUNTER_BLOCK) +
  106. MAX_BYTES_FOR_INSTANCE_COUNTERS;
  107. }
  108. }
  109. // else
  110. // bMask[dwIndex] = FALSE;
  111. }
  112. return(dwTemp);
  113. }
  114. VOID BuildPerfmonObjectBase(PPERF_OBJECT_MAP pObject,
  115. PPERF_OBJECT_TYPE_MAP pMap)
  116. {
  117. pMap->mObject.DefinitionLength = sizeof(PERF_OBJECT_TYPE) +
  118. sizeof(PERF_COUNTER_DEFINITION) *
  119. pObject->mdwCounters;
  120. pMap->mObject.HeaderLength = sizeof(PERF_OBJECT_TYPE);
  121. pMap->mObject.ObjectNameTitleIndex = pObject->mPerfId;
  122. pMap->mObject.ObjectNameTitle = 0;
  123. pMap->mObject.ObjectHelpTitleIndex = pObject->mPerfId + 1;
  124. pMap->mObject.ObjectHelpTitle = 0;
  125. pMap->mObject.DetailLevel = PERF_DETAIL_NOVICE;
  126. pMap->mObject.NumCounters = pObject->mdwCounters;
  127. pMap->mObject.NumInstances = 0;
  128. pMap->mObject.CodePage = 0; // Unicode
  129. ZeroMemory(&(pMap->mObject.PerfTime), sizeof(LARGE_INTEGER));
  130. ZeroMemory(&(pMap->mObject.PerfFreq), sizeof(LARGE_INTEGER));
  131. }
  132. VOID BuildPerfmonObjectCounters(PPERF_OBJECT_MAP pObject,
  133. PPERF_OBJECT_TYPE_MAP pMap)
  134. {
  135. DWORD dwIndex, dwTotal;
  136. dwTotal = sizeof(PERF_COUNTER_BLOCK);
  137. for(dwIndex = 0; dwIndex < pObject->mdwCounters; dwIndex++)
  138. {
  139. pMap->mCounter[dwIndex].ByteLength = sizeof(PERF_COUNTER_DEFINITION);
  140. pMap->mCounter[dwIndex].CounterNameTitleIndex =
  141. pObject->mCounter[dwIndex].mPerfId;
  142. pMap->mCounter[dwIndex].CounterNameTitle = 0;
  143. pMap->mCounter[dwIndex].CounterHelpTitleIndex =
  144. pObject->mCounter[dwIndex].mPerfId + 1;
  145. pMap->mCounter[dwIndex].CounterHelpTitle = 0;
  146. pMap->mCounter[dwIndex].DefaultScale = 0; // 1
  147. pMap->mCounter[dwIndex].DetailLevel = PERF_DETAIL_NOVICE;
  148. pMap->mCounter[dwIndex].CounterType =
  149. pObject->mCounter[dwIndex].mdwCounterType;
  150. //
  151. // We need to determine the counter size.
  152. //
  153. switch(pObject->mCounter[dwIndex].mdwCounterType &
  154. PERF_SIZE_VARIABLE_LEN)
  155. {
  156. case PERF_SIZE_DWORD:
  157. pMap->mCounter[dwIndex].CounterSize = sizeof(DWORD);
  158. break;
  159. case PERF_SIZE_LARGE:
  160. pMap->mCounter[dwIndex].CounterSize = sizeof(LARGE_INTEGER);
  161. break;
  162. default:
  163. pMap->mCounter[dwIndex].CounterSize = 0;
  164. break;
  165. }
  166. pMap->mCounter[dwIndex].CounterOffset = dwTotal;
  167. dwTotal += pMap->mCounter[dwIndex].CounterSize;
  168. }
  169. }
  170. VOID BuildPerfmonObjectInstanceStructure(PERF_INSTANCE_DEFINITION *pInstance,
  171. PWCHAR wszInstanceName)
  172. {
  173. DWORD dwLength;
  174. if (0 < (dwLength = wcslen(wszInstanceName) * sizeof(WCHAR)))
  175. dwLength += sizeof(WCHAR);
  176. pInstance->ByteLength = sizeof(PERF_INSTANCE_DEFINITION) +
  177. DWORD_MULTIPLE(dwLength);
  178. pInstance->ParentObjectTitleIndex = 0;
  179. pInstance->ParentObjectInstance = 0;
  180. pInstance->UniqueID = (DWORD) PERF_NO_UNIQUE_ID;
  181. pInstance->NameOffset = sizeof(PERF_INSTANCE_DEFINITION);
  182. pInstance->NameLength = dwLength;
  183. if (dwLength > 0)
  184. wcscpy((PWCHAR) (pInstance + 1), wszInstanceName);
  185. }
  186. DWORD BuildPerfmonObjectInstances(PPERF_OBJECT_MAP pObject,
  187. PPERF_OBJECT_TYPE_MAP pMap,
  188. PBYTE lpData)
  189. {
  190. PERF_INSTANCE_DEFINITION *pInstance;
  191. PERF_COUNTER_BLOCK *pBlock;
  192. PSHARE_INSTANCE pList;
  193. DWORD dwLoop;
  194. //
  195. // Go through all the instances and copy our instances over.
  196. //
  197. pInstance = (PERF_INSTANCE_DEFINITION *) lpData;
  198. pList = (PSHARE_INSTANCE) (gpHeader + 1);
  199. for(dwLoop = gpHeader->dwInstanceHeader; dwLoop != DWORD_NULL;
  200. dwLoop = pList[dwLoop].dwNextInList)
  201. {
  202. if (pObject->mdwFirstCounter == pList[dwLoop].dwFirstCounter)
  203. {
  204. //
  205. // Add the instance structure.
  206. //
  207. BuildPerfmonObjectInstanceStructure(pInstance,
  208. pList[dwLoop].wszInstanceName);
  209. //
  210. // Add the counter block.
  211. //
  212. pBlock = (PERF_COUNTER_BLOCK *) ((PBYTE) pInstance +
  213. pInstance->ByteLength);
  214. pBlock->ByteLength = sizeof(PERF_COUNTER_BLOCK) +
  215. pList[dwLoop].dwDataSize;
  216. //
  217. // Add the data.
  218. //
  219. CopyMemory(pBlock + 1,
  220. pList[dwLoop].Data,
  221. pList[dwLoop].dwDataSize);
  222. pMap->mObject.NumInstances++;
  223. pInstance = (PERF_INSTANCE_DEFINITION *) ((PBYTE) pInstance +
  224. pInstance->ByteLength +
  225. pBlock->ByteLength);
  226. }
  227. }
  228. //
  229. // If there are no instances, we need to include an empty instance.
  230. //
  231. if (0 == pMap->mObject.NumInstances)
  232. {
  233. BuildPerfmonObjectInstanceStructure(pInstance, L"");
  234. pBlock = (PERF_COUNTER_BLOCK *) ((PBYTE) pInstance +
  235. pInstance->ByteLength);
  236. pBlock->ByteLength = sizeof(PERF_COUNTER_BLOCK) +
  237. MAX_BYTES_FOR_INSTANCE_COUNTERS;
  238. ZeroMemory(pBlock + 1, MAX_BYTES_FOR_INSTANCE_COUNTERS);
  239. pInstance = (PERF_INSTANCE_DEFINITION *) ((PBYTE) pInstance +
  240. pInstance->ByteLength +
  241. pBlock->ByteLength);
  242. }
  243. return((PBYTE) pInstance - lpData);
  244. }
  245. DWORD BuildPerfmonObject(PPERF_OBJECT_MAP pObject, LPBYTE lpData)
  246. {
  247. PPERF_OBJECT_TYPE_MAP pMap;
  248. //
  249. // Set up the PERF_OBJECT_TYPE.
  250. //
  251. pMap = (PPERF_OBJECT_TYPE_MAP) lpData;
  252. BuildPerfmonObjectBase(pObject, pMap);
  253. BuildPerfmonObjectCounters(pObject, pMap);
  254. lpData += pMap->mObject.DefinitionLength;
  255. //
  256. // Add the instances and their counters.
  257. //
  258. lpData += BuildPerfmonObjectInstances(pObject, pMap, lpData);
  259. pMap->mObject.TotalByteLength = (DWORD) (lpData - (PBYTE) pMap);
  260. return(pMap->mObject.TotalByteLength);
  261. }
  262. DWORD BuildPerfmonBuffer(PBOOL bMask, LPBYTE *lppData, DWORD dwSpaceNeeded)
  263. {
  264. DWORD dwIndex, dwCount;
  265. for(dwIndex = dwCount = 0; dwIndex < gdwNumberOfPerfObjects; dwIndex++)
  266. {
  267. if (bMask[dwIndex])
  268. {
  269. *lppData += BuildPerfmonObject(&gPerfObject[dwIndex], *lppData);
  270. dwCount++;
  271. }
  272. }
  273. return(dwCount);
  274. }
  275. extern "C" DWORD APIENTRY DwCollectData(LPWSTR lpRequestType,
  276. LPVOID *lppData,
  277. LPDWORD lpcbTotalBytes,
  278. LPDWORD lpcObjectTypes)
  279. {
  280. DWORD dwSpaceNeeded;
  281. BOOL bMask[MAX_PERF_OBJECTS];
  282. PBYTE pStart;
  283. if (HandleNonCases(lpRequestType,
  284. lppData,
  285. lpcbTotalBytes,
  286. lpcObjectTypes,
  287. bMask))
  288. {
  289. return(ERROR_SUCCESS);
  290. }
  291. //
  292. // We have one or more objects that we need to report.
  293. //
  294. //
  295. // Lock the shared memory.
  296. //
  297. if (!gPerfShare.Lock())
  298. {
  299. *lpcbTotalBytes = (DWORD) 0;
  300. *lpcObjectTypes = (DWORD) 0;
  301. return(ERROR_SUCCESS);
  302. }
  303. //
  304. // Figure out how much space we need.
  305. //
  306. dwSpaceNeeded = ComputeSpaceNeeded(bMask);
  307. if (*lpcbTotalBytes < dwSpaceNeeded)
  308. {
  309. gPerfShare.Unlock();
  310. *lpcbTotalBytes = (DWORD) 0;
  311. *lpcObjectTypes = (DWORD) 0;
  312. return(ERROR_MORE_DATA);
  313. }
  314. //
  315. // Fill the buffer with the objects and their data.
  316. //
  317. pStart = (PBYTE) *lppData;
  318. *lpcObjectTypes = BuildPerfmonBuffer(bMask,
  319. (LPBYTE *) lppData,
  320. dwSpaceNeeded);
  321. *lpcbTotalBytes = ((PBYTE) *lppData) - pStart;
  322. //
  323. // We've finished, let's return.
  324. //
  325. gPerfShare.Unlock();
  326. return(ERROR_SUCCESS);
  327. }