1 // Copyright (C) 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
16 using System.Runtime.InteropServices;
\r
17 using Microsoft.Win32;
\r
18 using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
\r
20 namespace KancolleSniffer
\r
22 public class SystemProxy
\r
24 private InternetPerConnOptionList _orgList;
\r
25 private Uri _initialUri;
\r
27 private void SaveSettings()
\r
29 if (_orgList.dwSize != 0)
\r
33 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS},
\r
34 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL}
\r
36 var list = new InternetPerConnOptionList
\r
38 pOptions = MarshalOptions(opts),
\r
39 pszConnection = IntPtr.Zero,
\r
40 dwOptionCount = opts.Length,
\r
43 var listSize = list.dwSize = Marshal.SizeOf(list);
\r
44 if (InternetQueryOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,
\r
45 ref list, ref listSize))
\r
49 AdjustLocalIntranetZoneFlags();
\r
52 public void SetAutoConfigUrl(string url)
\r
55 var flagValue = new InternetPerConnOptionValue {dwValue = (int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL};
\r
56 var urlValue = new InternetPerConnOptionValue {pszValue = Marshal.StringToHGlobalAuto(url)};
\r
57 if (_initialUri == null)
\r
58 Uri.TryCreate(url, UriKind.Absolute, out _initialUri);
\r
61 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS, Value = flagValue},
\r
62 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL, Value = urlValue}
\r
64 var list = new InternetPerConnOptionList
\r
66 pOptions = MarshalOptions(opts),
\r
67 pszConnection = IntPtr.Zero,
\r
68 dwOptionCount = opts.Length,
\r
71 var listSize = list.dwSize = Marshal.SizeOf(list);
\r
72 var listBuff = Marshal.AllocCoTaskMem(listSize);
\r
73 Marshal.StructureToPtr(list, listBuff, false);
\r
74 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);
\r
77 Marshal.FreeHGlobal(urlValue.pszValue);
\r
78 Marshal.FreeCoTaskMem(list.pOptions);
\r
79 Marshal.FreeCoTaskMem(listBuff);
\r
82 public void RestoreSettings()
\r
84 if (_orgList.dwSize == 0)
\r
86 var size = Marshal.SizeOf(typeof(InternetPerConnOption));
\r
87 var urlOpt = (InternetPerConnOption)
\r
88 Marshal.PtrToStructure((IntPtr)((long)_orgList.pOptions + size), typeof(InternetPerConnOption));
\r
89 Uri.TryCreate(Marshal.PtrToStringUni(urlOpt.Value.pszValue) ?? "", UriKind.Absolute, out var orgUri);
\r
90 if (orgUri?.Authority == _initialUri?.Authority) // The restoration was sikipped or failed at last time.
\r
92 // Unselect the Use automatic configration script check box.
\r
94 (InternetPerConnOption)Marshal.PtrToStructure(_orgList.pOptions, typeof(InternetPerConnOption));
\r
95 flagsOpt.Value.dwValue &= ~(int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL;
\r
96 Marshal.StructureToPtr(flagsOpt, _orgList.pOptions, false);
\r
98 var listSize = _orgList.dwSize;
\r
99 var listBuff = Marshal.AllocCoTaskMem(listSize);
\r
100 Marshal.StructureToPtr(_orgList, listBuff, false);
\r
101 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);
\r
104 Marshal.FreeCoTaskMem(listBuff);
\r
105 Marshal.FreeHGlobal(urlOpt.Value.pszValue);
\r
106 Marshal.FreeCoTaskMem(_orgList.pOptions);
\r
107 _orgList.dwSize = 0;
\r
110 private IntPtr MarshalOptions(InternetPerConnOption[] opts)
\r
112 var buff = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(InternetPerConnOption)) * opts.Length);
\r
113 var size = Marshal.SizeOf(typeof(InternetPerConnOption));
\r
114 for (var i = 0; i < opts.Length; i++)
\r
116 var ptr = (IntPtr)((long)buff + (i * size));
\r
117 Marshal.StructureToPtr(opts[i], ptr, false);
\r
122 public static void Refresh()
\r
124 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PROXY_SETTINGS_CHANGED, IntPtr.Zero, 0);
\r
128 /// PACファイルでDIRECTを指定すると、すべてのサイトがローカルイントラネットになり、
\r
129 /// IEが互換表示になるなどの不具合があるので、イントラネットにならないようにする
\r
131 private void AdjustLocalIntranetZoneFlags()
\r
133 var zones = Registry.CurrentUser.OpenSubKey(
\r
134 @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1", true);
\r
137 if (!(zones.GetValue("Flags") is int flags))
\r
139 zones.SetValue("Flags", flags & (-1 ^ 0x108));
\r
142 [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]
\r
143 private static extern bool InternetQueryOption(IntPtr hInternet, InternetOption dwOption,
\r
144 ref InternetPerConnOptionList optionList, ref int lpdwBufferLength);
\r
146 [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]
\r
147 private static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption,
\r
148 IntPtr lpBuffer, int dwBufferLength);
\r
150 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
\r
151 private struct InternetPerConnOptionList
\r
154 public IntPtr pszConnection;
\r
155 public int dwOptionCount;
\r
156 public int dwOptionError;
\r
157 public IntPtr pOptions;
\r
160 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
\r
161 private struct InternetPerConnOption
\r
163 public PerConnOption dwOption;
\r
164 public InternetPerConnOptionValue Value;
\r
167 [StructLayout(LayoutKind.Explicit)]
\r
168 public struct InternetPerConnOptionValue
\r
170 [FieldOffset(0)] public int dwValue;
\r
171 [FieldOffset(0)] public IntPtr pszValue;
\r
172 [FieldOffset(0)] public FILETIME ftValue;
\r
175 // ReSharper disable UnusedMember.Local
\r
176 // ReSharper disable InconsistentNaming
\r
178 private enum InternetOption : uint
\r
180 INTERNET_OPTION_REFRESH = 0x00000025,
\r
181 INTERNET_OPTION_PER_CONNECTION_OPTION = 0x0000004B,
\r
182 INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 0x0000005F
\r
185 private enum PerConnOption
\r
187 INTERNET_PER_CONN_FLAGS = 1,
\r
188 INTERNET_PER_CONN_PROXY_SERVER = 2,
\r
189 INTERNET_PER_CONN_PROXY_BYPASS = 3,
\r
190 INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
\r
191 INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5
\r
195 private enum PerConnFlags
\r
197 PROXY_TYPE_DIRECT = 0x00000001,
\r
198 PROXY_TYPE_PROXY = 0x00000002,
\r
199 PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,
\r
200 PROXY_TYPE_AUTO_DETECT = 0x00000008
\r