|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
grovperf.cpp
Abstract:
SIS Groveler performance DLL main file
Authors:
John Douceur, 1998
Environment:
User Mode
Revision History:
--*/
#include "all.hxx"
static _TCHAR *service_name = _T("Groveler");
static DWORD first_counter; static DWORD first_help; static int open_count = 0;
static SharedData *shared_data;
static const int ms_per_100ns_inv = 10000;
static __int64 total_counter[num_perf_counters];
extern "C" DWORD CALLBACK OpenGrovelerPerformanceData(LPWSTR lpDeviceNames) { if (open_count == 0) { shared_data = new SharedData; ASSERT(shared_data != 0); HKEY path_key; _TCHAR perf_path[1024]; _stprintf(perf_path, _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Performance"), service_name); long result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, perf_path, 0, KEY_READ, &path_key); ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result)); if (result != ERROR_SUCCESS) { return result; } ASSERT(path_key != 0); first_counter = 0; DWORD ctr_size = sizeof(DWORD); result = RegQueryValueEx(path_key, _T("First Counter"), 0, 0, (BYTE *)&first_counter, &ctr_size); ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result)); if (result != ERROR_SUCCESS) { return result; } first_help = 0; ctr_size = sizeof(DWORD); result = RegQueryValueEx(path_key, _T("First Help"), 0, 0, (BYTE *)&first_help, &ctr_size); ASSERT_PRINTF(result == ERROR_SUCCESS, (_T("error = %d\n"), result)); if (result != ERROR_SUCCESS) { return result; } ASSERT(path_key != 0); RegCloseKey(path_key); path_key = 0; } open_count++; return ERROR_SUCCESS; }
extern "C" DWORD WINAPI CloseGrovelerPerformanceData() { open_count--; if (open_count == 0) { ASSERT(shared_data != 0); delete shared_data; shared_data = 0; } return ERROR_SUCCESS; }
extern "C" DWORD WINAPI CollectGrovelerPerformanceData( LPWSTR lpwszValue, LPVOID *lppData, LPDWORD lpcbBytes, LPDWORD lpcObjectTypes) { if (open_count == 0) { *lpcbBytes = 0; *lpcObjectTypes = 0; return ERROR_SUCCESS; } int num_partitions; SharedDataRecord records[max_shared_data_records]; bool ok = shared_data->extract_values(&num_partitions, records); if (!ok) { *lpcbBytes = 0; *lpcObjectTypes = 0; return ERROR_SUCCESS; } int data_size = space_needed_for_data(num_partitions); if (data_size > int(*lpcbBytes)) { *lpcbBytes = 0; *lpcObjectTypes = 0; return ERROR_MORE_DATA; } build_part_object_info_block(lppData, num_partitions, data_size); for (int index = 0; index < num_partitions; index++) { build_part_instance_info_block(lppData, index, records); } if (num_partitions > 0) { build_total_instance_info_block(lppData, num_partitions, records); } *lpcbBytes = data_size; *lpcObjectTypes = 1; return ERROR_SUCCESS; }
int space_needed_for_data( int num_partitions) { if (num_partitions > 0) { return sizeof(PartitionObjectInformationBlock) + num_partitions * sizeof(PartitionInstanceInformationBlock) + sizeof(TotalInstanceInformationBlock); } else { return sizeof(PartitionObjectInformationBlock); } }
void build_part_object_info_block( LPVOID *lppData, int num_partitions, int data_size) { int num_instances = 0; if (num_partitions > 0) { num_instances = num_partitions + 1; } PartitionObjectInformationBlock *block = (PartitionObjectInformationBlock *)*lppData; block->object_type.TotalByteLength = data_size; block->object_type.DefinitionLength = sizeof(PartitionObjectInformationBlock); block->object_type.HeaderLength = sizeof(PERF_OBJECT_TYPE); block->object_type.ObjectNameTitleIndex = first_counter; block->object_type.ObjectNameTitle = 0; block->object_type.ObjectHelpTitleIndex = first_help; block->object_type.ObjectHelpTitle = 0; block->object_type.DetailLevel = object_info.detail_level; block->object_type.NumCounters = num_perf_counters; block->object_type.DefaultCounter = 0; block->object_type.NumInstances = num_instances; block->object_type.CodePage = 0; for (int index = 0; index < num_perf_counters; index++) { block->definition[index].ByteLength = sizeof(PERF_COUNTER_DEFINITION); block->definition[index].CounterNameTitleIndex = first_counter + 2 * (index + 1); block->definition[index].CounterNameTitle = 0; block->definition[index].CounterHelpTitleIndex = first_help + 2 * (index + 1); block->definition[index].CounterHelpTitle = 0; block->definition[index].DefaultScale = 0; block->definition[index].DetailLevel = counter_info[index].detail_level; block->definition[index].CounterType = counter_info[index].counter_type; block->definition[index].CounterSize = sizeof(LARGE_INTEGER); block->definition[index].CounterOffset = FIELD_OFFSET( PartitionData, counter[index] ); } *lppData = (void *)(block + 1); }
void build_part_instance_info_block( LPVOID *lppData, int partition_index, SharedDataRecord *records) { PartitionInstanceInformationBlock *block = (PartitionInstanceInformationBlock *)*lppData; block->instance_def.ByteLength = FIELD_OFFSET(PartitionInstanceInformationBlock, partition_data); block->instance_def.ParentObjectTitleIndex = 0; block->instance_def.ParentObjectInstance = 0; block->instance_def.UniqueID = PERF_NO_UNIQUE_ID; block->instance_def.NameOffset = FIELD_OFFSET(PartitionInstanceInformationBlock, instance_name); block->instance_def.NameLength = sizeof(_TCHAR) * (partition_name_length);
_stprintf(block->instance_name, _T("%-.*s"), partition_name_length, records[partition_index].driveName);
block->partition_data.counter_block.ByteLength = sizeof(PartitionData); for (int index = 0; index < num_perf_counters; index++) { switch (counter_info[index].counter_type) { case PERF_100NSEC_TIMER: block->partition_data.counter[index].QuadPart = ms_per_100ns_inv * records[partition_index].fields[counter_info[index].source]; break; default: block->partition_data.counter[index].QuadPart = records[partition_index].fields[counter_info[index].source]; break; } } *lppData = (void *)(block + 1); }
void build_total_instance_info_block( LPVOID *lppData, int num_partitions, SharedDataRecord *records) { TotalInstanceInformationBlock *block = (TotalInstanceInformationBlock *)*lppData; block->instance_def.ByteLength = FIELD_OFFSET(TotalInstanceInformationBlock, partition_data); block->instance_def.ParentObjectTitleIndex = 0; block->instance_def.ParentObjectInstance = 0; block->instance_def.UniqueID = PERF_NO_UNIQUE_ID; block->instance_def.NameOffset = FIELD_OFFSET(TotalInstanceInformationBlock, instance_name); block->instance_def.NameLength = sizeof(_TCHAR) * (total_name_length); _tcscpy(block->instance_name, _T("_Total")); block->partition_data.counter_block.ByteLength = sizeof(PartitionData); for (int index = 0; index < num_perf_counters; index++) { total_counter[index] = 0; } for (int part = 0; part < num_partitions; part++) { for (index = 0; index < num_perf_counters; index++) { total_counter[index] += records[part].fields[counter_info[index].source]; } } for (index = 0; index < num_perf_counters; index++) { switch (counter_info[index].counter_type) { case PERF_100NSEC_TIMER: block->partition_data.counter[index].QuadPart = ms_per_100ns_inv * total_counter[index]; break; default: block->partition_data.counter[index].QuadPart = total_counter[index]; break; } } *lppData = (void *)(block + 1); }
|