2010-02-13 61 views
0

在VB6中,我打電話給Windows API DnsQueryVB6 - 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 

我的結構聲明來自here。我認爲其他(35)提供了一個足夠大的容器,當返回的實際結構比預期的要大時(那裏有一些變長的類型UNIONed)。有關更多詳細信息,請參閱DNS_RECORD structure

所以,我有2個問題:在VB

  1. 字符串是真的,在幕後,雙字指針(4個字節,又名一個Long)。有一點我認爲我可以將Name聲明爲String,因爲這隻需將指針放在那裏並正確工作(就像將VB字符串傳遞給API調用時一樣)。但是,我猜應用程序終止是因爲它是一個C風格的字符串而不是VB風格的字符串,並且VB在字符串開始之前查找長度值的內存位置,並獲取一些隨機數垃圾和炸燬。這是一個合理的猜測嗎?

  2. 當我使用返回DNS RR類型的DNS_PTR_DATA或DNS_A_DATA時,我對DnsQuery的調用起作用,但是當我嘗試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結構的指針,我得到了字符串的數量。當我通過其他(3)檢查其他(0)時,它們都具有使我懷疑接下來的四個字節是指針的值。那麼是什麼給了?爲什麼這個結構只是以「內聯」方式進入,而其他結構是作爲指向結構開始的指針?

我很感激任何幫助!

回答

0

1)C字符串和VB字符串不同,你不能只替換一個。您需要將C字符串顯式轉換爲VB字符串。換句話說,是的,你的猜測是合理的。

2)我快速瀏覽了微軟的文檔,其中說DNS_TXT_DATA是一個數字後跟一個指向字符串的指針(這就是你所看到的)。另一方面,DNS_PTR_DATA是指向結果記錄的一點。所以你所描述的似乎與文檔相匹配。

+0

1)VB字符串是否也以空字符結尾?所以VB字符串工作正常,因爲C字符串,但不是相反的方式,對嗎? 2)現在我終於明白了!我被inet_ntoa調用拋出,它返回一個(指向一個)字符串的指針。但它確實只是一種價值。不知何故,我得到它是一個指針。我現在確切地知道該怎麼做(但直到星期二才能回覆它)。 – ErikE 2010-02-14 23:58:12

+0

我不認爲VB字符串是nul-terminated;另外,他們使用廣泛的字符。您應該在兩個方向上使用轉換例程。 – jdigital 2010-02-16 19:16:11

+0

如果他們使用寬字符和API函數不,那麼CopyMemory將無法正常工作,但它確實有效。看來你在理論上比實際回答更多? – ErikE 2010-02-17 00:35:16

2

如果您在VBDnsRecord改變OtherspStringArray(0 To 8) As Long它會更容易訪問數組OT字符串指針這樣

 ... 
     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的尺寸完全相同平臺SDK中的聯合。

+0

我走開了,自己玩了一些東西,最終想出了......基本上就是你在這裏做了什麼(儘管我必須在你的數據類型上用匈牙利符號噓聲)。在你和jdigital之間,我想出了我的誤解。如果你明確地說「UNIONed元素直接嵌入到父結構體中,那麼在這裏根本就沒有任何指針」。 – ErikE 2010-02-17 01:02:44

+0

P.S.,這個結構體的大小是不是取決於它的大小? – ErikE 2010-02-17 02:36:12

+0

不,結構(聯合)恰好是64個字節。你對匈牙利人的變數(數據類型?)感到非常反感,但是花更多時間在Win32 API上卻會讓你失望。 – wqw 2010-02-17 08:37:51