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:
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?
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!
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
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
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