github.com/zooyer/miskit@v1.0.71/device/interface_windows.go (about)

     1  /**
     2   * @Author: zzy
     3   * @Email: zhangzhongyuan@didiglobal.com
     4   * @Description:
     5   * @File: interface_windows.go
     6   * @Package: device
     7   * @Version: 1.0.0
     8   * @Date: 2022/10/5 14:43
     9   */
    10  
    11  package device
    12  
    13  import (
    14  	"fmt"
    15  	"strings"
    16  	_ "unsafe"
    17  
    18  	"golang.org/x/sys/windows"
    19  	"golang.org/x/sys/windows/registry"
    20  )
    21  
    22  //go:linkname adapterAddresses net.adapterAddresses
    23  func adapterAddresses() ([]*windows.IpAdapterAddresses, error)
    24  
    25  func regString(key registry.Key, path, name string) (value string, err error) {
    26  	subKey, err := registry.OpenKey(key, path, registry.READ)
    27  	if err != nil {
    28  		return
    29  	}
    30  
    31  	defer subKey.Close()
    32  
    33  	if value, _, err = subKey.GetStringValue(name); err != nil {
    34  		return
    35  	}
    36  
    37  	return
    38  }
    39  
    40  func regInteger(key registry.Key, path, name string) (value uint64, err error) {
    41  	subKey, err := registry.OpenKey(key, path, registry.READ)
    42  	if err != nil {
    43  		return
    44  	}
    45  
    46  	defer subKey.Close()
    47  
    48  	if value, _, err = subKey.GetIntegerValue(name); err != nil {
    49  		return
    50  	}
    51  
    52  	return
    53  }
    54  
    55  // isPhysical1 判断设备前缀
    56  func isPhysical1(name string) (is bool, err error) {
    57  	var path = fmt.Sprintf("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", name)
    58  
    59  	instance, err := regString(registry.LOCAL_MACHINE, path, "PnPInstanceId")
    60  	if err != nil {
    61  		return
    62  	}
    63  
    64  	// 不包含USB网卡
    65  	return strings.HasPrefix(instance, "PCI"), nil
    66  }
    67  
    68  // isPhysical2 判断设备前缀和属性
    69  func isPhysical2(name string) (is bool, err error) {
    70  	const path = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"
    71  	key, err := registry.OpenKey(registry.LOCAL_MACHINE, path, registry.READ)
    72  	if err != nil {
    73  		return
    74  	}
    75  
    76  	defer key.Close()
    77  
    78  	stat, err := key.Stat()
    79  	if err != nil {
    80  		return
    81  	}
    82  
    83  	subs, err := key.ReadSubKeyNames(int(stat.SubKeyCount))
    84  	if err != nil {
    85  		return
    86  	}
    87  
    88  	for _, sub := range subs {
    89  		instance, err := regString(key, sub, "NetCfgInstanceId")
    90  		if err == registry.ErrNotExist || err != nil || instance != name {
    91  			continue
    92  		}
    93  
    94  		// 不包含USB网卡
    95  		device, err := regString(key, sub, "DeviceInstanceID")
    96  		if err == registry.ErrNotExist || err != nil || !strings.HasPrefix(device, "PCI") {
    97  			continue
    98  		}
    99  
   100  		// ox4 NCF_PHYSICAL 说明组件是一个物理适配器
   101  		value, err := regInteger(key, sub, "Characteristics")
   102  		if err == nil && value&0x4 == 0x4 {
   103  			return true, nil
   104  		}
   105  	}
   106  
   107  	return
   108  }
   109  
   110  // isPhysical3 isPhysical1增强版本,通过bus方式判断:https://blog.csdn.net/whf727/article/details/6660815
   111  func isPhysical3(name string) (is bool, err error) {
   112  	var path = fmt.Sprintf("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", name)
   113  
   114  	instance, err := regString(registry.LOCAL_MACHINE, path, "PnPInstanceId")
   115  	if err != nil {
   116  		return
   117  	}
   118  
   119  	// 不包含USB网卡
   120  	if !strings.HasPrefix(instance, "PCI") {
   121  		return
   122  	}
   123  
   124  	guid, err := windows.GUIDFromString("{4D36E972-E325-11CE-BFC1-08002BE10318}")
   125  	if err != nil {
   126  		return
   127  	}
   128  
   129  	dev, err := windows.SetupDiGetClassDevsEx(&guid, "", 0, windows.DIGCF_PRESENT, 0, "")
   130  	if err != nil {
   131  		return
   132  	}
   133  
   134  	defer dev.Close()
   135  
   136  	for i := 0; ; i++ {
   137  		info, err := dev.EnumDeviceInfo(i)
   138  		if err != nil {
   139  			if err == windows.ERROR_NO_MORE_ITEMS {
   140  				break
   141  			}
   142  			continue
   143  		}
   144  
   145  		id, err := dev.DeviceInstanceID(info)
   146  		if err != nil {
   147  			continue
   148  		}
   149  
   150  		if !strings.EqualFold(id, instance) {
   151  			continue
   152  		}
   153  
   154  		value, err := dev.DeviceRegistryProperty(info, windows.SPDRP_BUSNUMBER)
   155  		if err != nil {
   156  			continue
   157  		}
   158  
   159  		if num, ok := value.(uint32); ok && int32(num) != -1 {
   160  			return true, nil
   161  		}
   162  	}
   163  
   164  	return false, nil
   165  }
   166  
   167  func isPhysicalEthernet(index int) (is bool, err error) {
   168  	aas, err := adapterAddresses()
   169  	if err != nil {
   170  		return
   171  	}
   172  
   173  	for _, aa := range aas {
   174  		if int(aa.IfIndex) != index {
   175  			continue
   176  		}
   177  
   178  		// 有线网卡和无线网卡
   179  		if aa.IfType == windows.IF_TYPE_ETHERNET_CSMACD || aa.IfType == windows.IF_TYPE_IEEE80211 {
   180  			return isPhysical3(windows.BytePtrToString(aa.AdapterName))
   181  		}
   182  	}
   183  
   184  	return
   185  }