diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-02-15 03:28:59 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-02-15 03:28:59 +0000 |
commit | 2ece5109d6787390c81aa54df2c78d79a0d0647d (patch) | |
tree | 7530e86cee4b0ee18c2dc223355c915eb2f3048a /ext/win32/lib/win32/resolv9x.rb | |
parent | 8a180ee4b70cb2816bd89d0df51c9bcfbddf3609 (diff) |
split win32/resolv9x.rb
* ext/win32/lib/win32/resolv9x.rb: split code for Windows 9x from
resolv.rb. now it is rarely used.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53826 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/win32/lib/win32/resolv9x.rb')
-rw-r--r-- | ext/win32/lib/win32/resolv9x.rb | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/ext/win32/lib/win32/resolv9x.rb b/ext/win32/lib/win32/resolv9x.rb new file mode 100644 index 0000000000..a08a41fdf8 --- /dev/null +++ b/ext/win32/lib/win32/resolv9x.rb @@ -0,0 +1,253 @@ +#==================================================================== +# Windows 9x +#==================================================================== +module Win32 + module Resolv + TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP' + DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP' + WINDOWS = 'Software\Microsoft\Windows\CurrentVersion' + + class << self + # private + + def get_hosts_dir + Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg| + reg.read_s_expand('SystemRoot') + end + end + + def get_info + search = [] + nameserver = [] + begin + Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg| + if reg.read_s("EnableDNS") == "1" + domain = reg.read_s("Domain") + ns = reg.read_s("NameServer") + slist = reg.read_s("SearchList") + search << domain unless domain.empty? + search.concat(slist.split(/,\s*/)) + nameserver.concat(ns.split(/[,\s]\s*/)) + end + end + rescue Registry::Error + end + + dhcpinfo = get_dhcpinfo + search.concat(dhcpinfo[0]) + nameserver.concat(dhcpinfo[1]) + [ search, nameserver ] + end + + def get_dhcpinfo + macaddrs = {} + ipaddrs = {} + WsControl.get_iflist.each do |index, macaddr, *ipaddr| + macaddrs[macaddr] = 1 + ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 } + end + iflist = [ macaddrs, ipaddrs ] + + search = [] + nameserver = [] + version = -1 + Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg| + begin + version = API.unpackdw(reg.read_bin("Version")) + rescue Registry::Error + end + + reg.each_key do |key,| + catch(:not_used) do + reg.open(key) do |regdi| + dom, ns = get_dhcpinfo_key(version, regdi, iflist) + search << dom if dom + nameserver.concat(ns) if ns + end + end + end + end + [ search, nameserver ] + end + + def get_dhcpinfo_95(reg) + dhcp = reg.read_bin("DhcpInfo") + [ + API.unpackdw(dhcp[4..7]), + API.unpackdw(dhcp[8..11]), + 1, + dhcp[45..50], + reg.read_bin("OptionInfo"), + ] + end + + def get_dhcpinfo_98(reg) + [ + API.unpackdw(reg.read_bin("DhcpIPAddress")), + API.unpackdw(reg.read_bin("DhcpSubnetMask")), + API.unpackdw(reg.read_bin("HardwareType")), + reg.read_bin("HardwareAddress"), + reg.read_bin("OptionInfo"), + ] + end + + def get_dhcpinfo_key(version, reg, iflist) + info = case version + when 1 + get_dhcpinfo_95(reg) + when 2 + get_dhcpinfo_98(reg) + else + begin + get_dhcpinfo_98(reg) + rescue Registry::Error + get_dhcpinfo_95(reg) + end + end + ipaddr, netmask, hwtype, macaddr, opt = info + throw :not_used unless + ipaddr and ipaddr != 0 and + netmask and netmask != 0 and + macaddr and macaddr.size == 6 and + hwtype == 1 and + iflist[0][macaddr] and iflist[1][ipaddr] + + size = opt.size + idx = 0 + while idx <= size + opttype = opt[idx] + optsize = opt[idx + 1] + optval = opt[idx + 2, optsize] + case opttype + when 0xFF ## term + break + when 0x0F ## domain + domain = optval.chomp("\0") + when 0x06 ## dns + nameserver = optval.scan(/..../).collect { |addr| + "%d.%d.%d.%d" % addr.unpack('C4') + } + end + idx += optsize + 2 + end + [ domain, nameserver ] + rescue Registry::Error + throw :not_used + end + end + + module WsControl + module WSock32 + extend Importer + dlload "wsock32.dll" + end + WsControl = WSock32.extern "int WsControl(int, int, void *, void *, void *, void *", :stdcall + WSAGetLastError = WSock32.extern "int WSAGetLastError(void)", :stdcall + + MAX_TDI_ENTITIES = 512 + IPPROTO_TCP = 6 + WSCTL_TCP_QUERY_INFORMATION = 0 + INFO_CLASS_GENERIC = 0x100 + INFO_CLASS_PROTOCOL = 0x200 + INFO_TYPE_PROVIDER = 0x100 + ENTITY_LIST_ID = 0 + GENERIC_ENTITY = 0 + CL_NL_ENTITY = 0x301 + IF_ENTITY = 0x200 + ENTITY_TYPE_ID = 1 + CL_NL_IP = 0x303 + IF_MIB = 0x202 + IF_MIB_STATS_ID = 1 + IP_MIB_ADDRTABLE_ENTRY_ID = 0x102 + + def self.wsctl(tei_entity, tei_instance, + toi_class, toi_type, toi_id, + buffsize) + reqinfo = [ + ## TDIEntityID + tei_entity, tei_instance, + ## TDIObjectID + toi_class, toi_type, toi_id, + ## TCP_REQUEST_INFORMATION_EX + "" + ].pack('VVVVVa16') + reqsize = API.packdw(reqinfo.size) + buff = "\0" * buffsize + buffsize = API.packdw(buffsize) + result = WsControl.call( + IPPROTO_TCP, + WSCTL_TCP_QUERY_INFORMATION, + reqinfo, reqsize, + buff, buffsize) + if result != 0 + raise RuntimeError, "WsControl failed.(#{result})" + end + [ buff, API.unpackdw(buffsize) ] + end + private_class_method :wsctl + + def self.get_iflist + # Get TDI Entity List + entities, size = + wsctl(GENERIC_ENTITY, 0, + INFO_CLASS_GENERIC, + INFO_TYPE_PROVIDER, + ENTITY_LIST_ID, + MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID) + entities = entities[0, size]. + scan(/.{8}/). + collect { |e| e.unpack('VV') } + + # Get MIB Interface List + iflist = [] + ifcount = 0 + entities.each do |entity, instance| + if( (entity & IF_ENTITY)>0 ) + ifcount += 1 + etype, = wsctl(entity, instance, + INFO_CLASS_GENERIC, + INFO_TYPE_PROVIDER, + ENTITY_TYPE_ID, + 4) + if( (API.unpackdw(etype) & IF_MIB)==IF_MIB ) + ifentry, = wsctl(entity, instance, + INFO_CLASS_PROTOCOL, + INFO_TYPE_PROVIDER, + IF_MIB_STATS_ID, + 21 * 4 + 8 + 130) # sizeof(IFEntry) + iflist << [ + API.unpackdw(ifentry[0,4]), + ifentry[20, 6] + ] + end + end + end + + # Get IP Addresses + entities.each do |entity, instance| + if entity == CL_NL_ENTITY + etype, = wsctl(entity, instance, + INFO_CLASS_GENERIC, + INFO_TYPE_PROVIDER, + ENTITY_TYPE_ID, + 4) + if API.unpackdw(etype) == CL_NL_IP + ipentries, = wsctl(entity, instance, + INFO_CLASS_PROTOCOL, + INFO_TYPE_PROVIDER, + IP_MIB_ADDRTABLE_ENTRY_ID, + 24 * (ifcount+1)) # sizeof(IPAddrEntry) + ipentries.scan(/.{24}/) do |ipentry| + ipaddr, index = ipentry.unpack('VV') + if ifitem = iflist.assoc(index) + ifitem << ipaddr + end + end + end + end + end + iflist + end + end + end +end |