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

/*++
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);
}