#include #include #include #include #include #include #include #include "pdhitype.h" #include "pdhidef.h" #include "perfdata.h" // the following strings are for getting texts from perflib #define OLD_VERSION 0x010000 LPWSTR *BuildNameTable( LPWSTR szComputerName, // computer to query names from LPWSTR lpszLangId, // unicode value of Language subkey PDWORD pdwLastItem // size of array in elements ) /*++ BuildNameTable Arguments: hKeyRegistry Handle to an open registry (this can be local or remote.) and is the value returned by RegConnectRegistry or a default key. lpszLangId The unicode id of the language to look up. (default is 409) Return Value: pointer to an allocated table. (the caller must free it when finished!) the table is an array of pointers to zero terminated strings. NULL is returned if an error occured. --*/ { LPWSTR *lpReturnValue; LPWSTR *lpCounterId; LPWSTR lpCounterNames; LPWSTR lpHelpText; LPWSTR lpThisName; LONG lWin32Status; DWORD dwLastError; DWORD dwValueType; DWORD dwArraySize; DWORD dwBufferSize; DWORD dwCounterSize; DWORD dwHelpSize; DWORD dwThisCounter; DWORD dwSystemVersion; DWORD dwLastId; DWORD dwLastHelpId; HKEY hKeyRegistry = NULL; HKEY hKeyValue = NULL; HKEY hKeyNames = NULL; LPWSTR lpValueNameString; WCHAR CounterNameBuffer [50]; WCHAR HelpNameBuffer [50]; lpValueNameString = NULL; //initialize to NULL lpReturnValue = NULL; if (szComputerName == NULL) { // use local machine hKeyRegistry = HKEY_LOCAL_MACHINE; } else { if (RegConnectRegistryW (szComputerName, HKEY_LOCAL_MACHINE, &hKeyRegistry) != ERROR_SUCCESS) { // unable to connect to registry return NULL; } } // check for null arguments and insert defaults if necessary if (!lpszLangId) { lpszLangId = cszDefaultLangId; } // open registry to get number of items for computing array size lWin32Status = RegOpenKeyExW ( hKeyRegistry, cszNamesKey, RESERVED, KEY_READ, &hKeyValue); if (lWin32Status != ERROR_SUCCESS) { goto BNT_BAILOUT; } // get number of items dwBufferSize = sizeof (dwLastHelpId); lWin32Status = RegQueryValueExW ( hKeyValue, cszLastHelp, RESERVED, &dwValueType, (LPBYTE)&dwLastHelpId, &dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { goto BNT_BAILOUT; } // get number of items dwBufferSize = sizeof (dwLastId); lWin32Status = RegQueryValueExW ( hKeyValue, cszLastCounter, RESERVED, &dwValueType, (LPBYTE)&dwLastId, &dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { goto BNT_BAILOUT; } if (dwLastId < dwLastHelpId) dwLastId = dwLastHelpId; dwArraySize = dwLastId * sizeof(LPWSTR); // get Perflib system version dwBufferSize = sizeof (dwSystemVersion); lWin32Status = RegQueryValueExW ( hKeyValue, cszVersionName, RESERVED, &dwValueType, (LPBYTE)&dwSystemVersion, &dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { dwSystemVersion = OLD_VERSION; } if (dwSystemVersion == OLD_VERSION) { // get names from registry lpValueNameString = G_ALLOC (GPTR, lstrlenW(cszNamesKey) * sizeof (WCHAR) + lstrlenW(cszBackSlash) * sizeof (WCHAR) + lstrlenW(lpszLangId) * sizeof (WCHAR) + sizeof (UNICODE_NULL)); if (!lpValueNameString) goto BNT_BAILOUT; lstrcpyW (lpValueNameString, cszNamesKey); lstrcatW (lpValueNameString, cszBackSlash); lstrcatW (lpValueNameString, lpszLangId); lWin32Status = RegOpenKeyExW ( hKeyRegistry, lpValueNameString, RESERVED, KEY_READ, &hKeyNames); } else { if (szComputerName == NULL) { hKeyNames = HKEY_PERFORMANCE_DATA; } else { if (RegConnectRegistryW (szComputerName, HKEY_PERFORMANCE_DATA, &hKeyNames) != ERROR_SUCCESS) { goto BNT_BAILOUT; } } lstrcpyW (CounterNameBuffer, cszCounterName); lstrcatW (CounterNameBuffer, lpszLangId); lstrcpyW (HelpNameBuffer, cszHelpName); lstrcatW (HelpNameBuffer, lpszLangId); } // get size of counter names and add that to the arrays if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwBufferSize = 0; lWin32Status = RegQueryValueExW ( hKeyNames, dwSystemVersion == OLD_VERSION ? cszCounters : CounterNameBuffer, RESERVED, &dwValueType, NULL, &dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwCounterSize = dwBufferSize; // get size of counter names and add that to the arrays if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwBufferSize = 0; lWin32Status = RegQueryValueExW ( hKeyNames, dwSystemVersion == OLD_VERSION ? cszHelp : HelpNameBuffer, RESERVED, &dwValueType, NULL, &dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwHelpSize = dwBufferSize; lpReturnValue = G_ALLOC (GPTR, dwArraySize + dwCounterSize + dwHelpSize); if (!lpReturnValue) goto BNT_BAILOUT; // initialize pointers into buffer lpCounterId = lpReturnValue; lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize); lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize); // read counters into memory dwBufferSize = dwCounterSize; lWin32Status = RegQueryValueExW ( hKeyNames, dwSystemVersion == OLD_VERSION ? cszCounters : CounterNameBuffer, RESERVED, &dwValueType, (LPVOID)lpCounterNames, &dwBufferSize); if (!lpReturnValue) goto BNT_BAILOUT; dwBufferSize = dwHelpSize; lWin32Status = RegQueryValueExW ( hKeyNames, dwSystemVersion == OLD_VERSION ? cszHelp : HelpNameBuffer, RESERVED, &dwValueType, (LPVOID)lpHelpText, &dwBufferSize); if (!lpReturnValue) goto BNT_BAILOUT; // load counter array items for (lpThisName = lpCounterNames; *lpThisName; lpThisName += (lstrlenW(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); // point to corresponding counter name lpThisName += (lstrlenW(lpThisName)+1); // and load array element; lpCounterId[dwThisCounter] = lpThisName; } for (lpThisName = lpHelpText; *lpThisName; lpThisName += (lstrlenW(lpThisName)+1) ) { // first string should be an integer (in decimal unicode digits) dwThisCounter = wcstoul (lpThisName, NULL, 10); // point to corresponding counter name lpThisName += (lstrlenW(lpThisName)+1); // and load array element; lpCounterId[dwThisCounter] = lpThisName; } if (pdwLastItem) *pdwLastItem = dwLastId; G_FREE ((LPVOID)lpValueNameString); RegCloseKey (hKeyValue); if (dwSystemVersion == OLD_VERSION) RegCloseKey (hKeyNames); return lpReturnValue; BNT_BAILOUT: if (lWin32Status != ERROR_SUCCESS) { dwLastError = GetLastError(); } if (lpValueNameString) { G_FREE ((LPVOID)lpValueNameString); } if (lpReturnValue) { G_FREE ((LPVOID)lpReturnValue); } if (hKeyValue) RegCloseKey (hKeyValue); if (hKeyNames) RegCloseKey (hKeyNames); if (hKeyRegistry) RegCloseKey (hKeyNames); return NULL; } PERF_OBJECT_TYPE * GetObjectDefByTitleIndex( IN PERF_DATA_BLOCK *pDataBlock, IN DWORD ObjectTypeTitleIndex ) { DWORD NumTypeDef; PERF_OBJECT_TYPE *pObjectDef = NULL; PERF_OBJECT_TYPE *pReturnObject = NULL; __try { pObjectDef = FirstObject(pDataBlock); assert (pObjectDef != NULL); for ( NumTypeDef = 0; NumTypeDef < pDataBlock->NumObjectTypes; NumTypeDef++ ) { if ( pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) { pReturnObject = pObjectDef; break; } else { pObjectDef = NextObject(pObjectDef); } } } __except (EXCEPTION_EXECUTE_HANDLER) { pReturnObject = NULL; } return pReturnObject; } PERF_OBJECT_TYPE * GetObjectDefByName ( IN PERF_DATA_BLOCK *pDataBlock, IN DWORD dwLastNameIndex, IN LPCWSTR *NameArray, IN LPCWSTR szObjectName ) { DWORD NumTypeDef; PERF_OBJECT_TYPE *pReturnObject = NULL; PERF_OBJECT_TYPE *pObjectDef = NULL; __try { pObjectDef = FirstObject(pDataBlock); assert (pObjectDef != NULL); for ( NumTypeDef = 0; NumTypeDef < pDataBlock->NumObjectTypes; NumTypeDef++ ) { if ( pObjectDef->ObjectNameTitleIndex < dwLastNameIndex ) { // look up name of object & compare if (lstrcmpiW(NameArray[pObjectDef->ObjectNameTitleIndex], szObjectName) == 0) { pReturnObject = pObjectDef; break; } } pObjectDef = NextObject(pObjectDef); // get next } } __except (EXCEPTION_EXECUTE_HANDLER) { pReturnObject = NULL; } return pReturnObject; } PERF_INSTANCE_DEFINITION * GetInstance( IN PERF_OBJECT_TYPE *pObjectDef, IN LONG InstanceNumber ) { PERF_INSTANCE_DEFINITION *pInstanceDef; LONG NumInstance; if (!pObjectDef) { return 0; } pInstanceDef = FirstInstance(pObjectDef); for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { if ( InstanceNumber == NumInstance ) { return pInstanceDef; } pInstanceDef = NextInstance(pInstanceDef); } return NULL; } PERF_INSTANCE_DEFINITION * GetInstanceByUniqueId( IN PERF_OBJECT_TYPE *pObjectDef, IN LONG InstanceUniqueId ) { PERF_INSTANCE_DEFINITION *pInstanceDef; LONG NumInstance; if (!pObjectDef) { return 0; } pInstanceDef = FirstInstance(pObjectDef); for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { if ( InstanceUniqueId == pInstanceDef->UniqueID ) { return pInstanceDef; } pInstanceDef = NextInstance(pInstanceDef); } return NULL; } LPWSTR GetInstanceName( PPERF_INSTANCE_DEFINITION pInstDef) { return (LPWSTR) ((PCHAR) pInstDef + pInstDef->NameOffset); } DWORD GetAnsiInstanceName (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance, DWORD dwCodePage) { LPSTR szSource; DWORD dwLength; szSource = (LPSTR)GetInstanceName(pInstance); // the locale should be set here // pInstance->NameLength == the number of bytes (chars) in the string dwLength = mbstowcs (lpszInstance, szSource, pInstance->NameLength); lpszInstance[dwLength] = 0; // null terminate string buffer return dwLength; } DWORD GetUnicodeInstanceName (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance) { LPWSTR wszSource; DWORD dwLength; wszSource = GetInstanceName(pInstance) ; // pInstance->NameLength == length of string in BYTES so adjust to // number of wide characters here dwLength = pInstance->NameLength / sizeof(WCHAR); wcsncpy (lpszInstance, (LPWSTR)wszSource, dwLength); // add null termination if string length does not include the null if ((dwLength > 0) && (lpszInstance[dwLength-1] != 0)) { // i.e. it's the last character of the string lpszInstance[dwLength] = 0; // then add a terminating null char to the string } else { // assume that the length value includes the terminating NULL // so adjust value to indicate chars only dwLength--; } return (DWORD)(wcslen(lpszInstance)); // just incase there's null's in the string } void GetInstanceNameStr (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance, DWORD dwCodePage) { DWORD dwCharSize; DWORD dwLength; if (dwCodePage > 0) { dwCharSize = sizeof(CHAR); dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage); } else { // it's a UNICODE name dwCharSize = sizeof(WCHAR); dwLength = GetUnicodeInstanceName (pInstance, lpszInstance); } // sanity check here... // the returned string length (in characters) plus the terminating NULL // should be the same as the specified length in bytes divided by the // character size. If not then the codepage and instance data type // don't line up so test that here if ((dwLength + 1) != (pInstance->NameLength / dwCharSize)) { // something isn't quite right so try the "other" type of string type if (dwCharSize == sizeof(CHAR)) { // then we tried to read it as an ASCII string and that didn't work // so try it as a UNICODE (if that doesn't work give up and return // it any way. dwLength = GetUnicodeInstanceName (pInstance, lpszInstance); } else if (dwCharSize == sizeof(WCHAR)) { // then we tried to read it as a UNICODE string and that didn't work // so try it as an ASCII string (if that doesn't work give up and return // it any way. dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage); } } } PERF_INSTANCE_DEFINITION * GetInstanceByNameUsingParentTitleIndex( PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectDef, LPWSTR pInstanceName, LPWSTR pParentName, DWORD dwIndex ) { BOOL fHaveParent; PERF_OBJECT_TYPE *pParentObj; PERF_INSTANCE_DEFINITION *pParentInst, *pInstanceDef; LONG NumInstance; WCHAR InstanceName[256]; DWORD dwLocalIndex; fHaveParent = FALSE; pInstanceDef = FirstInstance(pObjectDef); dwLocalIndex = dwIndex; for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { GetInstanceNameStr(pInstanceDef,InstanceName, pObjectDef->CodePage); if ( lstrcmpiW(InstanceName, pInstanceName) == 0 ) { // Instance name matches if ( pParentName == NULL ) { // No parent, we're done if this is the right "copy" if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } else { // Must match parent as well pParentObj = GetObjectDefByTitleIndex( pDataBlock, pInstanceDef->ParentObjectTitleIndex); if (!pParentObj) { // can't locate the parent, forget it break ; } // Object type of parent found; now find parent // instance pParentInst = GetInstance(pParentObj, pInstanceDef->ParentObjectInstance); if (!pParentInst) { // can't locate the parent instance, forget it break ; } GetInstanceNameStr(pParentInst,InstanceName, pParentObj->CodePage); if ( lstrcmpiW(InstanceName, pParentName) == 0 ) { // Parent Instance Name matches that passed in if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } } } pInstanceDef = NextInstance(pInstanceDef); } return 0; } PERF_INSTANCE_DEFINITION * GetInstanceByName( PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectDef, LPWSTR pInstanceName, LPWSTR pParentName, DWORD dwIndex ) { BOOL fHaveParent; PERF_OBJECT_TYPE *pParentObj; PERF_INSTANCE_DEFINITION *pParentInst, *pInstanceDef; LONG NumInstance; WCHAR InstanceName[256]; DWORD dwLocalIndex; fHaveParent = FALSE; pInstanceDef = FirstInstance(pObjectDef); dwLocalIndex = dwIndex; for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { GetInstanceNameStr(pInstanceDef,InstanceName, pObjectDef->CodePage); if ( lstrcmpiW(InstanceName, pInstanceName) == 0 ) { // Instance name matches if ( !pInstanceDef->ParentObjectTitleIndex ) { // No parent, we're done if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } else { // Must match parent as well pParentObj = GetObjectDefByTitleIndex( pDataBlock, pInstanceDef->ParentObjectTitleIndex); // Object type of parent found; now find parent // instance pParentInst = GetInstance(pParentObj, pInstanceDef->ParentObjectInstance); GetInstanceNameStr(pParentInst,InstanceName, pParentObj->CodePage); if ( lstrcmpiW(InstanceName, pParentName) == 0 ) { // Parent Instance Name matches that passed in if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } } } pInstanceDef = NextInstance(pInstanceDef); } return 0; } // GetInstanceByName PERF_COUNTER_DEFINITION * GetCounterDefByName ( IN PERF_OBJECT_TYPE *pObject, IN DWORD dwLastNameIndex, IN LPWSTR *NameArray, IN LPWSTR szCounterName ) { DWORD NumTypeDef; PERF_COUNTER_DEFINITION *pThisCounter; pThisCounter = FirstCounter(pObject); for ( NumTypeDef = 0; NumTypeDef < pObject->NumCounters; NumTypeDef++ ) { if ((pThisCounter->CounterNameTitleIndex > 0) && (pThisCounter->CounterNameTitleIndex < dwLastNameIndex )) { // look up name of counter & compare if (lstrcmpiW(NameArray[pThisCounter->CounterNameTitleIndex], szCounterName) == 0) { return pThisCounter; } } pThisCounter = NextCounter(pThisCounter); // get next } return NULL; } PERF_COUNTER_DEFINITION * GetCounterDefByTitleIndex( IN PERF_OBJECT_TYPE *pObjectDef, IN DWORD CounterTitleIndex ) { DWORD NumCounters; PERF_COUNTER_DEFINITION * pCounterDef; pCounterDef = FirstCounter(pObjectDef); for ( NumCounters = 0; NumCounters < pObjectDef->NumCounters; NumCounters++ ) { if ( pCounterDef->CounterNameTitleIndex == CounterTitleIndex ) { return pCounterDef; } pCounterDef = NextCounter(pCounterDef); } return NULL; } LONG GetSystemPerfData ( IN HKEY hKeySystem, IN PPERF_DATA_BLOCK *pPerfData, IN LPWSTR szObjectList ) { // GetSystemPerfData LONG lError = ERROR_SUCCESS; DWORD Size; DWORD Type; if (*pPerfData == NULL) { *pPerfData = G_ALLOC (GPTR, INITIAL_SIZE); if (*pPerfData == NULL) return PDH_MEMORY_ALLOCATION_FAILURE; } __try { while (TRUE) { Size = HeapSize (hPdhHeap, 0, *pPerfData); lError = RegQueryValueExW ( hKeySystem, szObjectList, RESERVED, &Type, (LPBYTE)*pPerfData, &Size); if ((!lError) && (Size > 0) && ((*pPerfData)->Signature[0] == (WCHAR)'P') && ((*pPerfData)->Signature[1] == (WCHAR)'E') && ((*pPerfData)->Signature[2] == (WCHAR)'R') && ((*pPerfData)->Signature[3] == (WCHAR)'F')) { lError = ERROR_SUCCESS; break; } if (lError == ERROR_MORE_DATA) { Size = HeapSize (hPdhHeap, 0, *pPerfData); G_FREE (*pPerfData); *pPerfData = G_ALLOC (GPTR, (Size + EXTEND_SIZE)); if (*pPerfData == NULL) { break; } } else { break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { lError = GetExceptionCode(); } return lError; } // GetSystemPerfData