332 lines
7.9 KiB
C
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;
|
|
|
|
}
|