;; 
;;=====================================================================================----- 
;; 
;;FUNCTION       NicInfo() 
;; 
;;ACTION         Returns an array of arrays containing descriptions of each NIC 
;; 
;;AUTHOR         Glenn Barnas 
;;		 based on original concept by Ron Lewis (NTDoc) 
;; 
;;VERSION	 1.5  - 2015/08/27 
;; 
;;HISTORY        1.0  - 2005/01/11 - initial release, 15 elements (2 spare), no WMI 
;;		 1.2  - 2006/03/17 - 20 elements (2 spare), WMI for MAC and status info 
;;		        >> NOTE: Position of TEAM data elements changed in this release! << 
;;		 1.3  - 2007/04/02 - WMI PreAuth pointer use, Element 13 became Fixed Name 
;;		                    Servers, Expanded domain name to include connection, 
;;                                  primary,and search list 
;;               1.4  - 2007/07/02 - Added hostname to Domain list to identify query-by-IP 
;;               1.5  - 2015/08/27 - Added the ID for Hyper-V virtual NICs 
;; 
;;SYNTAX         NicInfo([target] [,WMIAuth]) 
;; 
;;PARAMETERS     Target - OPTIONAL - String 
;;               - name of remote system to query 
;; 
;;		 WMIAuth - OPTIONAL - Object 
;;               - Pre-authenticated object pointer for WMI calls 
;; 
;;REMARKS        Returns info about all physical NICs in a given system.  
;;               Identifies HP/Compaq NIC Teams. DHCP Lease times are in time offsets 
;;               and must be converted before use. 
;;               Elements 15 & 16 require WMI - they return nothing if WMI is unsupported. 
;;               Status (15) is only returned reliably on XP and 2K3 systems. 
;;               Elements 17-19 return data about HP NIC Teams. Other teams can be 
;;               supported with appropriate code changes. 
;; 
;;RETURNS        Array of arrays 
;;                - the first element of the array represents each NIC 
;;                - the second element represents one of 20 distinct NIC parameters 
;;                 NIC Elements: 
;;                -  0 : Adapter Description 
;;                -  1 : Manufacturer 
;;                -  2 : NIC GUID 
;;                -  3 : Speed/Duplex value 
;;                -  4 : Speed/Duplex text 
;;                -  5 : Driver Version 
;;                -  6 : DHCP boolean (1=Use DHCP) 
;;                -  7 : IP settings  (address,mask,gateway) *, ** 
;;                -  8 : Domain Info: Hostname;Connection;Primary;Search List **, *** 
;;                -  9 : DNS Server list ** 
;;                - 10 : DHCP Server, Lease Aquired, Lease Expires (if DHCP is enabled) 
;;                - 11 : WINS Server list ** 
;;                - 12 : Interface Name 
;;                - 13 : Fixed Name Servers 
;;                - 14 : Reserved for future use 
;;                - 15 : NIC Status (2=Ready,0=Disabled...) 
;;                - 16 : MAC Address - only if NIC is enabled/connected 
;;                - 17 : TEAM flag (Name of Team - HPTeam, Intel Team, etc.) 
;;                - 18 : # of adapters in team 
;;                - 19 : ID (GUIDs) of adapters in team 
;; 
;;                * If multiple IP addresses are assigned to a NIC, the IP addresses will 
;;                be presented as a space-delimited list, followed by a semicolon and the  
;;                space-delimited list of corresponding netmasks, followed by a semicolon 
;;                and the space-delimited list of corresponding gateways (usually just one). 
;;                 
;;                ** Any time multiple values are returned, they will be space delimited 
;; 
;;		  *** Individual sections are ";" delimited 
;; 
;;DEPENDENCIES   none 
;; 
;;TESTED WITH    NT4, W2K, WXP, W2K3 
;; 
;;EXAMPLES        
;;                $Array = NicInfo($COMPUTER) 
;;                If UBound($Array) < 0 
;;                  @SERROR ? 
;;                Else 
;;                  UBound($Array) + 1 ' NICs found.' ? 
;;                  For $X = 0 to UBound($Array) 
;;                    For $Y = 0 to UBound($Array[$X]) 
;;                      $y '. ' $Array[$X][$Y] ? 
;;                    Next 
;;                  Next 
;;                EndIf 
; 
Function NicInfo(OPTIONAL $_Target, OPTIONAL $_pAuth)
 
  Dim $_, $_Tmp, $_SubKeyCounter, $_NicArray, $_CurrentSubKey, $_aPNP, $_Tgt
  Dim $_Name, $_Key, $_Index, $_WorkRegKey, $_SubKey, $_colItems, $_objWMI
  Dim $_Regkey[4]
 
  ; Insure $_Target uses the format "\\target\" if specified, null otherwise 
  ; $_Tgt must be either a plain hostname or "." for WMI use 
  $_Tgt    =  IIf(CStr($_Target) <> '', Join(Split(CStr($_Target), '\'), '', 3), '.')
  $_Target =  IIf(CStr($_Target) <> '', '\\' + Join(Split(CStr($_Target), '\'), '', 3) + '\', '')
 
  ; Define the registry keys 
  $_RegKey[0] = $_Target + 'HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}'
  $_RegKey[1] = $_Target + 'HKLM\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002bE10318}'
  $_RegKey[2] = $_Target + 'HKLM\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\Tcpip_'
  $_RegKey[3] = $_Target + 'HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
  $_RegKey[4] = $_Target + 'HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName'
 
 
  ; init the enumeration index and array index 
  $_SubKeyCounter = 0
  $_Index = 0
 
 
  ; Enumerate all of the keys that are LAN adapters 
  $_CurrentSubKey = EnumKey($_RegKey[0], $_SubKeyCounter)
  If @ERROR
    Exit @ERROR							; exit now if can't read registry! 
  EndIf
 
  $_CurrentSubKey = EnumKey($_RegKey[0], $_SubKeyCounter)
  While @ERROR = 0
    $_Key = Val(ReadValue($_RegKey[0] + '\' + $_CurrentSubKey, 'Characteristics'))
    If $_Key = 4 Or $_Key = 132 Or $_Key >= 32768		; physical nic or virtual team 
      ReDim Preserve $_NicArray[$_Index]			; increase the array size 
      $_NicArray[$_Index] = $_CurrentSubKey			; add the subkey to the array 
      $_Index = $_Index + 1					; increment the array index 
    EndIf
    $_SubKeyCounter = $_SubKeyCounter + 1			; increment the enumeration index 
    $_CurrentSubKey = EnumKey($_RegKey[0], $_SubKeyCounter)	; get the next key 
  Loop
 
  ; Have an array of all the NIC subkeys now... Gather some appropriate data on each one 
  Dim $_NicData[UBound($_NicArray)]
 
  $_Index = 0
  Dim $_WorkArray[19]
  For Each $_SubKey In $_NicArray
    ; Start by determining the Speed/Duplex value name 
    $_SubKeyCounter = 0
    $_Name = ''
    $_WorkRegKey = $_RegKey[0] + '\' + $_SubKey + '\Ndi\Params'
 
    ; Enumerate all of the subkeys to locate the Speed/Duplex value name 
    $_CurrentSubKey = EnumKey($_WorkRegKey, $_SubKeyCounter)
    While @ERROR = 0 And $_Name = ''
      $_Key = ReadValue($_WorkRegKey + '\' + $_CurrentSubKey, 'ParamDesc')
      If InStr($_Key, 'Duplex') Or InStr($_Key, 'Connection Type')
        $_Name = $_CurrentSubKey							; Save the Key Name 
      EndIf
      $_SubKeyCounter = $_SubKeyCounter + 1						; increment the enum index 
      $_CurrentSubKey = EnumKey($_WorkRegKey, $_SubKeyCounter)				; get the next key 
    Loop	; enumerate subkeys 
 
    ; Collect the data for this adapter 
    $_WorkArray[0] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'DriverDesc')		; Adapter Description 
    $_WorkArray[1] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'ProviderName')		; Manufacturer 
    $_WorkArray[2] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'NetCfgInstanceId')	; NIC GUID 
    $_WorkArray[3] = ReadValue($_RegKey[0] + '\' + $_SubKey, $_Name)			; Speed/Duplex value 
    $_WorkArray[4] = ReadValue($_WorkRegKey + '\' + $_Name + '\Enum', $_WorkArray[3])	; Speed/Duplex text 
    $_WorkArray[4] = IIf($_WorkArray[4] = '', 'Undefined', $_WorkArray[4])		; undefined speed 
    $_WorkArray[5] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'DriverVersion')		; Driver Version 
 
    ; Get the IP address parameters - DHCP Enabled, IP Address, Netmask, Gateway 
    $_WorkRegKey = $_RegKey[3] + '\Interfaces\' + $_WorkArray[2]
    $_WorkArray[6] = Val(ReadValue($_WorkRegKey, 'EnableDHCP'))				; DHCP boolean 
    $_Key = IIf($_WorkArray[6] = 1, 'Dhcp', '')
    $_WorkArray[7] = ReadStringValue($_WorkRegKey, $_Key + 'IPAddress') + ';' +
                     ReadStringValue($_WorkRegKey, $_Key + 'SubnetMask') + ';' +
                     ReadStringValue($_WorkRegKey, $_Key + 'DefaultGateway')
 
    ; Gather additional DHCP info, if DHCP is enabled 
    If $_WorkArray[6]
      $_WorkArray[10] = ReadStringValue($_WorkRegKey, 'DhcpServer') + ';' +
                        ReadStringValue($_WorkRegKey, 'LeaseObtainedTime') + ';' +
                        ReadStringValue($_WorkRegKey, 'LeaseTerminatesTime')
    EndIf
 
    ; Get the computer's host name 
    $_WorkArray[8] = ReadValue($_RegKey[4], 'ComputerName') + ';'
 
 
    ; Get the Domain Name and DNS Server List 
    $_WorkArray[8] = $_WorkArray[8] + ReadStringValue($_WorkRegKey, $_Key + 'Domain')  + ';'
 
    $_WorkArray[9] = Join(Split(ReadStringValue($_WorkRegKey, $_Key + 'NameServer'), ','), ' ')
    $_WorkArray[13] = Join(Split(ReadStringValue($_WorkRegKey, 'NameServer'), ','), ' ')
 
    ; Gather the WINS Server list 
    $_WorkArray[11] = ReadStringValue($_RegKey[2] + $_WorkArray[2], 'NameServerList')
 
    ; Obtain the current interface name 
    $_WorkArray[12] = ReadStringValue($_RegKey[1] + '\' + $_WorkArray[2] + '\Connection', 'Name')
 
    ; temporarily save the PNP Instance ID for use by the WMI component later on 
    $_WorkArray[16] = ReadStringValue($_RegKey[1] + '\' + $_WorkArray[2] + '\Connection', 'PnpInstanceID')
 
    If ReadValue($_RegKey[0] + '\' + $_SubKey, 'Characteristics') > 32768
      $_WorkArray[17] = 1								; special flag 
      $_WorkArray[18] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'NumBindings')		; # of adapters in team 
      $_WorkArray[19] = '' ; ReadValue($_RegKey[0] + '\' + $_SubKey, 'TeamInstances')	; ID of adapters in team 
    EndIf
 
    $_WorkRegKey = $_RegKey[3] 
    $_WorkArray[8] = $_WorkArray[8] + ReadStringValue($_WorkRegKey, 'Domain')  + ';' + ReadStringValue($_WorkRegKey, 'SearchList')
 
;    ; Special values for Compaq/HP Team 
;    If ReadValue($_RegKey[0] + '\' + $_SubKey, 'Characteristics') = 32769 
;      $_WorkArray[17] = 'HPTEAM'							; special flag 
;      $_WorkArray[18] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'TeamAdapters')	; # of adapters in team 
;      $_WorkArray[19] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'TeamInstances')	; ID of adapters in team 
;    EndIf 
 
;    ; Special values for Intel Team 
;    If ReadValue($_RegKey[0] + '\' + $_SubKey, 'Characteristics') = 32929 
;      $_WorkArray[17] = 'Intel TEAM'							; special flag 
;      $_WorkArray[18] = ReadValue($_RegKey[0] + '\' + $_SubKey, 'TotalPhysicalAdapters')		; # of adapters in team 
;      $_WorkArray[19] = '' ; ReadValue($_RegKey[0] + '\' + $_SubKey, 'TeamInstances')	; ID of adapters in team 
;    EndIf 
 
    ; prepare for the next nic 
    $_NicData[$_Index] = $_WorkArray			; Assign the sub-array 
    $_Index = $_Index + 1				; increment the index pointer 
    ReDim $_WorkArray[19]				; clear the working sub-array 
 
  Next	; CurrentSubKey 
 
  ; Trim the outer array (NICs) 
  $_Index = $_Index - 1
  ReDim Preserve $_NicData[$_Index]
 
  ; Prepare for WMI lookups 
  $_Tmp = ''
  For $_ = 0 to $_Index
    $_Tmp = $_Tmp + $_NicData[$_][16] + ','		; put the PNP data into an index, and clear the value 
    $_NicData[$_][16] = ''				; the PNP value is not returned 
  Next
  $_Tmp = Left($_Tmp, Len($_Tmp) - 1)			; trim the ending delim 
  $_aPNP = Split($_Tmp, ',')				; put into a lookup array 
 
  ; Try to gather the remaining info via a single WMI collection 
  If $_pAuth
    $_objWMI = $_pAuth
  Else
    $_objWMI = GetObject("winmgmts:\\" + $_Tgt + "\root\cimv2")
  EndIf
  ; just ignore WMI if an error occurs. 
  if Not @ERROR
    ; Collect all data from all NICs 
    $_colItems = $_objWMI.ExecQuery('Select * from Win32_NetworkAdapter')
    For Each $_ in $_colItems
      ; Does the PNP Device ID exist in our lookup array? If so, where? That will be the NIC index 
      ; that we update with WMI data 
      $_Tmp = AScan($_aPNP, $_.PNPDeviceID)
      If $_Tmp >= 0
        $_NicData[$_Tmp][15] = $_.NetConnectionStatus	; XP, 2K3 & higher 
        If $_NicData[$_Tmp][15] <> 0
          $_NicData[$_Tmp][16] = $_.MACAddress		; only if NIC is enabled 
        EndIf
      EndIf
    Next
  EndIf
 
 
  ; Return the array of arrays 
  $NicInfo = $_NicData
 
  Exit 0
 
EndFunction
 
 
; Read a String_Multi_SZ val and return a space-delimited string 
Function ReadStringValue($_Key, $_Val)
 
  $ReadStringValue = Trim(Join(Split(ReadValue($_Key, $_Val), '|'), ' '))
 
EndFunction