windows-nt/Source/XPSP1/NT/sdktools/pviewer/perfdata.c
2020-09-26 16:20:57 +08:00

332 lines
7.9 KiB
C

/******************************************************************************
P E R F O R M A N C E D A T A
Name: perfdata.c
Description:
This module together with objdata.c, instdata.c, and cntrdata.c
access the performance data.
******************************************************************************/
#include <windows.h>
#include <winperf.h>
#include "perfdata.h"
#include <stdlib.h>
LPTSTR *gPerfTitleSz;
LPTSTR TitleData;
//*********************************************************************
//
// GetPerfData
//
// Get a new set of performance data.
//
// *ppData should be NULL initially.
// This function will allocate a buffer big enough to hold the
// data requested by szObjectIndex.
//
// *pDataSize specifies the initial buffer size. If the size is
// too small, the function will increase it until it is big enough
// then return the size through *pDataSize. Caller should
// deallocate *ppData if it is no longer being used.
//
// Returns ERROR_SUCCESS if no error occurs.
//
// Note: the trial and error loop is quite different from the normal
// registry operation. Normally if the buffer is too small,
// RegQueryValueEx returns the required size. In this case,
// the perflib, since the data is dynamic, a buffer big enough
// for the moment may not be enough for the next. Therefor,
// the required size is not returned.
//
// One should start with a resonable size to avoid the overhead
// of reallocation of memory.
//
DWORD GetPerfData (HKEY hPerfKey,
LPTSTR szObjectIndex,
PPERF_DATA *ppData,
DWORD *pDataSize)
{
DWORD DataSize;
DWORD dwR;
DWORD Type;
if (!*ppData)
*ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize);
do {
DataSize = *pDataSize;
dwR = RegQueryValueEx (hPerfKey,
szObjectIndex,
NULL,
&Type,
(BYTE *)*ppData,
&DataSize);
if (dwR == ERROR_MORE_DATA)
{
LocalFree (*ppData);
*pDataSize += 1024;
*ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize);
}
if (!*ppData)
{
LocalFree (*ppData);
return ERROR_NOT_ENOUGH_MEMORY;
}
} while (dwR == ERROR_MORE_DATA);
return dwR;
}
#ifdef UNICODE
#define atoi atoiW
//*********************************************************************
//
// atoiW
//
// Unicode version of atoi.
//
INT atoiW (LPTSTR s)
{
INT i = 0;
while (iswdigit (*s))
{
i = i*10 + (BYTE)*s - L'0';
s++;
}
return i;
}
#endif
//*********************************************************************
//
// GetPerfTitleSz
//
// Retrieves the performance data title strings.
//
// This call retrieves english version of the title strings.
//
// For NT 1.0, the counter names are stored in the "Counters" value
// in the ...\perflib\009 key. For 1.0a and later, the 009 key is no
// longer used. The counter names should be retrieved from "Counter 009"
// value of HKEY_PERFORMANCE_KEY.
//
// Caller should provide two pointers, one for buffering the title
// strings the other for indexing the title strings. This function will
// allocate memory for the TitleBuffer and TitleSz. To get the title
// string for a particular title index one would just index the TitleSz.
// *TitleLastIdx returns the highest index can be used. If TitleSz[N] is
// NULL then there is no Title for index N.
//
// Example: TitleSz[20] points to titile string for title index 20.
//
// When done with the TitleSz, caller should LocalFree(*TitleBuffer).
//
// This function returns ERROR_SUCCESS if no error.
//
DWORD GetPerfTitleSz (HKEY hKeyMachine,
HKEY hKeyPerf,
LPTSTR *TitleBuffer,
LPTSTR *TitleSz[],
DWORD *TitleLastIdx)
{
HKEY hKey1;
HKEY hKey2;
DWORD Type;
DWORD DataSize;
DWORD dwR;
DWORD Len;
DWORD Index;
DWORD dwTemp;
BOOL bNT10;
LPTSTR szCounterValueName;
LPTSTR szTitle;
// Initialize
//
hKey1 = NULL;
hKey2 = NULL;
*TitleBuffer = NULL;
*TitleSz = NULL;
// Open the perflib key to find out the last counter's index and system version.
//
dwR = RegOpenKeyEx (hKeyMachine,
TEXT("software\\microsoft\\windows nt\\currentversion\\perflib"),
0,
KEY_READ,
&hKey1);
if (dwR != ERROR_SUCCESS)
goto done;
// Get the last counter's index so we know how much memory to allocate for TitleSz
//
DataSize = sizeof (DWORD);
dwR = RegQueryValueEx (hKey1, TEXT("Last Counter"), 0, &Type, (LPBYTE)TitleLastIdx, &DataSize);
if (dwR != ERROR_SUCCESS)
goto done;
// Find system version, for system earlier than 1.0a, there's no version value.
//
dwR = RegQueryValueEx (hKey1, TEXT("Version"), 0, &Type, (LPBYTE)&dwTemp, &DataSize);
if (dwR != ERROR_SUCCESS)
// unable to read the value, assume NT 1.0
bNT10 = TRUE;
else
// found the value, so, NT 1.0a or later
bNT10 = FALSE;
// Now, get ready for the counter names and indexes.
//
if (bNT10)
{
// NT 1.0, so make hKey2 point to ...\perflib\009 and get
// the counters from value "Counters"
//
szCounterValueName = TEXT("Counters");
dwR = RegOpenKeyEx (hKeyMachine,
TEXT("software\\microsoft\\windows nt\\currentversion\\perflib\\009"),
0,
KEY_READ,
&hKey2);
if (dwR != ERROR_SUCCESS)
goto done;
}
else
{
// NT 1.0a or later. Get the counters in key HKEY_PERFORMANCE_KEY
// and from value "Counter 009"
//
szCounterValueName = TEXT("Counter 009");
hKey2 = hKeyPerf;
}
// Find out the size of the data.
//
dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, 0, &DataSize);
if (dwR != ERROR_SUCCESS)
goto done;
// Allocate memory
//
*TitleBuffer = (LPTSTR)LocalAlloc (LMEM_FIXED, DataSize);
if (!*TitleBuffer)
{
dwR = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
*TitleSz = (LPTSTR *)LocalAlloc (LPTR, (*TitleLastIdx+1) * sizeof (LPTSTR));
if (!*TitleSz)
{
dwR = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
// Query the data
//
dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, (BYTE *)*TitleBuffer, &DataSize);
if (dwR != ERROR_SUCCESS)
goto done;
// Setup the TitleSz array of pointers to point to beginning of each title string.
// TitleBuffer is type REG_MULTI_SZ.
//
szTitle = *TitleBuffer;
while (Len = lstrlen (szTitle))
{
Index = atoi (szTitle);
szTitle = szTitle + Len +1;
if (Index <= *TitleLastIdx)
(*TitleSz)[Index] = szTitle;
szTitle = szTitle + lstrlen (szTitle) +1;
}
done:
// Done. Now cleanup!
//
if (dwR != ERROR_SUCCESS)
{
// There was an error, free the allocated memory
//
if (*TitleBuffer) LocalFree (*TitleBuffer);
if (*TitleSz) LocalFree (*TitleSz);
}
// Close the hKeys.
//
if (hKey1) RegCloseKey (hKey1);
if (hKey2 && hKey2 != hKeyPerf) RegCloseKey (hKey2);
return dwR;
}