github.com/sagernet/sing@v0.2.6/common/wininet/wininet_windows.go (about) 1 package wininet 2 3 import ( 4 "os" 5 "syscall" 6 "unsafe" 7 8 "golang.org/x/sys/windows" 9 ) 10 11 var ( 12 modwininet = windows.NewLazySystemDLL("wininet.dll") 13 procInternetSetOptionW = modwininet.NewProc("InternetSetOptionW") 14 ) 15 16 const ( 17 internetOptionPerConnectionOption = 75 18 internetOptionSettingsChanged = 39 19 internetOptionRefresh = 37 20 internetOptionProxySettingsChanged = 95 21 ) 22 23 const ( 24 internetPerConnFlags = 1 25 internetPerConnProxyServer = 2 26 internetPerConnProxyBypass = 3 27 internetPerConnAutoconfigUrl = 4 28 internetPerConnAutodiscoveryFlags = 5 29 internetPerConnAutoconfigSecondaryUrl = 6 30 internetPerConnAutoconfigReloadDelayMins = 7 31 internetPerConnAutoconfigLastDetectTime = 8 32 internetPerConnAutoconfigLastDetectUrl = 9 33 internetPerConnFlagsUi = 10 34 internetOptionProxyUsername = 43 35 internetOptionProxyPassword = 44 36 ) 37 38 const ( 39 proxyTypeDirect = 1 40 proxyTypeProxy = 2 41 proxyTypeAutoProxyUrl = 4 42 proxyTypeAutoDetect = 8 43 ) 44 45 type internetPerConnOptionList struct { 46 dwSize uint32 47 pszConnection uintptr 48 dwOptionCount uint32 49 dwOptionError uint32 50 pOptions uintptr 51 } 52 53 type internetPerConnOption struct { 54 dwOption uint32 55 value uint64 56 } 57 58 func internetSetOption(option uintptr, lpBuffer uintptr, dwBufferSize uintptr) error { 59 r0, _, err := syscall.SyscallN(procInternetSetOptionW.Addr(), 0, option, lpBuffer, dwBufferSize) 60 if r0 != 1 { 61 return err 62 } 63 return nil 64 } 65 66 func setOptions(options ...internetPerConnOption) error { 67 var optionList internetPerConnOptionList 68 optionList.dwSize = uint32(unsafe.Sizeof(optionList)) 69 optionList.dwOptionCount = uint32(len(options)) 70 optionList.dwOptionError = 0 71 optionList.pOptions = uintptr(unsafe.Pointer(&options[0])) 72 err := internetSetOption(internetOptionPerConnectionOption, uintptr(unsafe.Pointer(&optionList)), uintptr(optionList.dwSize)) 73 if err != nil { 74 return os.NewSyscallError("InternetSetOption(PerConnectionOption)", err) 75 } 76 err = internetSetOption(internetOptionSettingsChanged, 0, 0) 77 if err != nil { 78 return os.NewSyscallError("InternetSetOption(SettingsChanged)", err) 79 } 80 err = internetSetOption(internetOptionProxySettingsChanged, 0, 0) 81 if err != nil { 82 return os.NewSyscallError("InternetSetOption(ProxySettingsChanged)", err) 83 } 84 err = internetSetOption(internetOptionRefresh, 0, 0) 85 if err != nil { 86 return os.NewSyscallError("InternetSetOption(Refresh)", err) 87 } 88 return nil 89 } 90 91 func ClearSystemProxy() error { 92 var flagsOption internetPerConnOption 93 flagsOption.dwOption = internetPerConnFlags 94 *((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeDirect | proxyTypeAutoDetect 95 return setOptions(flagsOption) 96 } 97 98 func SetSystemProxy(proxy string, bypass string) error { 99 var flagsOption internetPerConnOption 100 flagsOption.dwOption = internetPerConnFlags 101 *((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeProxy | proxyTypeDirect 102 var proxyOption internetPerConnOption 103 proxyOption.dwOption = internetPerConnProxyServer 104 *((*uintptr)(unsafe.Pointer(&proxyOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(proxy))) 105 if bypass == "" { 106 return setOptions(flagsOption, proxyOption) 107 } 108 var bypassOption internetPerConnOption 109 bypassOption.dwOption = internetPerConnProxyBypass 110 *((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(bypass))) 111 return setOptions(flagsOption, proxyOption, bypassOption) 112 }