⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modmxquery.bas

📁 简单、实用、特别。 有很多不足之处
💻 BAS
📖 第 1 页 / 共 2 页
字号:
Attribute VB_Name = "modMXQuery"

Option Explicit

' winsock
Private Const DNS_RECURSION As Byte = 1
Private Const AF_INET = 2
Private Const SOCKET_ERROR = -1
Private Const ERROR_BUFFER_OVERFLOW = 111
Private Const SOCK_DGRAM = 2
Private Const INADDR_NONE = &HFFFFFFFF
Private Const INADDR_ANY = &H0
' registry access
Private Const REG_SZ = 1&
Private Const ERROR_SUCCESS = 0&
Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const HKEY_CURRENT_USER = &H80000001
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const KEY_QUERY_VALUE = &H1&
Private Const KEY_ENUMERATE_SUB_KEYS = &H8&
Private Const KEY_NOTIFY = &H10&
Private Const READ_CONTROL = &H20000
Private Const SYNCHRONIZE = &H100000
Private Const STANDARD_RIGHTS_READ = READ_CONTROL
Private Const KEY_READ = STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY

' winsock
Private Type WSADATA
    wVersion                As Integer
    wHighVersion            As Integer
    szDescription(256)      As Byte
    szSystemStatus(128)     As Byte
    iMaxSockets             As Integer
    iMaxUdpDg               As Integer
    lpVendorInfo            As Long
End Type

Private Type DNS_HEADER
    qryID                   As Integer
    options                 As Byte
    response                As Byte
    qdcount                 As Integer
    ancount                 As Integer
    nscount                 As Integer
    arcount                 As Integer
End Type

Private Type IP_ADDRESS_STRING
    IpAddressStr(4 * 4 - 1) As Byte
End Type
 
Private Type IP_MASK_STRING
    IpMaskString(4 * 4 - 1) As Byte
End Type
 
Private Type IP_ADDR_STRING
    Next                    As Long
    IpAddress               As IP_ADDRESS_STRING
    IpMask                  As IP_MASK_STRING
    Context                 As Long
End Type

Private Type FIXED_INFO
    HostName(128 + 4 - 1)   As Byte
    DomainName(128 + 4 - 1) As Byte
    CurrentDnsServer        As Long
    DnsServerList           As IP_ADDR_STRING
    NodeType                As Long
    ScopeId(256 + 4 - 1)    As Byte
    EnableRouting           As Long
    EnableProxy             As Long
    EnableDns               As Long
End Type

Private Type SOCKADDR
    sin_family              As Integer
    sin_port                As Integer
    sin_addr                As Long
    sin_zero                As String * 8
End Type

Private Type HostEnt
    h_name                  As Long
    h_aliases               As Long
    h_addrtype              As Integer
    h_length                As Integer
    h_addr_list             As Long
End Type

' registry
Private Type FILETIME
    dwLowDateTime           As Long
    dwHighDateTime          As Long
End Type

' public type for passing DNS info
Public Type DNS_INFO
    Servers()               As String
    Count                   As Long
    LocalDomain             As String
    RootDomain              As String
End Type

' used below
Public Type MX_RECORD
    Server                  As String
    Pref                    As Integer
End Type

' public type for passing MX info
Public Type MX_INFO
    Best                    As String
    Domain                  As String
    List()                  As MX_RECORD
    Count                   As Long
End Type

Public DNS                  As DNS_INFO
Public MX                   As MX_INFO


' API prototypes

' winsock, 'wsock32.dll' used instead of 'ws2_32.dll' for wider compatibility
Private Declare Function gethostbyname Lib "wsock32.dll" (ByVal host_name As String) As Long
Private Declare Function gethostbyaddr Lib "ws2_32.dll" (addr As Long, ByVal addr_len As Long, ByVal addr_type As Long) As Long
Private Declare Function inet_addr Lib "wsock32.dll" (ByVal cp As String) As Long
Private Declare Function recvfrom Lib "wsock32.dll" (ByVal s As Long, buf As Any, ByVal buflen As Long, ByVal flags As Long, from As SOCKADDR, fromlen As Long) As Long
Private Declare Function socket Lib "wsock32.dll" (ByVal af As Long, ByVal s_type As Long, ByVal protocol As Long) As Long
Private Declare Function htons Lib "wsock32.dll" (ByVal hostshort As Long) As Integer
Private Declare Function ntohs Lib "wsock32.dll" (ByVal netshort As Long) As Integer
Private Declare Function sendto Lib "wsock32.dll" (ByVal s As Long, buf As Any, ByVal buflen As Long, ByVal flags As Long, to_addr As SOCKADDR, ByVal tolen As Long) As Long
Private Declare Function WSAGetLastError Lib "wsock32.dll" () As Long
Private Declare Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequired As Long, lpWSAData As WSADATA) As Long
Private Declare Function WSACleanup Lib "wsock32.dll" () As Long

' Registry access
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, ByVal lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As FILETIME) As Long

' misc
Private Declare Function GetNetworkParams Lib "iphlpapi.dll" (pFixedInfo As Any, pOutBufLen As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long


Public Sub GetDNSInfo()

    ' get the DNS servers and the local IP Domain name
    
    Dim sBuffer                 As String
    Dim sDNSBuff                As String
    Dim sDomainBuff             As String
    Dim sKey                    As String
    Dim lngFixedInfoNeeded      As Long
    Dim bytFixedInfoBuffer()    As Byte
    Dim udtFixedInfo            As FIXED_INFO
    Dim lngIpAddrStringPtr      As Long
    Dim udtIpAddrString         As IP_ADDR_STRING
    Dim strDnsIpAddress         As String
    Dim nRet                    As Long
    Dim sTmp()                  As String
    Dim I                       As Long
       
    ' get dns servers with the new GetNetworkParams call (only works on 98/ME/2000)
    ' if GetNetworkParams is not supported then try reading from the registry
    If Exported("iphlpapi.dll", "GetNetworkParams") Then
        nRet = GetNetworkParams(ByVal vbNullString, lngFixedInfoNeeded)
        If nRet = ERROR_BUFFER_OVERFLOW Then
            ReDim bytFixedInfoBuffer(lngFixedInfoNeeded)
            nRet = GetNetworkParams(bytFixedInfoBuffer(0), lngFixedInfoNeeded)
            CopyMemory udtFixedInfo, bytFixedInfoBuffer(0), Len(udtFixedInfo)
            With udtFixedInfo
                ' get the DNS servers
                lngIpAddrStringPtr = VarPtr(.DnsServerList)
                Do While lngIpAddrStringPtr
                    CopyMemory udtIpAddrString, ByVal lngIpAddrStringPtr, Len(udtIpAddrString)
                    With udtIpAddrString
                        strDnsIpAddress = StripTerminator(StrConv(.IpAddress.IpAddressStr, vbUnicode))
                        sDNSBuff = sDNSBuff & strDnsIpAddress & ","
                        lngIpAddrStringPtr = .Next
                    End With
                Loop
                ' get the ip domain name
                sDomainBuff = StripTerminator(StrConv(.DomainName, vbUnicode))
            End With
        End If
    End If
    
    ' if GetNetworkParams didn't get the data we need,
    ' try known locations in the registry for DNS & domain info
    If Len(sDNSBuff) = 0 Or Len(sDomainBuff) = 0 Then

        ' DNS servers configured through Network control panel applet (95/98/ME)
        sKey = "System\CurrentControlSet\Services\VxD\MSTCP"
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "NameServer", "")
        If Len(sBuffer) Then sDNSBuff = sBuffer & ","
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "Domain", "")
        If Len(sBuffer) Then sDomainBuff = sBuffer

        ' DNS servers configured through Network control panel applet (NT/2000)
        sKey = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "NameServer", "")
        If Len(sBuffer) Then sDNSBuff = sBuffer & ","
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "Domain", "")
        If Len(sBuffer) Then sDomainBuff = sBuffer

        ' DNS servers configured DHCP (NT/2000/XP)
        sKey = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "DhcpNameServer", "")
        If Len(sBuffer) Then sDNSBuff = sBuffer & ","
        sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey, "DHCPDomain", "")
        If Len(sBuffer) Then sDomainBuff = sBuffer

        ' DNS servers configured through Network control panel applet (XP)
        sKey = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"
        sTmp = EnumRegKey(HKEY_LOCAL_MACHINE, sKey)
        For I = 0 To UBound(sTmp)
            sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey & "\" & sTmp(I), "NameServer", "")
            If Len(sBuffer) Then sDNSBuff = sBuffer & ","
            sBuffer = GetRegStr(HKEY_LOCAL_MACHINE, sKey & "\" & sTmp(I), "Domain", "")
            If Len(sBuffer) Then sDomainBuff = sBuffer
        Next
        
        ' DNS servers configured DHCP (95/98/ME)
        ' *** haven't found one ***
    
    End If

    ' get rid of any space delimiters (2000)
    sDNSBuff = Replace(sDNSBuff, " ", ",")

    ' trim any trailing commas
    If Right(sDNSBuff, 1) = "," Then sDNSBuff = Left(sDNSBuff, Len(sDNSBuff) - 1)

    ' load our type struc
    DNS.Servers = Split(sDNSBuff, ",")
    DNS.Count = UBound(DNS.Servers) + 1
    DNS.LocalDomain = sDomainBuff

    ' cheap trick
    If sDomainBuff = "" And DNS.Count > 0 Then
        sDomainBuff = GetRemoteHostName(DNS.Servers(0))
        nRet = InStr(sDomainBuff, ".")
        If nRet Then
            DNS.LocalDomain = Mid$(sDomainBuff, nRet + 1)
        End If
    End If

    sTmp = Split(sDomainBuff, ".")
    nRet = UBound(sTmp)
    If nRet > 0 Then
        DNS.RootDomain = sTmp(nRet - 1) & "." & sTmp(nRet)
    Else
        DNS.RootDomain = sDomainBuff
    End If

End Sub

Public Function MX_Query(ByVal ms_Domain As String) As String
    
    ' Performs the actual IP work to contact the DNS server,
    ' calls the other functions to parse and return the
    ' best server to send email through
    
    Dim StartupData     As WSADATA
    Dim SocketBuffer    As SOCKADDR
    Dim IpAddr          As Long
    Dim iRC             As Integer
    Dim dnsHead         As DNS_HEADER
    Dim iSock           As Integer
    Dim dnsQuery()      As Byte
    Dim sQName          As String
    Dim dnsQueryNdx     As Integer
    Dim iTemp           As Integer
    Dim iNdx            As Integer
    Dim dnsReply(2048)  As Byte
    Dim iAnCount        As Integer
    Dim dwFlags         As Long


    MX.Count = 0
    MX.Best = vbNullString
    ReDim MX.List(0)

    ' if DNSInfo hasn't been called, call it now
    If DNS.Count = 0 Then GetDNSInfo
    
    ' check to see that we found a dns server
    If DNS.Count = 0 Then
        ' problem
        Err.Raise 20000, "MXQuery", "No DNS entries found, MX Query cannot contine."
        Exit Function
    End If
   
    ' if null was passed in then use the local domain name
    If Len(ms_Domain) = 0 Then ms_Domain = DNS.LocalDomain
    
    ' validate domain name
    If Len(ms_Domain) < 5 Then
        Err.Raise 20000, "MXQuery", "No Valid Domain Specified"
        Exit Function
    End If
   
    MX.Domain = ms_Domain
   
    ' Initialize the Winsock, request v1.1
    If WSAStartup(&H101, StartupData) <> ERROR_SUCCESS Then
        iRC = WSACleanup
        Exit Function
    End If
    
    ' Create a socket
    iSock = socket(AF_INET, SOCK_DGRAM, 0)
    If iSock = SOCKET_ERROR Then Exit Function

    ' convert the IP address string to a network ordered long
    IpAddr = GetHostByNameAlias(DNS.Servers(0))
    If IpAddr = -1 Then Exit Function
    
    ' Setup the connnection parameters
    SocketBuffer.sin_family = AF_INET
    SocketBuffer.sin_port = htons(53)
    SocketBuffer.sin_addr = IpAddr
    SocketBuffer.sin_zero = String$(8, 0)
    
    ' Set the DNS parameters
    dnsHead.qryID = htons(&H11DF)
    dnsHead.options = DNS_RECURSION
    dnsHead.qdcount = htons(1)
    dnsHead.ancount = 0
    dnsHead.nscount = 0
    dnsHead.arcount = 0
    
    dnsQueryNdx = 0
    
    ReDim dnsQuery(4000)
    
    ' Setup the dns structure to send the query in
    ' First goes the DNS header information
    CopyMemory dnsQuery(dnsQueryNdx), dnsHead, 12
    dnsQueryNdx = dnsQueryNdx + 12
    
    ' Then the domain name (as a QNAME)
    sQName = MakeQName(MX.Domain)
    iNdx = 0
    While (iNdx < Len(sQName))
        dnsQuery(dnsQueryNdx + iNdx) = Asc(Mid(sQName, iNdx + 1, 1))
        iNdx = iNdx + 1
    Wend

    dnsQueryNdx = dnsQueryNdx + Len(sQName)
    
    ' Null terminate the string
    dnsQuery(dnsQueryNdx) = &H0
    dnsQueryNdx = dnsQueryNdx + 1
    
    ' The type of query (15 means MX query)
    iTemp = htons(15)
    CopyMemory dnsQuery(dnsQueryNdx), iTemp, Len(iTemp)
    dnsQueryNdx = dnsQueryNdx + Len(iTemp)
    
    ' The class of query (1 means INET)
    iTemp = htons(1)
    CopyMemory dnsQuery(dnsQueryNdx), iTemp, Len(iTemp)
    dnsQueryNdx = dnsQueryNdx + Len(iTemp)
    
    ReDim Preserve dnsQuery(dnsQueryNdx - 1)
    ' Send the query to the DNS server
    iRC = sendto(iSock, dnsQuery(0), dnsQueryNdx + 1, 0, SocketBuffer, Len(SocketBuffer))
    If (iRC = SOCKET_ERROR) Or (iRC = 0) Then
        Err.Raise 20000, "MXQuery", "Problem sending MX query"
        iRC = WSACleanup
        Exit Function
    End If

    ' Wait for answer from the DNS server
    iRC = recvfrom(iSock, dnsReply(0), 2048, 0, SocketBuffer, Len(SocketBuffer))
    If (iRC = SOCKET_ERROR) Or (iRC = 0) Then
        Err.Raise 20000, "MXQuery", "Problem receiving MX query"
        iRC = WSACleanup
        Exit Function
    End If

    ' Get the number of answers
    CopyMemory iAnCount, dnsReply(6), 2
    iAnCount = ntohs(iAnCount)
    
    iRC = WSACleanup
    
    If iAnCount Then
        ' Parse the answer buffer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -