1+ //go:build windows
12// +build windows
23
34// windows系统代理配置
@@ -15,12 +16,15 @@ import (
1516var (
1617 wininet , _ = syscall .LoadLibrary ("Wininet.dll" )
1718 internetSetOption , _ = syscall .GetProcAddress (wininet , "InternetSetOptionW" )
19+ // https://learn.microsoft.com/zh-cn/windows/win32/api/wininet/nf-wininet-internetqueryoptionw
20+ internetQueryOption , _ = syscall .GetProcAddress (wininet , "InternetQueryOptionA" )
1821)
1922
2023const (
2124 _INTERNET_OPTION_PER_CONNECTION_OPTION = 75
2225 _INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95
2326 _INTERNET_OPTION_REFRESH = 37
27+ _INTERNET_OPTION_PROXY = 38
2428)
2529
2630const (
@@ -43,6 +47,12 @@ const (
4347 _INTERNET_PER_CONN_FLAGS_UI = 10
4448)
4549
50+ const (
51+ INTERNET_OPEN_TYPE_PRECONFIG = 0 // use registry configuration
52+ INTERNET_OPEN_TYPE_DIRECT = 1 // 禁用代理 direct to net
53+ INTERNET_OPEN_TYPE_PROXY = 3 // 启用代理 via named proxy
54+ )
55+
4656type internetPerConnOptionList struct {
4757 dwSize uint32
4858 pszConnection * uint16
@@ -56,6 +66,30 @@ type internetPreConnOption struct {
5666 value uint64
5767}
5868
69+ // internetProxyInfo https://learn.microsoft.com/zh-cn/windows/win32/api/wininet/ns-wininet-internet_proxy_info
70+ type internetProxyInfo struct {
71+ dwAccessType uint32
72+ lpszProxy * uint16
73+ lpszProxyBypass * uint16
74+ }
75+
76+ type ProxyStatus struct {
77+ // 代理类型
78+ // - 0: INTERNET_OPEN_TYPE_PRECONFIG: use registry configuration
79+ // - 1: INTERNET_OPEN_TYPE_DIRECT: 不代理 direct to net
80+ // - 3: INTERNET_OPEN_TYPE_PROXY: 使用代理服务器 via named proxy
81+ Type uint32
82+ Proxy string // 代理IP地址与端口,IP:Port,例如:"127.0.0.1:7890"
83+ // 请勿对以下列条目开头的地址使用代理服务器
84+ // 注意:
85+ // - 这里的地址是ASCII编码
86+ // - "<local>" 表示 本地(Intranet)地址,如果包含 "<local>" 则 DisableProxyIntranet 为 true
87+ //
88+ // 例如:["localhost","127.*"],
89+ Bypass []string
90+ DisableProxyIntranet bool // 请勿将代理服务器用于本地(Intranet)地址
91+ }
92+
5993// stringPtrAddr 获取C字符串(UTF16)的数组第一个位置的地址
6094func stringPtrAddr (str string ) (uint64 , error ) {
6195 scriptLocPtr , err := syscall .UTF16PtrFromString (str )
@@ -114,8 +148,8 @@ func SetPAC(scriptLoc string) error {
114148}
115149
116150// SetGlobalProxy 设置全局代理
117- // proxyServer: 代理服务器host :port,例如: "127.0.0.1:7890"
118- // bypass: 忽略代理列表,这些配置项开头的地址不进行代理
151+ // - proxyServer: 代理服务器 host :port,例如: "127.0.0.1:7890"
152+ // - bypass: 忽略代理列表,这些配置项开头的地址不进行代理,若包含 "<local>" 则 ”请勿将代理服务器用于本地(Intranet)地址“ 将勾选。
119153func SetGlobalProxy (proxyServer string , bypasses ... string ) error {
120154 if proxyServer == "" {
121155 return errors .New ("代理服务器(proxyServer)配置为空" )
@@ -210,3 +244,50 @@ func Flush() error {
210244 }
211245 return nil
212246}
247+
248+ // Status 获取当前系统代理配置
249+ func Status () (* ProxyStatus , error ) {
250+ var bufferLength uint32 = 1024 * 10
251+ buffer := make ([]byte , bufferLength )
252+ ret , _ , infoPtr := syscall .Syscall6 (internetQueryOption ,
253+ 4 ,
254+ 0 ,
255+ _INTERNET_OPTION_PROXY ,
256+ uintptr (unsafe .Pointer (& buffer [0 ])), uintptr (unsafe .Pointer (& bufferLength )),
257+ 0 , 0 )
258+ if ret != 1 {
259+ return nil , errors .New (fmt .Sprintf ("%s" , infoPtr ))
260+ }
261+ //fmt.Println(hex.Dump(buffer[:bufferLength]))
262+ proxyInfo := (* internetProxyInfo )(unsafe .Pointer (& buffer [0 ]))
263+ res := & ProxyStatus {
264+ Type : proxyInfo .dwAccessType ,
265+ Proxy : asciiPtrToString (proxyInfo .lpszProxy ),
266+ }
267+ bypassArr := asciiPtrToString (proxyInfo .lpszProxyBypass )
268+ res .Bypass = strings .SplitN (bypassArr , " " , - 1 )
269+ for _ , bypass := range res .Bypass {
270+ if bypass == "<local>" {
271+ res .DisableProxyIntranet = true
272+ break
273+ }
274+ }
275+ return res , nil
276+ }
277+
278+ // ASCIIPtrToString 将UTF16指针转换为ASCII字符串
279+ func asciiPtrToString (p * uint16 ) string {
280+ if p == nil {
281+ return ""
282+ }
283+ res := []byte {}
284+ end := unsafe .Pointer (p )
285+ for {
286+ if * (* uint8 )(end ) == 0 {
287+ break
288+ }
289+ res = append (res , * (* uint8 )(end ))
290+ end = unsafe .Pointer (uintptr (end ) + 1 )
291+ }
292+ return string (res )
293+ }
0 commit comments