You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

SystemProxy.cs 6.7 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System.Windows.Forms;
  2. using Microsoft.Win32;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.IO;
  8. using Shadowsocks.Model;
  9. namespace Shadowsocks.Controller
  10. {
  11. public static class SystemProxy
  12. {
  13. [DllImport("wininet.dll")]
  14. public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
  15. public const int INTERNET_OPTION_SETTINGS_CHANGED = 39;
  16. public const int INTERNET_OPTION_REFRESH = 37;
  17. static bool _settingsReturn, _refreshReturn;
  18. public static void NotifyIE()
  19. {
  20. // These lines implement the Interface in the beginning of program
  21. // They cause the OS to refresh the settings, causing IP to realy update
  22. _settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
  23. _refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
  24. }
  25. private static readonly DateTime UnixEpoch
  26. = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
  27. public static long ToUnixEpochMilliseconds(this DateTime dt)
  28. => (long)(dt - UnixEpoch).TotalMilliseconds;
  29. private static string GetTimestamp(DateTime value)
  30. {
  31. return value.ToString("yyyyMMddHHmmssfff");
  32. }
  33. public static void Update(Configuration config, bool forceDisable)
  34. {
  35. bool global = config.global;
  36. bool enabled = config.enabled;
  37. if (forceDisable)
  38. {
  39. enabled = false;
  40. }
  41. try
  42. {
  43. var registry = Registry.CurrentUser
  44. .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
  45. if (enabled)
  46. {
  47. if (global)
  48. {
  49. registry.SetValue("ProxyEnable", 1);
  50. registry.SetValue("ProxyServer", "127.0.0.1:" + config.localPort.ToString());
  51. registry.SetValue("AutoConfigURL", "");
  52. }
  53. else
  54. {
  55. string pacUrl;
  56. if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
  57. pacUrl = config.pacUrl;
  58. else
  59. pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}";
  60. registry.SetValue("ProxyEnable", 0);
  61. var readProxyServer = registry.GetValue("ProxyServer");
  62. registry.SetValue("ProxyServer", "");
  63. registry.SetValue("AutoConfigURL", pacUrl);
  64. }
  65. }
  66. else
  67. {
  68. registry.SetValue("ProxyEnable", 0);
  69. registry.SetValue("ProxyServer", "");
  70. registry.SetValue("AutoConfigURL", "");
  71. }
  72. //Set AutoDetectProxy
  73. IEAutoDetectProxy(!enabled);
  74. NotifyIE();
  75. //Must Notify IE first, or the connections do not chanage
  76. CopyProxySettingFromLan();
  77. }
  78. catch (Exception e)
  79. {
  80. Logging.LogUsefulException(e);
  81. // TODO this should be moved into views
  82. MessageBox.Show(I18N.GetString("Failed to update registry"));
  83. }
  84. }
  85. private static void CopyProxySettingFromLan()
  86. {
  87. var registry = Registry.CurrentUser
  88. .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections", true);
  89. var defaultValue = registry.GetValue("DefaultConnectionSettings");
  90. try
  91. {
  92. var connections = registry.GetValueNames();
  93. foreach (var each in connections)
  94. {
  95. switch (each.ToUpperInvariant())
  96. {
  97. case "DEFAULTCONNECTIONSETTINGS":
  98. case "LAN CONNECTION":
  99. case "SAVEDLEGACYSETTINGS":
  100. continue;
  101. default:
  102. //set all the connections's proxy as the lan
  103. registry.SetValue(each, defaultValue);
  104. continue;
  105. }
  106. }
  107. NotifyIE();
  108. }
  109. catch (IOException e)
  110. {
  111. Logging.LogUsefulException(e);
  112. }
  113. }
  114. /// <summary>
  115. /// Checks or unchecks the IE Options Connection setting of "Automatically detect Proxy"
  116. /// </summary>
  117. /// <param name="set">Provide 'true' if you want to check the 'Automatically detect Proxy' check box. To uncheck, pass 'false'</param>
  118. private static void IEAutoDetectProxy(bool set)
  119. {
  120. var registry = Registry.CurrentUser
  121. .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections", true);
  122. var defConnection = (byte[])registry.GetValue("DefaultConnectionSettings");
  123. var savedLegacySetting = (byte[])registry.GetValue("SavedLegacySettings");
  124. const int versionOffset = 4;
  125. const int optionsOffset = 8;
  126. if (set)
  127. {
  128. defConnection[optionsOffset] = (byte)(defConnection[optionsOffset] | 8);
  129. savedLegacySetting[optionsOffset] = (byte)(savedLegacySetting[optionsOffset] | 8);
  130. }
  131. else
  132. {
  133. defConnection[optionsOffset] = (byte)(defConnection[optionsOffset] & ~8);
  134. savedLegacySetting[optionsOffset] = (byte)(savedLegacySetting[optionsOffset] & ~8);
  135. }
  136. BitConverter.GetBytes(
  137. unchecked(BitConverter.ToUInt32(defConnection, versionOffset) + 1))
  138. .CopyTo(defConnection, versionOffset);
  139. BitConverter.GetBytes(
  140. unchecked(BitConverter.ToUInt32(savedLegacySetting, versionOffset) + 1))
  141. .CopyTo(savedLegacySetting, versionOffset);
  142. registry.SetValue("DefaultConnectionSettings", defConnection);
  143. registry.SetValue("SavedLegacySettings", savedLegacySetting);
  144. }
  145. }
  146. }