/*++ BUILD Version: 0001 // Increment this if a change has global effects Copyright (c) 1998-1999 Microsoft Corporation Module Name: PerfUtil.c Abstract: This file implements utility functions for performance monitoring functions Author: Eliot Gillum (t-eliotg) - July 5, 1998 Revision History --*/ #include #include #include "PerfUtil.h" WCHAR GLOBAL_STRING[] = L"Global"; WCHAR FOREIGN_STRING[] = L"Foreign"; WCHAR COSTLY_STRING[] = L"Costly"; WCHAR NULL_STRING[] = L"\0"; // pointer to null string // test for delimiter, end of line and non-digit characters // used by IsNumberInUnicodeList routine // #define DIGIT 1 #define DELIMITER 2 #define INVALID 3 #define EvalThisChar(c,d) ( \ (c == d) ? DELIMITER : \ (c == 0) ? DELIMITER : \ (c < (WCHAR)'0') ? INVALID : \ (c > (WCHAR)'9') ? INVALID : \ DIGIT) // convertIndices() // Takes a pointer to an array of PERF_COUNTER_DEFINITIONs and converts their indices // to be absolute by adding the appropriate value (dwFirstCounter/dwFirstHelp) // // BYTE *buf Pointer to an array of PERF_COUNTER_DEFINITIONs // int numCounters The number of PERF_COUNTER_DEFINITIONs to convert // DWORD dwFirstCounter Absolute index of the first counter in the series // DWORD dwFirstHelp Absolute index of the first help index in the series void convertIndices(BYTE *buf, int numCounters, DWORD dwFirstCounter, DWORD dwFirstHelp) { int i; // then the counter indices for (i=0; iCounterNameTitleIndex += dwFirstCounter; ((PERF_COUNTER_DEFINITION *)buf)->CounterHelpTitleIndex += dwFirstHelp; buf += sizeof(PERF_COUNTER_DEFINITION); } } DWORD GetQueryType ( IN LPWSTR lpValue ) /*++ GetQueryType returns the type of query described in the lpValue string so that the appropriate processing method may be used Arguments IN lpValue string passed to PerfRegQuery Value for processing Return Value QUERY_GLOBAL if lpValue == 0 (null pointer) lpValue == pointer to Null string lpValue == pointer to "Global" string QUERY_FOREIGN if lpValue == pointer to "Foreign" string QUERY_COSTLY if lpValue == pointer to "Costly" string otherwise: QUERY_ITEMS --*/ { WCHAR *pwcArgChar, *pwcTypeChar; BOOL bFound; if (lpValue == 0) { return QUERY_GLOBAL; } else if (*lpValue == 0) { return QUERY_GLOBAL; } // check for "Global" request pwcArgChar = lpValue; pwcTypeChar = GLOBAL_STRING; bFound = TRUE; // assume found until contradicted // check to the length of the shortest string while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { if (*pwcArgChar++ != *pwcTypeChar++) { bFound = FALSE; // no match break; // bail out now } } if (bFound) return QUERY_GLOBAL; // check for "Foreign" request pwcArgChar = lpValue; pwcTypeChar = FOREIGN_STRING; bFound = TRUE; // assume found until contradicted // check to the length of the shortest string while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { if (*pwcArgChar++ != *pwcTypeChar++) { bFound = FALSE; // no match break; // bail out now } } if (bFound) return QUERY_FOREIGN; // check for "Costly" request pwcArgChar = lpValue; pwcTypeChar = COSTLY_STRING; bFound = TRUE; // assume found until contradicted // check to the length of the shortest string while ((*pwcArgChar != 0) && (*pwcTypeChar != 0)) { if (*pwcArgChar++ != *pwcTypeChar++) { bFound = FALSE; // no match break; // bail out now } } if (bFound) return QUERY_COSTLY; // if not Global and not Foreign and not Costly, // then it must be an item list return QUERY_ITEMS; } BOOL IsNumberInUnicodeList ( IN DWORD dwNumber, IN LPWSTR lpwszUnicodeList ) /*++ IsNumberInUnicodeList Arguments: IN dwNumber DWORD number to find in list IN lpwszUnicodeList Null terminated, Space delimited list of decimal numbers Return Value: TRUE: dwNumber was found in the list of unicode number strings FALSE: dwNumber was not found in the list. --*/ { DWORD dwThisNumber; WCHAR *pwcThisChar; BOOL bValidNumber; BOOL bNewItem; BOOL bReturnValue; WCHAR wcDelimiter; // could be an argument to be more flexible if (lpwszUnicodeList == 0) return FALSE; // null pointer, # not found pwcThisChar = lpwszUnicodeList; dwThisNumber = 0; wcDelimiter = (WCHAR)' '; bValidNumber = FALSE; bNewItem = TRUE; while (TRUE) { switch (EvalThisChar (*pwcThisChar, wcDelimiter)) { case DIGIT: // if this is the first digit after a delimiter, then // set flags to start computing the new number if (bNewItem) { bNewItem = FALSE; bValidNumber = TRUE; } if (bValidNumber) { dwThisNumber *= 10; dwThisNumber += (*pwcThisChar - (WCHAR)'0'); } break; case DELIMITER: // a delimiter is either the delimiter character or the // end of the string ('\0') if when the delimiter has been // reached a valid number was found, then compare it to the // number from the argument list. if this is the end of the // string and no match was found, then return. // if (bValidNumber) { if (dwThisNumber == dwNumber) return TRUE; bValidNumber = FALSE; } if (*pwcThisChar == 0) { return FALSE; } else { bNewItem = TRUE; dwThisNumber = 0; } break; case INVALID: // if an invalid character was encountered, ignore all // characters up to the next delimiter and then start fresh. // the invalid number is not compared. bValidNumber = FALSE; break; default: break; } pwcThisChar++; } } // IsNumberInUnicodeList VOID CorrectInstanceName(PWCHAR IfcName) { WCHAR SpecialChars[] = L")(#\\/"; int k; int r; WCHAR *p; // // perfmon does not allow the following characters in the name. We need to munge the name // and replace them with some other character. // for(r=0; SpecialChars[r]; r++) { p = IfcName; while((p = wcschr(p, SpecialChars[r]))) { *p = L'-'; } } }