📄 prfdata.cpp
字号:
// The following functions are only necessary in the collection DLL// They are not needed by an app that simply updates the counters#ifdef PRFDATA_COLLECT_SUPPORTEDextern "C" {DWORD __declspec(dllexport) WINAPI PrfData_Open(LPWSTR lpDevNames) { // Create/open the shared memory containing the performance info CPrfData::Activate(); return(ERROR_SUCCESS);}DWORD __declspec(dllexport) WINAPI PrfData_Close(void) { // Nothing to do here return(ERROR_SUCCESS);}DWORD __declspec(dllexport) WINAPI PrfData_Collect(LPWSTR lpValueName, LPVOID* lppData, LPDWORD lpcbTotalBytes, LPDWORD lpNumObjectTypes) { // Call the class's static Collect function to populate the passed // memory block with our performance info return(CPrfData::Collect(lpValueName, (PBYTE*) lppData, lpcbTotalBytes, lpNumObjectTypes));}} // extern "C"// Export these 3 functions as the interface to our Performance Data#pragma comment(linker, "/export:PrfData_Open=_PrfData_Open@4")#pragma comment(linker, "/export:PrfData_Close=_PrfData_Close@0")#pragma comment(linker, "/export:PrfData_Collect=_PrfData_Collect@16")#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTED// This is a help class used to return only the requested objectsclass CWhichCtrs {public: CWhichCtrs(LPCWSTR pszObjNums = NULL); ~CWhichCtrs(); BOOL IsNumInList(int nNum);private: LPWSTR m_pszObjNums;};CWhichCtrs::CWhichCtrs(LPCWSTR pszObjNums) { // Save the list of requested object numbers if ((lstrcmpiW(L"Global", pszObjNums) == 0)) { m_pszObjNums = NULL; } else { m_pszObjNums = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pszObjNums) + 3) * sizeof(WCHAR)); // Put spaces around all the numbers wsprintfW(m_pszObjNums, L" %s ", pszObjNums); }}CWhichCtrs::~CWhichCtrs() { if (m_pszObjNums != NULL) HeapFree(GetProcessHeap(), 0, m_pszObjNums);}BOOL CWhichCtrs::IsNumInList(int nNum) { BOOL fIsNumInList = TRUE; if (m_pszObjNums != NULL) { // Put spaces around this number and see if it's in the list WCHAR szNum[10]; wsprintfW(szNum, L" %d ", nNum); fIsNumInList = (wcsstr(m_pszObjNums, szNum) != NULL); } return(fIsNumInList);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTED// Determine which parent objects need to be collectedvoid CPrfData::DetermineObjsToCollect(OBJORD ObjOrd) const { PPRFITM pPrfItm = CvtObjOrdToPrfItm(ObjOrd); // Assume this object is being collected chASSERT(pPrfItm->fCollectThisObj); if (pPrfItm->MaxInstances != (INSTID) PERF_NO_INSTANCES) { // If this counter supports instances, collect the // counters that any instances refer to (recursively). INSTID InstId = 0; for (; InstId < (INSTID) pPrfItm->MaxInstances; InstId++) { PRFMETRICS pm; CalcPrfMetrics(ObjOrd, InstId, &pm); if ((pm.pPIN[0] != 0) && (pm.pPID->ParentObjectTitleIndex != 0)) { // Instance is in use and refers to a parent object // Collect the parent object PPRFITM pPrfItmParent = CvtObjIdToPrfItm((OBJID) pm.pPID->ParentObjectTitleIndex); if (pPrfItmParent->fCollectThisObj == FALSE) { pPrfItmParent->fCollectThisObj = TRUE; DetermineObjsToCollect(CvtObjIdToObjOrd( (OBJID) pm.pPID->ParentObjectTitleIndex)); } } } }}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTEDDWORD CPrfData::Collect(LPWSTR lpValueName, PBYTE* ppbData, LPDWORD lpcbTotalBytes, LPDWORD lpNumObjectTypes) { DWORD dwErr = ERROR_SUCCESS; // Assume success PBYTE ppbOriginalStartOfBuffer = *ppbData; // Wrap everything inside an SEH frame so that we NEVER bring // down an app that is trying to collect our performance info __try { // While we do all this work, lock out other threads so that // our data structures do not become corrupted. sm_pPrfData->LockCtrs(); dwErr = sm_pPrfData->CollectAllObjs(lpValueName, ppbData, lpcbTotalBytes, lpNumObjectTypes); } __except (EXCEPTION_EXECUTE_HANDLER) { *ppbData = ppbOriginalStartOfBuffer; *lpcbTotalBytes = 0; *lpNumObjectTypes = 0; } sm_pPrfData->UnlockCtrs(); return(dwErr);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTED// Collects all of the requested objectsDWORD CPrfData::CollectAllObjs(LPWSTR lpValueName, PBYTE *ppbData, LPDWORD lpcbTotalBytes, LPDWORD lpNumObjectTypes) const { // lpValueName: [in] Set of object numbers requested // lppData: [in] Buffer where object info goes // [out] Address after our data // lpcbTotalBytes: [in] Size of buffer // [out] Bytes we put in buffer // lpNumObjectTypes: [in] Ignore // [out] Number of objects we put in the buffer // Return Value: ERROR_MORE_DATA or ERROR_SUCCESS DWORD dwErr = ERROR_SUCCESS; PBYTE pbWhereOurDataGoes = *ppbData; CWhichCtrs CtrList(lpValueName); *lpNumObjectTypes = 0; // Default to collecting none of our objects for (OBJORD ObjOrd = 0; ObjOrd < m_nNumObjects; ObjOrd++) { CvtObjOrdToPrfItm(ObjOrd)->fCollectThisObj = FALSE; } // Collect only the objects explicitly specified // and any instances' parent objects for (ObjOrd = 0; ObjOrd < m_nNumObjects; ObjOrd++) { // Should this object's counters be returned? if (CtrList.IsNumInList( CvtObjOrdToPrfItmIndex(ObjOrd) * 2 + m_dwFirstCounter)) { CvtObjOrdToPrfItm(ObjOrd)->fCollectThisObj = TRUE; DetermineObjsToCollect(ObjOrd); } } // Calculcate the bytes required for the desired objects DWORD cbBytesForAllObjs = 0; for (ObjOrd = 0; ObjOrd < m_nNumObjects; ObjOrd++) { if (CvtObjOrdToPrfItm(ObjOrd)->fCollectThisObj) cbBytesForAllObjs += CalcBytesForPrfObj(ObjOrd); } if (*lpcbTotalBytes < cbBytesForAllObjs) { // If buffer too small for desired objects, return failure *lpcbTotalBytes = 0; dwErr = ERROR_MORE_DATA; } else { // Buffer is big enough, append objects' data to buffer *lpcbTotalBytes = 0; for (ObjOrd = 0; ObjOrd < m_nNumObjects; ObjOrd++) { if (CvtObjOrdToPrfItm(ObjOrd)->fCollectThisObj) { CollectAnObj(ObjOrd, ppbData); *lpcbTotalBytes += CalcBytesForPrfObj(ObjOrd); (*lpNumObjectTypes)++; } } } return(dwErr);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTEDDWORD CPrfData::CollectAnObj(OBJORD ObjOrd, PBYTE *ppbData) const { chASSERT(IsValidObjOrd(ObjOrd)); PRFMETRICS pm; CalcPrfMetrics(ObjOrd, 0, &pm); // Append PERF_OBJECT_TYPE CopyMemory(*ppbData, pm.pPOT, pm.cbPOT); PPERF_OBJECT_TYPE pPOT = (PPERF_OBJECT_TYPE) *ppbData; pPOT->TotalByteLength = CalcBytesForPrfObj(ObjOrd); pPOT->NumInstances = (pm.MaxInstances == PERF_NO_INSTANCES) ? PERF_NO_INSTANCES : HowManyInstancesInUse(ObjOrd); *ppbData += pm.cbPOT; // Append array of PERF_COUNTER_DEFINITIONs CopyMemory(*ppbData, pm.pPCD, pm.cbPCD); *ppbData += pm.cbPCD; if (!pm.fSupportsInstances) { // Append 1 PERF_COUNTER_BLOCK CopyMemory(*ppbData, pm.pPCB, pm.cbPCB); *ppbData += pm.cbPCB; } else { // Append PERF_INSTANCE_DEFINITION/PERF_COUNTER_BLOCKs INSTID InstId = 0; for (; InstId < (INSTID) pm.MaxInstances; InstId++) { CalcPrfMetrics(ObjOrd, InstId, &pm); if (pm.pPIN[0] != 0) { // This instance is in use // Append PERF_INSTANCE_DEFINITIONs CopyMemory(*ppbData, pm.pPID, pm.cbPID); PPERF_INSTANCE_DEFINITION pPID = (PPERF_INSTANCE_DEFINITION) *ppbData; *ppbData += pm.cbPID; pPID->ByteLength = sizeof(PERF_INSTANCE_DEFINITION); // The ParentObjectTitleIndex contains the parent // object's ID. If this is not 0 (an invalid object ID), // convert the ID to the Performance Object number if (pPID->ParentObjectTitleIndex != 0) { PIINDEX pii = CvtObjIdToPrfItmIndex( (OBJID) pm.pPID->ParentObjectTitleIndex); pPID->ParentObjectTitleIndex = m_dwFirstCounter + 2 * pii; // Convert Instance ID to In-Use Instance number. pPID->ParentObjectInstance = CvtInstIdToInUseInstId(CvtObjIdToObjOrd( (OBJID) pm.pPID->ParentObjectTitleIndex), (INSTID) pm.pPID->ParentObjectInstance); } // Append instance name after PERF_INSTANCE_DEFINITION if (pPID->UniqueID == PERF_NO_UNIQUE_ID) { DWORD cchName = lstrlenW(pm.pPIN) + 1; DWORD cbName = cchName * sizeof(WCHAR); CopyMemory(*ppbData, pm.pPIN, cbName); // If an odd number of characters, add 2 bytes so // that next structure starts on 32-bit boundary if ((cchName & 1) == 1) cbName += 2; *ppbData += cbName; pPID->ByteLength += cbName; } // Append PERF_COUNTER_BLOCK to the buffer CopyMemory(*ppbData, pm.pPCB, pm.cbPCB); *ppbData += pm.cbPCB; } } } return(ERROR_SUCCESS);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTEDDWORD CPrfData::CalcBytesForPrfObj(OBJORD ObjOrd) const { chASSERT(IsValidObjOrd(ObjOrd)); PRFMETRICS pm; CalcPrfMetrics(ObjOrd, 0, &pm); DWORD cbBytesNeeded = pm.cbPOT + pm.cbPCD; if (!pm.fSupportsInstances) { cbBytesNeeded += pm.cbPCB; } else { cbBytesNeeded += (pm.cbPID + pm.cbPCB) * HowManyInstancesInUse(ObjOrd); INSTID InstId = 0; for (; InstId < (INSTID) pm.MaxInstances; InstId++) { CalcPrfMetrics(ObjOrd, InstId, &pm); if (pm.pPIN[0] != 0) { DWORD cch = lstrlenW(pm.pPIN) + 1; // For 0 character if ((cch & 1) == 1) cch++; // If an odd number of characters, add 2 bytes so // that next structure starts on 32-bit boundary cbBytesNeeded += sizeof(WCHAR) * cch; } } } return(cbBytesNeeded);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTEDint CPrfData::HowManyInstancesInUse(OBJORD ObjOrd) const { chASSERT(IsValidObjOrd(ObjOrd)); PRFMETRICS pm; CalcPrfMetrics(ObjOrd, 0, &pm); chASSERT(pm.fSupportsInstances); int nNumInstancesInUse = 0; INSTID InstId = 0; for (; InstId < (INSTID) pm.MaxInstances; InstId++) { if (pm.pPIN[0] != 0) nNumInstancesInUse++; pm.pPIN += pm.cbPIN / sizeof(pm.pPIN[0]); } return(nNumInstancesInUse);}#endif/////////////////////////////////////////////////////////////////////#ifdef PRFDATA_COLLECT_SUPPORTEDint CPrfData::CvtInstIdToInUseInstId( OBJORD ObjOrd, INSTID InstId) const { chASSERT(IsValidInstId(ObjOrd, InstId)); int nIndexInstInUse = 0; for (; InstId > 0; InstId--) { PRFMETRICS pm; CalcPrfMetrics(ObjOrd, InstId, &pm); if (pm.pPIN[0] != 0) nIndexInstInUse++; } return(nIndexInstInUse);}#endif//////////////////////////// End Of File ////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -