-
Notifications
You must be signed in to change notification settings - Fork 1
/
enableProxy_windows.go
141 lines (119 loc) · 4.72 KB
/
enableProxy_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//go:build windows
package main
import (
"fmt"
"log"
"syscall"
"unsafe"
"golang.org/x/sys/windows/registry"
)
func enableProxy(addrPort string) error {
fmt.Println("Setting up proxy on localhost:8888")
setWinInetProxy(addrPort)
setWinEnvProxy(addrPort)
}
func disableProxy() {
fmt.Println("Cleaning up proxy")
setWinInetProxy("")
setWinEnvProxy("")
}
func setWinInetProxy(proxy string) bool {
var exceptions, autoconfig string
var autodetect bool
options := [4]InternetConnectionOption{}
options[0].Option = INTERNET_PER_CONN_FLAGS
options[1].Option = INTERNET_PER_CONN_PROXY_SERVER
options[2].Option = INTERNET_PER_CONN_PROXY_BYPASS
options[3].Option = INTERNET_PER_CONN_AUTOCONFIG_URL
options[0].Value = PROXY_TYPE_DIRECT
if proxy != "" {
options[0].Value |= PROXY_TYPE_PROXY
options[1].Value = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(proxy)))
}
if exceptions != "" {
options[2].Value = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(exceptions)))
}
if autoconfig != "" {
options[0].Value |= PROXY_TYPE_AUTO_PROXY_URL
options[3].Value = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(autoconfig)))
}
if autodetect {
options[0].Value |= PROXY_TYPE_AUTO_DETECT
}
list := InternetPerConnOptionList{0, 0, uint32(4), 0, uintptr(unsafe.Pointer(&options))}
list.dwSize = uint32(unsafe.Sizeof(list))
var winInet = syscall.NewLazyDLL("WinInet.dll")
var proc = winInet.NewProc("InternetSetOptionW")
ret, _, err := proc.Call(0, uintptr(INTERNET_OPTION_PER_CONNECTION_OPTION), uintptr(unsafe.Pointer(&list)), uintptr(unsafe.Sizeof(list)))
if err != nil {
fmt.Println(err)
}
return ret > 0
}
type InternetPerConnOptionList struct {
dwSize uint32 // size of the INTERNET_PER_CONN_OPTION_LIST struct
pszConnection uintptr // connection name to set/query options
dwOptionCount uint32 // number of options to set/query
dwOptionError uint32 // on error, which option failed
options uintptr
}
type InternetConnectionOption struct {
Option uint32
Value uintptr // in c this is UNION(DWORD, LPTSTR, FILETIME)
}
const (
// options manifests for Internet{Query|Set}Option
INTERNET_OPTION_REFRESH = 37
INTERNET_OPTION_SETTINGS_CHANGED = 39
INTERNET_OPTION_PER_CONNECTION_OPTION = 75
// Options used in INTERNET_PER_CONN_OPTON struct
INTERNET_PER_CONN_FLAGS = 1 // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags
INTERNET_PER_CONN_PROXY_SERVER = 2 // Sets or retrieves a string containing the proxy servers.
INTERNET_PER_CONN_PROXY_BYPASS = 3 // Sets or retrieves a string containing the URLs that do not use the proxy server.
INTERNET_PER_CONN_AUTOCONFIG_URL = 4 // Sets or retrieves a string containing the URL to the automatic configuration script.
// PER_CONN_FLAGS
PROXY_TYPE_DIRECT = 0x00000001 // direct to net
PROXY_TYPE_PROXY = 0x00000002 // via named proxy
PROXY_TYPE_AUTO_PROXY_URL = 0x00000004 // autoproxy URL
PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
)
const (
envText = "Environment"
HWND_BROADCAST = 0xffff
WM_SETTINGCHANGE = 0x001A
SMTO_ABORTIFHUNG = 0x2
)
// SEE: https://support.microsoft.com/en-us/help/104011/how-to-propagate-environment-variables-to-the-system
// and https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx says:
// To programmatically add or modify system environment variables, add them to the
// KEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key,
// then broadcast a WM_SETTINGCHANGE message with lParam set to the string "Environment".
func setWinEnvProxy(value string) error {
k, err := registry.OpenKey(registry.CURRENT_USER, `Environment`, registry.SET_VALUE)
if err != nil {
log.Printf("%v\n", k)
log.Fatal(err)
}
defer k.Close()
if value == "" {
fmt.Println("Removing http_proxy environment variable")
err = k.DeleteValue("http_proxy")
} else {
fmt.Printf("Setting http_proxy environment variable = %s\n", value)
err = k.SetStringValue("http_proxy", value)
}
if err != nil {
fmt.Println("SetProxyEnvVar ERROR!!!")
}
// notify windows-friendly programs that the environment variable has changed
// note that not all programs listen for these changes, so some may need to be restarted
var proc = syscall.NewLazyDLL("user32.dll").NewProc("SendMessageTimeoutW")
//et, _, err :=
envUTF := uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(envText)))
proc.Call(HWND_BROADCAST, uintptr(WM_SETTINGCHANGE), 0, envUTF, uintptr(SMTO_ABORTIFHUNG), uintptr(5000))
//todo: reimplement check, ignore errors which are actually success messages
// if err != nil {
// fmt.Printf("UpdateEnvPath ERROR!!! %v %v ??!\n", ret, err)
// log.Fatal(err)
// }
}