home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / dos_win / winsnmp / mib / OBJVIEW.ZIP / OBJVIEW.C next >
Encoding:
C/C++ Source or Header  |  1995-01-30  |  14.8 KB  |  395 lines

  1. /*
  2.   Automatic Performance Counter Documentation. By Dimitris Staikos.
  3.   
  4.   Please read the README.TXT file for a short description, copyright notice and
  5.   usage instructions.
  6. */
  7.  
  8. #define STRICT
  9. #define UNICODE
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12.  
  13. // Don't include the world ...
  14. #define NOGDI             
  15. #define NOSOUND           
  16. #define NOCOMM            
  17. #define NODRIVERS         
  18. #define OEMRESOURCE       
  19. #define NONLS             
  20. #define NOSERVICE         
  21. #define NOKANJI           
  22. #define NOMINMAX          
  23. #define NOLOGERROR        
  24. #define NOPROFILER        
  25. #define NOMEMMGR          
  26. #define NOOPENFILE        
  27. #define NORESOURCE        
  28. #define NOATOM            
  29. #define NOLANGUAGE        
  30. #define NOLSTRING         
  31. #define NODBCS            
  32. #define NOKEYBOARDINFO    
  33. #define NOGDICAPMASKS     
  34. #define NOCOLOR           
  35. #define NOGDIOBJ          
  36. #define NODRAWTEXT        
  37. #define NOTEXTMETRIC      
  38. #define NOSCALABLEFONT    
  39. #define NOBITMAP          
  40. #define NORASTEROPS       
  41. #define NOMETAFILE        
  42. #define NOSYSMETRICS      
  43. #define NOSYSTEMPARAMSINFO
  44. #define NOMSG             
  45. #define NOWINSTYLES       
  46. #define NOWINOFFSETS      
  47. #define NOSHOWWINDOW      
  48. #define NODEFERWINDOWPOS  
  49. #define NOVIRTUALKEYCODES 
  50. #define NOKEYSTATES       
  51. #define NOWH              
  52. #define NOMENUS           
  53. #define NOSCROLL          
  54. #define NOCLIPBOARD       
  55. #define NOICONS           
  56. #define NOMB              
  57. #define NOSYSCOMMANDS     
  58. #define NOMDI             
  59. #define NOCTLMGR          
  60. #define NOWINMESSAGES     
  61. #define NOHELP            
  62.  
  63. #include <windows.h>
  64. #include <winperf.h>
  65.  
  66. #define MEM_STEP 8000
  67.  
  68. #define NUM_FLAGS 28
  69.  
  70. DWORD FlagTable[] = {    PERF_COUNTER_COUNTER, PERF_COUNTER_TIMER, PERF_COUNTER_QUEUELEN_TYPE,
  71.                         PERF_COUNTER_BULK_COUNT, PERF_COUNTER_TEXT, PERF_COUNTER_RAWCOUNT,
  72.                         PERF_COUNTER_LARGE_RAWCOUNT, PERF_COUNTER_RAWCOUNT_HEX, PERF_COUNTER_LARGE_RAWCOUNT_HEX,
  73.                         PERF_SAMPLE_FRACTION, PERF_SAMPLE_COUNTER, PERF_COUNTER_NODATA, PERF_COUNTER_TIMER_INV,
  74.                         PERF_SAMPLE_BASE, PERF_AVERAGE_TIMER, PERF_AVERAGE_BASE, PERF_AVERAGE_BULK,
  75.                         PERF_100NSEC_TIMER, PERF_100NSEC_TIMER_INV, PERF_COUNTER_MULTI_TIMER, PERF_COUNTER_MULTI_TIMER_INV,
  76.                         PERF_COUNTER_MULTI_BASE, PERF_100NSEC_MULTI_TIMER, PERF_100NSEC_MULTI_TIMER_INV,
  77.                         PERF_RAW_FRACTION, PERF_RAW_BASE, PERF_ELAPSED_TIME, PERF_COUNTER_HISTOGRAM_TYPE };
  78.  
  79. TCHAR FlagDescr[][40] = {   TEXT("PERF_COUNTER_COUNTER"), TEXT("PERF_COUNTER_TIMER"), TEXT("PERF_COUNTER_QUEUELEN_TYPE"),
  80.                             TEXT("PERF_COUNTER_BULK_COUNT"), TEXT("PERF_COUNTER_TEXT"), TEXT("PERF_COUNTER_RAWCOUNT"),
  81.                             TEXT("PERF_COUNTER_LARGE_RAWCOUNT"), TEXT("PERF_COUNTER_RAWCOUNT_HEX"), TEXT("PERF_COUNTER_LARGE_RAWCOUNT_HEX"),
  82.                             TEXT("PERF_SAMPLE_FRACTION"), TEXT("PERF_SAMPLE_COUNTER"), TEXT("PERF_COUNTER_NODATA"), TEXT("PERF_COUNTER_TIMER_INV"),
  83.                             TEXT("PERF_SAMPLE_BASE"), TEXT("PERF_AVERAGE_TIMER"), TEXT("PERF_AVERAGE_BASE"), TEXT("PERF_AVERAGE_BULK"),
  84.                             TEXT("PERF_100NSEC_TIMER"), TEXT("PERF_100NSEC_TIMER_INV"), TEXT("PERF_COUNTER_MULTI_TIMER"),
  85.                             TEXT("PERF_COUNTER_MULTI_TIMER_INV"),
  86.                             TEXT("PERF_COUNTER_MULTI_BASE"), TEXT("PERF_100NSEC_MULTI_TIMER"), TEXT("PERF_100NSEC_MULTI_TIMER_INV"),
  87.                             TEXT("PERF_RAW_FRACTION"), TEXT("PERF_RAW_BASE"), TEXT("PERF_ELAPSED_TIME"), TEXT("PERF_COUNTER_HISTOGRAM_TYPE") };
  88.  
  89. //******************************************************************************************
  90. // Helper Functions to walk the performance data structures
  91. //******************************************************************************************
  92. PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK pPerfData)
  93. {
  94.     return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength)) ;
  95. }
  96. //******************************************************************************************
  97. PPERF_OBJECT_TYPE NextObject (PPERF_OBJECT_TYPE pObject)
  98. {
  99.     return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + pObject->TotalByteLength)) ;
  100. }
  101. //******************************************************************************************
  102. PPERF_COUNTER_DEFINITION FirstCounter(PPERF_OBJECT_TYPE pObjectDef)
  103. {
  104.     return (PPERF_COUNTER_DEFINITION)((PCHAR) pObjectDef + pObjectDef->HeaderLength);
  105. }
  106. //******************************************************************************************
  107. PPERF_COUNTER_DEFINITION NextCounter(PPERF_COUNTER_DEFINITION pCounterDef)
  108. {
  109.     return (PPERF_COUNTER_DEFINITION)((PCHAR) pCounterDef + pCounterDef->ByteLength);
  110. }
  111. //******************************************************************************************
  112. PPERF_INSTANCE_DEFINITION FirstInstance (PPERF_OBJECT_TYPE pObject)
  113. {
  114.     return (PPERF_INSTANCE_DEFINITION)((PBYTE) pObject + pObject->DefinitionLength);
  115. }
  116. //******************************************************************************************
  117. PPERF_INSTANCE_DEFINITION NextInstance (PPERF_INSTANCE_DEFINITION pInstance)
  118. {
  119.     // next instance is after this instance + this instance's counter data
  120.     PPERF_COUNTER_BLOCK  pCtrBlk;
  121.  
  122.     pCtrBlk = (PPERF_COUNTER_BLOCK)((PBYTE)pInstance + pInstance->ByteLength);
  123.  
  124.     return (PPERF_INSTANCE_DEFINITION)((PBYTE)pInstance + pInstance->ByteLength + pCtrBlk->ByteLength);
  125. }
  126. //******************************************************************************************
  127. // Obvious ...
  128. //******************************************************************************************
  129. TCHAR *DetailLevelAsString(DWORD DetailLevel)
  130. {
  131.     switch (DetailLevel)
  132.     {
  133.         case PERF_DETAIL_NOVICE     :    return TEXT("NOVICE");
  134.         case PERF_DETAIL_ADVANCED     :    return TEXT("ADVANCED");
  135.         case PERF_DETAIL_EXPERT     :    return TEXT("EXPERT");
  136.         case PERF_DETAIL_WIZARD     :    return TEXT("WIZARD");
  137.         default                           :   return TEXT("Unexpected !!!");
  138.     }
  139. }
  140. //******************************************************************************************
  141. // Searches through the counter types table to find the description for this counter type
  142. //******************************************************************************************
  143. void PrintCounterFlags(DWORD dwFlags)
  144. {
  145.     int i;
  146.  
  147.     for (i=0; i<NUM_FLAGS; i++)
  148.       if (dwFlags == FlagTable[i])
  149.       {
  150.         wprintf(TEXT("%s (%u)\n\n"), FlagDescr[i], dwFlags);
  151.         break;
  152.       }
  153.  
  154.     if (NUM_FLAGS==i)
  155.       wprintf(TEXT("Unexpected Flags Combination (%u)\n\n"), dwFlags);
  156. }
  157. /*******************************************************************************************
  158.  Searches the multi string pointed to by lptstr for the index 'dwIndex', and then prints
  159.  the associated string. This is used to print a counter title or a counter explanation
  160.  from their indices.
  161.  Comment : This code is not the most effective way to do the search, but I found it almost
  162.             ready, and it works, so ...
  163. ********************************************************************************************/
  164. void PrintStringByIndex(DWORD dwIndex, LPTSTR lptstr)
  165. {
  166.     DWORD dwHelpIndex;
  167.  
  168.   __try
  169.   {
  170.     while (*lptstr)
  171.     {
  172.         // get the counter index
  173.         swscanf (lptstr, TEXT(" %d"), &dwHelpIndex);
  174.         if (dwHelpIndex == dwIndex)
  175.         {
  176.             // get the counter name
  177.             lptstr += lstrlen(lptstr) + 1;
  178.             wprintf(TEXT("(%u) %s\n"), dwIndex, lptstr);
  179.             return;
  180.         }
  181.  
  182.         lptstr += lstrlen(lptstr) + 1;
  183.     }
  184.  
  185.     if (!*lptstr)
  186.       _putws(TEXT("ERROR : Index Not Found !!!"));
  187.   }
  188.   __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  189.   {
  190.     _putws(TEXT("ERROR : An Access Violation Occured while searching for the index"));
  191.   }
  192. }
  193.  
  194. /******************************************************************************************
  195.  Retrieves from HKEY_PERFORMANCE_DATA the value of the string passed as parameter
  196.  and returning the memory in pMem.
  197.  Returns TRUE if it succeeds, FALSE upon failure. pMem is changed only when TRUE is about
  198.  to be returned.
  199.  When performance data is retrieved, the dwNeeded parameter in the call to RegQueryValueEx
  200.  is NOT changed to reflect the needed size, CONTRARY to what the documentation states.
  201.  The code checks for this condition, and if it is detected the dwNeeded parameter is
  202.  increased by MEM_STEP. When requesting "Counter 009" or "Help 009" the dwNeeded parameter
  203.  is changed by the system, so the manual adjustment is avoided.
  204. *******************************************************************************************/
  205. BOOL PerformanceKeyRetrieve(LPTSTR szName, LPVOID *pMemory)
  206. {
  207.   LPVOID pMem;
  208.   DWORD dwNeeded, dwType, dwHelp;
  209.   LONG lError;
  210.   BOOL bRetVal;
  211.  
  212.   __try
  213.   {
  214.         dwNeeded = MEM_STEP;
  215.         pMem = HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, dwNeeded);
  216.  
  217.       do
  218.       {
  219.         dwHelp = dwNeeded;
  220.         lError = RegQueryValueEx(HKEY_PERFORMANCE_DATA, szName, NULL, &dwType, pMem, &dwNeeded);
  221.         if (lError == ERROR_MORE_DATA)
  222.         {
  223.           if (dwHelp == dwNeeded)    // Check if manual adjustment is neccessary
  224.             dwNeeded += MEM_STEP;
  225.  
  226.           pMem = HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, pMem, dwNeeded);
  227.           wprintf(TEXT("Buffer not big enough. Trying with buffer size %d bytes\n"), dwNeeded);
  228.         }
  229.         else if (lError == ERROR_SUCCESS)
  230.         {
  231.           bRetVal = TRUE;
  232.           _putws(TEXT("Succesful Retrieval !!!\n"));
  233.         }
  234.         else
  235.         {
  236.           wprintf(TEXT("Unexpected Error : Failed to open subkey 009 of Perflib - Error Code %d\n%s"), lError,
  237.                   TEXT("If your lang key is not 009 please change the source code to the correct value\n"));
  238.  
  239.           HeapFree(GetProcessHeap(), 0, pMem);
  240.           bRetVal = FALSE;
  241.         }
  242.       }    while (lError == ERROR_MORE_DATA);
  243.  
  244.   }
  245.   __except ((GetExceptionCode()==STATUS_NO_MEMORY || GetExceptionCode()==STATUS_ACCESS_VIOLATION) ?
  246.              EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  247.   {
  248.     wprintf(TEXT("PerformanceKeyRetrieve()\nFailed to allocate memory for request \"%s\". Error Code = %d\n"),
  249.             szName, GetLastError());
  250.       
  251.     bRetVal = FALSE;
  252.   }
  253.  
  254.   if (bRetVal)
  255.     *pMemory = pMem;
  256.  
  257.   return bRetVal;
  258. }
  259. //******************************************************************************************
  260. main(void)
  261. {
  262.   DWORD j, k;
  263.   LPVOID pMem, pMem2, pMem3;
  264.   LONG lj;    // lj used for instances loop. NumInstances is LONG
  265.               // and not DWORD as stated in the documentation.
  266.  
  267.   PPERF_DATA_BLOCK           pPDB;
  268.   PPERF_OBJECT_TYPE          pPOT;
  269.   PPERF_COUNTER_DEFINITION   pPCD;
  270.   PPERF_INSTANCE_DEFINITION  pPID;
  271.   
  272.   _putws(TEXT("Performance Object Types Automatic Documentation"));
  273.   _putws(TEXT("Written By D.Staikos (dstaikos@theseas.ntua.gr)\n\n"));
  274.   
  275.   // Retrieval of Title Descriptions from registry
  276.   _putws(TEXT("Counter Titles Retrieval\n"));
  277.   if (!PerformanceKeyRetrieve(TEXT("Counter 009"), &pMem2))
  278.   {
  279.     RegCloseKey(HKEY_PERFORMANCE_DATA);
  280.     return -1;
  281.   }
  282.  
  283.   // Retrieval of Counter Explanations from registry
  284.   _putws(TEXT("Counter Explanations Retrieval\n"));
  285.   if (!PerformanceKeyRetrieve(TEXT("Help 009"), &pMem3))
  286.   {
  287.     HeapFree(GetProcessHeap(), 0, pMem2);
  288.     RegCloseKey(HKEY_PERFORMANCE_DATA);
  289.     return -1;
  290.   }
  291.   
  292.   // Retrieve All performance data. A call for performance data will NOT set the
  293.   // dwNeeded variable when ERROR_MORE_DATA is returned, so I have to do a retry loop
  294.   // increasing the step by MEM_STEP.
  295.   // An indication for the process of the retries is displayed.
  296.   _putws(TEXT("Moving on to Global Data Retrieval\n"));
  297.   if (!PerformanceKeyRetrieve(TEXT("Global"), &pMem))
  298.   {
  299.     HeapFree(GetProcessHeap(), 0, pMem2);
  300.     HeapFree(GetProcessHeap(), 0, pMem3);
  301.     RegCloseKey(HKEY_PERFORMANCE_DATA);
  302.     return -1;
  303.   }
  304.         
  305.   // Type the data on the screen ...
  306.   pPDB = (PPERF_DATA_BLOCK)pMem;
  307.   _putws(TEXT("OBJECT TYPE DEFINITIONS"));
  308.   wprintf(TEXT("Number of Object Types in Output : %u\n\n"), pPDB->NumObjectTypes);
  309.  
  310.   pPOT = FirstObject(pPDB);
  311.  
  312.   for (k=0; k<pPDB->NumObjectTypes; k++)
  313.   {
  314.     _putws(TEXT("---------------------------------------------------------------------------------------"));
  315.     _putws(TEXT("---------------------------------------------------------------------------------------\n"));
  316.  
  317.     wprintf(TEXT("OBJECT TYPE #%u OF %u\n\nOBJECT TYPE TITLE INDEX : "), k+1, pPDB->NumObjectTypes);
  318.     PrintStringByIndex(pPOT->ObjectNameTitleIndex, (LPTSTR)pMem2);
  319.     
  320.     wprintf(TEXT("OBJECT TYPE HELP        : "));
  321.     PrintStringByIndex(pPOT->ObjectHelpTitleIndex, (LPTSTR)pMem3);
  322.  
  323.     wprintf(TEXT("DETAIL LEVEL            : %s\n"), DetailLevelAsString(pPOT->DetailLevel));
  324.     wprintf(TEXT("NUMBER OF COUNTERS      : %u\n"), pPOT->NumCounters);
  325.     if (pPOT->NumInstances == PERF_NO_INSTANCES)
  326.       _putws(TEXT("NUMBER OF INSTANCES     : NO INSTANCES\n"));
  327.     else
  328.       wprintf(TEXT("NUMBER OF INSTANCES     : %d\n\n"), pPOT->NumInstances);
  329.  
  330.     // Display the counter definitions ...
  331.     _putws(TEXT("COUNTER DEFINITIONS\n"));
  332.     pPCD = FirstCounter(pPOT);
  333.  
  334.     __try
  335.     {
  336.         for (j=0; j<pPOT->NumCounters; j++)
  337.         {
  338.              wprintf(TEXT("COUNTER #%u OF %u\nCOUNTER NAME INDEX : "), j+1, pPOT->NumCounters);
  339.              PrintStringByIndex(pPCD->CounterNameTitleIndex, (LPTSTR)pMem2);
  340.  
  341.             wprintf(TEXT("COUNTER HELP INDEX : "));
  342.             PrintStringByIndex(pPCD->CounterHelpTitleIndex, (LPTSTR)pMem3);
  343.  
  344.             wprintf(TEXT("DEFAULT SCALE      : 10^(%d)\n"), pPCD->DefaultScale);
  345.             wprintf(TEXT("DETAIL LEVEL       : %s\n"), DetailLevelAsString(pPCD->DetailLevel));
  346.             wprintf(TEXT("COUNTER SIZE       : %u bytes\n"), pPCD->CounterSize);
  347.             wprintf(TEXT("COUNTER TYPE       : "));
  348.             PrintCounterFlags(pPCD->CounterType);
  349.  
  350.             pPCD = NextCounter(pPCD);
  351.         }
  352.  
  353.         // It once occured that zero was reported ...
  354.         if ((pPOT->NumInstances != PERF_NO_INSTANCES) && pPOT->NumInstances)
  355.         {
  356.             _putws(TEXT("INSTANCES\n"));
  357.             pPID = FirstInstance(pPOT);
  358.              for (lj=0; lj<pPOT->NumInstances; lj++)
  359.             {
  360.                 wprintf(TEXT("\tINSTANCE #%d OF %d\n"), lj+1, pPOT->NumInstances);
  361.                 wprintf(TEXT("\tParent Object Title Index : %u\n"), pPID->ParentObjectTitleIndex);
  362.                 wprintf(TEXT("\tParent Object Instance    : %u\n"), pPID->ParentObjectInstance);
  363.                 wprintf(TEXT("\tUnique ID                 : "));
  364.                 if (pPID->UniqueID == PERF_NO_UNIQUE_ID)
  365.                   _putws(TEXT("PERF_NO_UNIQUE_ID"));
  366.                 else
  367.                   wprintf(TEXT("%u\n"), pPID->UniqueID);
  368.  
  369.                 if (pPID->NameLength)
  370.                   wprintf(TEXT("\tInstance Name             : %s\n\n"), (LPCTSTR)((LPBYTE)pPID + pPID->NameOffset));
  371.                 else
  372.                   wprintf(TEXT("\tInstance Name             : UNNAMED(%d)\n\n"), lj);
  373.  
  374.                 pPID = NextInstance(pPID);
  375.             }
  376.         }
  377.     }
  378.     __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  379.     {
  380.         // Do nothing. Just try to continue to the next group ...
  381.         _putws(TEXT("\n\nACCESS VIOLATION\n\n"));
  382.     }
  383.  
  384.     pPOT = NextObject(pPOT);
  385.   }
  386.  
  387.   RegCloseKey(HKEY_PERFORMANCE_DATA);
  388.   HeapFree(GetProcessHeap(), 0, pMem);
  389.   HeapFree(GetProcessHeap(), 0, pMem2);
  390.   HeapFree(GetProcessHeap(), 0, pMem3);
  391.   _putws(TEXT("Program Completed Succesfully"));
  392.     
  393.   return 0;
  394. }
  395.