Hello, I'm an academic student from Brazil, and I have a project of updating and porting to Linux an application called YANA(Yet Another Network Analyzer). You can find it on the following link: http://sourceforge.net/projects/yana/.
The latest version was written using Lazarus 0.9.22 and seemingly Free Pascal 2.0.4(I'm not entirely sure of it), which was back in 2007. Since then, much has changed in these two tools, and many things need to be reworked on YANA. But the first problem is that I can't even compile the code provided by the author, because it uses Kylix compatibility-only units for Linux, libc and kernelioctl, and it relies on a specific dll of Windows, IP Helper DLL. Therefore, this fact locks the software to Windows and Linux running on a i386 platform. I successfully compiled and ran all the utility modules that composes it as separate programs, but when they are put together with a particular unit, which I will send as an attachment to this e-mail, the whole process broke down in others platforms. My intent is to remove this dependency and make the software more cross-platform possible, but I actually have no clue about how to do it, so please: can any of you help me by telling the first steps which I must take, the beginning is hard, but once the flow is established, the outcome will be a natural consequence of it. Thank you in advance for any help.
{TODO : remove Windows dll dependency - currently it may work only under Win32 } {TODO : redo string grid lines append - scrolls to top on timer} {TODO : Datagrams Discarded (Out) } {TODO : Forward Policy } {TODO : Age (sec) } {TODO : Adapters info tab; Description } {TODO : change adapters inormation: +DescriptionÄ™ +Ip AddressÄ™ +WINS +Secondary WINS Server.} {TODO : Change interface informationas as follows: Index of Interface - Shows the index that identifies the interface. Type of Interface - Shows the type of interface. Max Transmission Unit - Shows the Maximum Transmission Unit (MTU). Speed of Interface - Shows the speed of the interface in bits per second. Physical Address of Adapter - Shows the length of the physical address. Administrative Status - Shows whether the interface is administratively enabled or disabled. Operational Status - Shows the operational status of the interface. The following values are available: NON_OPERATIONAL, UNREACHABLE, DISCONNECTED, CONNECTING, CONNECTED, OPERATIONAL. Bytes Received - Shows the number of octets of data received through this interface. +Unicast Packets Received - Shows the number of unicast packets received through this interface. +Non Unicast Packets Received- Shows the number of non-unicast packets received through this interface. Broadcast and multicast packets are included. +Received packets discarded - Shows the number of incoming packets that were discarded even though they did not have errors. +Erroneous packets received - Shows the number of incoming packets that were discarded because of errors. +Unknown Protocol packets received - Shows the number of incoming packets that were discarded because the protocol was unknown. Bytes Sent - - Shows the number of octets of data sent through this interface. +Unicast Packets sent - Shows the number of unicast packets sent through this interface. +Non Unicast Packets sent - Shows the number of non-unicast packets sent through this interface. Broadcast and multicast packets are included. +Outgoing packets discarded - Shows the number of outgoing packets that were discarded even though they did not have errors. +Erroneous packets sent - Shows the number of outgoing packets that were discarded because of errors. +Output Queue Length - Shows the output queue length. } (* ========================== Delphi IPHelper functions ========================== Required OS : NT4/SP4 or higher, WIN98/WIN98se Developed on: D6 Ent. & Prof. Tested on : WIN-NT4/SP6, WIN98se, WIN95/OSR1 : WIN98, W2K-SP2, 3, 4 : W2K, W2K prof, W2K server Warning - currently only supports Delphi 5 and later unless int64 is removed (Int64 is only used to force Format to show unsigned 32-bit numbers) ================================================================ This software is FREEWARE ------------------------- If this software works, it was surely written by Dirk Claessens dirkcl@@pandora.be (If it doesn't, I don't know anything about it.) ================================================================ List of Fixes & Additions v1.1 dirkcl ----- Fix : wrong errorcode reported in GetNetworkParams() Fix : RTTI MaxHops 20 > 128 Add : ICMP -statistics Add : Well-Known port numbers Add : RecentIP list Add : Timer update v1.2 dirkcl ---- Fix : Recent IP's correct update ADD : ICMP-error codes translated v1.3 - 18th September 2001 ---- Angus Robertson, Magenta Systems Ltd, England delphi@@magsys.co.uk, http://www.magsys.co.uk/delphi/ Slowly converting procs into functions that can be used by other programs, ie Get_ becomes IpHlp Primary improvements are that current DNS server is now shown, also in/out bytes for each interface (aka adaptor) All functions are dynamically loaded so program can be used on W95/NT4 Tested with Delphi 6 on Windows 2000 and XP v1.4 - 28th February 2002 - Angus ---- Fixed major memory leak in IpHlpIfTable (except instead of finally) Fixed major memory leak in Get_AdaptersInfo (incremented buffer pointer) Created IpHlpAdaptersInfo which returns TAdaptorRows Note: IpHlpNetworkParams returns dynamic DNS address (and other stuff) Note: IpHlpIfEntry returns bytes in/out for a network adaptor v1.5 - 5th October 2003 ---- Jean-Pierre Turchi "From South of France" <jpturchi@@mageos.com> Cosmetic (more readable) and add-in's from iana.org in "WellKnownPorts" v1.6 - 1st April 2007 ---- Sergei Kostigoff <sergei@@kostigoff.net> Minor cosmetics Output results to string grids v1.7 - 12th May 2007 ---- Sergei Kostigoff <sergei@@kostigoff.net> Proto type strings moved to RFC1213ip unit IPForwTypes strings moved to RFC1213ip unit (and renamed to sIpRouteTypeString) ARPEntryType strings moved to RFC1213ip unit (and renamed to... *) { @abstract(@bold(uIpHelper); no forms. IP helper functions) @br Original source has been written by Dirk Claessens <dirkcl@@pandora.be>. @br Original license message is as follows: @preformatted( ========================== Delphi IPHelper functions ========================== Required OS : NT4/SP4 or higher, WIN98/WIN98se Developed on: D6 Ent. & Prof. Tested on : WIN-NT4/SP6, WIN98se, WIN95/OSR1 : WIN98, W2K-SP2, 3, 4 : W2K, W2K prof, W2K server Warning - currently only supports Delphi 5 and later unless int64 is removed (Int64 is only used to force Format to show unsigned 32-bit numbers) ================================================================ This software is FREEWARE ------------------------- If this software works, it was surely written by Dirk Claessens dirkcl@@pandora.be (If it doesn't, I don't know anything about it.) ================================================================ ) Miscellaneous IP functions collection. } unit uIpHelper; {$H+} {$IFDEF FPC} {$mode Delphi} {$ENDIF} interface uses {$IFDEF LINUX} Libc, Types, KernelIoctl, {$ELSE} Windows, Classes, {$ENDIF} SysUtils, Grids, rfc1213const, rfc1213if, rfc1213ip, rfc1213tcp, uYanaUtil, uIpHlpApi; // replace or remove on beta stage!!! var { List of recent IP addresses} RecentIPs : TStringList; //------conversion of well-known port numbers to service names---------------- type { well known port record structure } TWellKnownPort = record Prt: DWORD; Srv: string[15]; end; const // Only most "popular" services. Names and descriptions given // as per http://www.iana.org/assignments/port-numbers WellKnownPorts: array[1..37] of TWellKnownPort = ( // ( Prt: 0; Srv: 'RESRVED' ), { Reserved } ( Prt: 7; Srv: 'echo' ), { Ping } ( Prt: 9; Srv: 'discard' ), { Discard } ( Prt: 11; Srv: 'systat' ), { Active Users } ( Prt: 13; Srv: 'daytime' ), { Daytime (RFC 867) } ( Prt: 17; Srv: 'qotd' ), { Quote of the Day } ( Prt: 19; Srv: 'chargen' ), { Character Generator } ( Prt: 20; Srv: 'ftp-data' ), { File Transfer [Default Data] } ( Prt: 21; Srv: 'ftp' ), { File Transfer [Control] } ( Prt: 22; Srv: 'ssh' ), { SSH Remote Login Protocol } ( Prt: 23; Srv: 'telnet' ), { Telnet } ( Prt: 25; Srv: 'smtp' ), { Simple Mail Transfer } ( Prt: 37; Srv: 'time' ), { Time } ( Prt: 43; Srv: 'nicname' ), { Who Is } ( Prt: 53; Srv: 'domain' ), { Domain Name Server } ( Prt: 67; Srv: 'bootps' ), { Bootstrap Protocol Server } ( Prt: 68; Srv: 'bootpc' ), { Bootstrap Protocol Client } ( Prt: 69; Srv: 'tftp' ), { Trivial File Transfer } ( Prt: 70; Srv: 'gopher' ), { Gopher } ( Prt: 79; Srv: 'finger' ), { Finger } ( Prt: 80; Srv: 'http' ), { World Wide Web HTTP } ( Prt: 88; Srv: 'kerberos' ), { Kerberos } ( Prt: 109; Srv: 'pop2' ), { Post Office Protocol - Version 2 } ( Prt: 110; Srv: 'pop3' ), { Post Office Protocol - Version 3 } ( Prt: 111; Srv: 'sunrpc' ), { SUN Remote Procedure Call } ( Prt: 119; Srv: 'nntp' ), { Network News Transfer Protocol } ( Prt: 123; Srv: 'ntp' ), { Network Time protocol } ( Prt: 135; Srv: 'epmap' ), { DCE endpoint resolution; NETBIOS RPC } ( Prt: 137; Srv: 'netbios-ns' ), { NETBIOS Name Service } ( Prt: 138; Srv: 'netbios-dgm' ), { NETBIOS Datagram Service } ( Prt: 139; Srv: 'netbios-ssn' ), { NETBIOS Session Service } ( Prt: 143; Srv: 'imap' ), { Internet Message Access Protocol } ( Prt: 161; Srv: 'snmp' ), { SNMP } ( Prt: 169; Srv: 'send' ), { SEND } ( Prt: 179; Srv: 'bgp' ), { Border Gateway Protocol } ( Prt: 515; Srv: 'printer' ), { spooler } ( Prt: 4000; Srv: 'terabase' ), { Terabase; also used by ICQ} ( Prt: 8080; Srv: 'http-alt' ) { HTTP Alternate (see port 80) } ); //-----------conversion of ICMP error codes to strings-------------------------- {taken from www.sockets.com/ms_icmp.c } const { offset of ICMP error (@link(IcmpErr))} ICMP_ERROR_BASE = 11000; { ICMP error strings array } IcmpErr : array[1..22] of string = ('IP_BUFFER_TOO_SMALL','IP_DEST_NET_UNREACHABLE', 'IP_DEST_HOST_UNREACHABLE', 'IP_PROTOCOL_UNREACHABLE', 'IP_DEST_PORT_UNREACHABLE', 'IP_NO_RESOURCES', 'IP_BAD_OPTION','IP_HARDWARE_ERROR', 'IP_PACKET_TOO_BIG', 'IP_REQUEST_TIMED_OUT', 'IP_BAD_REQUEST','IP_BAD_ROUTE', 'IP_TTL_EXPIRED_TRANSIT', 'IP_TTL_EXPIRED_REASSEM','IP_PARAMETER_PROBLEM', 'IP_SOURCE_QUENCH', 'IP_OPTION_TOO_BIG', 'IP_BAD_DESTINATION','IP_ADDRESS_DELETED', 'IP_SPEC_MTU_CHANGE', 'IP_MTU_CHANGE', 'IP_UNLOAD' ); type // for IpHlpNetworkParams TNetworkParams = record HostName: string ; DomainName: string ; CurrentDnsServer: string ; DnsServerTot: integer ; DnsServerNames: array [0..9] of string ; NodeType: UINT; ScopeID: string ; EnableRouting: UINT; EnableProxy: UINT; EnableDNS: UINT; end; // dynamic array of rows TIfRows = array of TMibIfRow ; // for IpHlpAdaptersInfo TAdaptorInfo = record AdapterName: string ; Description: string ; MacAddress: string ; Index: DWORD; aType: UINT; DHCPEnabled: UINT; CurrIPAddress: string ; CurrIPMask: string ; IPAddressTot: integer ; IPAddressList: array of string ; IPMaskList: array of string ; GatewayTot: integer ; GatewayList: array of string ; DHCPTot: integer ; DHCPServer: array of string ; HaveWINS: BOOL; PrimWINSTot: integer ; PrimWINSServer: array of string ; SecWINSTot: integer ; SecWINSServer: array of string ; LeaseObtained: LongInt ; // UNIX time, seconds since 1970 LeaseExpires: LongInt; // UNIX time, seconds since 1970 end ; // dynamic array of records TAdaptorRows = array of TAdaptorInfo ; //---------------exported stuff----------------------------------------------- { Info on installed adapters } function IpHlpAdaptersInfo(var AdpTot: integer;var AdpRows: TAdaptorRows): integer ; {} procedure Get_AdaptersInfo( List: TStrings ); {} function IpHlpNetworkParams (var NetworkParams: TNetworkParams): integer ; {} procedure Get_NetworkParams( List: TStrings ); {} procedure Get_ARPTable( List: TStrings ); {} procedure Get_TCPTable( List: TStrings ); {} procedure Get_TCPStatistics( List: TStrings ); {} function IpHlpTCPStatistics (var TCPStats: TMibTCPStats): integer ; {} procedure Get_UDPTable( List: TStrings ); {} procedure Get_UDPStatistics( List: TStrings ); {} function IpHlpUdpStatistics (UdpStats: TMibUDPStats): integer ; {} procedure Get_IPAddrTable( List: TStrings ); {} procedure Get_IPForwardTable( List: TStrings ); {} procedure Get_IPStatistics( List: TStrings ); {} function IpHlpIPStatistics (var IPStats: TMibIPStats): integer ; {} function Get_RTTAndHopCount( IPAddr: DWORD; MaxHops: Longint; var RTT: longint; var HopCount: longint ): integer; {} procedure Get_ICMPStats( ICMPIn, ICMPOut: TStrings ); { include bytes in/out for each adaptor } function IpHlpIfTable(var IfTot: integer; var IfRows: TIfRows): integer ; { get interface table to TStrings } procedure Get_IfTable( List: TStrings ); {} function IpHlpIfEntry(Index: integer; var IfRow: TMibIfRow): integer ; {} procedure Get_RecentDestIPs( List: TStrings ); // string grid interface {} procedure DoNetworkParams(sg : TStringGrid); {} procedure DoArpTable(sg : TStringGrid); {} procedure DoTcpTable(sg: TStringGrid); {} procedure DoUdpTable(sg : TStringGrid); {} procedure DoTCPStatistics(sg : TStringGrid); {} procedure DoICMPInputStatistics( sg : TStringGrid ); {} procedure DoIcmpOutputStatistics(sg : TStringGrid); {} procedure DoUdpStatistics(sg : TStringGrid); {} procedure DoIpStatistics(sg : TStringGrid); {} procedure DoIPAddrTable(sg : TStringGrid); { fill ip forward string grid } procedure DoIPForwardTable(sg : TStringGrid); { fill adapaters info string grid } procedure DoAdaptersInfo(sg: TStringGrid); { fill interfaces table string grid } procedure DoIfTable(sg: TStringGrid); // conversion utils { converts numerical MAC-address to ww-xx-yy-zz string } function MacAddr2Str( MacAddr: TMacAddress; size: integer ): string; { converts IP-address in network byte order DWORD to dotted decimal string} function IpAddr2Str( IPAddr: DWORD ): string; { converts dotted decimal IP-address to network byte order DWORD} function Str2IpAddr( IPStr: string ): DWORD; { converts port number in network byte order to string } function Port2Str( nwoPort: DWORD ): string; { converts port number in network byte order to DWORD } function Port2Wrd( nwoPort: DWORD ): DWORD; { converts well-known port numbers to service ID } function Port2Svc( Port: DWORD ): string; { conversion of ICMP error codes to strings } function ICMPErr2Str( ICMPErrCode: DWORD) : string; implementation //--------------General utilities----------------------------------------------- { extracts next "token" from string, then eats string } function NextToken( var s: string; Separator: char ): string; var Sep_Pos: integer; begin Result := ''; if length( s ) > 0 then begin Sep_Pos := pos( Separator, s ); if Sep_Pos > 0 then begin Result := copy( s, 1, Pred( Sep_Pos ) ); Delete( s, 1, Sep_Pos ); end else begin Result := s; s := ''; end; end; end; //------------------------------------------------------------------------------ { concerts numerical MAC-address to ww-xx-yy-zz string } function MacAddr2Str( MacAddr: TMacAddress; size: integer ): string; var i : integer; begin if Size = 0 then begin Result := '00-00-00-00-00-00'; EXIT; end else Result := ''; // for i := 1 to Size do Result := Result + IntToHex( MacAddr[i], 2 ) + '-'; Delete( Result, Length( Result ), 1 ); end; //------------------------------------------------------------------------------ { converts IP-address in network byte order DWORD to dotted decimal string} function IpAddr2Str( IPAddr: DWORD ): string; var i : integer; begin Result := ''; for i := 1 to 4 do begin Result := Result + Format( '%d.', [IPAddr and $FF] ); IPAddr := IPAddr shr 8; end; Delete( Result, Length( Result ), 1 ); end; //------------------------------------------------------------------------------ { converts dotted decimal IP-address to network byte order DWORD} function Str2IpAddr( IPStr: string ): DWORD; var i : integer; Num : DWORD; begin Result := 0; for i := 1 to 4 do try Num := ( StrToInt( NextToken( IPStr, '.' ) ) ) shl 24; Result := ( Result shr 8 ) or Num; except Result := 0; end; end; //------------------------------------------------------------------------------ { converts port number in network byte order to DWORD } function Port2Wrd( nwoPort: DWORD ): DWORD; begin Result := Swap( WORD( nwoPort ) ); end; //------------------------------------------------------------------------------ { converts port number in network byte order to string } function Port2Str( nwoPort: DWORD ): string; begin Result := IntToStr( Port2Wrd( nwoPort ) ); end; //------------------------------------------------------------------------------ { converts well-known port numbers to service ID } function Port2Svc( Port: DWORD ): string; var i : integer; begin // Result := Format( '%4d', [Port] ); // in case port not found Result := IntToStr(Port); // svk for i := Low( WellKnownPorts ) to High( WellKnownPorts ) do if Port = WellKnownPorts[i].Prt then begin { svk } Result := Result +': ' + WellKnownPorts[i].Srv; BREAK; end; end; //----------------------------------------------------------------------------- { general, fixed network parameters } procedure Get_NetworkParams( List: TStrings ); var NetworkParams: TNetworkParams ; I, ErrorCode: integer ; begin if not Assigned( List ) then EXIT; List.Clear; ErrorCode := IpHlpNetworkParams (NetworkParams) ; if ErrorCode <> 0 then begin List.Add (SysErrorMessage (ErrorCode)); exit; end; with NetworkParams do begin List.Add( 'HOSTNAME : ' + HostName ); List.Add( 'DOMAIN : ' + DomainName ); List.Add( 'NETBIOS NODE TYPE : ' + NETBIOSTypes[NodeType] ); List.Add( 'DHCP SCOPE : ' + ScopeID ); List.Add( 'ROUTING ENABLED : ' + IntToStr( EnableRouting ) ); List.Add( 'PROXY ENABLED : ' + IntToStr( EnableProxy ) ); List.Add( 'DNS ENABLED : ' + IntToStr( EnableDNS ) ); if DnsServerTot <> 0 then begin for I := 0 to Pred (DnsServerTot) do List.Add( 'DNS SERVER ADDR : ' + DnsServerNames [I] ) ; end; // if end; // with end ; //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// function IpHlpNetworkParams (var NetworkParams: TNetworkParams): integer ; var FixedInfo : PTFixedInfo; // Angus InfoSize : Longint; PDnsServer : PTIP_ADDR_STRING ; // Angus begin InfoSize := 0 ; // Angus result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; result := GetNetworkParams( Nil, @InfoSize ); // Angus if result <> ERROR_BUFFER_OVERFLOW then exit ; // Angus GetMem (FixedInfo, InfoSize) ; // Angus try result := GetNetworkParams( FixedInfo, @InfoSize ); // Angus if result <> ERROR_SUCCESS then exit ; NetworkParams.DnsServerTot := 0 ; with FixedInfo^ do begin NetworkParams.HostName := trim (HostName) ; NetworkParams.DomainName := trim (DomainName) ; NetworkParams.ScopeId := trim (ScopeID) ; NetworkParams.NodeType := NodeType ; NetworkParams.EnableRouting := EnableRouting ; NetworkParams.EnableProxy := EnableProxy ; NetworkParams.EnableDNS := EnableDNS ; NetworkParams.DnsServerNames [0] := DNSServerList.IPAddress ; // Angus if NetworkParams.DnsServerNames [0] <> '' then NetworkParams.DnsServerTot := 1 ; PDnsServer := DnsServerList.Next; while PDnsServer <> Nil do begin NetworkParams.DnsServerNames [NetworkParams.DnsServerTot] := PDnsServer^.IPAddress ; // Angus inc (NetworkParams.DnsServerTot) ; if NetworkParams.DnsServerTot >= Length (NetworkParams.DnsServerNames) then exit ; PDnsServer := PDnsServer.Next ; end; end ; finally FreeMem (FixedInfo) ; // Angus end ; end; //------------------------------------------------------------------------------ function ICMPErr2Str( ICMPErrCode: DWORD) : string; begin Result := 'Unknown Error : ' + IntToStr( ICMPErrCode ); dec( ICMPErrCode, ICMP_ERROR_BASE ); if ICMPErrCode in [Low(ICMpErr)..High(ICMPErr)] then Result := ICMPErr[ ICMPErrCode]; end; //------------------------------------------------------------------------------ // include bytes in/out for each adaptor function IpHlpIfTable(var IfTot: integer; var IfRows: TIfRows): integer ; var I, TableSize : integer; pBuf, pNext : PChar; begin result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; SetLength (IfRows, 0) ; IfTot := 0 ; // Angus TableSize := 0; // first call: get memsize needed result := GetIfTable (Nil, @TableSize, false) ; // Angus if result <> ERROR_INSUFFICIENT_BUFFER then exit ; GetMem( pBuf, TableSize ); try FillChar (pBuf^, TableSize, #0); // clear buffer, since W98 does not // get table pointer result := GetIfTable (PTMibIfTable (pBuf), @TableSize, false) ; if result <> NO_ERROR then exit ; IfTot := PTMibIfTable (pBuf)^.dwNumEntries ; if IfTot = 0 then exit ; SetLength (IfRows, IfTot) ; pNext := pBuf + SizeOf(IfTot) ; for i := 0 to Pred (IfTot) do begin IfRows [i] := PTMibIfRow (pNext )^ ; inc (pNext, SizeOf (TMibIfRow)) ; end; finally FreeMem (pBuf) ; end ; end; procedure Get_IfTable( List: TStrings ); var IfRows : TIfRows ; Error, I : integer; NumEntries : integer; sDescr, sIfName: string ; begin if not Assigned( List ) then EXIT; List.Clear; SetLength (IfRows, 0) ; Error := IpHlpIfTable (NumEntries, IfRows) ; if (Error <> 0) then List.Add( SysErrorMessage( GetLastError ) ) else if NumEntries = 0 then List.Add( 'no entries.' ) else begin for I := 0 to Pred (NumEntries) do begin with IfRows [I] do begin if wszName [1] = #0 then sIfName := '' else sIfName := WideCharToString (@wszName) ; // convert Unicode to string sIfName := trim (sIfName) ; sDescr := bDescr ; sDescr := trim (sDescr); List.Add (Format ( '%0.8x |%3d | %16s |%8d |%12d |%2d |%2d |%10d |%10d | %-s| %-s', [dwIndex, dwType, MacAddr2Str( TMacAddress( bPhysAddr ), dwPhysAddrLen ), dwMTU, dwSpeed, dwAdminStatus, dwOPerStatus, Int64 (dwInOctets), Int64 (dwOutOctets), // counters are 32-bit sIfName, sDescr] ) // Angus, added in/out ); end; end ; end ; SetLength (IfRows, 0) ; // free memory end ; function IpHlpIfEntry(Index: integer; var IfRow: TMibIfRow): integer ; begin result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; FillChar (IfRow, SizeOf (TMibIfRow), #0); // clear buffer, since W98 does not IfRow.dwIndex := Index ; result := GetIfEntry (@IfRow) ; end ; //----------------------------------------------------------------------------- { Info on installed adapters } function IpHlpAdaptersInfo(var AdpTot: integer; var AdpRows: TAdaptorRows): integer ; var BufLen : DWORD; AdapterInfo : PTIP_ADAPTER_INFO; PIpAddr : PTIP_ADDR_STRING; PBuf : PCHAR ; I : integer ; begin SetLength (AdpRows, 4) ; AdpTot := 0 ; BufLen := 0 ; result := GetAdaptersInfo( Nil, @BufLen ); if (result <> ERROR_INSUFFICIENT_BUFFER) and (result = NO_ERROR) then exit ; GetMem( pBuf, BufLen ); try FillChar (pBuf^, BufLen, #0); // clear buffer result := GetAdaptersInfo( PTIP_ADAPTER_INFO (PBuf), @BufLen ); if result = NO_ERROR then begin AdapterInfo := PTIP_ADAPTER_INFO (PBuf) ; while ( AdapterInfo <> nil ) do begin AdpRows [AdpTot].IPAddressTot := 0 ; SetLength (AdpRows [AdpTot].IPAddressList, 2) ; SetLength (AdpRows [AdpTot].IPMaskList, 2) ; AdpRows [AdpTot].GatewayTot := 0 ; SetLength (AdpRows [AdpTot].GatewayList, 2) ; AdpRows [AdpTot].DHCPTot := 0 ; SetLength (AdpRows [AdpTot].DHCPServer, 2) ; AdpRows [AdpTot].PrimWINSTot := 0 ; SetLength (AdpRows [AdpTot].PrimWINSServer, 2) ; AdpRows [AdpTot].SecWINSTot := 0 ; SetLength (AdpRows [AdpTot].SecWINSServer, 2) ; AdpRows [AdpTot].CurrIPAddress := NULL_IP; AdpRows [AdpTot].CurrIPMask := NULL_IP; AdpRows [AdpTot].AdapterName := Trim( string( AdapterInfo^.AdapterName ) ); AdpRows [AdpTot].Description := Trim( string( AdapterInfo^.Description ) ); AdpRows [AdpTot].MacAddress := MacAddr2Str( TMacAddress( AdapterInfo^.Address ), AdapterInfo^.AddressLength ) ; AdpRows [AdpTot].Index := AdapterInfo^.Index ; AdpRows [AdpTot].aType := AdapterInfo^.aType ; AdpRows [AdpTot].DHCPEnabled := AdapterInfo^.DHCPEnabled ; if AdapterInfo^.CurrentIPAddress <> Nil then begin AdpRows [AdpTot].CurrIPAddress := AdapterInfo^.CurrentIPAddress.IpAddress ; AdpRows [AdpTot].CurrIPMask := AdapterInfo^.CurrentIPAddress.IpMask ; end ; // get list of IP addresses and masks for IPAddressList I := 0 ; PIpAddr := @AdapterInfo^.IPAddressList ; while (PIpAddr <> Nil) do begin AdpRows [AdpTot].IPAddressList [I] := PIpAddr.IpAddress ; AdpRows [AdpTot].IPMaskList [I] := PIpAddr.IpMask ; PIpAddr := PIpAddr.Next ; inc (I) ; if Length (AdpRows [AdpTot].IPAddressList) <= I then begin SetLength (AdpRows [AdpTot].IPAddressList, I * 2) ; SetLength (AdpRows [AdpTot].IPMaskList, I * 2) ; end ; end ; AdpRows [AdpTot].IPAddressTot := I ; // get list of IP addresses for GatewayList I := 0 ; PIpAddr := @AdapterInfo^.GatewayList ; while (PIpAddr <> Nil) do begin AdpRows [AdpTot].GatewayList [I] := PIpAddr.IpAddress ; PIpAddr := PIpAddr.Next ; inc (I) ; if Length (AdpRows [AdpTot].GatewayList) <= I then SetLength (AdpRows [AdpTot].GatewayList, I * 2) ; end ; AdpRows [AdpTot].GatewayTot := I ; // get list of IP addresses for GatewayList I := 0 ; PIpAddr := @AdapterInfo^.DHCPServer ; while (PIpAddr <> Nil) do begin AdpRows [AdpTot].DHCPServer [I] := PIpAddr.IpAddress ; PIpAddr := PIpAddr.Next ; inc (I) ; if Length (AdpRows [AdpTot].DHCPServer) <= I then SetLength (AdpRows [AdpTot].DHCPServer, I * 2) ; end ; AdpRows [AdpTot].DHCPTot := I ; // get list of IP addresses for PrimaryWINSServer I := 0 ; PIpAddr := @AdapterInfo^.PrimaryWINSServer ; while (PIpAddr <> Nil) do begin AdpRows [AdpTot].PrimWINSServer [I] := PIpAddr.IpAddress ; PIpAddr := PIpAddr.Next ; inc (I) ; if Length (AdpRows [AdpTot].PrimWINSServer) <= I then SetLength (AdpRows [AdpTot].PrimWINSServer, I * 2) ; end ; AdpRows [AdpTot].PrimWINSTot := I ; // get list of IP addresses for SecondaryWINSServer I := 0 ; PIpAddr := @AdapterInfo^.SecondaryWINSServer ; while (PIpAddr <> Nil) do begin AdpRows [AdpTot].SecWINSServer [I] := PIpAddr.IpAddress ; PIpAddr := PIpAddr.Next ; inc (I) ; if Length (AdpRows [AdpTot].SecWINSServer) <= I then SetLength (AdpRows [AdpTot].SecWINSServer, I * 2) ; end ; AdpRows [AdpTot].SecWINSTot := I ; AdpRows [AdpTot].LeaseObtained := AdapterInfo^.LeaseObtained ; AdpRows [AdpTot].LeaseExpires := AdapterInfo^.LeaseExpires ; inc (AdpTot) ; if Length (AdpRows) <= AdpTot then SetLength (AdpRows, AdpTot * 2) ; // more memory AdapterInfo := AdapterInfo^.Next; end ; SetLength (AdpRows, AdpTot) ; end ; finally FreeMem( pBuf ); end ; end ; procedure Get_AdaptersInfo( List: TStrings ); var AdpTot: integer; AdpRows: TAdaptorRows ; Error: DWORD ; I: integer ; //J: integer ; jpt - see below //S: string ; id. begin if not Assigned( List ) then EXIT; List.Clear; SetLength (AdpRows, 0) ; AdpTot := 0 ; Error := IpHlpAdaptersInfo(AdpTot, AdpRows) ; if (Error <> 0) then List.Add( SysErrorMessage( GetLastError ) ) else if AdpTot = 0 then List.Add( 'no entries.' ) else begin for I := 0 to Pred (AdpTot) do begin with AdpRows [I] do begin //List.Add(AdapterName + '|' + Description ); // jpt : not useful List.Add( Format('%8.8x | %6s | %16s | %2d | %16s | %16s | %16s', [Index, ifTypeStr[aType], MacAddress, DHCPEnabled, GatewayList [0], DHCPServer [0], PrimWINSServer [0]] ) ); {if IPAddressTot <> 0 then // jpt : not useful begin S := '' ; for J := 0 to Pred (IPAddressTot) do S := S + IPAddressList [J] + '/' + IPMaskList [J] + ' | ' ; List.Add(IntToStr (IPAddressTot) + ' IP Addresse(s): ' + S); end ; List.Add( ' ' ); } end ; end ; end ; SetLength (AdpRows, 0) ; end ; //----------------------------------------------------------------------------- { get round trip time and hopcount to indicated IP } function Get_RTTAndHopCount( IPAddr: DWORD; MaxHops: Longint; var RTT: Longint; var HopCount: Longint ): integer; begin if not GetRTTAndHopCount( IPAddr, @HopCount, MaxHops, @RTT ) then begin Result := GetLastError; RTT := -1; // Destination unreachable, BAD_HOST_NAME,etc... HopCount := -1; end else Result := NO_ERROR; end; //----------------------------------------------------------------------------- { ARP-table lists relations between remote IP and remote MAC-address. NOTE: these are cached entries ;when there is no more network traffic to a node, entry is deleted after a few minutes. } procedure Get_ARPTable( List: TStrings ); var IPNetRow : TMibIPNetRow; TableSize : DWORD; NumEntries : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; begin if not Assigned( List ) then EXIT; List.Clear; // first call: get table length TableSize := 0; ErrorCode := GetIPNetTable( Nil, @TableSize, false ); // Angus // if ErrorCode = ERROR_NO_DATA then begin List.Add( ' ARP-cache empty.' ); EXIT; end; // get table GetMem( pBuf, TableSize ); NumEntries := 0 ; try ErrorCode := GetIpNetTable( PTMIBIPNetTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBIPNetTable( pBuf )^.dwNumEntries; if NumEntries > 0 then // paranoia striking, but you never know... begin inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin IPNetRow := PTMIBIPNetRow( PBuf )^; with IPNetRow do List.Add( Format( '%8x | %12s | %16s | %10s', [dwIndex, MacAddr2Str( bPhysAddr, dwPhysAddrLen ), IPAddr2Str( dwAddr ), sipNetToMediaTypeString[dwType] ])); inc( pBuf, SizeOf( IPNetRow ) ); end; end else List.Add( ' ARP-cache empty.' ); end else List.Add( SysErrorMessage( ErrorCode ) ); // we _must_ restore pointer! finally dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( IPNetRow ) ); FreeMem( pBuf ); end ; end; //------------------------------------------------------------------------------ procedure Get_TCPTable( List: TStrings ); var TCPRow : TMIBTCPRow; i, NumEntries : integer; TableSize : DWORD; ErrorCode : DWORD; DestIP : string; pBuf : PChar; begin if not Assigned( List ) then EXIT; List.Clear; RecentIPs.Clear; // first call : get size of table TableSize := 0; NumEntries := 0 ; ErrorCode := GetTCPTable(Nil, @TableSize, false ); // Angus if Errorcode <> ERROR_INSUFFICIENT_BUFFER then EXIT; // get required memory size, call again GetMem( pBuf, TableSize ); // get table ErrorCode := GetTCPTable( PTMIBTCPTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBTCPTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin TCPRow := PTMIBTCPRow( pBuf )^; // get next record with TCPRow do begin if dwRemoteAddr = 0 then dwRemotePort := 0; DestIP := IPAddr2Str( dwRemoteAddr ); List.Add( Format( '%15s : %-7s | %15s : %-7s | %-16s', [IpAddr2Str( dwLocalAddr ), Port2Svc( Port2Wrd( dwLocalPort ) ), DestIP, Port2Svc( Port2Wrd( dwRemotePort ) ), stcpConnStateString[dwState] ] ) ); // if (not ( dwRemoteAddr = 0 )) and ( RecentIps.IndexOf(DestIP) = -1 ) then RecentIPs.Add( DestIP ); end; inc( pBuf, SizeOf( TMIBTCPRow ) ); end; end; end else List.Add( SyserrorMessage( ErrorCode ) ); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibTCPRow ) ); FreeMem( pBuf ); end; //------------------------------------------------------------------------------ procedure Get_TCPStatistics( List: TStrings ); var TCPStats : TMibTCPStats; ErrorCode : DWORD; begin if not Assigned( List ) then EXIT; List.Clear; if NOT LoadIpHlp then exit ; ErrorCode := GetTCPStatistics( @TCPStats ); if ErrorCode = NO_ERROR then with TCPStats do begin List.Add( 'Retransmission algorithm : ' + sTcpRtoAlgorithmString[dwRTOAlgorithm] ); List.Add( 'Minimum Timeout : ' + IntToStr( dwRTOMin ) + ' ms' ); List.Add( 'Maximum Timeout : ' + IntToStr( dwRTOMax ) + ' ms' ); List.Add( 'Maximum Pend.Connections : ' + IntToStr( dwRTOAlgorithm ) ); List.Add( 'Active Opens : ' + IntToStr( dwActiveOpens ) ); List.Add( 'Passive Opens : ' + IntToStr( dwPassiveOpens ) ); List.Add( 'Failed Open Attempts : ' + IntToStr( dwAttemptFails ) ); List.Add( 'Established conn. Reset : ' + IntToStr( dwEstabResets ) ); List.Add( 'Current Established Conn.: ' + IntToStr( dwCurrEstab ) ); List.Add( 'Segments Received : ' + IntToStr( dwInSegs ) ); List.Add( 'Segments Sent : ' + IntToStr( dwOutSegs ) ); List.Add( 'Segments Retransmitted : ' + IntToStr( dwReTransSegs ) ); List.Add( 'Incoming Errors : ' + IntToStr( dwInErrs ) ); List.Add( 'Outgoing Resets : ' + IntToStr( dwOutRsts ) ); List.Add( 'Cumulative Connections : ' + IntToStr( dwNumConns ) ); end else List.Add( SyserrorMessage( ErrorCode ) ); end; function IpHlpTCPStatistics (var TCPStats: TMibTCPStats): integer ; begin result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; result := GetTCPStatistics( @TCPStats ); end; //------------------------------------------------------------------------------ procedure Get_UDPTable( List: TStrings ); var UDPRow : TMIBUDPRow; i, NumEntries : integer; TableSize : DWORD; ErrorCode : DWORD; pBuf : PChar; begin if not Assigned( List ) then EXIT; List.Clear; // first call : get size of table TableSize := 0; NumEntries := 0 ; ErrorCode := GetUDPTable(Nil, @TableSize, false ); if Errorcode <> ERROR_INSUFFICIENT_BUFFER then EXIT; // get required size of memory, call again GetMem( pBuf, TableSize ); // get table ErrorCode := GetUDPTable( PTMIBUDPTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBUDPTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin UDPRow := PTMIBUDPRow( pBuf )^; // get next record with UDPRow do List.Add( Format( '%15s : %-6s', [IpAddr2Str( dwLocalAddr ), Port2Svc( Port2Wrd( dwLocalPort ) ) ] ) ); inc( pBuf, SizeOf( TMIBUDPRow ) ); end; end else List.Add( 'no entries.' ); end else List.Add( SyserrorMessage( ErrorCode ) ); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibUDPRow ) ); FreeMem( pBuf ); end; //------------------------------------------------------------------------------ procedure Get_IPAddrTable( List: TStrings ); var IPAddrRow : TMibIPAddrRow; TableSize : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; NumEntries : DWORD; begin if not Assigned( List ) then EXIT; List.Clear; TableSize := 0; ; NumEntries := 0 ; // first call: get table length ErrorCode := GetIpAddrTable(Nil, @TableSize, true ); // Angus if Errorcode <> ERROR_INSUFFICIENT_BUFFER then EXIT; GetMem( pBuf, TableSize ); // get table ErrorCode := GetIpAddrTable( PTMibIPAddrTable( pBuf ), @TableSize, true ); if ErrorCode = NO_ERROR then begin NumEntries := PTMibIPAddrTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); for i := 1 to NumEntries do begin IPAddrRow := PTMIBIPAddrRow( pBuf )^; with IPAddrRow do List.Add( Format( '%8.8x | %15s | %15s | %15s | %8.8d', [dwIndex, IPAddr2Str( dwAddr ), IPAddr2Str( dwMask ), IPAddr2Str( dwBCastAddr ), dwReasmSize ] ) ); inc( pBuf, SizeOf( TMIBIPAddrRow ) ); end; end else List.Add( 'no entries.' ); end else List.Add( SysErrorMessage( ErrorCode ) ); // we must restore pointer! dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( IPAddrRow ) ); FreeMem( pBuf ); end; //----------------------------------------------------------------------------- { gets entries in routing table; equivalent to "Route Print" } procedure Get_IPForwardTable( List: TStrings ); var IPForwRow : TMibIPForwardRow; TableSize : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; NumEntries : DWORD; begin if not Assigned( List ) then EXIT; List.Clear; TableSize := 0; // first call: get table length NumEntries := 0 ; ErrorCode := GetIpForwardTable(Nil, @TableSize, true); if Errorcode <> ERROR_INSUFFICIENT_BUFFER then EXIT; // get table GetMem( pBuf, TableSize ); ErrorCode := GetIpForwardTable( PTMibIPForwardTable( pBuf ), @TableSize, true); if ErrorCode = NO_ERROR then begin NumEntries := PTMibIPForwardTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); for i := 1 to NumEntries do begin IPForwRow := PTMibIPForwardRow( pBuf )^; with IPForwRow do begin if (dwForwardType < 1) or (dwForwardType > 4) then dwForwardType := 1 ; // Angus, allow for bad value List.Add( Format( '%15s | %15s | %15s | %8.8x | %7s | %5.5d | %7s | %2.2d', [IPAddr2Str( dwForwardDest ), IPAddr2Str( dwForwardMask ), IPAddr2Str( dwForwardNextHop ), dwForwardIFIndex, sIpRouteTypeString[dwForwardType], dwForwardNextHopAS, sIpRouteProtoString[dwForwardProto], dwForwardMetric1 ] ) ); end ; inc( pBuf, SizeOf( TMibIPForwardRow ) ); end; end else List.Add( 'no entries.' ); end else List.Add( SysErrorMessage( ErrorCode ) ); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibIPForwardRow ) ); FreeMem( pBuf ); end; //------------------------------------------------------------------------------ procedure Get_IPStatistics( List: TStrings ); var IPStats : TMibIPStats; ErrorCode : integer; begin if not Assigned( List ) then EXIT; if NOT LoadIpHlp then exit ; ErrorCode := GetIPStatistics( @IPStats ); if ErrorCode = NO_ERROR then begin List.Clear; with IPStats do begin if dwForwarding = 1 then List.add( 'Forwarding Enabled : ' + 'Yes' ) else List.add( 'Forwarding Enabled : ' + 'No' ); List.add( 'Default TTL : ' + inttostr( dwDefaultTTL ) ); List.add( 'Datagrams Received : ' + inttostr( dwInReceives ) ); List.add( 'Header Errors (In) : ' + inttostr( dwInHdrErrors ) ); List.add( 'Address Errors (In) : ' + inttostr( dwInAddrErrors ) ); List.add( 'Datagrams Forwarded : ' + inttostr( dwForwDatagrams ) ); // Angus List.add( 'Unknown Protocols (In) : ' + inttostr( dwInUnknownProtos ) ); List.add( 'Datagrams Discarded : ' + inttostr( dwInDiscards ) ); List.add( 'Datagrams Delivered : ' + inttostr( dwInDelivers ) ); List.add( 'Requests Out : ' + inttostr( dwOutRequests ) ); List.add( 'Routings Discarded : ' + inttostr( dwRoutingDiscards ) ); List.add( 'No Routes (Out) : ' + inttostr( dwOutNoRoutes ) ); List.add( 'Reassemble TimeOuts : ' + inttostr( dwReasmTimeOut ) ); List.add( 'Reassemble Requests : ' + inttostr( dwReasmReqds ) ); List.add( 'Succesfull Reassemblies : ' + inttostr( dwReasmOKs ) ); List.add( 'Failed Reassemblies : ' + inttostr( dwReasmFails ) ); List.add( 'Succesful Fragmentations: ' + inttostr( dwFragOKs ) ); List.add( 'Failed Fragmentations : ' + inttostr( dwFragFails ) ); List.add( 'Datagrams Fragmented : ' + inttostr( dwFRagCreates ) ); List.add( 'Number of Interfaces : ' + inttostr( dwNumIf ) ); List.add( 'Number of IP-addresses : ' + inttostr( dwNumAddr ) ); List.add( 'Routes in RoutingTable : ' + inttostr( dwNumRoutes ) ); end; end else List.Add( SysErrorMessage( ErrorCode ) ); end; function IpHlpIPStatistics (var IPStats: TMibIPStats): integer ; // Angus begin result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; result := GetIPStatistics( @IPStats ); end ; //------------------------------------------------------------------------------ procedure Get_UdpStatistics( List: TStrings ); var UdpStats : TMibUDPStats; ErrorCode : integer; begin if not Assigned( List ) then EXIT; ErrorCode := GetUDPStatistics( @UdpStats ); if ErrorCode = NO_ERROR then begin List.Clear; with UDPStats do begin List.add( 'Datagrams (In) : ' + inttostr( dwInDatagrams ) ); List.add( 'Datagrams (Out) : ' + inttostr( dwOutDatagrams ) ); List.add( 'No Ports : ' + inttostr( dwNoPorts ) ); List.add( 'Errors (In) : ' + inttostr( dwInErrors ) ); List.add( 'UDP Listen Ports : ' + inttostr( dwNumAddrs ) ); end; end else List.Add( SysErrorMessage( ErrorCode ) ); end; //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *// function IpHlpUdpStatistics (UdpStats: TMibUDPStats): integer ; // Angus begin result := ERROR_NOT_SUPPORTED ; if NOT LoadIpHlp then exit ; result := GetUDPStatistics (@UdpStats) ; end ; //------------------------------------------------------------------------------ procedure Get_ICMPStats( ICMPIn, ICMPOut: TStrings ); var ErrorCode : DWORD; ICMPStats : PTMibICMPInfo; begin if ( ICMPIn = nil ) or ( ICMPOut = nil ) then EXIT; ICMPIn.Clear; ICMPOut.Clear; New( ICMPStats ); ErrorCode := GetICMPStatistics( ICMPStats ); if ErrorCode = NO_ERROR then begin with ICMPStats.InStats do begin ICMPIn.Add( 'Messages received : ' + IntToStr( dwMsgs ) ); ICMPIn.Add( 'Errors : ' + IntToStr( dwErrors ) ); ICMPIn.Add( 'Dest. Unreachable : ' + IntToStr( dwDestUnreachs ) ); ICMPIn.Add( 'Time Exceeded : ' + IntToStr( dwTimeEcxcds ) ); ICMPIn.Add( 'Param. Problems : ' + IntToStr( dwParmProbs ) ); ICMPIn.Add( 'Source Quench : ' + IntToStr( dwSrcQuenchs ) ); ICMPIn.Add( 'Redirects : ' + IntToStr( dwRedirects ) ); ICMPIn.Add( 'Echo Requests : ' + IntToStr( dwEchos ) ); ICMPIn.Add( 'Echo Replies : ' + IntToStr( dwEchoReps ) ); ICMPIn.Add( 'Timestamp Requests : ' + IntToStr( dwTimeStamps ) ); ICMPIn.Add( 'Timestamp Replies : ' + IntToStr( dwTimeStampReps ) ); ICMPIn.Add( 'Addr. Masks Requests : ' + IntToStr( dwAddrMasks ) ); ICMPIn.Add( 'Addr. Mask Replies : ' + IntToStr( dwAddrReps ) ); end; // with ICMPStats.OutStats do begin ICMPOut.Add( 'Messages sent : ' + IntToStr( dwMsgs ) ); ICMPOut.Add( 'Errors : ' + IntToStr( dwErrors ) ); ICMPOut.Add( 'Dest. Unreachable : ' + IntToStr( dwDestUnreachs ) ); ICMPOut.Add( 'Time Exceeded : ' + IntToStr( dwTimeEcxcds ) ); ICMPOut.Add( 'Param. Problems : ' + IntToStr( dwParmProbs ) ); ICMPOut.Add( 'Source Quench : ' + IntToStr( dwSrcQuenchs ) ); ICMPOut.Add( 'Redirects : ' + IntToStr( dwRedirects ) ); ICMPOut.Add( 'Echo Requests : ' + IntToStr( dwEchos ) ); ICMPOut.Add( 'Echo Replies : ' + IntToStr( dwEchoReps ) ); ICMPOut.Add( 'Timestamp Requests : ' + IntToStr( dwTimeStamps ) ); ICMPOut.Add( 'Timestamp Replies : ' + IntToStr( dwTimeStampReps ) ); ICMPOut.Add( 'Addr. Masks Requests : ' + IntToStr( dwAddrMasks ) ); ICMPOut.Add( 'Addr. Mask Replies : ' + IntToStr( dwAddrReps ) ); end; end else IcmpIn.Add( SysErrorMessage( ErrorCode ) ); Dispose( ICMPStats ); end; //------------------------------------------------------------------------------ procedure Get_RecentDestIPs( List: TStrings ); begin if Assigned( List ) then List.Assign( RecentIPs ) end; //-------------------------------- procedure DoNetworkParams(sg : TStringGrid); var NetworkParams : TNetworkParams; i, ErrorCode : integer; //******************************* procedure AppendRow(const Parameter, Value : string); var RowIdx: integer; begin with sg do begin RowIdx := RowCount-1; Cells[0,RowIdx] := Parameter; Cells[1,RowIdx] := Value; RowCount := RowCount + 1; end; end; //******************************* begin if not Assigned(sg) then exit; sg.RowCount := 2; ErrorCode := IpHlpNetworkParams (NetworkParams) ; if ErrorCode <> 0 then begin AppendRow('Error', SysErrorMessage (ErrorCode)); exit; end ; with NetworkParams do begin AppendRow('Host name',HostName); AppendRow('Domain name',DomainName); AppendRow('NETBIOS node type', NETBIOSTypes[NodeType]); AppendRow('DHCP scope', ScopeID); AppendRow('Routing enabled', IntToStr(EnableRouting)); AppendRow('Proxy enabled', IntToStr(EnableProxy)); AppendRow('DNS enabled', IntToStr(EnableDNS)); if DnsServerTot <> 0 then begin for i:= 0 to Pred (DnsServerTot) do begin AppendRow('DNS server address', DnsServerNames[I]); end; end; // if DnsServerTot <> 0 end; end; //----------------- procedure DoArpTable(sg : TStringGrid); var IPNetRow : TMibIPNetRow; TableSize : DWORD; NumEntries : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; //************************************* procedure AppendRow(AdapterIndex, RemoteMAC, RemoteIp, ArpType : string); var RowIdx: integer; begin with sg do begin RowIdx := RowCount-1; Cells[0,RowIdx] := AdapterIndex; Cells[1,RowIdx] := RemoteMAC; Cells[2,RowIdx] := RemoteIp; Cells[3,RowIdx] := ArpType; RowCount := RowCount + 1; end; end; //************************************* begin if not Assigned(sg) then exit; sg.RowCount := 2; // first call: get table length TableSize := 0; ErrorCode := GetIPNetTable( Nil, @TableSize, false ); // Angus // if ErrorCode = ERROR_NO_DATA then begin AppendRow('ARP-cache empty.','','','' ); exit; end; // get table GetMem( pBuf, TableSize ); NumEntries := 0 ; try ErrorCode := GetIpNetTable( PTMIBIPNetTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBIPNetTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin // paranoia striking, but you never know... inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin IPNetRow := PTMIBIPNetRow( PBuf )^; with IPNetRow do AppendRow(HexLS(dwIndex), MacAddr2Str( bPhysAddr, dwPhysAddrLen ), IPAddr2Str( dwAddr ), sipNetToMediaTypeString[dwType]); inc( pBuf, SizeOf( IPNetRow ) ); end; // for end else // if NumEntries > 0 AppendRow('ARP-cache empty.','','','' ); end else // if ErrorCode = NO_ERROR AppendRow('Error', SysErrorMessage( ErrorCode ), '',''); // we _must_ restore pointer! finally dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( IPNetRow ) ); FreeMem( pBuf ); end ; end; //------------------------ procedure DoTcpTable(sg: TStringGrid); var TCPRow : TMIBTCPRow; i,NumEntries : integer; TableSize : DWORD; ErrorCode : DWORD; DestIP : string; pBuf : PChar; //************************************************ procedure AppendRow(LocalIP, LocalPort, RemoteIP, RemotePort, State : string); begin sg.Cells[0,sg.RowCount-1] := LocalIp; sg.Cells[1,sg.RowCount-1] := LocalPort; sg.Cells[2,sg.RowCount-1] := RemoteIp; sg.Cells[3,sg.RowCount-1] := RemotePort; sg.Cells[4,sg.RowCount-1] := State; sg.RowCount := sg.RowCount + 1; end; //************************************************ begin if not Assigned(sg) then exit; sg.RowCount := 2; RecentIPs.Clear; // first call : get size of table TableSize := 0; NumEntries := 0 ; ErrorCode := GetTCPTable(Nil, @TableSize, false ); // Angus if Errorcode <> ERROR_INSUFFICIENT_BUFFER then exit; // get required memory size, call again GetMem( pBuf, TableSize ); // get table ErrorCode := GetTCPTable( PTMIBTCPTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBTCPTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin TCPRow := PTMIBTCPRow( pBuf )^; // get next record with TCPRow do begin if dwRemoteAddr = 0 then dwRemotePort := 0; DestIP := IPAddr2Str( dwRemoteAddr ); AppendRow( IpAddr2Str( dwLocalAddr ), Port2Svc( Port2Wrd( dwLocalPort ) ), DestIP, Port2Svc( Port2Wrd( dwRemotePort ) ), stcpConnStateString[dwState] ); // if (not ( dwRemoteAddr = 0 )) and ( RecentIps.IndexOf(DestIP) = -1 ) then RecentIPs.Add( DestIP ); end; // with TCPRow inc( pBuf, SizeOf( TMIBTCPRow ) ); end; end; end else AppendRow('Error', SyserrorMessage( ErrorCode ), '','','' ); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibTCPRow ) ); FreeMem( pBuf ); end; //---------------------------- procedure DoUdpTable(sg : TStringGrid); var UDPRow : TMIBUDPRow; i,NumEntries : integer; TableSize : DWORD; ErrorCode : DWORD; pBuf : PChar; //************************************************ procedure AppendRow(LocalIp, Port : string); begin sg.Cells[0,sg.RowCount-1] := LocalIp; sg.Cells[1,sg.RowCount-1] := Port; sg.RowCount := sg.RowCount + 1; end; //************************************************ begin if not Assigned(sg) then exit; sg.RowCount := 2; // first call : get size of table TableSize := 0; NumEntries := 0 ; ErrorCode := GetUDPTable(Nil, @TableSize, false ); if Errorcode <> ERROR_INSUFFICIENT_BUFFER then exit; // get required size of memory, call again GetMem( pBuf, TableSize ); // get table ErrorCode := GetUDPTable( PTMIBUDPTable( pBuf ), @TableSize, false ); if ErrorCode = NO_ERROR then begin NumEntries := PTMIBUDPTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); // get past table size for i := 1 to NumEntries do begin UDPRow := PTMIBUDPRow( pBuf )^; // get next record with UDPRow do AppendRow(IpAddr2Str( dwLocalAddr ), Port2Svc( Port2Wrd( dwLocalPort ) )); inc( pBuf, SizeOf( TMIBUDPRow ) ); end; end else AppendRow('no entries.', '' ); end else AppendRow('Error', SyserrorMessage( ErrorCode )); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibUDPRow ) ); FreeMem( pBuf ); end; //------------------------------------- procedure DoTCPStatistics(sg : TStringGrid); var TCPStats : TMibTCPStats; ErrorCode : DWORD; //================= procedure AppendRow(Parameter, Value: string); begin sg.Cells[0,sg.RowCount-1] := Parameter; sg.Cells[1,sg.RowCount-1] := Value; sg.RowCount := sg.RowCount + 1; end; //================= begin if not Assigned(sg) then exit; sg.RowCount := 2; if NOT LoadIpHlp then exit; ErrorCode := GetTCPStatistics( @TCPStats ); if ErrorCode = NO_ERROR then with TCPStats do begin AppendRow('Retransmission algorithm', sTcpRtoAlgorithmString[dwRTOAlgorithm] ); AppendRow('Minimum Timeout', IntToStr( dwRTOMin ) + ' ms' ); AppendRow('Maximum Timeout', IntToStr( dwRTOMax ) + ' ms' ); AppendRow('Maximum Pending Connections', IntToStr( dwRTOAlgorithm ) ); AppendRow('Active Opens', IntToStr( dwActiveOpens ) ); AppendRow('Passive Opens', IntToStr( dwPassiveOpens ) ); AppendRow('Failed Open Attempts', IntToStr( dwAttemptFails ) ); AppendRow('Established connections Reset', IntToStr( dwEstabResets ) ); AppendRow('Current Established Connections', IntToStr( dwCurrEstab ) ); AppendRow('Segments Received', IntToStr( dwInSegs ) ); AppendRow('Segments Sent', IntToStr( dwOutSegs ) ); AppendRow('Segments Retransmitted', IntToStr( dwReTransSegs ) ); AppendRow('Incoming Errors', IntToStr( dwInErrs ) ); AppendRow('Outgoing Resets', IntToStr( dwOutRsts ) ); AppendRow('Cumulative Connections', IntToStr( dwNumConns ) ); end else AppendRow('Error', SyserrorMessage( ErrorCode )); end; //--------------------------------------- procedure DoICMPInputStatistics( sg : TStringGrid ); var ErrorCode : DWORD; ICMPStats : PTMibICMPInfo; //================= procedure AppendRow(Parameter, Value: string); begin sg.Cells[0,sg.RowCount-1] := Parameter; sg.Cells[1,sg.RowCount-1] := Value; sg.RowCount := sg.RowCount + 1; end; //================= begin if not Assigned(sg) then exit; sg.RowCount := 2; New( ICMPStats ); ErrorCode := GetICMPStatistics( ICMPStats ); if ErrorCode = NO_ERROR then begin with ICMPStats.InStats do begin AppendRow('Messages received', IntToStr( dwMsgs ) ); AppendRow('Errors', IntToStr( dwErrors ) ); AppendRow('Destination Unreachable', IntToStr( dwDestUnreachs ) ); AppendRow('Time Exceeded', IntToStr( dwTimeEcxcds ) ); AppendRow('Parameter Problems', IntToStr( dwParmProbs ) ); AppendRow('Source Quench', IntToStr( dwSrcQuenchs ) ); AppendRow('Redirects', IntToStr( dwRedirects ) ); AppendRow('Echo Requests', IntToStr( dwEchos ) ); AppendRow('Echo Replies', IntToStr( dwEchoReps ) ); AppendRow('Timestamp Requests', IntToStr( dwTimeStamps ) ); AppendRow('Timestamp Replies', IntToStr( dwTimeStampReps ) ); AppendRow('Address Masks Requests', IntToStr( dwAddrMasks ) ); AppendRow('Address Mask Replies', IntToStr( dwAddrReps ) ); end; end else AppendRow('Error', SysErrorMessage( ErrorCode )); Dispose( ICMPStats ); end; //------------------------------------------------- procedure DoIcmpOutputStatistics(sg : TStringGrid); var ErrorCode : DWORD; ICMPStats : PTMibICMPInfo; //================= procedure AppendRow(Parameter, Value: string); begin sg.Cells[0,sg.RowCount-1] := Parameter; sg.Cells[1,sg.RowCount-1] := Value; sg.RowCount := sg.RowCount + 1; end; //================= begin if not Assigned(sg) then exit; sg.RowCount := 2; New( ICMPStats ); ErrorCode := GetICMPStatistics( ICMPStats ); if ErrorCode = NO_ERROR then begin with ICMPStats.OutStats do begin AppendRow('Messages sent', IntToStr( dwMsgs ) ); AppendRow('Errors', IntToStr( dwErrors ) ); AppendRow('Destination Unreachable', IntToStr( dwDestUnreachs ) ); AppendRow('Time Exceeded', IntToStr( dwTimeEcxcds ) ); AppendRow('Parameter Problems', IntToStr( dwParmProbs ) ); AppendRow('Source Quench', IntToStr( dwSrcQuenchs ) ); AppendRow('Redirects', IntToStr( dwRedirects ) ); AppendRow('Echo Requests', IntToStr( dwEchos ) ); AppendRow('Echo Replies', IntToStr( dwEchoReps ) ); AppendRow('Timestamp Requests', IntToStr( dwTimeStamps ) ); AppendRow('Timestamp Replies', IntToStr( dwTimeStampReps ) ); AppendRow('Address Masks Requests', IntToStr( dwAddrMasks ) ); AppendRow('Address Mask Replies', IntToStr( dwAddrReps ) ); end; end else AppendRow('Error', SysErrorMessage( ErrorCode )); Dispose( ICMPStats ); end; {-- procedure DoIcmpOutput} //------------------------------------------------------------------------------ procedure DoUdpStatistics(sg : TStringGrid); var UdpStats : TMibUDPStats; ErrorCode : integer; //================= procedure AppendRow(Parameter, Value : string); begin sg.Cells[0,sg.RowCount-1] := Parameter; sg.Cells[1,sg.RowCount-1] := Value; sg.RowCount := sg.RowCount + 1; end; //================= begin if not Assigned(sg) then exit; sg.RowCount := 2; ErrorCode := GetUDPStatistics( @UdpStats ); if ErrorCode = NO_ERROR then begin with UDPStats do begin AppendRow('Datagrams (In)', inttostr( dwInDatagrams ) ); AppendRow('Datagrams (Out)', inttostr( dwOutDatagrams ) ); AppendRow('No Ports', inttostr( dwNoPorts ) ); AppendRow('Errors (In)', inttostr( dwInErrors ) ); AppendRow('UDP Listen Ports', inttostr( dwNumAddrs ) ); end; end else AppendRow('Error', SysErrorMessage( ErrorCode )); end; //--------------------------------------------------- procedure DoIpStatistics(sg : TStringGrid); var IPStats : TMibIPStats; ErrorCode : integer; //================= procedure AppendRow(Parameter, Value : string); begin sg.Cells[0,sg.RowCount-1] := Parameter; sg.Cells[1,sg.RowCount-1] := Value; sg.RowCount := sg.RowCount + 1; end; //================= begin if not Assigned(sg) then exit; if NOT LoadIpHlp then exit; sg.RowCount := 2; ErrorCode := GetIPStatistics( @IPStats ); if ErrorCode = NO_ERROR then begin with IPStats do begin if dwForwarding = 1 then AppendRow('Forwarding Enabled', 'Yes' ) else AppendRow('Forwarding Enabled', 'No' ); AppendRow('Default TTL', inttostr( dwDefaultTTL ) ); AppendRow('Datagrams Received', inttostr( dwInReceives ) ); AppendRow('Header Errors (In)', inttostr( dwInHdrErrors ) ); AppendRow('Address Errors (In)', inttostr( dwInAddrErrors ) ); AppendRow('Datagrams Forwarded', inttostr( dwForwDatagrams ) ); // Angus AppendRow('Unknown Protocols (In)', inttostr( dwInUnknownProtos ) ); AppendRow('Datagrams Discarded', inttostr( dwInDiscards ) ); AppendRow('Datagrams Delivered', inttostr( dwInDelivers ) ); AppendRow('Requests Out', inttostr( dwOutRequests ) ); AppendRow('Routings Discarded', inttostr( dwRoutingDiscards ) ); AppendRow('No Routes (Out)', inttostr( dwOutNoRoutes ) ); AppendRow('Reassemble TimeOuts', inttostr( dwReasmTimeOut ) ); AppendRow('Reassemble Requests', inttostr( dwReasmReqds ) ); AppendRow('Successfull Reassemblies', inttostr( dwReasmOKs ) ); AppendRow('Failed Reassemblies', inttostr( dwReasmFails ) ); AppendRow('Successful Fragmentations', inttostr( dwFragOKs ) ); AppendRow('Failed Fragmentations', inttostr( dwFragFails ) ); AppendRow('Datagrams Fragmented', inttostr( dwFRagCreates ) ); AppendRow('Number of Interfaces', inttostr( dwNumIf ) ); AppendRow('Number of IP-addresses', inttostr( dwNumAddr ) ); AppendRow('Routes in Routing Table', inttostr( dwNumRoutes ) ); end; end else AppendRow('Error', SysErrorMessage( ErrorCode )); end; //------------------------------------------------------------------------------ procedure DoIPAddrTable(sg : TStringGrid); var IPAddrRow : TMibIPAddrRow; TableSize : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; NumEntries : DWORD; //*********************************** procedure AppendRow(const index,ip,subnet,broadcast,reasm: string); begin sg.Cells[0,sg.RowCount-1] := index; sg.Cells[1,sg.RowCount-1] := ip; sg.Cells[2,sg.RowCount-1] := subnet; sg.Cells[3,sg.RowCount-1] := broadcast; sg.Cells[4,sg.RowCount-1] := reasm; sg.RowCount := sg.RowCount + 1; end; //*********************************** begin if not Assigned(sg) then exit; sg.RowCount := 2; TableSize := 0; ; NumEntries := 0 ; // first call: get table length ErrorCode := GetIpAddrTable(Nil, @TableSize, true ); // Angus if Errorcode <> ERROR_INSUFFICIENT_BUFFER then exit; GetMem( pBuf, TableSize ); // get table ErrorCode := GetIpAddrTable( PTMibIPAddrTable( pBuf ), @TableSize, true ); if ErrorCode = NO_ERROR then begin NumEntries := PTMibIPAddrTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); for i := 1 to NumEntries do begin IPAddrRow := PTMIBIPAddrRow( pBuf )^; with IPAddrRow do AppendRow( HexLS(dwIndex), IPAddr2Str( dwAddr ), IPAddr2Str( dwMask ), IPAddr2Str( dwBCastAddr ), IntToStr(dwReasmSize)); inc( pBuf, SizeOf( TMIBIPAddrRow ) ); end; end else AppendRow('no entries.','','','','' ); end else AppendRow('Error', SysErrorMessage( ErrorCode ),'','',''); // we must restore pointer! dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( IPAddrRow ) ); FreeMem( pBuf ); end; //----------------------------------------------------------------------------- { gets entries in routing table; equivalent to "Route Print" } procedure DoIPForwardTable(sg : TStringGrid); var IPForwRow : TMibIPForwardRow; TableSize : DWORD; ErrorCode : DWORD; i : integer; pBuf : PChar; NumEntries : DWORD; //*********************************** procedure AppendRow(const fw_dest_ip,fw_mask,ip_next_hop,if_index, fw_type,next_as_nr,fw_proto,fw_metric : string); begin sg.Cells[0,sg.RowCount-1] := fw_dest_ip; sg.Cells[1,sg.RowCount-1] := fw_mask; sg.Cells[2,sg.RowCount-1] := ip_next_hop; sg.Cells[3,sg.RowCount-1] := if_index; sg.Cells[4,sg.RowCount-1] := fw_type; sg.Cells[5,sg.RowCount-1] := next_as_nr; sg.Cells[6,sg.RowCount-1] := fw_proto; sg.Cells[7,sg.RowCount-1] := fw_metric; sg.RowCount := sg.RowCount + 1; end; //*********************************** begin if not Assigned(sg) then exit; sg.RowCount := 2; TableSize := 0; // first call: get table length NumEntries := 0 ; ErrorCode := GetIpForwardTable(Nil, @TableSize, true); if Errorcode <> ERROR_INSUFFICIENT_BUFFER then exit; // get table GetMem( pBuf, TableSize ); ErrorCode := GetIpForwardTable( PTMibIPForwardTable( pBuf ), @TableSize, true); if ErrorCode = NO_ERROR then begin NumEntries := PTMibIPForwardTable( pBuf )^.dwNumEntries; if NumEntries > 0 then begin inc( pBuf, SizeOf( DWORD ) ); for i := 1 to NumEntries do begin IPForwRow := PTMibIPForwardRow( pBuf )^; with IPForwRow do begin if (dwForwardType < 1) or (dwForwardType > 4) then dwForwardType := 1 ; // Angus, allow for bad value AppendRow( IPAddr2Str( dwForwardDest ), IPAddr2Str( dwForwardMask ), IPAddr2Str( dwForwardNextHop ), HexLS(dwForwardIFIndex), sIpRouteTypeString[dwForwardType], IntToStr(dwForwardNextHopAS), sIpRouteProtoString[dwForwardProto], IntToStr(dwForwardMetric1) ); end ; inc( pBuf, SizeOf( TMibIPForwardRow ) ); end; end else AppendRow('no entries.','','','','','','','' ); end else AppendRow('Error', SysErrorMessage( ErrorCode ),'','','','','',''); dec( pBuf, SizeOf( DWORD ) + NumEntries * SizeOf( TMibIPForwardRow ) ); FreeMem( pBuf ); end; //------------------------------------------------ procedure DoAdaptersInfo(sg: TStringGrid); var AdpTot: integer; AdpRows: TAdaptorRows ; Error: DWORD ; I: integer ; //J: integer ; jpt - see below //S: string ; id. //**************************************** procedure AppendRow(const adaptIdx,Typ,MAC,DHCP,DefGateway,DHCPsrv,PrimaryWinsSrv:string); begin with sg do begin Cells[0,RowCount-1] := adaptIdx; Cells[1,RowCount-1] := Typ; Cells[2,RowCount-1] := MAC; Cells[3,RowCount-1] := DHCP; Cells[4,RowCount-1] := DefGateway; Cells[5,RowCount-1] := DHCPsrv; Cells[6,RowCount-1] := PrimaryWinsSrv; RowCount := RowCount + 1; end; end; //**************************************** begin if not Assigned(sg) then exit; sg.RowCount := 2; SetLength (AdpRows, 0) ; AdpTot := 0 ; Error := IpHlpAdaptersInfo(AdpTot, AdpRows) ; if (Error <> 0) then AppendRow('Error', SysErrorMessage( GetLastError ),'','','','','' ) else if AdpTot = 0 then AppendRow('no entries.','','','','','','' ) else begin for i := 0 to Pred (AdpTot) do begin with AdpRows [i] do begin AppendRow( HexLS(Index), ifTypeStr[aType], MacAddress, IntToStr(DHCPEnabled), GatewayList [0], DHCPServer [0], PrimWINSServer [0]); end ; // with end ; // for end ; // if else SetLength (AdpRows, 0) ; end ; //--------------------------------------- procedure DoIfTable(sg: TStringGrid); var IfRows : TIfRows ; Error, I : integer; NumEntries : integer; sDescr, sIfName: string; //*************************************** procedure AppendRow(const index,typ,MAC,MTU,speed,adminstatus,operstatus,inp,outp,name,descr:string); var RowIdx: integer; begin with sg do begin RowIdx := RowCount-1; Cells[0,RowIdx] := index; Cells[1,RowIdx] := typ; Cells[2,RowIdx] := MAC; Cells[3,RowIdx] := MTU; Cells[4,RowIdx] := speed; Cells[5,RowIdx] := AdminStatus; Cells[6,RowIdx] := OperStatus; Cells[7,RowIdx] := inp; Cells[8,RowIdx] := outp; Cells[9,RowIdx] := name; Cells[10,RowIdx] := descr; RowCount := RowCount +1; end; end; //*************************************** begin if not Assigned(sg) then exit; sg.RowCount := 2; SetLength (IfRows, 0) ; Error := IpHlpIfTable(NumEntries, IfRows); if (Error <> 0) then AppendRow('Error', SysErrorMessage(GetLastError),'','','','','','','','','') else if NumEntries = 0 then AppendRow('no entries.','','','','','','','','','','' ) else begin for I := 0 to Pred (NumEntries) do begin with IfRows [I] do begin if wszName [1] = #0 then sIfName := '' else sIfName := WideCharToString (@wszName) ; // convert Unicode to string sIfName := trim (sIfName) ; sDescr := bDescr ; sDescr := trim (sDescr); AppendRow( HexLS(dwIndex), HexLS(dwType), MacAddr2Str( TMacAddress( bPhysAddr ), dwPhysAddrLen ), IntToStr(dwMTU), IntToStr(dwSpeed), IntToStr(dwAdminStatus), IntToStr(dwOPerStatus), IntToStr(Int64 (dwInOctets)), IntToStr(Int64 (dwOutOctets)), // counters are 32-bit sIfName, sDescr ); // Angus, added in/out end; end ; end ; SetLength (IfRows, 0) ; // free memory end ; initialization RecentIPs := TStringList.Create; finalization RecentIPs.Free; end.
-- _______________________________________________ Lazarus mailing list Lazarus@lists.lazarus.freepascal.org http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus