2010-02-13 1 views
0

En VB6, je lance un appel à l'API Windows DnsQuery.VB6 - Appel de l'API Windows à DnsQuery - Fonction et pointeur Question

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 

Ma déclaration du struct est venu de here. Je suppose que les autres (35) doivent fournir un conteneur assez grand lorsque la structure réelle retournée est plus grande que prévu (il y a quelques types de longueur variable UNIONed dedans). Voir le DNS_RECORD structure pour plus de détails.

Donc, j'ai 2 questions:

  1. cordes en VB sont vraiment, dans les coulisses, les pointeurs de mots doubles (4 octets, alias un long). Pour un peu j'ai pensé que je pourrais déclarer Name comme une chaîne puisque ceci placerait juste le pointeur dedans et fonctionnerait correctement (comme quand passer VB Strings dans les appels d'API). Cependant, j'imagine que les terminaisons d'application que j'ai sont parce que c'est une chaîne de style C et non une chaîne de style VB, et VB regarde dans l'emplacement de mémoire juste avant le début de la chaîne pour une valeur de longueur ordures et explosions. Est-ce une supposition raisonnable?

  2. Mon appel à DnsQuery fonctionne quand je retourne un DNS DNS de type DNS_PTR_DATA ou DNS_A_DATA, mais quand j'essaie DNS_TXT_DATA, il fait exploser. Est-ce que quelqu'un d'autre peut repérer ce que je fais mal? Regardez Case DNS_TYPE_TEXT, et voir mes commentaires ci-dessous.

    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 
    

    Maintenant, quand je mets un point d'arrêt sur la ligne CopyMemory et contrôler la valeur de Ptr, je me attends quelque chose dans les millions ou plus, ce qui indique qu'il est un pointeur, que je reçois la valeur 1 (ce qui explique pourquoi tout éclate quand j'essaie de copier à partir de cet emplacement de mémoire). Cela semble indiquer à moi qu'au lieu d'un pointeur vers la structure DNS_TXT_DATA attendue, j'obtiens le nombre de chaînes. Quand j'examine Other (0) à Other (3), ils ont tous des valeurs qui me font penser que les quatre octets suivants sont un pointeur. Alors qu'est-ce qui donne? Pourquoi cette structure arrive-t-elle juste en ligne, mais les autres arrivent-ils comme des indicateurs du début de la structure?

J'apprécie n'importe quelle aide!

Répondre

0

1) Les chaînes de caractères C et VB sont différentes et vous ne pouvez pas les remplacer par d'autres. Vous devrez convertir explicitement la chaîne C en une chaîne VB. En d'autres termes, oui, votre estimation est raisonnable.

2) J'ai jeté un coup d'œil aux documents Microsoft, qui indiquent que DNS_TXT_DATA est un nombre suivi d'un pointeur vers une chaîne (ce que vous voyez). DNS_PTR_DATA, d'autre part, est un point à l'enregistrement résultant. Donc ce que vous décrivez semble correspondre à la documentation.

+0

1) Les chaînes VB ne sont-elles pas également terminées par un caractère nul? Donc, les chaînes VB fonctionnent bien en tant que chaînes C, mais pas l'inverse, non? et 2) Maintenant, je le vois enfin! J'ai été découragé par l'appel à inet_ntoa, qui renvoie une chaîne (pointeur vers a). Mais c'est vraiment une valeur. D'une manière ou d'une autre, je devinais que c'était un pointeur.Je sais exactement quoi faire maintenant (mais je n'y reviendrai que mardi). – ErikE

+0

Je ne crois pas que les chaînes VB sont à terminaison nulle; aussi, ils utilisent des caractères larges. Vous devez utiliser des routines de conversion dans les deux sens. – jdigital

+0

Si elles utilisent des caractères larges et que les fonctions API ne le font pas, CopyMemory ne fonctionnera pas correctement, mais cela fonctionne. Il semble que vous répondez plus à la théorie qu'à la pratique? – ErikE

2

Si vous changez Others en VBDnsRecord-pStringArray(0 To 8) As Long il sera plus facile d'accéder au tableau ot pointeurs de chaîne comme ce

 ... 
     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 

Neuf Longs sont exactement 36 octets afin Len(VBDnsRecords) reste 64 octets, exactement la taille de la DNS_RECORD union dans Platform SDK.

+0

Je suis parti et j'ai joué avec des choses par moi-même et j'ai fini par trouver ... fondamentalement exactement ce que vous avez fait ici (bien que je doive boo à la notation hongroise sur vos types de données). Entre toi et jdigital, j'ai compris mon idée fausse. Il aurait été bien que l'un d'entre vous dise explicitement que "les éléments UNION sont directement intégrés dans la structure parente, il n'y a aucun pointeur ici". – ErikE

+0

P.S., la structure ne change-t-elle pas en fonction de ce qu'elle contient? – ErikE

+0

Non, la structure (union) est exactement de 64 octets. Vous êtes légitimement dégoûté par le hongrois sur les variables (types de données?) Mais passer plus de temps avec Win32 API vous sortira de boo ... – wqw