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  }