home *** CD-ROM | disk | FTP | other *** search
- /*
- Automatic Performance Counter Documentation. By Dimitris Staikos.
-
- Please read the README.TXT file for a short description, copyright notice and
- usage instructions.
- */
-
- #define STRICT
- #define UNICODE
- #include <stdio.h>
- #include <stdlib.h>
-
- // Don't include the world ...
- #define NOGDI
- #define NOSOUND
- #define NOCOMM
- #define NODRIVERS
- #define OEMRESOURCE
- #define NONLS
- #define NOSERVICE
- #define NOKANJI
- #define NOMINMAX
- #define NOLOGERROR
- #define NOPROFILER
- #define NOMEMMGR
- #define NOOPENFILE
- #define NORESOURCE
- #define NOATOM
- #define NOLANGUAGE
- #define NOLSTRING
- #define NODBCS
- #define NOKEYBOARDINFO
- #define NOGDICAPMASKS
- #define NOCOLOR
- #define NOGDIOBJ
- #define NODRAWTEXT
- #define NOTEXTMETRIC
- #define NOSCALABLEFONT
- #define NOBITMAP
- #define NORASTEROPS
- #define NOMETAFILE
- #define NOSYSMETRICS
- #define NOSYSTEMPARAMSINFO
- #define NOMSG
- #define NOWINSTYLES
- #define NOWINOFFSETS
- #define NOSHOWWINDOW
- #define NODEFERWINDOWPOS
- #define NOVIRTUALKEYCODES
- #define NOKEYSTATES
- #define NOWH
- #define NOMENUS
- #define NOSCROLL
- #define NOCLIPBOARD
- #define NOICONS
- #define NOMB
- #define NOSYSCOMMANDS
- #define NOMDI
- #define NOCTLMGR
- #define NOWINMESSAGES
- #define NOHELP
-
- #include <windows.h>
- #include <winperf.h>
-
- #define MEM_STEP 8000
-
- #define NUM_FLAGS 28
-
- DWORD FlagTable[] = { PERF_COUNTER_COUNTER, PERF_COUNTER_TIMER, PERF_COUNTER_QUEUELEN_TYPE,
- PERF_COUNTER_BULK_COUNT, PERF_COUNTER_TEXT, PERF_COUNTER_RAWCOUNT,
- PERF_COUNTER_LARGE_RAWCOUNT, PERF_COUNTER_RAWCOUNT_HEX, PERF_COUNTER_LARGE_RAWCOUNT_HEX,
- PERF_SAMPLE_FRACTION, PERF_SAMPLE_COUNTER, PERF_COUNTER_NODATA, PERF_COUNTER_TIMER_INV,
- PERF_SAMPLE_BASE, PERF_AVERAGE_TIMER, PERF_AVERAGE_BASE, PERF_AVERAGE_BULK,
- PERF_100NSEC_TIMER, PERF_100NSEC_TIMER_INV, PERF_COUNTER_MULTI_TIMER, PERF_COUNTER_MULTI_TIMER_INV,
- PERF_COUNTER_MULTI_BASE, PERF_100NSEC_MULTI_TIMER, PERF_100NSEC_MULTI_TIMER_INV,
- PERF_RAW_FRACTION, PERF_RAW_BASE, PERF_ELAPSED_TIME, PERF_COUNTER_HISTOGRAM_TYPE };
-
- TCHAR FlagDescr[][40] = { TEXT("PERF_COUNTER_COUNTER"), TEXT("PERF_COUNTER_TIMER"), TEXT("PERF_COUNTER_QUEUELEN_TYPE"),
- TEXT("PERF_COUNTER_BULK_COUNT"), TEXT("PERF_COUNTER_TEXT"), TEXT("PERF_COUNTER_RAWCOUNT"),
- TEXT("PERF_COUNTER_LARGE_RAWCOUNT"), TEXT("PERF_COUNTER_RAWCOUNT_HEX"), TEXT("PERF_COUNTER_LARGE_RAWCOUNT_HEX"),
- TEXT("PERF_SAMPLE_FRACTION"), TEXT("PERF_SAMPLE_COUNTER"), TEXT("PERF_COUNTER_NODATA"), TEXT("PERF_COUNTER_TIMER_INV"),
- TEXT("PERF_SAMPLE_BASE"), TEXT("PERF_AVERAGE_TIMER"), TEXT("PERF_AVERAGE_BASE"), TEXT("PERF_AVERAGE_BULK"),
- TEXT("PERF_100NSEC_TIMER"), TEXT("PERF_100NSEC_TIMER_INV"), TEXT("PERF_COUNTER_MULTI_TIMER"),
- TEXT("PERF_COUNTER_MULTI_TIMER_INV"),
- TEXT("PERF_COUNTER_MULTI_BASE"), TEXT("PERF_100NSEC_MULTI_TIMER"), TEXT("PERF_100NSEC_MULTI_TIMER_INV"),
- TEXT("PERF_RAW_FRACTION"), TEXT("PERF_RAW_BASE"), TEXT("PERF_ELAPSED_TIME"), TEXT("PERF_COUNTER_HISTOGRAM_TYPE") };
-
- //******************************************************************************************
- // Helper Functions to walk the performance data structures
- //******************************************************************************************
- PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK pPerfData)
- {
- return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength)) ;
- }
- //******************************************************************************************
- PPERF_OBJECT_TYPE NextObject (PPERF_OBJECT_TYPE pObject)
- {
- return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + pObject->TotalByteLength)) ;
- }
- //******************************************************************************************
- PPERF_COUNTER_DEFINITION FirstCounter(PPERF_OBJECT_TYPE pObjectDef)
- {
- return (PPERF_COUNTER_DEFINITION)((PCHAR) pObjectDef + pObjectDef->HeaderLength);
- }
- //******************************************************************************************
- PPERF_COUNTER_DEFINITION NextCounter(PPERF_COUNTER_DEFINITION pCounterDef)
- {
- return (PPERF_COUNTER_DEFINITION)((PCHAR) pCounterDef + pCounterDef->ByteLength);
- }
- //******************************************************************************************
- PPERF_INSTANCE_DEFINITION FirstInstance (PPERF_OBJECT_TYPE pObject)
- {
- return (PPERF_INSTANCE_DEFINITION)((PBYTE) pObject + pObject->DefinitionLength);
- }
- //******************************************************************************************
- PPERF_INSTANCE_DEFINITION NextInstance (PPERF_INSTANCE_DEFINITION pInstance)
- {
- // next instance is after this instance + this instance's counter data
- PPERF_COUNTER_BLOCK pCtrBlk;
-
- pCtrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)pInstance + pInstance->ByteLength);
-
- return (PPERF_INSTANCE_DEFINITION)((PBYTE)pInstance + pInstance->ByteLength + pCtrBlk->ByteLength);
- }
- //******************************************************************************************
- // Obvious ...
- //******************************************************************************************
- TCHAR *DetailLevelAsString(DWORD DetailLevel)
- {
- switch (DetailLevel)
- {
- case PERF_DETAIL_NOVICE : return TEXT("NOVICE");
- case PERF_DETAIL_ADVANCED : return TEXT("ADVANCED");
- case PERF_DETAIL_EXPERT : return TEXT("EXPERT");
- case PERF_DETAIL_WIZARD : return TEXT("WIZARD");
- default : return TEXT("Unexpected !!!");
- }
- }
- //******************************************************************************************
- // Searches through the counter types table to find the description for this counter type
- //******************************************************************************************
- void PrintCounterFlags(DWORD dwFlags)
- {
- int i;
-
- for (i=0; i<NUM_FLAGS; i++)
- if (dwFlags == FlagTable[i])
- {
- wprintf(TEXT("%s (%u)\n\n"), FlagDescr[i], dwFlags);
- break;
- }
-
- if (NUM_FLAGS==i)
- wprintf(TEXT("Unexpected Flags Combination (%u)\n\n"), dwFlags);
- }
- /*******************************************************************************************
- Searches the multi string pointed to by lptstr for the index 'dwIndex', and then prints
- the associated string. This is used to print a counter title or a counter explanation
- from their indices.
- Comment : This code is not the most effective way to do the search, but I found it almost
- ready, and it works, so ...
- ********************************************************************************************/
- void PrintStringByIndex(DWORD dwIndex, LPTSTR lptstr)
- {
- DWORD dwHelpIndex;
-
- __try
- {
- while (*lptstr)
- {
- // get the counter index
- swscanf (lptstr, TEXT(" %d"), &dwHelpIndex);
- if (dwHelpIndex == dwIndex)
- {
- // get the counter name
- lptstr += lstrlen(lptstr) + 1;
- wprintf(TEXT("(%u) %s\n"), dwIndex, lptstr);
- return;
- }
-
- lptstr += lstrlen(lptstr) + 1;
- }
-
- if (!*lptstr)
- _putws(TEXT("ERROR : Index Not Found !!!"));
- }
- __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- _putws(TEXT("ERROR : An Access Violation Occured while searching for the index"));
- }
- }
-
- /******************************************************************************************
- Retrieves from HKEY_PERFORMANCE_DATA the value of the string passed as parameter
- and returning the memory in pMem.
- Returns TRUE if it succeeds, FALSE upon failure. pMem is changed only when TRUE is about
- to be returned.
- When performance data is retrieved, the dwNeeded parameter in the call to RegQueryValueEx
- is NOT changed to reflect the needed size, CONTRARY to what the documentation states.
- The code checks for this condition, and if it is detected the dwNeeded parameter is
- increased by MEM_STEP. When requesting "Counter 009" or "Help 009" the dwNeeded parameter
- is changed by the system, so the manual adjustment is avoided.
- *******************************************************************************************/
- BOOL PerformanceKeyRetrieve(LPTSTR szName, LPVOID *pMemory)
- {
- LPVOID pMem;
- DWORD dwNeeded, dwType, dwHelp;
- LONG lError;
- BOOL bRetVal;
-
- __try
- {
- dwNeeded = MEM_STEP;
- pMem = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, dwNeeded);
-
- do
- {
- dwHelp = dwNeeded;
- lError = RegQueryValueEx(HKEY_PERFORMANCE_DATA, szName, NULL, &dwType, pMem, &dwNeeded);
- if (lError == ERROR_MORE_DATA)
- {
- if (dwHelp == dwNeeded) // Check if manual adjustment is neccessary
- dwNeeded += MEM_STEP;
-
- pMem = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, pMem, dwNeeded);
- wprintf(TEXT("Buffer not big enough. Trying with buffer size %d bytes\n"), dwNeeded);
- }
- else if (lError == ERROR_SUCCESS)
- {
- bRetVal = TRUE;
- _putws(TEXT("Succesful Retrieval !!!\n"));
- }
- else
- {
- wprintf(TEXT("Unexpected Error : Failed to open subkey 009 of Perflib - Error Code %d\n%s"), lError,
- TEXT("If your lang key is not 009 please change the source code to the correct value\n"));
-
- HeapFree(GetProcessHeap(), 0, pMem);
- bRetVal = FALSE;
- }
- } while (lError == ERROR_MORE_DATA);
-
- }
- __except ((GetExceptionCode()==STATUS_NO_MEMORY || GetExceptionCode()==STATUS_ACCESS_VIOLATION) ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- wprintf(TEXT("PerformanceKeyRetrieve()\nFailed to allocate memory for request \"%s\". Error Code = %d\n"),
- szName, GetLastError());
-
- bRetVal = FALSE;
- }
-
- if (bRetVal)
- *pMemory = pMem;
-
- return bRetVal;
- }
- //******************************************************************************************
- main(void)
- {
- DWORD j, k;
- LPVOID pMem, pMem2, pMem3;
- LONG lj; // lj used for instances loop. NumInstances is LONG
- // and not DWORD as stated in the documentation.
-
- PPERF_DATA_BLOCK pPDB;
- PPERF_OBJECT_TYPE pPOT;
- PPERF_COUNTER_DEFINITION pPCD;
- PPERF_INSTANCE_DEFINITION pPID;
-
- _putws(TEXT("Performance Object Types Automatic Documentation"));
- _putws(TEXT("Written By D.Staikos (dstaikos@theseas.ntua.gr)\n\n"));
-
- // Retrieval of Title Descriptions from registry
- _putws(TEXT("Counter Titles Retrieval\n"));
- if (!PerformanceKeyRetrieve(TEXT("Counter 009"), &pMem2))
- {
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- return -1;
- }
-
- // Retrieval of Counter Explanations from registry
- _putws(TEXT("Counter Explanations Retrieval\n"));
- if (!PerformanceKeyRetrieve(TEXT("Help 009"), &pMem3))
- {
- HeapFree(GetProcessHeap(), 0, pMem2);
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- return -1;
- }
-
- // Retrieve All performance data. A call for performance data will NOT set the
- // dwNeeded variable when ERROR_MORE_DATA is returned, so I have to do a retry loop
- // increasing the step by MEM_STEP.
- // An indication for the process of the retries is displayed.
- _putws(TEXT("Moving on to Global Data Retrieval\n"));
- if (!PerformanceKeyRetrieve(TEXT("Global"), &pMem))
- {
- HeapFree(GetProcessHeap(), 0, pMem2);
- HeapFree(GetProcessHeap(), 0, pMem3);
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- return -1;
- }
-
- // Type the data on the screen ...
- pPDB = (PPERF_DATA_BLOCK)pMem;
- _putws(TEXT("OBJECT TYPE DEFINITIONS"));
- wprintf(TEXT("Number of Object Types in Output : %u\n\n"), pPDB->NumObjectTypes);
-
- pPOT = FirstObject(pPDB);
-
- for (k=0; k<pPDB->NumObjectTypes; k++)
- {
- _putws(TEXT("---------------------------------------------------------------------------------------"));
- _putws(TEXT("---------------------------------------------------------------------------------------\n"));
-
- wprintf(TEXT("OBJECT TYPE #%u OF %u\n\nOBJECT TYPE TITLE INDEX : "), k+1, pPDB->NumObjectTypes);
- PrintStringByIndex(pPOT->ObjectNameTitleIndex, (LPTSTR)pMem2);
-
- wprintf(TEXT("OBJECT TYPE HELP : "));
- PrintStringByIndex(pPOT->ObjectHelpTitleIndex, (LPTSTR)pMem3);
-
- wprintf(TEXT("DETAIL LEVEL : %s\n"), DetailLevelAsString(pPOT->DetailLevel));
- wprintf(TEXT("NUMBER OF COUNTERS : %u\n"), pPOT->NumCounters);
- if (pPOT->NumInstances == PERF_NO_INSTANCES)
- _putws(TEXT("NUMBER OF INSTANCES : NO INSTANCES\n"));
- else
- wprintf(TEXT("NUMBER OF INSTANCES : %d\n\n"), pPOT->NumInstances);
-
- // Display the counter definitions ...
- _putws(TEXT("COUNTER DEFINITIONS\n"));
- pPCD = FirstCounter(pPOT);
-
- __try
- {
- for (j=0; j<pPOT->NumCounters; j++)
- {
- wprintf(TEXT("COUNTER #%u OF %u\nCOUNTER NAME INDEX : "), j+1, pPOT->NumCounters);
- PrintStringByIndex(pPCD->CounterNameTitleIndex, (LPTSTR)pMem2);
-
- wprintf(TEXT("COUNTER HELP INDEX : "));
- PrintStringByIndex(pPCD->CounterHelpTitleIndex, (LPTSTR)pMem3);
-
- wprintf(TEXT("DEFAULT SCALE : 10^(%d)\n"), pPCD->DefaultScale);
- wprintf(TEXT("DETAIL LEVEL : %s\n"), DetailLevelAsString(pPCD->DetailLevel));
- wprintf(TEXT("COUNTER SIZE : %u bytes\n"), pPCD->CounterSize);
- wprintf(TEXT("COUNTER TYPE : "));
- PrintCounterFlags(pPCD->CounterType);
-
- pPCD = NextCounter(pPCD);
- }
-
- // It once occured that zero was reported ...
- if ((pPOT->NumInstances != PERF_NO_INSTANCES) && pPOT->NumInstances)
- {
- _putws(TEXT("INSTANCES\n"));
- pPID = FirstInstance(pPOT);
- for (lj=0; lj<pPOT->NumInstances; lj++)
- {
- wprintf(TEXT("\tINSTANCE #%d OF %d\n"), lj+1, pPOT->NumInstances);
- wprintf(TEXT("\tParent Object Title Index : %u\n"), pPID->ParentObjectTitleIndex);
- wprintf(TEXT("\tParent Object Instance : %u\n"), pPID->ParentObjectInstance);
- wprintf(TEXT("\tUnique ID : "));
- if (pPID->UniqueID == PERF_NO_UNIQUE_ID)
- _putws(TEXT("PERF_NO_UNIQUE_ID"));
- else
- wprintf(TEXT("%u\n"), pPID->UniqueID);
-
- if (pPID->NameLength)
- wprintf(TEXT("\tInstance Name : %s\n\n"), (LPCTSTR)((LPBYTE)pPID + pPID->NameOffset));
- else
- wprintf(TEXT("\tInstance Name : UNNAMED(%d)\n\n"), lj);
-
- pPID = NextInstance(pPID);
- }
- }
- }
- __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Do nothing. Just try to continue to the next group ...
- _putws(TEXT("\n\nACCESS VIOLATION\n\n"));
- }
-
- pPOT = NextObject(pPOT);
- }
-
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- HeapFree(GetProcessHeap(), 0, pMem);
- HeapFree(GetProcessHeap(), 0, pMem2);
- HeapFree(GetProcessHeap(), 0, pMem3);
- _putws(TEXT("Program Completed Succesfully"));
-
- return 0;
- }
-