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.
291 lines
8.9 KiB
291 lines
8.9 KiB
/*++
|
|
|
|
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[] = L"Groveler";
|
|
|
|
static DWORD first_counter;
|
|
static DWORD first_help;
|
|
static int open_count = 0;
|
|
|
|
static SharedData *shared_data = NULL;
|
|
|
|
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 != NULL);
|
|
HKEY path_key;
|
|
_TCHAR perf_path[1024];
|
|
|
|
(void)StringCbPrintf(perf_path,
|
|
sizeof(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)
|
|
{
|
|
RegCloseKey(path_key);
|
|
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)
|
|
{
|
|
RegCloseKey(path_key);
|
|
return result;
|
|
}
|
|
ASSERT(path_key != 0);
|
|
RegCloseKey(path_key);
|
|
path_key = 0;
|
|
}
|
|
open_count++;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
extern "C" DWORD WINAPI CloseGrovelerPerformanceData()
|
|
{
|
|
ASSERT(open_count > 0);
|
|
open_count--;
|
|
if (open_count == 0)
|
|
{
|
|
ASSERT(shared_data != NULL);
|
|
delete shared_data;
|
|
shared_data = NULL;
|
|
}
|
|
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);
|
|
|
|
(void)StringCbPrintf(block->instance_name, sizeof(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);
|
|
}
|