📄 prfdata.cpp
字号:
/********************************************************************Module name: PrfData.cppNotices: Written 1998 by Jeffrey RichterDescription: C++ template classes for Performance Object data types.********************************************************************///#include "CmnHdr.h"#include "StdAfx.h"#include "PrfData.h"//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Helper function that finds a set of bytes in a memory blockPBYTE FindMemory(PBYTE pbBuf, DWORD cbBuf, PBYTE pbSearchBytes, DWORD cbSearchBytes) { for (DWORD n = 0; n < (cbBuf - cbSearchBytes); n++) { if (pbBuf[n] == pbSearchBytes[0]) { for (DWORD x = 1; x < cbSearchBytes; x++) { if (pbBuf[n + x] != pbSearchBytes[x]) break; // Not a match } if (x == cbSearchBytes) return(&pbBuf[n]); // Match! } } return(NULL); // Not found at all}/////////////////////////////////////////////////////////////////////// Address of the ONE instance of this class (See Collect)//CPrfData* CPrfData::sm_pPrfData = NULL;/////////////////////////////////////////////////////////////////////// Constructor: initializes member variables CPrfData::CPrfData(LPCWSTR pszAppName, PPRFITM pPrfItms) : m_pszAppName(pszAppName), m_pPrfItms(pPrfItms), m_nNumPrfItems(0), m_nNumObjects(0), m_pPrfData(NULL), m_hfm(NULL), m_dwFirstCounter(0), m_dwLastCounter(0), m_dwFirstHelp(1), m_dwLastHelp(1), m_Optex(pszAppName, 4000),m_bIsActive(false) { chASSERT(sm_pPrfData == NULL); // Only one instance can exist sm_pPrfData = this; // Sanity check performance data object/counter map VerifyPrfItemTable();}///////////////////////////////////////////////////////////////////// // DestructorCPrfData::~CPrfData() { if (m_pPrfData != NULL) UnmapViewOfFile(m_pPrfData); if (m_hfm != NULL) CloseHandle(m_hfm);}/////////////////////////////////////////////////////////////////////// Installs performance object/counter map info into registryvoid CPrfData::InstallPrfData(LPCWSTR pszDllPathname) { DWORD dwLastCounter = 0, dwLastHelp = 1; // Read the last counter/help global values from the registry CRegSettings regPerfLib, regApp; chVERIFY(ERROR_SUCCESS == regPerfLib.OpenSubkey(FALSE, HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib")); regPerfLib.GetDWORD(L"Last Counter", &dwLastCounter); regPerfLib.GetDWORD(L"Last Help", &dwLastHelp); // Read the first/last counter/help app values from the registry WCHAR szSubkey[100]; wsprintfW(szSubkey, L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance", m_pszAppName); chVERIFY(ERROR_SUCCESS == regApp.OpenSubkey(FALSE, HKEY_LOCAL_MACHINE, szSubkey)); // Advance to the next counter / help m_dwFirstCounter = m_dwLastCounter = dwLastCounter + 2; m_dwFirstHelp = m_dwLastHelp = dwLastHelp + 2; // Install our counters into the registry AppendRegStrings(regPerfLib, TRUE, &m_dwLastCounter); AppendRegStrings(regPerfLib, FALSE, &m_dwLastHelp); // Tell the registry where the next set of counter can go regPerfLib.SetDWORD(L"Last Counter", m_dwLastCounter); regPerfLib.SetDWORD(L"Last Help", m_dwLastHelp); // Save the installation results for our app regApp.SetString(L"Library", pszDllPathname); regApp.SetString(L"Open", L"PrfData_Open"); regApp.SetString(L"Close", L"PrfData_Close"); regApp.SetString(L"Collect", L"PrfData_Collect"); regApp.SetDWORD (L"First Counter", m_dwFirstCounter); regApp.SetDWORD (L"First Help", m_dwFirstHelp); regApp.SetDWORD (L"Last Counter", m_dwLastCounter); regApp.SetDWORD (L"Last Help", m_dwLastHelp); }/////////////////////////////////////////////////////////////////////// Takes this app's performance info out of the registryvoid CPrfData::UninstallPrfData() { // Read the last counter/help global values from the registry CRegSettings regPerfLib, regApp; chVERIFY(ERROR_SUCCESS == regPerfLib.OpenSubkey(FALSE, HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib")); DWORD dwLastCounter = 0, dwLastHelp = 1; regPerfLib.GetDWORD(L"Last Counter", &dwLastCounter); regPerfLib.GetDWORD(L"Last Help", &dwLastHelp); // Read the first/last counter/help app values from the registry WCHAR szSubkey[100]; wsprintfW(szSubkey, L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance", m_pszAppName); if(ERROR_SUCCESS != regApp.OpenSubkey(TRUE, HKEY_LOCAL_MACHINE, szSubkey)) { regApp.CloseKey(); return; // Not installed } regApp.CloseKey(); if (ERROR_SUCCESS == regApp.OpenSubkey(FALSE, HKEY_LOCAL_MACHINE, szSubkey)) { regApp.GetDWORD(L"First Counter", &m_dwFirstCounter); regApp.GetDWORD(L"First Help", &m_dwFirstHelp); regApp.GetDWORD(L"Last Counter", &m_dwLastCounter); regApp.GetDWORD(L"Last Help", &m_dwLastHelp); PIINDEX num_items = (m_dwLastCounter - m_dwFirstCounter) / 2 + 1; if (num_items == m_nNumPrfItems) { // Only do sanity check when the number of items match. // Else, installing of removing counters will be non-trivial chASSERT((DWORD) m_nNumPrfItems == (m_dwLastCounter - m_dwFirstCounter) / 2 + 1); chASSERT((DWORD) m_nNumPrfItems == (m_dwLastHelp - m_dwFirstHelp) / 2 + 1); chASSERT((m_dwFirstCounter <= m_dwLastCounter) && (m_dwFirstHelp <= m_dwLastHelp)); chASSERT((m_dwLastCounter <= dwLastCounter) && (m_dwLastHelp <= dwLastHelp)); } // Remove the strings from the registry RemoveRegStrings(regPerfLib, TRUE, m_dwFirstCounter, m_dwLastCounter); RemoveRegStrings(regPerfLib, FALSE, m_dwFirstHelp, m_dwLastHelp); // If these counters are the last in, truncate the end // otherwise we leave a gap in the performance counter numbers if (m_dwLastCounter == dwLastCounter) { dwLastCounter -= (int) num_items * 2; dwLastHelp -= (int) num_items * 2; regPerfLib.SetDWORD(L"Last Counter", dwLastCounter); regPerfLib.SetDWORD(L"Last Help", dwLastHelp); } } // Delete the app's registry key regApp.CloseKey(); ::RegDeleteKeyW(HKEY_LOCAL_MACHINE, szSubkey);}/////////////////////////////////////////////////////////////////////// Appends our performance object/counter text/help in the registryvoid CPrfData::AppendRegStrings(CRegSettings& regPerfLib, BOOL fCounter, PDWORD pdwIndex) { // Calculate the number of required for the stuff we want to add DWORD cbInc = 0; for (PIINDEX pii = 0; m_pPrfItms[pii].pit != PIT_END; pii++) { cbInc += (6 + 1) * sizeof(WCHAR); // 6 digit index plus 0-char cbInc += (lstrlenW(fCounter ? m_pPrfItms[pii].pszName : m_pPrfItms[pii].pszHelp) + 1) * sizeof(WCHAR); } // Allocate buffer big enough for original + new data & read it in CRegSettings regLang(FALSE, regPerfLib, L"009"); LPCWSTR pszValue = fCounter ? L"Counter" : L"Help"; DWORD cbOrig = 0; regLang.GetSize(pszValue, &cbOrig); LPWSTR psz = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, cbOrig + cbInc); regLang.GetMultiString(pszValue, psz, cbOrig); // Append our new stuff to the end of the buffer // Subtract 1 for extra terminating 0 char LPWSTR pszInc = (LPWSTR) ((PBYTE) psz + cbOrig) - 1; // Append our strings for (pii = 0; m_pPrfItms[pii].pit != PIT_END; pii++) { LPCWSTR psz = fCounter ? m_pPrfItms[pii].pszName : m_pPrfItms[pii].pszHelp; lstrcpyW(pszInc += wsprintfW(pszInc, L"%d", *pdwIndex) + 1, psz); pszInc += lstrlenW(psz) + 1; *pdwIndex += 2; // Always increment the number by 2 } *pdwIndex -= 2; *pszInc++ = 0; // Append extra terminating 0-char regLang.SetMultiString(pszValue, psz); HeapFree(GetProcessHeap(), 0, psz);}/////////////////////////////////////////////////////////////////////// Remove the object/counter strings from the registryvoid CPrfData::RemoveRegStrings(CRegSettings& regPerfLib, BOOL fCounter, DWORD dwIndexLo, DWORD dwIndexHi) { // Allocate buffer big enough for original data & read it in CRegSettings regLang(FALSE, regPerfLib, L"009"); LPCWSTR pszValue = fCounter ? L"Counter" : L"Help"; DWORD cbOrig = 0; regLang.GetSize(pszValue, &cbOrig); LPWSTR psz = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, cbOrig); regLang.GetMultiString(pszValue, psz, cbOrig); // Find the bounds of what we want to remove WCHAR szNum[10] = { 0 }; // Look for \0#\0 wsprintfW(&szNum[1], L"%d", dwIndexLo); PBYTE pbLo = FindMemory((PBYTE) psz, cbOrig, (PBYTE) szNum, sizeof(WCHAR) * (lstrlenW(&szNum[1]) + 2)); pbLo += sizeof(WCHAR); // 1st byte of stuff to remove wsprintfW(&szNum[1], L"%d", dwIndexHi); PBYTE pbHi = FindMemory((PBYTE) psz, cbOrig, (PBYTE) szNum, sizeof(WCHAR) * (lstrlenW(&szNum[1]) + 2)); pbHi += sizeof(WCHAR); // 1st byte of last counter to remove // Skip over number and text pbHi += (lstrlenW((LPCWSTR) pbHi) + 1) * sizeof(WCHAR); pbHi += (lstrlenW((LPCWSTR) pbHi) + 1) * sizeof(WCHAR); // Shift the strings to keep down over the stuff to delete chASSERT(pbLo <= pbHi); MoveMemory(pbLo, pbHi, ((PBYTE) psz + cbOrig) - pbHi); // Save the updated string information regLang.SetMultiString(pszValue, psz); HeapFree(GetProcessHeap(), 0, psz);}/////////////////////////////////////////////////////////////////////// Creates the shared memory region for the performance informationDWORD CPrfData::ActivatePrfData() { // Read the first/last object/counter text/help values WCHAR szSubkey[100]; wsprintfW(szSubkey, L"SYSTEM\\CurrentControlSet\\Services\\%s\\Performance", m_pszAppName); CRegSettings regApp(TRUE, HKEY_LOCAL_MACHINE, szSubkey); regApp.GetDWORD(L"First Counter", &m_dwFirstCounter); regApp.GetDWORD(L"First Help", &m_dwFirstHelp); regApp.GetDWORD(L"Last Counter", &m_dwLastCounter); regApp.GetDWORD(L"Last Help", &m_dwLastHelp); // Do sanity checks chASSERT((DWORD) m_nNumPrfItems == (m_dwLastCounter - m_dwFirstCounter) / 2 + 1); chASSERT((DWORD) m_nNumPrfItems == (m_dwLastHelp - m_dwFirstHelp) / 2 + 1); chASSERT(m_pPrfData == NULL); // This can only be done once // Calculate how many bytes are needed for the shared memory DWORD cbBytesNeededForAllObjs = 0; for (OBJORD ObjOrd = 0; ObjOrd < (OBJORD) m_nNumObjects; ObjOrd++) { PRFMETRICS pm; PPRFITM pPrfObj; CalcPrfMetrics(ObjOrd, 0, &pm, &pPrfObj); // No instances Instances // --------------------------- --------------------------- // 1 PERF_OBJECT_TABLE 1 PERF_OBJECT_TABLE // 1 PERF_COUNTER_DEFINITION 1 PERF_COUNTER_DEFINITION // 0 PERF_INSTANCE_DEFINITION x PERF_INSTANCE_DEFINITIONs // 1 PERF_COUNTER_BLOCK x PERF_COUNTER_BLOCKs // 0 instance names x instance names pPrfObj->cbOffsetToNextObj = pm.cbPOT + pm.cbPCD + pm.cbPID * (pm.fSupportsInstances ? pm.MaxInstances : 0) + pm.cbPCB * (pm.fSupportsInstances ? pm.MaxInstances : 1) + pm.cbPIN * (pm.fSupportsInstances ? pm.MaxInstances : 0); cbBytesNeededForAllObjs += pPrfObj->cbOffsetToNextObj; } // Attempt to allocate a MMF big enough for the data m_hfm = CreateFileMappingW((HANDLE) 0xffffffff, NULL, PAGE_READWRITE, 0, cbBytesNeededForAllObjs, m_pszAppName); // If dwErr = ERROR_ALREADY_EXISTS, another app has created the // shared data area. This instance doesn't need to initialize it DWORD dwErr = GetLastError(); if (m_hfm == NULL) return(dwErr); m_pPrfData = (PBYTE) MapViewOfFile(m_hfm, FILE_MAP_WRITE, 0, 0, 0); if (dwErr == ERROR_ALREADY_EXISTS) { m_bIsActive = true; return(dwErr); } // This instance actually allocated the shared data, initialize it DWORD dwCounter = m_dwFirstCounter, dwHelp = m_dwFirstHelp; // Set the PERF_OBJECT_TYPEs for each object for (ObjOrd = 0; ObjOrd < m_nNumObjects; ObjOrd++) { PRFMETRICS pm; PPRFITM pPrfObj; CalcPrfMetrics(ObjOrd, 0, &pm, &pPrfObj); // Set the PERF_OBJECT_TYPE members pm.pPOT->TotalByteLength = 0; // Set in Collect function pm.pPOT->DefinitionLength = sizeof(PERF_OBJECT_TYPE) + sizeof(PERF_COUNTER_DEFINITION) * (int) pPrfObj->NumCounters; pm.pPOT->HeaderLength = sizeof(PERF_OBJECT_TYPE); pm.pPOT->ObjectNameTitleIndex = dwCounter; pm.pPOT->ObjectNameTitle = NULL; // Set by PerfMon pm.pPOT->ObjectHelpTitleIndex = dwHelp; pm.pPOT->ObjectHelpTitle = NULL; // Set by PerfMon pm.pPOT->DetailLevel = pPrfObj->dwDetailLevel; pm.pPOT->NumCounters = (DWORD) pPrfObj->NumCounters; if (pPrfObj->DefCounter == (CTRID) -1) { pm.pPOT->DefaultCounter = -1; } else { // If a default CTRID specified, convert it to index CvtCtrIdToPrfItmIndex(pPrfObj->DefCounter, (int*) &pm.pPOT->DefaultCounter); } pm.pPOT->NumInstances = (int) pPrfObj->MaxInstances; pm.pPOT->CodePage = NULL; pm.pPOT->PerfTime.QuadPart = 0; pm.pPOT->PerfFreq.QuadPart = 0; dwCounter += 2; dwHelp += 2; // Set the PERF_COUNTER_DEFINITIONs for each counter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -