2016-10-10 3 views
4

Ich versuche WinHttpGetIEProxyConfigForCurrentUser Funktion aufrufen, um die automatisch erkannt IE Proxy-Einstellungen zu erhalten. Es akzeptiert einen inout-struct-Parameter gemäß documentation. Ich verwende folgenden Code:Golang: Winapi Aufruf mit Strukturparameter

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 
} 

Es sieht aus wie der Aufruf erfolgreich ist, settings nicht gleich Null ist, aber sobald ich es greife ich Panik bekommen. Hier ist die Ausgabe:

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

A Go-String ist nicht das gleiche wie ein C-String, und in diesem Fall die Dokumentation aussehen die Felder breiten Zeichen sein sollen (?), So werden diese sollten wahrscheinlich '* uint16' statt String . Sie übergeben auch einen Zeiger auf einen Zeiger auf den Syscall, der nur einen einzelnen Zeiger erfordert. loswerden der zusätzlichen '&' in den Argumenten. – JimB

+0

Danke für den Tipp. Wie konvertiere ich den '* uint16' in einen Go-String? Ich habe 'UTF16PtrFromString' gefunden, das die umgekehrte Umwandlung macht, aber nichts, um zurück zu konvertieren. – rosencreuz

Antwort

4

Sie müssen einen Zeiger auf Ihre zugewiesene Struktur übergeben, die Sie bereits mit der Funktion new erstellt haben. Entfernen Sie die zusätzliche & aus dem Syscall; uintptr(unsafe.Pointer(settings))

Sie müssen auch eine Struktur haben, die dasselbe Layout wie die C-Struktur hat, die von dem Syscall erwartet wird. Die Struktur Definition wie folgt aussieht:

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

die zu

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

Jede dieser LPWSTR Felder sein wird, eine Null-terminierte, 16bit/char string übersetzen sollte. Um diese in eine Go-Zeichenfolge umzuwandeln, müssen Sie zuerst die *uint16 in eine []uint16 Schicht konvertieren und dann diese Schicht in eine utf8-Zeichenfolge decodieren.

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

Sie nehmen die Adresse einer Adresse hier ein:

// 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) 

Entfernen Sie die & von Syscall Anruf ein sollte es funktionieren.

+0

Sie haben Recht. Allerdings gibt es immer noch Probleme mit der Art von 'lpszProxy'. 'string' scheint nicht richtig zu sein. Ich habe '* uint16' versucht, aber ich finde keine Möglichkeit, es in eine Zeichenkette umzuwandeln. – rosencreuz