sing-box/common/settings/proxy_windows.go

112 lines
3.4 KiB
Go
Raw Normal View History

package settings
import (
"os"
"syscall"
"unsafe"
F "github.com/sagernet/sing/common/format"
"golang.org/x/sys/windows"
)
var (
modwininet = windows.NewLazySystemDLL("settings.dll")
procInternetSetOptionW = modwininet.NewProc("InternetSetOptionW")
)
const (
internetOptionPerConnectionOption = 75
internetOptionSettingsChanged = 39
internetOptionRefresh = 37
internetOptionProxySettingsChanged = 95
)
const (
internetPerConnFlags = 1
internetPerConnProxyServer = 2
internetPerConnProxyBypass = 3
internetPerConnAutoconfigUrl = 4
internetPerConnAutodiscoveryFlags = 5
internetPerConnAutoconfigSecondaryUrl = 6
internetPerConnAutoconfigReloadDelayMins = 7
internetPerConnAutoconfigLastDetectTime = 8
internetPerConnAutoconfigLastDetectUrl = 9
internetPerConnFlagsUi = 10
internetOptionProxyUsername = 43
internetOptionProxyPassword = 44
)
const (
proxyTypeDirect = 1
proxyTypeProxy = 2
proxyTypeAutoProxyUrl = 4
proxyTypeAutoDetect = 8
)
type internetPerConnOptionList struct {
dwSize uint32
pszConnection uintptr
dwOptionCount uint32
dwOptionError uint32
pOptions uintptr
}
type internetPerConnOption struct {
dwOption uint32
value [8]byte
}
func internetSetOption(option uintptr, lpBuffer uintptr, dwBufferSize uintptr) error {
r0, _, err := syscall.SyscallN(procInternetSetOptionW.Addr(), 0, option, lpBuffer, dwBufferSize)
if r0 != 1 {
return err
}
return nil
}
func setOptions(options ...internetPerConnOption) error {
var optionList internetPerConnOptionList
optionList.dwSize = uint32(unsafe.Sizeof(optionList))
optionList.dwOptionCount = uint32(len(options))
optionList.dwOptionError = 0
optionList.pOptions = uintptr(unsafe.Pointer(&options[0]))
err := internetSetOption(internetOptionPerConnectionOption, uintptr(unsafe.Pointer(&optionList)), uintptr(optionList.dwSize))
if err != nil {
return os.NewSyscallError("InternetSetOption(Direct)", err)
}
err = internetSetOption(internetOptionSettingsChanged, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(SettingsChanged)", err)
}
err = internetSetOption(internetOptionProxySettingsChanged, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(ProxySettingsChanged)", err)
}
err = internetSetOption(internetOptionRefresh, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(Refresh)", err)
}
return nil
}
func ClearSystemProxy() error {
var flagsOption internetPerConnOption
flagsOption.dwOption = internetPerConnFlags
*((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeDirect | proxyTypeAutoDetect
return setOptions(flagsOption)
}
func SetSystemProxy(port uint16, mixed bool) error {
var flagsOption internetPerConnOption
flagsOption.dwOption = internetPerConnFlags
*((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeProxy | proxyTypeDirect
var proxyOption internetPerConnOption
proxyOption.dwOption = internetPerConnProxyServer
*((*uintptr)(unsafe.Pointer(&proxyOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(F.ToString("http://127.0.0.1:", port))))
var bypassOption internetPerConnOption
bypassOption.dwOption = internetPerConnProxyBypass
*((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("local")))
return setOptions(flagsOption, proxyOption, bypassOption)
}