Golang: winapi call with struct parameter

I'm trying to call a function WinHttpGetIEProxyConfigForCurrentUserto get automatically discovered configuration IE proxy. It takes an inout struct parameter as per the documentation . I am using the 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 seems that the call is successful, settingsnot zero, but as soon as I receive it, I get a panic. Here's the conclusion:

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

You need to pass a pointer to the selected structure that you have already created using the function new. Remove excess &from syscall;uintptr(unsafe.Pointer(settings))

, , C, syscall. :

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 /char . 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]))
}
+4

:

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

+1

Source: https://habr.com/ru/post/1657293/


All Articles