VB6 - вызов API Windows для DnsQuery - вопрос о функциях и указателях - PullRequest
0 голосов
/ 13 февраля 2010

В VB6 я звоню в Windows API DnsQuery .

Private Declare Function DnsQuery Lib "dnsapi" Alias "DnsQuery_A" ( _
   ByVal lpstrName As String, _
   ByVal wType As Integer, _
   ByVal Options As Long, _
   ByVal pServers As Long, _
   ppQueryResultsSet As Long, _
   ByVal pReserved As Long) As Long

Private Type VBDnsRecord
   pNext           As Long
   pName           As Long
   'Name            As String ' Commented out, see question
   wType           As Integer
   wDataLength     As Integer
   Flags           As Long
   dwTtl           As Long
   dwReserved      As Long
   ptrData         As Long
   Others(35)      As Byte
End Type

Мое объявление структуры пришло от здесь . Я предполагаю, что Others (35) должен предоставить достаточно большой контейнер, когда возвращаемая фактическая структура больше ожидаемой (там есть несколько типов переменной длины UNIONed). См. DNS_RECORD структуру для получения более подробной информации.

Итак, у меня есть 2 вопроса:

  1. Строки в VB на самом деле, за кулисами, указатели двойных слов (4 байта, или длинная). Некоторое время я думал, что мог бы объявить Name как String, так как это просто поместило бы туда указатель и работало бы правильно (как при передаче строк VB в вызовы API). Тем не менее, я предполагаю, что завершения приложений, которые я получил, заключаются в том, что это строка в стиле C, а не строка в стиле VB, и VB ищет в ячейке памяти перед началом строки значение длины и получает случайное значение. мусор и взрывается. Это разумное предположение?

  2. Мой вызов DnsQuery работает, когда я использую, возвращает тип DNS RR DNS_PTR_DATA или DNS_A_DATA, но когда я пытаюсь DNS_TXT_DATA, он взрывается. Может кто-то еще заметит, что я делаю не так? Посмотрите на Дело DNS_TYPE_TEXT и посмотрите мои комментарии ниже.

    RetVal = DnsQuery(DnsName,
    QueryType, DNS_QUERY_BYPASS_CACHE,
    pServers, pDnsRecord, 0)
        If RetVal = 0 Then
           pNext = pDnsRecord
           Do While pNext <> 0
              CopyMemory DnsRecord, pNext, Len(DnsRecord)
              Select Case DnsRecord.wType
                 Case DNS_TYPE_A
                    Ptr = inet_ntoa(DnsRecord.ptrData)
                    TempString = String(lstrlen(Ptr), 0)
                    CopyMemory ByVal TempString, Ptr, Len(TempString)
                 Case DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME,
    DNS_TYPE_DNAME, DNS_TYPE_MB,
    DNS_TYPE_MD, DNS_TYPE_MF,
    DNS_TYPE_MG, DNS_TYPE_MR
                    Ptr = DnsRecord.ptrData
                    TempString = String$(lstrlen(Ptr), 0)
                    CopyMemory ByVal TempString, Ptr, Len(TempString)
                 Case DNS_TYPE_TEXT, DNS_TYPE_HINFO, DNS_TYPE_ISDN,
    DNS_TYPE_TEXT, DNS_TYPE_X25
                    Dim TextData As Dns_Txt_Data
                    Ptr = DnsRecord.ptrData
                    CopyMemory VarPtr(TextData), Ptr, Len(TextData)
                    Stop
                 Case Else
                    TempString = "unhandled resource record type"
             End Select
             If Not FullRecord Then
                DnsLookup = "   " & TempString
                Exit Do
             Else
                DnsLookup = DnsLookup & " " & vbCrLf &
    DnsTypeNameFromCode(DnsRecord.wType)
    & " " & TempString
             End If
             pNext = DnsRecord.pNext
          Loop
    

    Теперь, когда я ставлю точку останова на строку CopyMemory и проверяю значение Ptr, я ожидаю что-то в миллионах или выше, указывая, что это указатель, только я получаю значение 1 (что объясняет, почему все взрывается, когда я пытаюсь скопировать из этого места памяти). Мне кажется, это указывает на то, что вместо указателя на ожидаемую структуру DNS_TXT_DATA я получаю количество строк. Когда я проверяю Other (0) - Other (3), все они имеют значения, которые заставляют меня подозревать, что следующие четыре байта являются указателями. Так что же дает? Почему эта структура просто входит "в строку", а остальные входят как указатели на начало структуры?

Я ценю любую помощь!

Ответы [ 2 ]

2 голосов
/ 13 февраля 2010

Если вы измените Others в VBDnsRecord на pStringArray(0 To 8) As Long, вам будет проще получить доступ к массиву указателей на строки, как этот

        ...
        ElseIf uRecord.wType = DNS_TYPE_TEXT Then
            For lIdx = 0 To uRecord.prt - 1
                sName = String(lstrlen(uRecord.pStringArray(lIdx)), 0)
                Call CopyMemory(ByVal sName, uRecord.pStringArray(lIdx), Len(sName))
                If LenB(Resolve) <> 0 Then
                    Resolve = Resolve & vbCrLf
                End If
                Resolve = Resolve & sName
            Next
        End If

Девять Longs - это ровно 36 байтов, поэтому Len(VBDnsRecords) остается 64 байта, в точности размер объединения DNS_RECORD в Platform SDK.

0 голосов
/ 13 февраля 2010

1) Строки C и VB разные, и вы не можете просто заменить одну на другую. Вам нужно будет явно преобразовать строку C в строку VB. Другими словами, да, ваше предположение обоснованно.

2) Я быстро взглянул на документы Microsoft, которые говорят, что DNS_TXT_DATA - это число, за которым следует указатель на строку (что вы и видите). DNS_PTR_DATA , с другой стороны, указывает на результирующую запись. То, что вы описываете, похоже, соответствует документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...