2016-10-10 2 views
4

WinHttpGetIEProxyConfigForCurrentUser 함수를 호출하여 자동으로 탐지 된 IE 프록시 설정을 가져 오려고합니다. documentation에 따라 inout 구조체 매개 변수를 허용합니다.golang : struct 매개 변수가있는 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'이어야합니다 . 또한 포인터 하나만 필요로하는 syscall에 대한 포인터에 대한 포인터를 전달하고 있습니다. 인수에서 여분의'&'를 제거하십시오. – JimB

+0

팁 주셔서 감사. '* uint16'을 go 문자열로 변환하려면 어떻게해야합니까? 반대 변환을하는'UTF16PtrFromString'을 찾았지만 다시 변환 할 것은 없습니다. – rosencreuz

답변

4

new 함수로 이미 생성 한 할당 된 구조체에 대한 포인터를 전달해야합니다. syscall에서 여분의 &을 제거하십시오. uintptr(unsafe.Pointer(settings))

또한 시스템 레이아웃에서 예상되는 C 구조체와 동일한 레이아웃을 가진 구조체가 있어야합니다. 그 LPWSTR 각 필드는 null로 끝나는, 16 비트/문자 문자열이 될 것입니다

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

로 번역해야하는

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

: 같은 구조체 정의 보인다. 이를 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

관련 문제