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 string _currentUrl;
\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
60 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS, Value = flagValue},
\r
61 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL, Value = urlValue}
\r
63 var list = new InternetPerConnOptionList
\r
65 pOptions = MarshalOptions(opts),
\r
66 pszConnection = IntPtr.Zero,
\r
67 dwOptionCount = opts.Length,
\r
70 var listSize = list.dwSize = Marshal.SizeOf(list);
\r
71 var listBuff = Marshal.AllocCoTaskMem(listSize);
\r
72 Marshal.StructureToPtr(list, listBuff, false);
\r
73 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);
\r
76 Marshal.FreeHGlobal(urlValue.pszValue);
\r
77 Marshal.FreeCoTaskMem(list.pOptions);
\r
78 Marshal.FreeCoTaskMem(listBuff);
\r
81 public void RestoreSettings()
\r
83 if (_orgList.dwSize == 0)
\r
85 var size = Marshal.SizeOf(typeof(InternetPerConnOption));
\r
86 var urlOpt = (InternetPerConnOption)
\r
87 Marshal.PtrToStructure((IntPtr)((long)_orgList.pOptions + size), typeof(InternetPerConnOption));
\r
88 var orgUrl = Marshal.PtrToStringUni(urlOpt.Value.pszValue);
\r
89 if (orgUrl == _currentUrl) // The restoration was sikipped or failed at last time.
\r
91 // Unselect the Use automatic configration script check box.
\r
93 (InternetPerConnOption)Marshal.PtrToStructure(_orgList.pOptions, typeof(InternetPerConnOption));
\r
94 flagsOpt.Value.dwValue &= ~(int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL;
\r
95 Marshal.StructureToPtr(flagsOpt, _orgList.pOptions, false);
\r
97 var listSize = _orgList.dwSize;
\r
98 var listBuff = Marshal.AllocCoTaskMem(listSize);
\r
99 Marshal.StructureToPtr(_orgList, listBuff, false);
\r
100 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);
\r
103 Marshal.FreeCoTaskMem(listBuff);
\r
104 Marshal.FreeHGlobal(urlOpt.Value.pszValue);
\r
105 Marshal.FreeCoTaskMem(_orgList.pOptions);
\r
106 _orgList.dwSize = 0;
\r
109 private IntPtr MarshalOptions(InternetPerConnOption[] opts)
\r
111 var buff = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(InternetPerConnOption)) * opts.Length);
\r
112 var size = Marshal.SizeOf(typeof(InternetPerConnOption));
\r
113 for (var i = 0; i < opts.Length; i++)
\r
115 var ptr = (IntPtr)((long)buff + (i * size));
\r
116 Marshal.StructureToPtr(opts[i], ptr, false);
\r
121 public static void Refresh()
\r
123 InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PROXY_SETTINGS_CHANGED, IntPtr.Zero, 0);
\r
127 /// PACファイルでDIRECTを指定すると、すべてのサイトがローカルイントラネットになり、
\r
128 /// IEが互換表示になるなどの不具合があるので、イントラネットにならないようにする
\r
130 private void AdjustLocalIntranetZoneFlags()
\r
132 var zones = Registry.CurrentUser.OpenSubKey(
\r
133 @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1", true);
\r
136 if (!(zones.GetValue("Flags") is int flags))
\r
138 zones.SetValue("Flags", flags & (-1 ^ 0x108));
\r
141 [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]
\r
142 private static extern bool InternetQueryOption(IntPtr hInternet, InternetOption dwOption,
\r
143 ref InternetPerConnOptionList optionList, ref int lpdwBufferLength);
\r
145 [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]
\r
146 private static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption,
\r
147 IntPtr lpBuffer, int dwBufferLength);
\r
149 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
\r
150 private struct InternetPerConnOptionList
\r
153 public IntPtr pszConnection;
\r
154 public int dwOptionCount;
\r
155 public int dwOptionError;
\r
156 public IntPtr pOptions;
\r
159 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
\r
160 private struct InternetPerConnOption
\r
162 public PerConnOption dwOption;
\r
163 public InternetPerConnOptionValue Value;
\r
166 [StructLayout(LayoutKind.Explicit)]
\r
167 public struct InternetPerConnOptionValue
\r
169 [FieldOffset(0)] public int dwValue;
\r
170 [FieldOffset(0)] public IntPtr pszValue;
\r
171 [FieldOffset(0)] public FILETIME ftValue;
\r
174 // ReSharper disable UnusedMember.Local
\r
175 // ReSharper disable InconsistentNaming
\r
177 private enum InternetOption : uint
\r
179 INTERNET_OPTION_REFRESH = 0x00000025,
\r
180 INTERNET_OPTION_PER_CONNECTION_OPTION = 0x0000004B,
\r
181 INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 0x0000005F
\r
184 private enum PerConnOption
\r
186 INTERNET_PER_CONN_FLAGS = 1,
\r
187 INTERNET_PER_CONN_PROXY_SERVER = 2,
\r
188 INTERNET_PER_CONN_PROXY_BYPASS = 3,
\r
189 INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
\r
190 INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5
\r
194 private enum PerConnFlags
\r
196 PROXY_TYPE_DIRECT = 0x00000001,
\r
197 PROXY_TYPE_PROXY = 0x00000002,
\r
198 PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,
\r
199 PROXY_TYPE_AUTO_DETECT = 0x00000008
\r