网卡相关的一些功能代码

Posted 黑暗煎饼果子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网卡相关的一些功能代码相关的知识,希望对你有一定的参考价值。

获取网卡信息(支持多网卡)

uses
  Registry;


function GetAdapterInformation: AnsiString;
//{$DEFINE PHY_NETWORKCARD_ONLY} {是否只获取物理网卡}

  function _GetSystem32Dir: AnsiString;
  var
    nBuf: array[0..MAX_PATH] of AnsiChar;
  begin
    GetSystemDirectoryA(nBuf, MAX_PATH);
    Result := nBuf;
    if Result[Length(Result)] <> \ then
      Result := Result + \;
  end;

  const
    MAX_ADAPTER_NAME_LENGTH = 256;
    MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
    MAX_ADAPTER_ADDRESS_LENGTH = 8;

  type
    time_t = Longint;
    PIP_MASK_STRING = ^IP_MASK_STRING;
    IP_ADDRESS_STRING = record
      S: array [0..15] of AnsiChar;
    end;
    PIP_ADDRESS_STRING = ^IP_ADDRESS_STRING;
    IP_MASK_STRING = IP_ADDRESS_STRING;
    TIpAddressString = IP_ADDRESS_STRING;
    PIpAddressString = PIP_MASK_STRING;

    PIP_ADDR_STRING = ^IP_ADDR_STRING;
    _IP_ADDR_STRING = record
      Next: PIP_ADDR_STRING;
      IpAddress: IP_ADDRESS_STRING;
      IpMask: IP_MASK_STRING;
      Context: DWORD;
    end;
    IP_ADDR_STRING = _IP_ADDR_STRING;
    TIpAddrString = IP_ADDR_STRING;
    PIpAddrString = PIP_ADDR_STRING;

    PIPAdapterInfo = ^TIPAdapterInfo;
    TIPAdapterInfo = record {IP_ADAPTER_INFO}
      Next: PIPAdapterInfo;
      ComboIndex: Cardinal;
      AdapterName: Array[0..MAX_ADAPTER_NAME_LENGTH + 3] of AnsiChar;
      Description: Array[0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of AnsiChar;
      AddressLength: Integer; {MAC}
      Address: Array[1..MAX_ADAPTER_ADDRESS_LENGTH] of Byte;
      Index: Cardinal;
      _Type: Longint;
      DhcpEnabled: Longint;
      CurrentIpAddress: PIP_ADDR_STRING; {IP}
      IpAddressList: IP_ADDR_STRING;
      GatewayList: IP_ADDR_STRING; {网关}
      DhcpServer: IP_ADDR_STRING; {DHCP服务器}
      HaveWins: Boolean;
      PrimaryWinsServer: IP_ADDR_STRING;
      SecondaryWinsServer: IP_ADDR_STRING;
      LeaseObtained: time_t;
      LeaseExpires: time_t;
    end;

    _GetAdaptersInfo = function(AI: PIPAdapterInfo; var BufLen: Integer): Integer; stdcall;

  function _MACToStr(AByteArr: PByte; ALen: Integer): AnsiString;
  Begin
    Result := ‘‘;
    while (ALen > 0) do
    begin
      Result := Result + IntToHex(AByteArr^, 2) + -;
      AByteArr := Pointer(Integer(AByteArr) + SizeOf(Byte));
      Dec(ALen);
    end;
    SetLength(Result, Length(Result) - 1);
  End;

  function _IsNetWorkCard(AAdapterID: string): Boolean;
  var
    i: Integer;
    nStrs: TStringList;
  const
    {虚拟适配器}
    NCF_VIRTUAL = $001;
    {软件模拟的适配器}
    NCF_SOFTWARE_ENUMERATED = $002;
    {物理适配器}
    NCF_PHYSICAL = $004;
    {不显示用户接口}
    NCF_HIDDEN = $008;
    {没有相关的服务(设备驱动程序)}
    NCF_NO_SERVICE = $010;
    {不能被用户删除(例如通过控制面板或设备管理器)}
    NCF_NOT_USER_REMOVABLE = $020;
    {组件有多个端口,每个端口作为单独的设备安装。每个端口有自己的hw_id(组件ID)并可被单独安装,这只适合于EISA适配器}
    NCF_MULTIPORT_INSTANCED_ADAPTER = $040;
    {支持用户接口(例如,Advanced Page或Customer Properties Sheet}
    NCF_HAS_UI = $080;
    {是一个过滤器}
    NCF_FILTER = $400;

    __CST_BASKKEY = \SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318};
    __CST_INSTANCEID = NetCfgInstanceId;
    __CST_CCT = Characteristics;
  begin
    Result := False;
    with TRegistry.Create do
    try
      RootKey := HKEY_LOCAL_MACHINE;
      if not OpenKey(__CST_BASKKEY, False) then
        Exit;

      nStrs := TStringList.Create;
      try
        GetKeyNames(nStrs);
        CloseKey;
        for i := 0 to nStrs.Count - 1 do
        begin
          if not OpenKey(__CST_BASKKEY + \ + nStrs[i], False) then
            Exit;
          if not ValueExists(__CST_INSTANCEID) then
            Exit;
          if not (ReadString(__CST_INSTANCEID) = AAdapterID) then
            Continue;
          if not ValueExists(__CST_CCT) then
            Exit;
          {只过滤物理网卡}
          if ReadInteger(__CST_CCT) and NCF_PHYSICAL = NCF_PHYSICAL then
          begin
            Result := True;
            Break;
          end;
        end;
      finally
        nStrs.Free;
      end;
    finally
      Free;
    end;
    Result := True;
  end;

var
  nHWND: THandle;
  nGetAdaptersInfo: _GetAdaptersInfo;
  nAI, nWork: PIPAdapterInfo;
  nSize, nRes, nLH, nLO, x: Integer;
  nStr, nHPY, nOther: AnsiString;
begin
  Result := ‘‘;
  nHWND := LoadLibraryA(PAnsiChar(_GetSystem32Dir + iphlpapi.dll));
  if nHWND = 0 then
    Exit;
  nGetAdaptersInfo := GetProcAddress(nHWND, PAnsiChar(GetAdaptersInfo));
  if not Assigned(nGetAdaptersInfo) then
    Exit;
  nSize := 5120;
  GetMem(nAI, nSize);
  try
    nRes := nGetAdaptersInfo(nAI, nSize);
    if (nRes <> ERROR_SUCCESS) then
    begin
      SetLastError(nRes);
      RaiseLastWin32Error;
    end
    else
    begin
      nWork := nAI;
      nLH := 0;
      nLO := 0;
      SetLength(nHPY, nSize);
      SetLength(nOther, nSize);
      Repeat
        try
          {返回 名称 + MAC}
          nStr := Trim(nWork^.Description) + &
            + Trim(_MACToStr(@nWork^.Address, nWork^.AddressLength)) + #13#10{网卡MAC};
(*
          {返回 名称+ID+MAC}
          nStr := Trim(nWork^.Description) + & {网卡名称(描述)}
            + Trim(nWork^.AdapterName) + & {网卡ID}
            + Trim(_MACToStr(@nWork^.Address, nWork^.AddressLength)) + &#13#10{网卡MAC};
*)
          x := Length(nStr);
          if _IsNetWorkCard(nWork^.AdapterName) then
          begin
            Move(nStr[1], nHPY[nLH + 1], x);
            Inc(nLH, x);
          end
          else
          begin
            Move(nStr[1], nOther[nLO + 1], x);
            Inc(nLO, x);
          end;
          nWork := nWork^.Next;
        except
        end;
      Until (nWork = nil);
      Result := Trim(Copy(nHPY, 1, nLH) + Copy(nOther, 1, nLO));
    end;
  finally
    FreeMem(nAI);
    Freelibrary(nHWND);
  end;
end;

 

获取网卡连接状态

const  
  MAX_INTERFACE_NAME_LEN = 256;
  MAXLEN_PHYSADDR = 8;
  MAXLEN_IFDESCR = 256;
  MIB_IF_TYPE_OTHER = 1;
  MIB_IF_TYPE_ETHERNET = 6;
  MIB_IF_TYPE_TOKENRING = 9;
  MIB_IF_TYPE_FDDI = 15;
  MIB_IF_TYPE_PPP = 23;
  MIB_IF_TYPE_LOOPBACK = 24;
  MIB_IF_TYPE_SLIP = 28;
  MIB_IF_ADMIN_STATUS_UP = 1;
  MIB_IF_ADMIN_STATUS_DOWN = 2;
  MIB_IF_ADMIN_STATUS_TESTING = 3;
  MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0;
  MIB_IF_OPER_STATUS_UNREACHABLE = 1;
  MIB_IF_OPER_STATUS_DISCONNECTED = 2;
  MIB_IF_OPER_STATUS_CONNECTING = 3;
  MIB_IF_OPER_STATUS_CONNECTED = 4;
  MIB_IF_OPER_STATUS_OPERATIONAL = 5;
type  
  MIB_PHYSADDR = array[0..MAXLEN_PHYSADDR - 1] of Byte;
  MIB_IFDESCR = array[0..MAXLEN_IFDESCR - 1] of Char;
  
  PMIB_IFROW = ^MIB_IFROW;
  MIB_IFROW = packed record  
    wszName: array[0..MAX_INTERFACE_NAME_LEN - 1] of WCHAR;
    dwIndex,   
    dwType,   
    dwMtu,   
    dwSpeed,   
    dwPhysAddrLen: DWORD;
    bPhysAddr: MIB_PHYSADDR;
    dwAdminStatus,   
    dwOperStatus,   
    dwLastChange,   
    dwInOctets,   
    dwInUcastPkts,   
    dwInNUcastPkts,   
    dwInDiscards,   
    dwInErrors,   
    dwInUnknownProtos,   
    dwOutOctets,   
    dwOutUcastPkts,   
    dwOutNUcastPkts,   
    dwOutDiscards,   
    dwOutErrors,   
    dwOutQLen,   
    dwDescrLen: DWORD;
    bDescr: MIB_IFDESCR;
  end;
  
  PMIB_IFTABLE = ^MIB_IFTABLE;
  MIB_IFTABLE = packed record  
    dwNumEntries: DWORD;
    table: array[0..0] of MIB_IFROW;
  end;
  
  TAdapterStatus = record  
    dwType,   
    dwOperStatus: DWORD;
    bDescr: MIB_IFDESCR;
  end;
  TAdapterStatuses = array of TAdapterStatus;
  
function GetIfTable(pIfTable: PMIB_IFTABLE; pdwSize: PULONG; bOrder: BOOL): DWORD;
  stdcall; external iphlpapi.dll; 
  
procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses); {先调用, 获取适配器信息}
function GetAdapterTypeString(const dwType: DWORD): string; {获取适配器类型中文描述}
function GetAdapterStatusString(const dwOperStatus: DWORD): string; {获取适配器状态中文描述}

  
implementation  

var  
  dwSize: DWORD;
  pMibIfTable: PMIB_IFTABLE;
  
function GetAdapterTypeString(const dwType: DWORD): string;
begin  
  case dwType of  
    MIB_IF_TYPE_OTHER: Result := 其他;
    MIB_IF_TYPE_ETHERNET: Result := 以太网;
    MIB_IF_TYPE_TOKENRING: Result := 令牌环;
    MIB_IF_TYPE_FDDI: Result := FDDI;
    MIB_IF_TYPE_PPP: Result := PPP;
    MIB_IF_TYPE_LOOPBACK: Result := 回路;
    MIB_IF_TYPE_SLIP: Result := SLIP;
  end;
end;

function GetAdapterStatusString(const dwOperStatus: DWORD): string;
begin  
  case dwOperStatus of  
    MIB_IF_OPER_STATUS_NON_OPERATIONAL: Result := 掉线;
    MIB_IF_OPER_STATUS_UNREACHABLE: Result := 不可达;
    MIB_IF_OPER_STATUS_DISCONNECTED: Result := 断开;
    MIB_IF_OPER_STATUS_CONNECTING: Result := 连接中;
    MIB_IF_OPER_STATUS_CONNECTED: Result := 已连接;
    MIB_IF_OPER_STATUS_OPERATIONAL: Result := 连通;
  end;
end;

procedure ScanAdapters(var AdapterStatuses: TAdapterStatuses);
var  
  dwRetVal: DWORD;
  num, i: Longint;
begin  
  dwRetVal := GetIfTable(pMibIfTable, @dwSize, False);
  if dwRetVal = NO_ERROR then  
  begin  
    num := pMibIfTable^.dwNumEntries;
    if Length(AdapterStatuses) <> num then  
      SetLength(AdapterStatuses, num);
    for i := Low(AdapterStatuses) to High(AdapterStatuses) do  
    begin  
      AdapterStatuses[i].dwType := pMibIfTable^.table[i].dwType;
      AdapterStatuses[i].dwOperStatus := pMibIfTable^.table[i].dwOperStatus;
      AdapterStatuses[i].bDescr := pMibIfTable^.table[i].bDescr;
    end;
  end;
end;

initialization  
  GetIfTable(nil, @dwSize, False);
  GetMem(pMibIfTable, dwSize);
     
finalization  
  FreeMem(pMibIfTable);
end. 

 

以上是关于网卡相关的一些功能代码的主要内容,如果未能解决你的问题,请参考以下文章

从零开始配置vim(27)——代码片段

从零开始配置vim(27)——代码片段

从零开始配置vim(27)——代码片段

创建自己的代码片段(CodeSnippet)

Jekyll 偏移代码片段高亮的初始行

如何在Sublime Text中添加代码片段