{\r
private readonly Config _config;\r
private readonly Control _parent;\r
- private string _prevAutoConfigUrl;\r
+ private readonly SystemProxy _systemProxy = new SystemProxy();\r
private int _prevProxyPort;\r
private int _autoConfigRetryCount;\r
private readonly Timer _timer = new Timer {Interval = 1000};\r
}\r
if (_config.Proxy.Auto && result)\r
{\r
- if (_prevAutoConfigUrl == null)\r
- {\r
- SystemProxy.AdjustLocalIntranetZoneFlags();\r
- _prevAutoConfigUrl = SystemProxy.AutoConfigUrl;\r
- }\r
SetAndCheckAutoConfigUrl();\r
}\r
_prevProxyPort = _config.Proxy.Listen;\r
private void SetAutoConfigUrl()\r
{\r
var count = _autoConfigRetryCount == 0 ? "" : _autoConfigRetryCount.ToString();\r
- SystemProxy.AutoConfigUrl = $"http://localhost:{_config.Proxy.Listen}/proxy{count}.pac";\r
+ _systemProxy.SetAutoConfigUrl(\r
+ $"http://localhost:{_config.Proxy.Listen}/proxy{count}.pac");\r
}\r
\r
private void RestoreSystemProxy()\r
{\r
_timer.Stop();\r
- if (_prevAutoConfigUrl == null)\r
- return;\r
- if (_prevAutoConfigUrl == "")\r
- {\r
- SystemProxy.AutoConfigUrl = "";\r
- return;\r
- }\r
- HttpWebRequest request;\r
- try\r
- {\r
- request = WebRequest.CreateHttp(_prevAutoConfigUrl);\r
- if (!request.Address.IsLoopback)\r
- throw new Exception();\r
- }\r
- catch\r
- {\r
- // httpではなくloopbackでもない\r
- SystemProxy.AutoConfigUrl = _prevAutoConfigUrl;\r
- return;\r
- }\r
- try\r
- {\r
- request.GetResponse().Dispose();\r
- }\r
- catch\r
- {\r
- // httpサーバーが応答しない\r
- SystemProxy.AutoConfigUrl = "";\r
- return;\r
- }\r
- SystemProxy.AutoConfigUrl = _prevAutoConfigUrl;\r
+ _systemProxy.RestoreSettings();\r
}\r
\r
public void UpdatePacFile()\r
\r
using System;\r
using System.Runtime.InteropServices;\r
-using Microsoft.Win32;\r
-\r
-// ReSharper disable InconsistentNaming\r
+using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;\r
\r
namespace KancolleSniffer\r
{\r
- public static class SystemProxy\r
+ public class SystemProxy\r
{\r
- private const string _regPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";\r
- private const string _regName = "AutoConfigURL";\r
+ private InternetPerConnOptionList _orgList;\r
+ private string _currentUrl;\r
\r
- public static string AutoConfigUrl\r
+ private void SaveSettings()\r
{\r
- get\r
+ if (_orgList.dwSize != 0)\r
+ return;\r
+ var opts = new[]\r
{\r
- using (var regkey = Registry.CurrentUser.OpenSubKey(_regPath))\r
- {\r
- if (regkey == null)\r
- return "";\r
- return regkey.GetValue(_regName) as string ?? "";\r
- }\r
- }\r
- set\r
+ new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS},\r
+ new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL}\r
+ };\r
+ var list = new InternetPerConnOptionList\r
+ {\r
+ pOptions = MarshalOptions(opts),\r
+ pszConnection = IntPtr.Zero,\r
+ dwOptionCount = opts.Length,\r
+ dwOptionError = 0\r
+ };\r
+ var listSize = list.dwSize = Marshal.SizeOf(list);\r
+ if (InternetQueryOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,\r
+ ref list, ref listSize))\r
{\r
- using (var regkey = Registry.CurrentUser.OpenSubKey(_regPath, true))\r
- {\r
- if (regkey == null)\r
- return;\r
- if (value == "")\r
- {\r
- regkey.DeleteValue(_regName, false);\r
- }\r
- else\r
- {\r
- regkey.SetValue(_regName, value);\r
- }\r
- }\r
- Refresh();\r
+ _orgList = list;\r
}\r
}\r
\r
- /// <summary>\r
- /// PACファイルでDIRECTを指定すると、すべてのサイトがローカルイントラネットになり、\r
- /// IEが互換表示になるなどの不具合があるので、イントラネットにならないようにする\r
- /// </summary>\r
- public static void AdjustLocalIntranetZoneFlags()\r
+ public void SetAutoConfigUrl(string url)\r
{\r
- var zones = Registry.CurrentUser.OpenSubKey(_regPath + @"\Zones\1", true);\r
- if (zones == null)\r
- return;\r
- if (!(zones.GetValue("Flags") is int flags))\r
+ SaveSettings();\r
+ var flagValue = new InternetPerConnOptionValue {dwValue = (int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL};\r
+ var urlValue = new InternetPerConnOptionValue {pszValue = Marshal.StringToHGlobalAuto(url)};\r
+ _currentUrl = url;\r
+ var opts = new[]\r
+ {\r
+ new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS, Value = flagValue},\r
+ new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL, Value = urlValue}\r
+ };\r
+ var list = new InternetPerConnOptionList\r
+ {\r
+ pOptions = MarshalOptions(opts),\r
+ pszConnection = IntPtr.Zero,\r
+ dwOptionCount = opts.Length,\r
+ dwOptionError = 0\r
+ };\r
+ var listSize = list.dwSize = Marshal.SizeOf(list);\r
+ var listBuff = Marshal.AllocCoTaskMem(listSize);\r
+ Marshal.StructureToPtr(list, listBuff, false);\r
+ InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);\r
+ Refresh();\r
+\r
+ Marshal.FreeHGlobal(urlValue.pszValue);\r
+ Marshal.FreeCoTaskMem(list.pOptions);\r
+ Marshal.FreeCoTaskMem(listBuff);\r
+ }\r
+\r
+ public void RestoreSettings()\r
+ {\r
+ if (_orgList.dwSize == 0)\r
return;\r
- zones.SetValue("Flags", flags & (-1 ^ 0x108));\r
+ var size = Marshal.SizeOf(typeof(InternetPerConnOption));\r
+ var urlOpt = (InternetPerConnOption)\r
+ Marshal.PtrToStructure((IntPtr)((long)_orgList.pOptions + size), typeof(InternetPerConnOption));\r
+ var orgUrl = Marshal.PtrToStringUni(urlOpt.Value.pszValue);\r
+ if (orgUrl == _currentUrl) // The restoration was sikipped or failed at last time.\r
+ {\r
+ // Unselect the Use automatic configration script check box.\r
+ var flagsOpt =\r
+ (InternetPerConnOption)Marshal.PtrToStructure(_orgList.pOptions, typeof(InternetPerConnOption));\r
+ flagsOpt.Value.dwValue &= ~(int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL;\r
+ Marshal.StructureToPtr(flagsOpt, _orgList.pOptions, false);\r
+ }\r
+ var listSize = _orgList.dwSize;\r
+ var listBuff = Marshal.AllocCoTaskMem(listSize);\r
+ Marshal.StructureToPtr(_orgList, listBuff, false);\r
+ InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);\r
+ Refresh();\r
+\r
+ Marshal.FreeCoTaskMem(listBuff);\r
+ Marshal.FreeHGlobal(urlOpt.Value.pszValue);\r
+ Marshal.FreeCoTaskMem(_orgList.pOptions);\r
+ _orgList.dwSize = 0;\r
+ }\r
+\r
+ private IntPtr MarshalOptions(InternetPerConnOption[] opts)\r
+ {\r
+ var buff = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(InternetPerConnOption)) * opts.Length);\r
+ var size = Marshal.SizeOf(typeof(InternetPerConnOption));\r
+ for (var i = 0; i < opts.Length; i++)\r
+ {\r
+ var ptr = (IntPtr)((long)buff + (i * size));\r
+ Marshal.StructureToPtr(opts[i], ptr, false);\r
+ }\r
+ return buff;\r
}\r
\r
public static void Refresh()\r
{\r
- InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);\r
- InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);\r
+ InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PROXY_SETTINGS_CHANGED, IntPtr.Zero, 0);\r
}\r
\r
- [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)]\r
+ [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]\r
+ private static extern bool InternetQueryOption(IntPtr hInternet, InternetOption dwOption,\r
+ ref InternetPerConnOptionList optionList, ref int lpdwBufferLength);\r
+\r
+ [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]\r
private static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption,\r
IntPtr lpBuffer, int dwBufferLength);\r
\r
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\r
+ private struct InternetPerConnOptionList\r
+ {\r
+ public int dwSize;\r
+ public IntPtr pszConnection;\r
+ public int dwOptionCount;\r
+ public int dwOptionError;\r
+ public IntPtr pOptions;\r
+ }\r
+\r
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\r
+ private struct InternetPerConnOption\r
+ {\r
+ public PerConnOption dwOption;\r
+ public InternetPerConnOptionValue Value;\r
+ }\r
+\r
+ [StructLayout(LayoutKind.Explicit)]\r
+ public struct InternetPerConnOptionValue\r
+ {\r
+ [FieldOffset(0)] public int dwValue;\r
+ [FieldOffset(0)] public IntPtr pszValue;\r
+ [FieldOffset(0)] public FILETIME ftValue;\r
+ }\r
+\r
+// ReSharper disable UnusedMember.Local\r
+// ReSharper disable InconsistentNaming\r
+\r
private enum InternetOption : uint\r
{\r
- INTERNET_OPTION_REFRESH = 37,\r
- INTERNET_OPTION_SETTINGS_CHANGED = 39\r
+ INTERNET_OPTION_REFRESH = 0x00000025,\r
+ INTERNET_OPTION_PER_CONNECTION_OPTION = 0x0000004B,\r
+ INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 0x0000005F\r
+ }\r
+\r
+ private enum PerConnOption\r
+ {\r
+ INTERNET_PER_CONN_FLAGS = 1,\r
+ INTERNET_PER_CONN_PROXY_SERVER = 2,\r
+ INTERNET_PER_CONN_PROXY_BYPASS = 3,\r
+ INTERNET_PER_CONN_AUTOCONFIG_URL = 4,\r
+ INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5\r
+ }\r
+\r
+ [Flags]\r
+ private enum PerConnFlags\r
+ {\r
+ PROXY_TYPE_DIRECT = 0x00000001,\r
+ PROXY_TYPE_PROXY = 0x00000002,\r
+ PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,\r
+ PROXY_TYPE_AUTO_DETECT = 0x00000008\r
}\r
}\r
}
\ No newline at end of file