I'm trying to call WinHttpGetIEProxyConfigForCurrentUser
function to get the automatically detected IE proxy settings. It accepts an inout struct parameter according to documentation. I'm using following code:
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
}
It looks like the call is successful, settings
is not nil, but as soon as I access it I get panic. Here's the output:
1 The operation completed successfully.
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x1 pc=0x4d2bb4]
You need to pass a pointer to your allocated struct, which you already created with the new
function. Remove the extra &
from the syscall; uintptr(unsafe.Pointer(settings))
You also need to have a struct that has the same layout as the C struct expected by the syscall. The struct definition looks like:
typedef struct {
BOOL fAutoDetect;
LPWSTR lpszAutoConfigUrl;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
Which should translate to
type WINHTTP_CURRENT_USER_IE_PROXY_CONFIG struct {
fAutoDetect bool
lpszAutoConfigUrl *uint16
lpszProxy *uint16
lpszProxyBypass *uint16
}
Each of those LPWSTR
fields is going to be a null-terminated, 16bit/char string. For windows you can generally use the syscall UTF16
functions, but here we first need to convert the *uint16
to a []uint16
slice, then decode that slice to a utf8 string. There function that the syscall pakcage uses to do this isn't exported, but we can easily copy that:
// utf16PtrToString is like UTF16ToString, but takes *uint16
// as a parameter instead of []uint16.
// max is how many times p can be advanced looking for the null terminator.
// If max is hit, the string is truncated at that point.
func utf16PtrToString(p *uint16, max int) string {
if p == nil {
return ""
}
// Find NUL terminator.
end := unsafe.Pointer(p)
n := 0
for *(*uint16)(end) != 0 && n < max {
end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
n++
}
s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n]
return string(utf16.Decode(s))
}
Or use the exported version that was recently added to golang.org/x/sys/windows
, windows.UTF16PtrToString
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With