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.

284 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. grovperf.cpp
  5. Abstract:
  6. SIS Groveler performance DLL main file
  7. Authors:
  8. John Douceur, 1998
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "all.hxx"
  14. static _TCHAR *service_name = _T("Groveler");
  15. static DWORD first_counter;
  16. static DWORD first_help;
  17. static int open_count = 0;
  18. static SharedData *shared_data;
  19. static const int ms_per_100ns_inv = 10000;
  20. static __int64 total_counter[num_perf_counters];
  21. extern "C" DWORD CALLBACK OpenGrovelerPerformanceData(LPWSTR lpDeviceNames)
  22. {
  23. if (open_count == 0)
  24. {
  25. shared_data = new SharedData;
  26. ASSERT(shared_data != 0);
  27. HKEY path_key;
  28. _TCHAR perf_path[1024];
  29. _stprintf(perf_path,
  30. _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Performance"),
  31. service_name);
  32. long result =
  33. RegOpenKeyEx(HKEY_LOCAL_MACHINE, perf_path, 0, KEY_READ, &path_key);
  34. ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result));
  35. if (result != ERROR_SUCCESS)
  36. {
  37. return result;
  38. }
  39. ASSERT(path_key != 0);
  40. first_counter = 0;
  41. DWORD ctr_size = sizeof(DWORD);
  42. result = RegQueryValueEx(path_key, _T("First Counter"), 0, 0,
  43. (BYTE *)&first_counter, &ctr_size);
  44. ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result));
  45. if (result != ERROR_SUCCESS)
  46. {
  47. return result;
  48. }
  49. first_help = 0;
  50. ctr_size = sizeof(DWORD);
  51. result = RegQueryValueEx(path_key, _T("First Help"), 0, 0,
  52. (BYTE *)&first_help, &ctr_size);
  53. ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result));
  54. if (result != ERROR_SUCCESS)
  55. {
  56. return result;
  57. }
  58. ASSERT(path_key != 0);
  59. RegCloseKey(path_key);
  60. path_key = 0;
  61. }
  62. open_count++;
  63. return ERROR_SUCCESS;
  64. }
  65. extern "C" DWORD WINAPI CloseGrovelerPerformanceData()
  66. {
  67. open_count--;
  68. if (open_count == 0)
  69. {
  70. ASSERT(shared_data != 0);
  71. delete shared_data;
  72. shared_data = 0;
  73. }
  74. return ERROR_SUCCESS;
  75. }
  76. extern "C" DWORD WINAPI CollectGrovelerPerformanceData(
  77. LPWSTR lpwszValue,
  78. LPVOID *lppData,
  79. LPDWORD lpcbBytes,
  80. LPDWORD lpcObjectTypes)
  81. {
  82. if (open_count == 0)
  83. {
  84. *lpcbBytes = 0;
  85. *lpcObjectTypes = 0;
  86. return ERROR_SUCCESS;
  87. }
  88. int num_partitions;
  89. SharedDataRecord records[max_shared_data_records];
  90. bool ok = shared_data->extract_values(&num_partitions, records);
  91. if (!ok)
  92. {
  93. *lpcbBytes = 0;
  94. *lpcObjectTypes = 0;
  95. return ERROR_SUCCESS;
  96. }
  97. int data_size = space_needed_for_data(num_partitions);
  98. if (data_size > int(*lpcbBytes))
  99. {
  100. *lpcbBytes = 0;
  101. *lpcObjectTypes = 0;
  102. return ERROR_MORE_DATA;
  103. }
  104. build_part_object_info_block(lppData, num_partitions, data_size);
  105. for (int index = 0; index < num_partitions; index++)
  106. {
  107. build_part_instance_info_block(lppData, index, records);
  108. }
  109. if (num_partitions > 0)
  110. {
  111. build_total_instance_info_block(lppData, num_partitions, records);
  112. }
  113. *lpcbBytes = data_size;
  114. *lpcObjectTypes = 1;
  115. return ERROR_SUCCESS;
  116. }
  117. int space_needed_for_data(
  118. int num_partitions)
  119. {
  120. if (num_partitions > 0)
  121. {
  122. return sizeof(PartitionObjectInformationBlock) +
  123. num_partitions * sizeof(PartitionInstanceInformationBlock) +
  124. sizeof(TotalInstanceInformationBlock);
  125. }
  126. else
  127. {
  128. return sizeof(PartitionObjectInformationBlock);
  129. }
  130. }
  131. void build_part_object_info_block(
  132. LPVOID *lppData,
  133. int num_partitions,
  134. int data_size)
  135. {
  136. int num_instances = 0;
  137. if (num_partitions > 0)
  138. {
  139. num_instances = num_partitions + 1;
  140. }
  141. PartitionObjectInformationBlock *block =
  142. (PartitionObjectInformationBlock *)*lppData;
  143. block->object_type.TotalByteLength = data_size;
  144. block->object_type.DefinitionLength =
  145. sizeof(PartitionObjectInformationBlock);
  146. block->object_type.HeaderLength = sizeof(PERF_OBJECT_TYPE);
  147. block->object_type.ObjectNameTitleIndex = first_counter;
  148. block->object_type.ObjectNameTitle = 0;
  149. block->object_type.ObjectHelpTitleIndex = first_help;
  150. block->object_type.ObjectHelpTitle = 0;
  151. block->object_type.DetailLevel = object_info.detail_level;
  152. block->object_type.NumCounters = num_perf_counters;
  153. block->object_type.DefaultCounter = 0;
  154. block->object_type.NumInstances = num_instances;
  155. block->object_type.CodePage = 0;
  156. for (int index = 0; index < num_perf_counters; index++)
  157. {
  158. block->definition[index].ByteLength = sizeof(PERF_COUNTER_DEFINITION);
  159. block->definition[index].CounterNameTitleIndex =
  160. first_counter + 2 * (index + 1);
  161. block->definition[index].CounterNameTitle = 0;
  162. block->definition[index].CounterHelpTitleIndex =
  163. first_help + 2 * (index + 1);
  164. block->definition[index].CounterHelpTitle = 0;
  165. block->definition[index].DefaultScale = 0;
  166. block->definition[index].DetailLevel = counter_info[index].detail_level;
  167. block->definition[index].CounterType = counter_info[index].counter_type;
  168. block->definition[index].CounterSize = sizeof(LARGE_INTEGER);
  169. block->definition[index].CounterOffset =
  170. FIELD_OFFSET( PartitionData, counter[index] );
  171. }
  172. *lppData = (void *)(block + 1);
  173. }
  174. void build_part_instance_info_block(
  175. LPVOID *lppData,
  176. int partition_index,
  177. SharedDataRecord *records)
  178. {
  179. PartitionInstanceInformationBlock *block =
  180. (PartitionInstanceInformationBlock *)*lppData;
  181. block->instance_def.ByteLength =
  182. FIELD_OFFSET(PartitionInstanceInformationBlock, partition_data);
  183. block->instance_def.ParentObjectTitleIndex = 0;
  184. block->instance_def.ParentObjectInstance = 0;
  185. block->instance_def.UniqueID = PERF_NO_UNIQUE_ID;
  186. block->instance_def.NameOffset =
  187. FIELD_OFFSET(PartitionInstanceInformationBlock, instance_name);
  188. block->instance_def.NameLength =
  189. sizeof(_TCHAR) * (partition_name_length);
  190. _stprintf(block->instance_name, _T("%-.*s"),
  191. partition_name_length,
  192. records[partition_index].driveName);
  193. block->partition_data.counter_block.ByteLength = sizeof(PartitionData);
  194. for (int index = 0; index < num_perf_counters; index++)
  195. {
  196. switch (counter_info[index].counter_type)
  197. {
  198. case PERF_100NSEC_TIMER:
  199. block->partition_data.counter[index].QuadPart = ms_per_100ns_inv *
  200. records[partition_index].fields[counter_info[index].source];
  201. break;
  202. default:
  203. block->partition_data.counter[index].QuadPart =
  204. records[partition_index].fields[counter_info[index].source];
  205. break;
  206. }
  207. }
  208. *lppData = (void *)(block + 1);
  209. }
  210. void build_total_instance_info_block(
  211. LPVOID *lppData,
  212. int num_partitions,
  213. SharedDataRecord *records)
  214. {
  215. TotalInstanceInformationBlock *block =
  216. (TotalInstanceInformationBlock *)*lppData;
  217. block->instance_def.ByteLength =
  218. FIELD_OFFSET(TotalInstanceInformationBlock, partition_data);
  219. block->instance_def.ParentObjectTitleIndex = 0;
  220. block->instance_def.ParentObjectInstance = 0;
  221. block->instance_def.UniqueID = PERF_NO_UNIQUE_ID;
  222. block->instance_def.NameOffset =
  223. FIELD_OFFSET(TotalInstanceInformationBlock, instance_name);
  224. block->instance_def.NameLength =
  225. sizeof(_TCHAR) * (total_name_length);
  226. _tcscpy(block->instance_name, _T("_Total"));
  227. block->partition_data.counter_block.ByteLength = sizeof(PartitionData);
  228. for (int index = 0; index < num_perf_counters; index++)
  229. {
  230. total_counter[index] = 0;
  231. }
  232. for (int part = 0; part < num_partitions; part++)
  233. {
  234. for (index = 0; index < num_perf_counters; index++)
  235. {
  236. total_counter[index] +=
  237. records[part].fields[counter_info[index].source];
  238. }
  239. }
  240. for (index = 0; index < num_perf_counters; index++)
  241. {
  242. switch (counter_info[index].counter_type)
  243. {
  244. case PERF_100NSEC_TIMER:
  245. block->partition_data.counter[index].QuadPart =
  246. ms_per_100ns_inv * total_counter[index];
  247. break;
  248. default:
  249. block->partition_data.counter[index].QuadPart =
  250. total_counter[index];
  251. break;
  252. }
  253. }
  254. *lppData = (void *)(block + 1);
  255. }