-- GetAdaptersAddresses for Windows XP or later only -- Pete Stoner. -- returns information about network adapters including the friendly name (name -- shown in network connections folder). -- with special thanks to Jacques Deschênes for removing dependancies on -- external libraries (win32lib and Unicode). -- example call is commented out at the bottom of this file -- function returns a sequence if successful an error integer if not -- See the MS API docs for full details on the GetAdaptersAddresses call ----------------------------------------------------------------------------- without warning include dll.e include machine.e global constant ADAPTER_TYPE=1, ADAPTER_NAME=2, ADAPTER_FRIENDLYNAME=3, ADAPTER_DESCRIPTION=4, ADAPTER_MAC_ADDRESS=5, ADAPTER_STATUS=6, DHCP_ENABLED=7, DYNAMIC_DNS=8, DNS_SUFFIX=9 constant iphlpapi = open_dll( "iphlpapi.dll" ) constant xGetAdaptersAddresses = define_c_func( iphlpapi, "GetAdaptersAddresses", {C_ULONG, -- Family, see constants below C_ULONG, -- Flags ([in] Type of addresses to retrieve, see constants below C_POINTER, -- Reserved [in] The calling application should pass NULL for this parameter. C_POINTER, -- [out] Pointer to a buffer. -- On successful return, this buffer contains the address information. C_ULONG}, -- pOutBufLen [in, out] Pointer to a variable that specifies the -- size of the buffer pointed to by pAdapterAddresses. C_INT) -- return code -- FAMILY constant AF_INET= 2 constant AF_INET6= 23 constant AF_UNSPEC= 0 -- flags returned constant IP_ADAPTER_DDNS_ENABLED = #0001, IP_ADAPTER_REGISTER_ADAPTER_SUFFIX = #0002, IP_ADAPTER_DHCP_ENABLED = #0004, IP_ADAPTER_RECEIVE_ONLY = #0008, IP_ADAPTER_NO_MULTICAST = #0010, IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG = #0020 constant -- possible return values ERROR_SUCCESS = 0, ERROR_BUFFER_OVERFLOW = 111, ERROR_INVALID_PARAMETER = 87, ERROR_NO_DATA = 232, ERROR_NOT_SUPPORTED = 50 -- adapter type constants global constant IF_TYPE_OTHER = 1, IF_TYPE_ETHERNET = 6, IF_TYPE_TOKENRING = 9, IF_TYPE_FDDI = 15, IF_TYPE_PPP = 23, IF_TYPE_LOOPBACK = 24, IF_TYPE_SLIP = 28 -- Operational status of the interface constant IfoperStatusDesc = { "The interface is up and operational.", -- IfOperStatusUp = 1 "The interface is not operational.", -- IfOperStatusDown = 2 "The interface is being tested.", -- IfOperStatusTesting = 3 "The interface status is unknown.", -- IfOperStatusUnknown = 4 "The interface is dormant.", -- IfOperStatusDormant = 5 "The interface is not present.", -- IfOperStatusNotPresent = 6 "The interface is operational, but a networking layer " & "below the interface is not operational." -- IfOperStatusLowerLayerDown = 7 } function GetAdapterName(atom pName) sequence name integer i,wc name = "" wc = peek(pName) i = 0 while wc do name &= wc i += 1 wc = peek(pName+i) end while return name end function function GetUnicodeData(atom ptr) sequence name integer i,wc name = "" wc = peek(ptr) + peek(ptr+1)*256 i = 0 while wc do name &= wc i += 2 wc = peek(ptr+i) + peek(ptr+i+1)*256 end while return name end function global function GetAdaptersAddresses() atom struct, pOutBufLen, dwStatus, flags, num, pNext integer dhcp, dDNS, interface_type sequence FriendlyName, Description, macAddr, DnsSuffix, operStatus object data data = {} struct = allocate(78) pOutBufLen = allocate(4) poke4( pOutBufLen,4 ) -- poke the wrong size for first call dwStatus = c_func( xGetAdaptersAddresses, {AF_INET, 0, NULL, struct, pOutBufLen} ) if dwStatus != ERROR_BUFFER_OVERFLOW then data = dwStatus else free(struct) struct = allocate(peek4u(pOutBufLen)) mem_set(struct,0,peek4u(pOutBufLen)) -- now use the correct buffer size dwStatus = c_func(xGetAdaptersAddresses,{AF_INET, 0, NULL, struct, pOutBufLen}) if dwStatus = ERROR_SUCCESS then pNext = struct data = {} while pNext do FriendlyName = GetUnicodeData(peek4u(pNext+40)) Description = GetUnicodeData(peek4u(pNext+36)) DnsSuffix = GetUnicodeData(peek4u(pNext+32)) interface_type = peek4u(pNext+64) macAddr = peek({pNext+44, peek4u(pNext+52)}) operStatus = IfoperStatusDesc[peek4u(pNext+68)] flags = peek4u(pNext+56) if and_bits(IP_ADAPTER_DHCP_ENABLED, flags) then dhcp = 1 else dhcp = 0 end if if and_bits(IP_ADAPTER_DDNS_ENABLED, flags) then dDNS = 1 else dDNS = 0 end if data &= {{interface_type, GetAdapterName(peek4u(pNext+12)), FriendlyName, Description, macAddr, operStatus, dhcp, dDNS, DnsSuffix, flags}} pNext = peek4u(pNext+8) end while else data = dwStatus end if end if free(struct) free(pOutBufLen) return data end function ------------------------------------------------- -- example usage ------------------------------------------------ -- object data -- data = GetAdaptersAddresses() -- if sequence(data) then -- for i = 1 to length(data) do -- if data[i][ADAPTER_TYPE] != IF_TYPE_LOOPBACK then -- don't care about loopback adapter -- printf(1,"Adapter Type: %d\n", data[i][ADAPTER_TYPE]) -- printf(1," Friendly name: %s\n",{data[i][ADAPTER_FRIENDLYNAME]}) -- printf(1," Windows Name: %s\n", {data[i][ADAPTER_NAME]}) -- printf(1," Description: %s\n", {data[i][ADAPTER_DESCRIPTION]}) -- printf(1," Mac Addr: %02x-%02x-%02x-%02x-%02x-%02x\n", data[i][ADAPTER_MAC_ADDRESS]) -- printf(1," Oper Status: %s\n", {data[i][ADAPTER_STATUS]}) -- printf(1," DHCP Enabled: %d\n", data[i][DHCP_ENABLED]) -- printf(1," DNS Enabled: %d\n", data[i][DYNAMIC_DNS]) -- printf(1," DNS Suffix: %s\n\n", {data[i][DNS_SUFFIX]}) -- end if -- end for -- end if