2016-10-10 38 views
4

我試圖調用WinHttpGetIEProxyConfigForCurrentUser函數來獲取自動檢測到的IE代理設置。它接受根據documentation的inout結構參數。我使用下面的代碼:golang:winapi調用結構參數

func GetProxySettings() { 
    winhttp, _ := syscall.LoadLibrary("winhttp.dll") 
    getIEProxy, _ := syscall.GetProcAddress(winhttp, "WinHttpGetIEProxyConfigForCurrentUser") 

    settings := new(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG) 
    var nargs uintptr = 1 

    ret, _, callErr := syscall.Syscall(uintptr(getIEProxy), nargs, uintptr(unsafe.Pointer(&settings)), 0, 0) 
    fmt.Println(ret, callErr) 
    if settings != nil { 
     fmt.Println(settings.fAutoDetect) 
     fmt.Println(settings.lpszAutoConfigUrl) 
     fmt.Println(settings.lpszProxy) 
     fmt.Println(settings.lpszProxyBypass) 
    } 
} 

type WINHTTP_CURRENT_USER_IE_PROXY_CONFIG struct { 
    fAutoDetect  bool 
    lpszAutoConfigUrl string 
    lpszProxy   string 
    lpszProxyBypass string 
} 

它看起來像調用成功,settings不是零,但只要我訪問它,我得到的恐慌。下面是輸出:

1 The operation completed successfully. 
panic: runtime error: invalid memory address or nil pointer dereference 
[signal 0xc0000005 code=0x0 addr=0x1 pc=0x4d2bb4] 
+1

Go字符串與C字符串不同,在這種情況下,文檔看起來像字段應該是寬字符(?),所以這些應該可能是'* uint16'而不是字符串。你還傳遞一個指向系統調用的指針,它只需要一個指針。擺脫參數中額外的'&'。 – JimB

+0

感謝您的提示。如何將'* uint16'轉換爲去串?我發現'UTF16PtrFromString'做了相反的轉換,但沒有任何東西可以轉換回來。 – rosencreuz

回答

4

您需要將指針傳遞給您已經使用new函數創建的已分配結構。從系統調用中刪除額外的&; uintptr(unsafe.Pointer(settings))

您還需要具有與系統調用預期的C結構具有相同佈局的結構。結構定義是這樣的:

typedef struct { 
    BOOL fAutoDetect; 
    LPWSTR lpszAutoConfigUrl; 
    LPWSTR lpszProxy; 
    LPWSTR lpszProxyBypass; 
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; 

這應該轉化爲

type WINHTTP_CURRENT_USER_IE_PROXY_CONFIG struct { 
    fAutoDetect  bool 
    lpszAutoConfigUrl *uint16 
    lpszProxy   *uint16 
    lpszProxyBypass *uint16 
} 

每個那些LPWSTR領域將是一個空結束,16位/字符的字符串。爲了將它們轉換爲Go字符串,首先需要將*uint16轉換爲[]uint16切片,然後將該切片解碼爲utf8字符串。

// Convert a *uint16 C string to a Go String 
func GoWString(s *uint16) string { 
    if s == nil { 
     return "" 
    } 

    p := (*[1<<30 - 1]uint16)(unsafe.Pointer(s)) 

    // find the string length 
    sz := 0 
    for p[sz] != 0 { 
     sz++ 
    } 

    return string(utf16.Decode(p[:sz:sz])) 
} 
1

你把這裏的地址的地址:

// The type of settings is *WINHTTP_CURRENT_USER_IE_PROXY_CONFIG 
settings := new(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG) 

// ... 

// The type of &settings is **WINHTTP_CURRENT_USER_IE_PROXY_CONFIG 
ret, _, callErr := syscall.Syscall(uintptr(getIEProxy), nargs, uintptr(unsafe.Pointer(&settings)), 0, 0) 

取出&Syscall調用一個它應該工作。

+0

你說得對。但是'lpszProxy'的類型仍然存在問題。 'string'似乎並不正確。我試過'* uint16',但我找不到將其轉換爲字符串的方法。 – rosencreuz