/****************************************************************************** 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 #include #include "perfdata.h" #include 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; }