home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kompon / d2345 / MSYSINFO.ZIP / Source / MiTeC_PerfLibNT.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-26  |  40KB  |  1,136 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       MiTeC System Information Component              }
  5. {           Performance Library for WinNT               }
  6. {           version 5.6 for Delphi 3,4,5                }
  7. {                                                       }
  8. {       Copyright ⌐ 1997,2001 Michal Mutl               }
  9. {                                                       }
  10. {*******************************************************}
  11.  
  12. {$INCLUDE MITEC_DEF.INC}
  13.  
  14. unit MiTeC_PerfLibNT;
  15.  
  16. interface
  17.  
  18. uses Windows, Classes, SysUtils;
  19.  
  20. //resourcestring
  21. const
  22.   SPERFNUMHEX_BadSize = 'Bad Size (PERF_NUMBER_HEX)';
  23.   SPERFNUMDEC_BadSize = 'Bad Size (PERF_NUMBER_DEC)';
  24.   SPERFNUMDEC1K_BadSize = 'Bad Size (PERF_NUMBER_DEC1000)';
  25.   SPERFCNTR_BadSize = 'Bad Size (PERF_COUNTER)';
  26.   SPERFCNTRRATE_BadSize = 'Bad Size (PERF_COUNTER_RATE)';
  27.   SPERFCNTRBASE_BadSize = 'Bad Size (PERF_COUNTER_BASE)';
  28.   SPERFCNTRELAPS_BadSize = 'Bad Size (PERF_COUNTER_ELAPSED)';
  29.   SUnknownType = 'Cannot display data';
  30.   SPERFTYPETEXT_BadData = 'Bad Data (PERF_TYPE_TEXT)';
  31.  
  32.   SPerSec = '/sec';
  33.   SPercent = ' %';
  34.   SSecs = ' secs';
  35.   SFrac = 'Frac';
  36.   SElapsed = 'Elapsed';
  37.  
  38.   SNoname = '<noname>';
  39.  
  40. const
  41.   Timer100N = 10000000;
  42.   Timer1S = 1000;
  43.  
  44.   PERF_DETAIL_NOVICE      = $00000000;
  45.   PERF_DETAIL_ADVANCED    = $00000100;
  46.   PERF_DETAIL_EXPERT      = $00000200;
  47.   PERF_DETAIL_WIZARD      = $00000300;
  48.  
  49. //                      PERF_COUNTER_DEFINITION
  50. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  51. //
  52. //  PERF_COUNTER_DEFINITION.CounterType field values
  53. //
  54. //
  55. //        Counter ID Field Definition:
  56. //
  57. //   3      2        2    2    2        1        1    1
  58. //   1      8        4    2    0        6        2    0    8                0
  59. //  +--------+--------+----+----+--------+--------+----+----+----------------+
  60. //  |Display |Calculation  |Time|Counter |        |Ctr |Size|                |
  61. //  |Flags   |Modifiers    |Base|SubType |Reserved|Type|Fld |   Reserved     |
  62. //  +--------+--------+----+----+--------+--------+----+----+----------------+
  63. //
  64. //
  65.   PERF_SIZE_DWORD         = $00000000;
  66.   PERF_SIZE_LARGE         = $00000100;
  67.   PERF_SIZE_ZERO          = $00000200;  // for Zero Length fields
  68.   PERF_SIZE_VARIABLE_LEN  = $00000300;  // length is in CounterLength field of Counter Definition struct
  69.   //
  70.   //  select one of the following values to indicate the counter field usage
  71.   //
  72.   PERF_TYPE_NUMBER        = $00000000;  // a number (not a counter)
  73.   PERF_TYPE_COUNTER       = $00000400;  // an increasing numeric value
  74.   PERF_TYPE_TEXT          = $00000800;  // a text field
  75.   PERF_TYPE_ZERO          = $00000C00;  // displays a zero
  76.   //
  77.   //  If the PERF_TYPE_NUMBER field was selected, then select one of the
  78.   //  following to describe the Number
  79.   //
  80.   PERF_NUMBER_HEX         = $00000000;  // display as HEX value
  81.   PERF_NUMBER_DECIMAL     = $00010000;  // display as a decimal integer
  82.   PERF_NUMBER_DEC_1000    = $00020000;  // display as a decimal/1000
  83.   //
  84.   //  If the PERF_TYPE_COUNTER value was selected then select one of the
  85.   //  following to indicate the type of counter
  86.   //
  87.   PERF_COUNTER_VALUE      = $00000000;  // display counter value
  88.   PERF_COUNTER_RATE       = $00010000;  // divide ctr / delta time
  89.   PERF_COUNTER_FRACTION   = $00020000;  // divide ctr / base
  90.   PERF_COUNTER_BASE       = $00030000;  // base value used in fractions
  91.   PERF_COUNTER_ELAPSED    = $00040000;  // subtract counter from current time
  92.   PERF_COUNTER_QUEUELEN   = $00050000;  // Use Queuelen processing func.
  93.   PERF_COUNTER_HISTOGRAM  = $00060000;  // Counter begins or ends a histogram
  94.   //
  95.   //  If the PERF_TYPE_TEXT value was selected, then select one of the
  96.   //  following to indicate the type of TEXT data.
  97.   //
  98.   PERF_TEXT_UNICODE       = $00000000;  // type of text in text field
  99.   PERF_TEXT_ASCII         = $00010000;  // ASCII using the CodePage field
  100.   //
  101.   //  Timer SubTypes
  102.   //
  103.   PERF_TIMER_TICK         = $00000000;  // use system perf. freq for base
  104.   PERF_TIMER_100NS        = $00100000;  // use 100 NS timer time base units
  105.   PERF_OBJECT_TIMER       = $00200000;  // use the object timer freq
  106.   //
  107.   //  Any types that have calculations performed can use one or more of
  108.   //  the following calculation modification flags listed here
  109.   //
  110.   PERF_DELTA_COUNTER      = $00400000;  // compute difference first
  111.   PERF_DELTA_BASE         = $00800000;  // compute base diff as well
  112.   PERF_INVERSE_COUNTER    = $01000000;  // show as 1.00-value (assumes:
  113.   PERF_MULTI_COUNTER      = $02000000;  // sum of multiple instances
  114.   //
  115.   //  Select one of the following values to indicate the display suffix (if any)
  116.   //
  117.   PERF_DISPLAY_NO_SUFFIX  = $00000000;  // no suffix
  118.   PERF_DISPLAY_PER_SEC    = $10000000;  // "/sec"
  119.   PERF_DISPLAY_PERCENT    = $20000000;  // "%"
  120.   PERF_DISPLAY_SECONDS    = $30000000;  // "secs"
  121.   PERF_DISPLAY_NOSHOW     = $40000000;  // value is not displayed
  122.   //
  123.   //  Predefined counter types
  124.   //
  125.  
  126.   // 32-bit Counter.  Divide delta by delta time.  Display suffix: "/sec"
  127.   PERF_COUNTER_COUNTER =
  128.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  129.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PER_SEC;
  130.  
  131.  
  132.   // 64-bit Timer.  Divide delta by delta time.  Display suffix: "%"
  133.   PERF_COUNTER_TIMER =
  134.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  135.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
  136.  
  137.   // Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix.
  138.   PERF_COUNTER_QUEUELEN_TYPE =
  139.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
  140.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
  141.  
  142.   // Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix.
  143.   PERF_COUNTER_LARGE_QUEUELEN_TYPE =
  144.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
  145.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
  146.  
  147.   // 64-bit Counter.  Divide delta by delta time. Display Suffix: "/sec"
  148.   PERF_COUNTER_BULK_COUNT =
  149.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  150.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PER_SEC;
  151.  
  152.   // Indicates the counter is not a  counter but rather Unicode text Display as text.
  153.   PERF_COUNTER_TEXT =
  154.               PERF_SIZE_VARIABLE_LEN or PERF_TYPE_TEXT or PERF_TEXT_UNICODE or
  155.               PERF_DISPLAY_NO_SUFFIX;
  156.  
  157.   // Indicates the data is a counter  which should not be
  158.   // time averaged on display (such as an error counter on a serial line)
  159.   // Display as is.  No Display Suffix.
  160.   PERF_COUNTER_RAWCOUNT =
  161.               PERF_SIZE_DWORD or PERF_TYPE_NUMBER or PERF_NUMBER_DECIMAL or
  162.               PERF_DISPLAY_NO_SUFFIX;
  163.  
  164.   // Same as PERF_COUNTER_RAWCOUNT except its size is a large integer
  165.   PERF_COUNTER_LARGE_RAWCOUNT =
  166.               PERF_SIZE_LARGE or PERF_TYPE_NUMBER or PERF_NUMBER_DECIMAL or
  167.               PERF_DISPLAY_NO_SUFFIX;
  168.  
  169.   // Special case for RAWCOUNT that want to be displayed in hex
  170.   // Indicates the data is a counter  which should not be
  171.   // time averaged on display (such as an error counter on a serial line)
  172.   // Display as is.  No Display Suffix.
  173.   PERF_COUNTER_RAWCOUNT_HEX =
  174.               PERF_SIZE_DWORD or PERF_TYPE_NUMBER or PERF_NUMBER_HEX or
  175.               PERF_DISPLAY_NO_SUFFIX;
  176.  
  177.   // Same as PERF_COUNTER_RAWCOUNT_HEX except its size is a large integer
  178.   PERF_COUNTER_LARGE_RAWCOUNT_HEX =
  179.               PERF_SIZE_LARGE or PERF_TYPE_NUMBER or PERF_NUMBER_HEX or
  180.               PERF_DISPLAY_NO_SUFFIX;
  181.  
  182.  
  183.   // A count which is either 1 or 0 on each sampling interrupt (% busy)
  184.   // Divide delta by delta base. Display Suffix: "%"
  185.   PERF_SAMPLE_FRACTION =
  186.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
  187.               PERF_DELTA_COUNTER or PERF_DELTA_BASE or PERF_DISPLAY_PERCENT;
  188.  
  189.   // A count which is sampled on each sampling interrupt (queue length)
  190.   // Divide delta by delta time. No Display Suffix.
  191.   PERF_SAMPLE_COUNTER =
  192.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  193.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
  194.  
  195.   // A label: no data is associated with this counter (it has 0 length)
  196.   // Do not display.
  197.   PERF_COUNTER_NODATA =
  198.               PERF_SIZE_ZERO or PERF_DISPLAY_NOSHOW;
  199.  
  200.   // 64-bit Timer inverse (e.g., idle is measured, but display busy %)
  201.   // Display 100 - delta divided by delta time.  Display suffix: "%"
  202.   PERF_COUNTER_TIMER_INV =
  203.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  204.               PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_INVERSE_COUNTER or
  205.               PERF_DISPLAY_PERCENT;
  206.  
  207.   // The divisor for a sample, used with the previous counter to form a
  208.   // sampled %.  You must check for >0 before dividing by this!  This
  209.   // counter will directly follow the  numerator counter.  It should not
  210.   // be displayed to the user.
  211.   PERF_SAMPLE_BASE =
  212.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
  213.               PERF_DISPLAY_NOSHOW or
  214.               $00000001;  // for compatibility with pre-beta versions
  215.  
  216.   // A timer which, when divided by an average base, produces a time
  217.   // in seconds which is the average time of some operation.  This
  218.   // timer times total operations, and  the base is the number of opera-
  219.   // tions.  Display Suffix: "sec"
  220.   PERF_AVERAGE_TIMER =
  221.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
  222.               PERF_DISPLAY_SECONDS;
  223.  
  224.   // Used as the denominator in the computation of time or count
  225.   // averages.  Must directly follow the numerator counter.  Not dis-
  226.   // played to the user.
  227.   PERF_AVERAGE_BASE =
  228.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
  229.               PERF_DISPLAY_NOSHOW or
  230.               $00000002;  // for compatibility with pre-beta versions
  231.  
  232.  
  233.   // A bulk count which, when divided (typically) by the number of
  234.   // operations, gives (typically) the number of bytes per operation.
  235.   // No Display Suffix.
  236.   PERF_AVERAGE_BULK =
  237.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION  or
  238.               PERF_DISPLAY_NOSHOW;
  239.  
  240.   // 64-bit Timer in 100 nsec units. Display delta divided by
  241.   // delta time.  Display suffix: "%"
  242.   PERF_100NSEC_TIMER =
  243.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  244.               PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
  245.  
  246.   // 64-bit Timer inverse (e.g., idle is measured, but display busy %)
  247.   // Display 100 - delta divided by delta time.  Display suffix: "%"
  248.   PERF_100NSEC_TIMER_INV =
  249.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  250.               PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_INVERSE_COUNTER  or
  251.               PERF_DISPLAY_PERCENT;
  252.  
  253.   // 64-bit Timer.  Divide delta by delta time.  Display suffix: "%"
  254.   // Timer for multiple instances, so result can exceed 100%.
  255.   PERF_COUNTER_MULTI_TIMER =
  256.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  257.               PERF_DELTA_COUNTER or PERF_TIMER_TICK or PERF_MULTI_COUNTER or
  258.               PERF_DISPLAY_PERCENT;
  259.  
  260.   // 64-bit Timer inverse (e.g., idle is measured, but display busy %)
  261.   // Display 100 * _MULTI_BASE - delta divided by delta time.
  262.   // Display suffix: "%" Timer for multiple instances, so result
  263.   // can exceed 100%.  Followed by a counter of type _MULTI_BASE.
  264.   PERF_COUNTER_MULTI_TIMER_INV =
  265.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
  266.               PERF_DELTA_COUNTER or PERF_MULTI_COUNTER or PERF_TIMER_TICK or
  267.               PERF_INVERSE_COUNTER or PERF_DISPLAY_PERCENT;
  268.  
  269.   // Number of instances to which the preceding _MULTI_..._INV counter
  270.   // applies.  Used as a factor to get the percentage.
  271.   PERF_COUNTER_MULTI_BASE =
  272.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
  273.               PERF_MULTI_COUNTER or PERF_DISPLAY_NOSHOW;
  274.  
  275.   // 64-bit Timer in 100 nsec units. Display delta divided by delta time.
  276.   // Display suffix: "%" Timer for multiple instances, so result can exceed 100%.
  277.   PERF_100NSEC_MULTI_TIMER =
  278.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_DELTA_COUNTER  or
  279.               PERF_COUNTER_RATE or PERF_TIMER_100NS or PERF_MULTI_COUNTER or
  280.               PERF_DISPLAY_PERCENT;
  281.  
  282.   // 64-bit Timer inverse (e.g., idle is measured, but display busy %)
  283.   // Display 100 * _MULTI_BASE - delta divided by delta time.
  284.   // Display suffix: "%" Timer for multiple instances, so result
  285.   // can exceed 100%.  Followed by a counter of type _MULTI_BASE.
  286.   PERF_100NSEC_MULTI_TIMER_INV =
  287.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_DELTA_COUNTER  or
  288.               PERF_COUNTER_RATE or PERF_TIMER_100NS or PERF_MULTI_COUNTER or
  289.               PERF_INVERSE_COUNTER or PERF_DISPLAY_PERCENT;
  290.  
  291.   // Indicates the data is a fraction of the following counter  which
  292.   // should not be time averaged on display (such as free space over
  293.   // total space.) Display as is.  Display the quotient as "%".
  294.   PERF_RAW_FRACTION =
  295.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
  296.               PERF_DISPLAY_PERCENT;
  297.  
  298.   // Indicates the data is a base for the preceding counter which should
  299.   // not be time averaged on display (such as free space over total space.)
  300.   PERF_RAW_BASE =
  301.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
  302.               PERF_DISPLAY_NOSHOW or
  303.               $00000003;  // for compatibility with pre-beta versions
  304.  
  305.   // The data collected in this counter is actually the start time of the
  306.   // item being measured. For display, this data is subtracted from the
  307.   // sample time to yield the elapsed time as the difference between the two.
  308.   // In the definition below, the PerfTime field of the Object contains
  309.   // the sample time as indicated by the PERF_OBJECT_TIMER bit and the
  310.   // difference is scaled by the PerfFreq of the Object to convert the time
  311.   // units into seconds.
  312.   PERF_ELAPSED_TIME =
  313.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_ELAPSED or
  314.               PERF_OBJECT_TIMER or PERF_DISPLAY_SECONDS;
  315.   //
  316.   //  The following counter type can be used with the preceding types to
  317.   //  define a range of values to be displayed in a histogram.
  318.   //
  319.  
  320.   PERF_COUNTER_HISTOGRAM_TYPE   = $80000000;
  321.                                           // Counter begins or ends a histogram
  322.   //
  323.   //  This counter is used to display the difference from one sample
  324.   //  to the next. The counter value is a constantly increasing number
  325.   //  and the value displayed is the difference between the current
  326.   //  value and the previous value. Negative numbers are not allowed
  327.   //  which shouldn't be a problem as long as the counter value is
  328.   //  increasing or unchanged.
  329.   //
  330.   PERF_COUNTER_DELTA =
  331.               PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_VALUE or
  332.               PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
  333.  
  334.   PERF_COUNTER_LARGE_DELTA =
  335.               PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_VALUE or
  336.               PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
  337.  
  338.  
  339. type
  340.   PLARGE_INTEGER = ^LARGE_INTEGER;
  341.  
  342.   PPERF_OBJECT_TYPE = ^TPERF_OBJECT_TYPE;
  343.   TPERF_OBJECT_TYPE = packed record
  344.     TotalByteLength,
  345.     DefinitionLength,
  346.     HeaderLength,
  347.     ObjectNameTitleIndex: DWORD;
  348.     ObjectNameTitle: LPWSTR;
  349.     ObjectHelpTitleIndex: DWORD;
  350.     ObjectHelpTitle: LPWSTR;
  351.     DetailLevel,
  352.     NumCounters,
  353.     DefaultCounter,
  354.     NumInstances,
  355.     CodePage: DWORD;
  356.     PerfTime,
  357.     PerfFreq: LARGE_INTEGER;
  358.   end;
  359.  
  360.   PPERF_COUNTER_DEFINITION = ^TPERF_COUNTER_DEFINITION;
  361.   TPERF_COUNTER_DEFINITION = packed record
  362.     ByteLength,
  363.     CounterNameTitleIndex: DWORD;
  364.     CounterNameTitle: LPWSTR;
  365.     CounterHelpTitleIndex: DWORD;
  366.     CounterHelpTitle: LPWSTR;
  367.     DefaultScale,
  368.     DetailLevel,
  369.     CounterType,
  370.     CounterSize,
  371.     CounterOffset: DWORD;
  372.   end;
  373.  
  374.   PPERF_INSTANCE_DEFINITION = ^TPERF_INSTANCE_DEFINITION;
  375.   TPERF_INSTANCE_DEFINITION = packed record
  376.     ByteLength,
  377.     ParentObjectTitleIndex,
  378.     ParentObjectInstance,
  379.     UniqueID,
  380.     NameOffset,
  381.     NameLength: DWORD;
  382.   end;
  383.  
  384.   PPERF_COUNTER_BLOCK = ^TPERF_COUNTER_BLOCK;
  385.   TPERF_COUNTER_BLOCK = packed record
  386.     ByteLength: DWORD;
  387.   end;
  388.  
  389.   PPERF_DATA_BLOCK = ^TPERF_DATA_BLOCK;
  390.   TPERF_DATA_BLOCK = packed record
  391.     Signature: array [0..3] of WCHAR;
  392.     LittleEndian,
  393.     Version,
  394.     Revision,
  395.     TotalByteLength,
  396.     HeaderLength,
  397.     NumObjectTypes,
  398.     DefaultObject: DWORD;
  399.     SystemTime: SYSTEMTIME;
  400.     PerfTime,
  401.     PerfFreq,
  402.     PerfTime100nSec: LARGE_INTEGER;
  403.     SystemNameLength,
  404.     SystemNameOffset: DWORD;
  405.   end;
  406.  
  407.   TPerfLibNT = class;
  408.  
  409.   TPerfObject = class;
  410.  
  411.   TDetailLevel = (Novice,Advanced,Expert,Wizard);
  412.  
  413.   TPerfCounter = class(TObject)
  414.   private
  415.     FPerfObject: TPerfObject;
  416.  
  417.     FName: string;
  418.     FDescription: string;
  419.     FCounterOffset: DWORD;
  420.     FDefaultScale: DWORD;
  421.     FCounterSize: DWORD;
  422.     FDetailLevel: TDetailLevel;
  423.     FCounterType: DWORD;
  424.     FIndex: DWORD;
  425.  
  426.     function GetData(InstanceIndex: DWORD): PChar;
  427.     function GetDataStr(InstanceIndex: DWORD): string;
  428.     function GetDataStrEx(InstanceIndex: DWORD): string;
  429.   protected
  430.     property CounterOffset: DWORD read FCounterOffset;
  431.     property Index: DWORD read FIndex;
  432.   public
  433.     constructor Create(AIndex: DWORD; APerfObject: TPerfObject; APerfCntr: PPERF_COUNTER_DEFINITION);
  434.     destructor Destroy; override;
  435.  
  436.     property Name: string read FName;
  437.     property Description: string read FDescription;
  438.     property DefaultScale: DWORD read FDefaultScale;
  439.     property DetailLevel: TDetailLevel read FDetailLevel;
  440.     property CounterType: DWORD read FCounterType;
  441.     property CounterSize: DWORD read FCounterSize;
  442.     property ParentObject: TPerfObject read FPerfObject;
  443.  
  444.     property Data[InstanceIndex: DWORD]: PChar read GetData;
  445.     property DataStr[InstanceIndex: DWORD]: string read GetDataStr;
  446.     property DataStrEx[InstanceIndex: DWORD]: string read GetDataStrEx;
  447.   end;
  448.  
  449.   PPerfInstance = ^TPerfInstance;
  450.   TPerfInstance = record
  451.     Name: string;
  452.     ID,
  453.     Index: DWORD;
  454.   end;
  455.  
  456.   TPerfObject = class(TObject)
  457.   private
  458.     FCounters: TStringList;
  459.  
  460.     FPerfLib: TPerfLibNT;
  461.     FName: string;
  462.     FDescription: string;
  463.     FCodePage: DWORD;
  464.     FCounterCount: integer;
  465.     FDefaultCounter: integer;
  466.     FDetailLevel: TDetailLevel;
  467.     FPerfObj: PPERF_OBJECT_TYPE;
  468.     FPerfTime: LARGE_INTEGER;
  469.     FPerfFreq: LARGE_INTEGER;
  470.     FIndex: DWORD;
  471.     function GetCounter(Index: integer): TPerfCounter;
  472.     function GetInstance(Index: integer): TPerfInstance;
  473.     function GetInstanceCount: integer;
  474.   protected
  475.     property Index: DWORD read FIndex;
  476.     property PerfLib: TPerfLibNT read FPerfLib;
  477.     property PerfObj: PPERF_OBJECT_TYPE read FPerfObj;
  478.   public
  479.     constructor Create(AIndex: DWORD; APerfLib: TPerfLibNT; APerfObj: PPERF_OBJECT_TYPE);
  480.     destructor Destroy; override;
  481.  
  482.     function GetCntrIndexByName(AName: string): integer;
  483.     {function GetInstIndexByName(AName: string): integer;
  484.     function GetInstIndexByID(AID: DWORD): integer;}
  485.  
  486.     property Name: string read FName;
  487.     property Description: string read FDescription;
  488.     property DetailLevel: TDetailLevel read FDetailLevel;
  489.     property CounterCount: integer read FCounterCount;
  490.     property DefaultCounter: integer read FDefaultCounter;
  491.     property InstanceCount: integer read GetInstanceCount;
  492.     property CodePage: DWORD read FCodePage;
  493.     property PerfTime: LARGE_INTEGER read FPerfTime;
  494.     property PerfFreq: LARGE_INTEGER read FPerfFreq;
  495.  
  496.     property Counters[Index: integer]: TPerfCounter read GetCounter;
  497.     property Instances[Index: integer]: TPerfInstance read GetInstance;
  498.   end;
  499.  
  500.   TPerfLibNT = class(TPersistent)
  501.   private
  502.     FPerfData: PPERF_DATA_BLOCK;
  503.  
  504.     FCounters,
  505.     FHelps,
  506.     FObjects: TStringList;
  507.     FPerfTime: LARGE_INTEGER;
  508.     FPerfFreq: LARGE_INTEGER;
  509.     FPerfTime100nsec: LARGE_INTEGER;
  510.     FRevision: DWORD;
  511.     FVersion: DWORD;
  512.  
  513.     procedure GetNameStrings;
  514.     procedure ReadObjects;
  515.     function GetObject(Index: integer): TPerfObject;
  516.     function GetObjectCount: integer;
  517.   protected
  518.     function GetCounterData(ObjectIndex,InstanceIndex,CounterIndex: DWORD): PChar;
  519.     property Helps: TStringList read FHelps;
  520.   public
  521.     constructor Create;
  522.     destructor Destroy; override;
  523.  
  524.     procedure TakeSnapshot;
  525.     procedure Refresh;
  526.     function GetIndexByName(AName: string): integer;
  527.  
  528.     property Names: TStringList read FCounters;
  529.     property PerfTime: LARGE_INTEGER read FPerfTime;
  530.     property PerfFreq: LARGE_INTEGER read FPerfFreq;
  531.     property PerfTime100nsec: LARGE_INTEGER read FPerfTime100nsec;
  532.     property Version: DWORD read FVersion;
  533.     property Revision: DWORD read FRevision;
  534.     property ObjectCount: integer read GetObjectCount;
  535.     property Objects[Index: integer]: TPerfObject read GetObject;
  536.   end;
  537.  
  538.   function FormatData(AType, ASize: Integer; AVerbose: Boolean; AData: PChar): string;
  539.   function GetCounterTypeStr(AType: DWORD): string;
  540.   function GetDetailLevelStr(ALevel: TDetailLevel): string;
  541.  
  542. implementation
  543.  
  544. const
  545.   rkPerfLib = {HKLM\}'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib';
  546.     rvLastCounter = 'LastCounter';
  547.   rkPerfLib009 = {HKLM\}'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009';
  548.     rvCounter = 'Counter';
  549.     rvHelp = 'Help';
  550.   rkGlobal = 'Global';
  551.  
  552. function FirstObject(APerfData: PPERF_DATA_BLOCK): PPERF_OBJECT_TYPE;
  553. begin
  554.   Result:=PPERF_OBJECT_TYPE(PCHAR(APerfData)+APerfData^.HeaderLength);
  555. end;
  556.  
  557. function NextObject(APerfObj: PPERF_OBJECT_TYPE): PPERF_OBJECT_TYPE;
  558. begin
  559.   Result:=PPERF_OBJECT_TYPE(PCHAR(APerfObj)+APerfObj^.TotalByteLength);
  560. end;
  561.  
  562. function FirstInstance(APerfObj: PPERF_OBJECT_TYPE): PPERF_INSTANCE_DEFINITION;
  563. begin
  564.   Result:=PPERF_INSTANCE_DEFINITION(PCHAR(APerfObj)+APerfObj^.DefinitionLength);
  565. end;
  566.  
  567. function NextInstance(APerfInst: PPERF_INSTANCE_DEFINITION): PPERF_INSTANCE_DEFINITION;
  568. var
  569.   PerfCntrBlk: PPERF_COUNTER_BLOCK;
  570. begin
  571.   PerfCntrBlk:=PPERF_COUNTER_BLOCK(PCHAR(APerfInst)+APerfInst^.ByteLength);
  572.   result:=PPERF_INSTANCE_DEFINITION(PCHAR(PerfCntrBlk)+PerfCntrBlk^.ByteLength);
  573. end;
  574.  
  575. function FirstCounter(APerfObj: PPERF_OBJECT_TYPE): PPERF_COUNTER_DEFINITION;
  576. begin
  577.   Result:=PPERF_COUNTER_DEFINITION(PCHAR(APerfObj)+APerfObj^.HeaderLength);
  578. end;
  579.  
  580. function NextCounter(APerfCntr: PPERF_COUNTER_DEFINITION): PPERF_COUNTER_DEFINITION;
  581. begin
  582.   Result:=PPERF_COUNTER_DEFINITION(PCHAR(APerfCntr)+APerfCntr^.ByteLength);
  583. end;
  584.  
  585.  
  586. //   3      2        2    2    2        1        1    1
  587. //   1      8        4    2    0        6        2    0    8                0
  588. //  +--------+--------+----+----+--------+--------+----+----+----------------+
  589. //  |Display |Calculation  |Time|Counter |        |Ctr |Size|                |
  590. //  |Flags   |Modifiers    |Base|SubType |Reserved|Type|Fld |   Reserved     |
  591. //  +--------+--------+----+----+--------+--------+----+----+----------------+
  592.  
  593.  
  594. function FormatData;
  595. var
  596.   SizeFld,
  597.   CtrType,
  598.   CounterSubType,
  599.   //TimeBase,
  600.   //CalculationModifiers,
  601.   DisplayFlags: Integer;
  602.   s: string;
  603.   time: int64;
  604.   n: extended;
  605. const
  606.  DeltaTime: Integer = 1;
  607.  Base: extended = 1;
  608. begin
  609.   SizeFld:=AType and $300;
  610.   CtrType:=AType and $c00;
  611.   CounterSubType:=AType and $f0000;
  612. //  TimeBase:=AType and $300000;
  613. //  CalculationModifiers:=AType and $fc00000;
  614.   DisplayFlags:=AType and $f0000000;
  615.  
  616.   s:='';
  617.  
  618.   case SizeFld of
  619.     PERF_SIZE_DWORD: ASize := 4;
  620.     PERF_SIZE_LARGE: ASize := 8;
  621.     PERF_SIZE_ZERO: ASize := 0;
  622.     PERF_SIZE_VARIABLE_LEN: ; // length is in CounterLength field
  623.   end;
  624.  
  625.   case CtrType of
  626.     PERF_TYPE_NUMBER :
  627.       case CounterSubType of
  628.         PERF_NUMBER_HEX:
  629.           case ASize of
  630.             4: s:=IntToHex(PInteger(AData)^,8);
  631.             8: s:=IntToHex(PLARGE_INTEGER(AData)^.HighPart,8)+':'+IntToHex(PLARGE_INTEGER(AData)^.LowPart,8);
  632.             else s:=SPERFNUMHEX_BadSize;
  633.           end;
  634.         PERF_NUMBER_DECIMAL:
  635.           case ASize of
  636.             4: s:=IntToStr(PInteger(AData)^);
  637.             8: s:=Format('%d',[PLARGE_INTEGER(AData)^.QuadPart]);
  638.             else s:=SPERFNUMDEC_BadSize;
  639.           end;
  640.         PERF_NUMBER_DEC_1000:
  641.           case ASize of
  642.             4: s:=IntToStr(PInteger(AData)^ div 1000);
  643.             8: s:=Format('%n',[PLARGE_INTEGER(AData)^.QuadPart/1000]);
  644.             else s:=SPERFNUMDEC1K_BadSize;
  645.           end
  646.       end;
  647.  
  648.     PERF_TYPE_COUNTER:
  649.       case CounterSubType of
  650.         PERF_COUNTER_VALUE :
  651.           case ASize of
  652.             4: s:=IntToStr(PInteger(AData)^);
  653.             8: s:=Format('%d',[PLARGE_INTEGER(AData)^.QuadPart]);
  654.             else s:=SPERFCNTR_BadSize;
  655.           end;
  656.         PERF_COUNTER_RATE :
  657.           case ASize of
  658.             4: s:=IntToStr(PInteger(AData)^ div deltaTime);
  659.             8: s:=Format('%n',[PLARGE_INTEGER(AData)^.QuadPart/deltatime]);
  660.             else s:=SPERFCNTRRATE_BadSize;
  661.           end;
  662.  
  663.         PERF_COUNTER_FRACTION: begin
  664.           case ASize of
  665.             4: n:=PInteger(AData)^/base;
  666.             8: n:=PLARGE_INTEGER(AData)^.QuadPart/base;
  667.             else
  668.               n:=0;
  669.           end;
  670.           if (ASize=4) or (ASize=8) then  begin
  671.             if DisplayFlags=PERF_DISPLAY_PERCENT then
  672.               n:=n*100;
  673.             s:=Format('%1.3n',[n]);
  674.             if AVerbose then
  675.               s:=SFrac+' '+s;
  676.           end
  677.         end;
  678.  
  679.         PERF_COUNTER_BASE:
  680.           case ASize of
  681.             4 : base:=PInteger(AData)^;
  682.             8 : base:=PLARGE_INTEGER(AData)^.QuadPart;
  683.             else s:=SPERFCNTRBASE_BadSize;
  684.           end;
  685.  
  686.         PERF_COUNTER_ELAPSED: begin
  687.           QueryPerformanceFrequency(time);
  688.           case ASize of
  689.             4 : s:=IntToStr(low(time)-PInteger(AData)^);
  690.             8 : s:=Format('%n',[PLARGE_INTEGER(AData)^.QuadPart/time]);
  691.             else s:=SPERFCNTRELAPS_BadSize;
  692.           end;
  693.           if AVerbose then
  694.             s:=SElapsed+' '+s;
  695.         end;
  696.  
  697.         PERF_COUNTER_QUEUELEN:
  698.           s:='QUEUELEN';
  699.  
  700.         PERF_COUNTER_HISTOGRAM:
  701.           s:='HISTOGRAM';
  702.         else s:=SUnknownType;
  703.       end;
  704.  
  705.     PERF_TYPE_TEXT:
  706.       s:=SPERFTYPETEXT_BadData;
  707.     PERF_TYPE_ZERO:
  708.       s:='0';
  709.   end;
  710.  
  711.   if AVerbose then
  712.     case DisplayFlags of
  713.       PERF_DISPLAY_PER_SEC: s:=s+SPerSec;
  714.       PERF_DISPLAY_PERCENT: s:=s+SPercent;
  715.       PERF_DISPLAY_SECONDS: s:=s+SSecs;
  716.       PERF_DISPLAY_NOSHOW: s:='';
  717.     end;
  718.  
  719.   result:=s;
  720. end;
  721.  
  722. function GetCounterTypeStr(AType: DWORD): string;
  723. var
  724.   CtrType,
  725.   CtrSubType: integer;
  726. begin
  727.   CtrType:=AType and $c00;
  728.   CtrSubType:=AType and $f0000;
  729.  
  730.   Result:='';
  731.  
  732.   case AType of
  733.     PERF_COUNTER_COUNTER: Result:='PERF_COUNTER_COUNTER';
  734.     PERF_COUNTER_TIMER: Result:='PERF_COUNTER_TIMER';
  735.     PERF_COUNTER_QUEUELEN_TYPE: Result:='PERF_COUNTER_QUEUELEN_TYPE';
  736.     PERF_COUNTER_LARGE_QUEUELEN_TYPE: Result:='PERF_COUNTER_LARGE_QUEUELEN_TYPE';
  737.     PERF_COUNTER_BULK_COUNT: Result:='PERF_COUNTER_BULK_COUNT';
  738.     PERF_COUNTER_TEXT: Result:='PERF_COUNTER_TEXT';
  739.     PERF_COUNTER_RAWCOUNT: Result:='PERF_COUNTER_RAWCOUNT';
  740.     PERF_COUNTER_LARGE_RAWCOUNT: Result:='PERF_COUNTER_LARGE_RAWCOUNT';
  741.     PERF_COUNTER_RAWCOUNT_HEX: Result:='PERF_COUNTER_RAWCOUNT_HEX';
  742.     PERF_COUNTER_LARGE_RAWCOUNT_HEX: Result:='PERF_COUNTER_LARGE_RAWCOUNT_HEX';
  743.     PERF_SAMPLE_FRACTION: Result:='PERF_SAMPLE_FRACTION';
  744.     PERF_SAMPLE_COUNTER: Result:='PERF_SAMPLE_COUNTER';
  745.     PERF_COUNTER_NODATA: Result:='PERF_COUNTER_NODATA';
  746.     PERF_COUNTER_TIMER_INV: Result:='PERF_COUNTER_TIMER_INV';
  747.     PERF_SAMPLE_BASE: Result:='PERF_SAMPLE_BASE';
  748.     PERF_AVERAGE_TIMER: Result:='PERF_AVERAGE_TIMER';
  749.     PERF_AVERAGE_BASE: Result:='PERF_AVERAGE_BASE';
  750.     PERF_AVERAGE_BULK: Result:='PERF_AVERAGE_BULK';
  751.     PERF_100NSEC_TIMER: Result:='PERF_100NSEC_TIMER';
  752.     PERF_100NSEC_TIMER_INV: Result:='PERF_100NSEC_TIMER_INV';
  753.     PERF_COUNTER_MULTI_TIMER: Result:='PERF_COUNTER_MULTI_TIMER';
  754.     PERF_COUNTER_MULTI_TIMER_INV: Result:='PERF_COUNTER_MULTI_TIMER_INV';
  755.     PERF_COUNTER_MULTI_BASE: Result:='PERF_COUNTER_MULTI_BASE';
  756.     PERF_100NSEC_MULTI_TIMER: Result:='PERF_100NSEC_MULTI_TIMER';
  757.     PERF_100NSEC_MULTI_TIMER_INV: Result:='PERF_100NSEC_MULTI_TIMER_INV';
  758.     PERF_RAW_FRACTION: Result:='PERF_RAW_FRACTION';
  759.     PERF_RAW_BASE: Result:='PERF_RAW_BASE';
  760.     PERF_ELAPSED_TIME: Result:='PERF_ELAPSED_TIME';
  761.     PERF_COUNTER_HISTOGRAM_TYPE: Result:='PERF_COUNTER_HISTOGRAM_TYPE';
  762.     PERF_COUNTER_DELTA: Result:='PERF_COUNTER_DELTA';
  763.     PERF_COUNTER_LARGE_DELTA: Result:='PERF_COUNTER_LARGE_DELTA';
  764.   end;
  765.  
  766.   if Result='' then
  767.     case CtrType of
  768.       PERF_TYPE_NUMBER :
  769.         case CtrSubType of
  770.           PERF_NUMBER_HEX: Result:='PERF_NUMBER_HEX';
  771.           PERF_NUMBER_DECIMAL: Result:='PERF_NUMBER_DEC';
  772.           PERF_NUMBER_DEC_1000: Result:='PERF_NUMBER_DEC1000';
  773.         end;
  774.       PERF_TYPE_COUNTER:
  775.         case CtrSubType of
  776.           PERF_COUNTER_VALUE: Result:='PERF_COUNTER_VALUE';
  777.           PERF_COUNTER_RATE : Result:='PERF_COUNTER_RATE';
  778.           PERF_COUNTER_FRACTION: Result:='PERF_COUNTER_FRACTION';
  779.           PERF_COUNTER_BASE: Result:='PERF_COUNTER_BASE';
  780.           PERF_COUNTER_ELAPSED: Result:='PERF_COUNTER_ELAPSED';
  781.           PERF_COUNTER_QUEUELEN: Result:='PERF_COUNTER_QUEUELEN';
  782.           PERF_COUNTER_HISTOGRAM: Result:='PERF_COUNTER_HISTOGRAM';
  783.         end;
  784.       PERF_TYPE_TEXT:
  785.         case CtrSubType of
  786.           PERF_TEXT_UNICODE: Result:='PERF_TEXT_UNICODE';
  787.           PERF_TEXT_ASCII: Result:='PERF_TEXT_ASCII';
  788.         end;
  789.       PERF_TYPE_ZERO: Result:='PERF_TYPE_ZERO';
  790.     end;
  791.   if Result='' then
  792.     Result:='0x'+IntToHex(AType,8);
  793. end;
  794.  
  795. function GetDetailLevelStr(ALevel: TDetailLevel): string;
  796. begin
  797.   case ALevel of
  798.     Novice: Result:='Novice';
  799.     Advanced: Result:='Advanced';
  800.     Expert: Result:='Expert';
  801.     Wizard: Result:='Wizard';
  802.   end;
  803. end;
  804.  
  805. { TPerfLibNT }
  806.  
  807. constructor TPerfLibNT.Create;
  808. begin
  809.   FCounters:=TStringList.Create;
  810.   FHelps:=TStringList.Create;
  811.   FObjects:=TStringList.Create;
  812.   FPerfData:=AllocMem(MaxWord);
  813. end;
  814.  
  815. destructor TPerfLibNT.Destroy;
  816. begin
  817.   while FCounters.Count>0 do begin
  818.     Freemem(PChar(FCounters.Objects[FCounters.Count-1]));
  819.     FCounters.Delete(FCounters.Count-1);
  820.   end;
  821.   while FHelps.Count>0 do begin
  822.     Freemem(PChar(FHelps.Objects[FHelps.Count-1]));
  823.     FHelps.Delete(FHelps.Count-1);
  824.   end;
  825.   while FObjects.Count>0 do begin
  826.     FObjects.Objects[FObjects.Count-1].Free;
  827.     FObjects.Delete(FObjects.Count-1);
  828.   end;
  829.   FCounters.Free;
  830.   FObjects.Free;
  831.   FHelps.Free;
  832.   FreeMem(FPerfData);
  833.   inherited;
  834. end;
  835.  
  836. function TPerfLibNT.GetIndexByName(AName: string): integer;
  837. begin
  838.   Result:=FObjects.IndexOf(AName);
  839. end;
  840.  
  841. procedure TPerfLibNT.GetNameStrings;
  842. var
  843.   hkPerfLib,
  844.   hkPerfLib009: HKEY;
  845.   dwBufferSize,
  846.   dwBuffer,
  847.   dwMaxValueLen: DWORD;
  848.   lpNameStrings: PChar;
  849.   p: integer;
  850.   szID,
  851.   szName: string;
  852. begin
  853.   while FCounters.Count>0 do begin
  854.     Freemem(PChar(FCounters.Objects[FCounters.Count-1]));
  855.     FCounters.Delete(FCounters.Count-1);
  856.   end;
  857.   while FHelps.Count>0 do begin
  858.     Freemem(PChar(FHelps.Objects[FHelps.Count-1]));
  859.     FHelps.Delete(FHelps.Count-1);
  860.   end;
  861.   RegOpenKeyEx(HKEY_LOCAL_MACHINE,rkPerfLib,0,KEY_READ,hkPerflib);
  862.   dwBufferSize:=sizeof(dwBuffer);
  863.   RegQueryValueEx(hkPerflib,rvLastCounter,nil,nil,PBYTE(@dwBuffer),@dwBufferSize);
  864.   RegCloseKey(hkPerflib);
  865.   RegOpenKeyEx(HKEY_LOCAL_MACHINE,rkPerfLib009,0,KEY_READ,hkPerflib009);
  866.   RegQueryInfoKey(hkPerflib009,nil,nil,nil,nil,nil,nil,nil,nil,@dwMaxValueLen,nil,nil);
  867.   dwBuffer:=dwMaxValueLen+1;
  868.   lpNameStrings:=AllocMem(dwBuffer*sizeof(char));
  869.  
  870.   RegQueryValueEx(hkPerflib009,rvCounter,nil,nil,PBYTE(lpNameStrings),@dwBuffer);
  871.   p:=0;
  872.   repeat
  873.     szID:=lpNameStrings+p;
  874.     Inc(p,Length(szID)+1);
  875.     szName:=lpNameStrings+p;
  876.     Inc(p,Length(szName)+1);
  877.     FCounters.AddObject(szName,TObject(StrToInt(szID)));
  878.   until lpNameStrings[p]=#0;
  879.  
  880.   RegQueryInfoKey(hkPerflib009,nil,nil,nil,nil,nil,nil,nil,nil,@dwMaxValueLen,nil,nil);
  881.   dwBuffer:=dwMaxValueLen+1;
  882.   ReallocMem(lpNameStrings,dwBuffer*sizeof(char));
  883.   RegQueryValueEx(hkPerflib009,rvHelp,nil,nil,PBYTE(lpNameStrings),@dwBuffer);
  884.  
  885.   p:=0;
  886.   repeat
  887.     szID:=lpNameStrings+p;
  888.     Inc(p,Length(szID)+1);
  889.     szName:=lpNameStrings+p;
  890.     Inc(p,Length(szName)+1);
  891.     FHelps.AddObject(szName,TObject(StrToInt(szID)));
  892.   until lpNameStrings[p]=#0;
  893.   FreeMem(lpNameStrings);
  894.   RegCloseKey(hkPerflib009);
  895. end;
  896.  
  897. function TPerfLibNT.GetObject(Index: integer): TPerfObject;
  898. begin
  899.   if Index<FObjects.Count then
  900.     Result:=TPerfObject(FObjects.Objects[Index])
  901.   else
  902.     Result:=nil;
  903. end;
  904.  
  905. function TPerfLibNT.GetObjectCount: integer;
  906. begin
  907.   Result:=FPerfData^.NumObjectTypes;
  908. end;
  909.  
  910. function TPerfLibNT.GetCounterData(ObjectIndex,
  911.   InstanceIndex, CounterIndex: DWORD): PChar;
  912. var
  913.   po: PPERF_OBJECT_TYPE;
  914.   pc: PPERF_COUNTER_DEFINITION;
  915.   pi: PPERF_INSTANCE_DEFINITION;
  916.   i: DWORD;
  917. begin
  918.   po:=FirstObject(FPerfData);
  919.   if ObjectIndex>0 then
  920.     for i:=0 to ObjectIndex-1 do
  921.       po:=NextObject(po);
  922.   pc:=FirstCounter(po);
  923.   if CounterIndex>0 then
  924.     for i:=0 to CounterIndex-1 do
  925.       pc:=NextCounter(pc);
  926.   if Integer(po^.NumInstances)>0 then begin
  927.     pi:=FirstInstance(po);
  928.     if InstanceIndex>0 then
  929.       for i:=0 to InstanceIndex-1 do
  930.         pi:=NextInstance(pi);
  931.     Result:=PChar(pi)+pi^.ByteLength+pc^.CounterOffset;
  932.   end else begin
  933.     Result:=PChar(po)+po^.DefinitionLength+pc^.CounterOffset;
  934.   end;
  935. end;
  936.  
  937. procedure TPerfLibNT.ReadObjects;
  938. var
  939.   PerfObj: PPERF_OBJECT_TYPE;
  940.   PO: TPerfObject;
  941.   i: integer;
  942. begin
  943.   while FObjects.Count>0 do begin
  944.     FObjects.Objects[FObjects.Count-1].Free;
  945.     FObjects.Delete(FObjects.Count-1);
  946.   end;
  947.   PerfObj:=FirstObject(FPerfData);
  948.   for i:=0 to FPerfData^.NumObjectTypes-1 do begin
  949.     PO:=TPerfObject.Create(FObjects.Count,Self,PerfObj);
  950.     FObjects.AddObject(PO.Name,PO);
  951.     PerfObj:=NextObject(PerfObj);
  952.   end;
  953. end;
  954.  
  955. procedure TPerfLibNT.Refresh;
  956. begin
  957.   GetNameStrings;
  958.   TakeSnapShot;
  959.   ReadObjects;
  960. end;
  961.  
  962. procedure TPerfLibNT.TakeSnapshot;
  963. var
  964.   BufferSize: DWORD;
  965. const
  966.   BYTEINCREMENT = 4096;
  967. begin
  968.   BufferSize:=MaxWord;
  969.   ReallocMem(FPerfData,BufferSize);
  970.   while RegQueryValueEx(HKEY_PERFORMANCE_DATA,rkGlobal,nil,nil,PBYTE(FPerfData),@BufferSize)=ERROR_MORE_DATA do begin
  971.     BufferSize:=BufferSize+BYTEINCREMENT;
  972.     ReallocMem(FPerfData,BufferSize);
  973.   end;
  974.   FPerfTime:=FPerfData^.PerfTime;
  975.   FPerfFreq:=FPerfData^.PerfFreq;
  976.   FPerfTime100nsec:=FPerfData^.PerfTime100nSec;
  977.   FVersion:=FPerfData^.Version;
  978.   FRevision:=FPerfData^.Revision;
  979. end;
  980.  
  981. { TPerfObject }
  982.  
  983. constructor TPerfObject.Create;
  984. var
  985.   PerfCntr: PPERF_COUNTER_DEFINITION;
  986.   //PtrToCntr: PPERF_COUNTER_BLOCK;
  987.   i :DWORD;
  988.   PC: TPerfCounter;
  989. begin
  990.   FPerfLib:=APerfLib;
  991.   FPerfObj:=APerfObj;
  992.   FIndex:=AIndex;
  993.   FName:=FPerfLib.Names[FPerfLib.Names.IndexOfObject(TObject(APerfObj^.ObjectNameTitleIndex))];
  994.   FDescription:=FPerfLib.Helps[FPerfLib.Helps.IndexOfObject(TObject(APerfObj^.ObjectHelpTitleIndex))];
  995.   FCodePage:=APerfObj^.CodePage;
  996.   FCounterCount:=APerfObj^.NumCounters;
  997.   FDefaultCounter:=APerfObj^.DefaultCounter;
  998.   FPerfTime:=APerfObj^.PerfTime;
  999.   FPerfFreq:=APerfObj^.PerfFreq;
  1000.   case APerfObj^.DetailLevel of
  1001.     PERF_DETAIL_NOVICE: FDetailLevel:=Novice;
  1002.     PERF_DETAIL_ADVANCED: FDetailLevel:=Advanced;
  1003.     PERF_DETAIL_EXPERT: FDetailLevel:=Expert;
  1004.     PERF_DETAIL_WIZARD: FDetailLevel:=Wizard;
  1005.   end;
  1006.   FCounters:=TStringList.Create;
  1007.  
  1008.   PerfCntr:=FirstCounter(APerfObj);
  1009.   //PtrToCntr:=PPERF_COUNTER_BLOCK(PChar(APerfObj)+APerfObj^.DefinitionLength);
  1010.   for i:=0 to CounterCount-1 do begin
  1011.     PC:=TPerfCounter.Create(FCounters.Count,Self,PerfCntr);
  1012.     FCounters.AddObject(PC.Name,PC);
  1013.     PerfCntr:=NextCounter(PerfCntr);
  1014.   end;
  1015. end;
  1016.  
  1017. destructor TPerfObject.Destroy;
  1018. begin
  1019.   while FCounters.Count>0 do begin
  1020.     FCounters.Objects[FCounters.Count-1].Free;
  1021.     FCounters.Delete(FCounters.Count-1);
  1022.   end;
  1023.   FCounters.Free;
  1024.   inherited;
  1025. end;
  1026.  
  1027. function TPerfObject.GetCounter(Index: integer): TPerfCounter;
  1028. begin
  1029.   if Index<FCounters.Count then
  1030.     Result:=TPerfCounter(FCounters.Objects[Index])
  1031.   else
  1032.     Result:=nil;
  1033. end;
  1034.  
  1035. function TPerfObject.GetCntrIndexByName(AName: string): integer;
  1036. begin
  1037.   Result:=FCounters.IndexOf(AName);
  1038. end;
  1039.  
  1040. function TPerfObject.GetInstance(Index: integer): TPerfInstance;
  1041. var
  1042.   pi: PPERF_INSTANCE_DEFINITION;
  1043.   i: integer;
  1044. begin
  1045.   if Index<InstanceCount then begin
  1046.     pi:=FirstInstance(FPerfObj);
  1047.     if Index>0 then
  1048.       for i:=0 to Index-1 do
  1049.         pi:=NextInstance(pi);
  1050.     Result.Name:='';
  1051.     Result.Index:=Index;
  1052.     for i:=0 to pi^.NameLength-1 do
  1053.       if PChar(pi)[pi^.NameOffset+i]<>#0 then
  1054.         Result.Name:=Result.Name+PChar(pi)[pi^.NameOffset+i];
  1055.     Result.ID:=pi^.UniqueID;
  1056.   end;
  1057. end;
  1058.  
  1059. {function TPerfObject.GetInstIndexByID(AID: DWORD): integer;
  1060. var
  1061.   i: integer;
  1062. begin
  1063.   Result:=-1;
  1064. end;
  1065.  
  1066. function TPerfObject.GetInstIndexByName(AName: string): integer;
  1067. begin
  1068.   Result:=-1;
  1069. end;}
  1070.  
  1071. function TPerfObject.GetInstanceCount: integer;
  1072. var
  1073.   po: PPERF_OBJECT_TYPE;
  1074.   i: integer;
  1075. begin
  1076.   po:=FirstObject(FPerfLib.FPerfData);
  1077.   if Index>0 then
  1078.     for i:=0 to Index-1 do
  1079.       po:=NextObject(po);
  1080.   Result:=po^.NumInstances;
  1081. end;
  1082.  
  1083. { TPerfCounter }
  1084.  
  1085.  
  1086. constructor TPerfCounter.Create;
  1087. var
  1088.   idx: integer;
  1089. begin
  1090.   FPerfObject:=APerfObject;
  1091.   FIndex:=AIndex;
  1092.   idx:=FPerfObject.PerfLib.Names.IndexOfObject(TObject(APerfCntr^.CounterNameTitleIndex));
  1093.   if idx>-1 then
  1094.     FName:=FPerfObject.PerfLib.Names[idx]
  1095.   else
  1096.     FName:=SNoname;
  1097.   idx:=FPerfObject.PerfLib.Helps.IndexOfObject(TObject(APerfCntr^.CounterHelpTitleIndex));
  1098.   if idx>-1 then
  1099.     FDescription:=FPerfObject.PerfLib.Helps[idx]
  1100.   else
  1101.     FDescription:='';
  1102.   FCounterOffset:=APerfCntr^.CounterOffset;
  1103.   FDefaultScale:=APerfCntr^.DefaultScale;
  1104.   FCounterSize:=APerfCntr^.CounterSize;
  1105.   FCounterType:=APerfCntr^.CounterType;
  1106.   case APerfCntr^.DetailLevel of
  1107.     PERF_DETAIL_NOVICE: FDetailLevel:=Novice;
  1108.     PERF_DETAIL_ADVANCED: FDetailLevel:=Advanced;
  1109.     PERF_DETAIL_EXPERT: FDetailLevel:=Expert;
  1110.     PERF_DETAIL_WIZARD: FDetailLevel:=Wizard;
  1111.   end;
  1112. end;
  1113.  
  1114. destructor TPerfCounter.Destroy;
  1115. begin
  1116.  
  1117.   inherited;
  1118. end;
  1119.  
  1120. function TPerfCounter.GetData;
  1121. begin
  1122.   result:=FPerfObject.PerfLib.GetCounterData(FPerfObject.Index,InstanceIndex,Self.Index);
  1123. end;
  1124.  
  1125. function TPerfCounter.GetDataStr;
  1126. begin
  1127.   Result:=FormatData(CounterType,CounterSize,False,Data[InstanceIndex]);
  1128. end;
  1129.  
  1130. function TPerfCounter.GetDataStrEx;
  1131. begin
  1132.   Result:=FormatData(CounterType,CounterSize,True,Data[InstanceIndex]);
  1133. end;
  1134.  
  1135. end.
  1136.