OSDN Git Service

プロキシの自動設定をバージョン9の方法に戻す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / SystemProxy.cs
1 // Copyright (C) 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\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
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\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
14 \r
15 using System;\r
16 using System.Runtime.InteropServices;\r
17 using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;\r
18 \r
19 namespace KancolleSniffer\r
20 {\r
21     public class SystemProxy\r
22     {\r
23         private InternetPerConnOptionList _orgList;\r
24         private string _currentUrl;\r
25 \r
26         private void SaveSettings()\r
27         {\r
28             if (_orgList.dwSize != 0)\r
29                 return;\r
30             var opts = new[]\r
31             {\r
32                 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS},\r
33                 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL}\r
34             };\r
35             var list = new InternetPerConnOptionList\r
36             {\r
37                 pOptions = MarshalOptions(opts),\r
38                 pszConnection = IntPtr.Zero,\r
39                 dwOptionCount = opts.Length,\r
40                 dwOptionError = 0\r
41             };\r
42             var listSize = list.dwSize = Marshal.SizeOf(list);\r
43             if (InternetQueryOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,\r
44                 ref list, ref listSize))\r
45             {\r
46                 _orgList = list;\r
47             }\r
48         }\r
49 \r
50         public void SetAutoConfigUrl(string url)\r
51         {\r
52             SaveSettings();\r
53             var flagValue = new InternetPerConnOptionValue {dwValue = (int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL};\r
54             var urlValue = new InternetPerConnOptionValue {pszValue = Marshal.StringToHGlobalAuto(url)};\r
55             _currentUrl = url;\r
56             var opts = new[]\r
57             {\r
58                 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_FLAGS, Value = flagValue},\r
59                 new InternetPerConnOption {dwOption = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL, Value = urlValue}\r
60             };\r
61             var list = new InternetPerConnOptionList\r
62             {\r
63                 pOptions = MarshalOptions(opts),\r
64                 pszConnection = IntPtr.Zero,\r
65                 dwOptionCount = opts.Length,\r
66                 dwOptionError = 0\r
67             };\r
68             var listSize = list.dwSize = Marshal.SizeOf(list);\r
69             var listBuff = Marshal.AllocCoTaskMem(listSize);\r
70             Marshal.StructureToPtr(list, listBuff, false);\r
71             InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);\r
72             Refresh();\r
73 \r
74             Marshal.FreeHGlobal(urlValue.pszValue);\r
75             Marshal.FreeCoTaskMem(list.pOptions);\r
76             Marshal.FreeCoTaskMem(listBuff);\r
77         }\r
78 \r
79         public void RestoreSettings()\r
80         {\r
81             if (_orgList.dwSize == 0)\r
82                 return;\r
83             var size = Marshal.SizeOf(typeof(InternetPerConnOption));\r
84             var urlOpt = (InternetPerConnOption)\r
85                 Marshal.PtrToStructure((IntPtr)((long)_orgList.pOptions + size), typeof(InternetPerConnOption));\r
86             var orgUrl = Marshal.PtrToStringUni(urlOpt.Value.pszValue);\r
87             if (orgUrl == _currentUrl) // The restoration was sikipped or failed at last time.\r
88             {\r
89                 // Unselect the Use automatic configration script check box.\r
90                 var flagsOpt =\r
91                     (InternetPerConnOption)Marshal.PtrToStructure(_orgList.pOptions, typeof(InternetPerConnOption));\r
92                 flagsOpt.Value.dwValue &= ~(int)PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL;\r
93                 Marshal.StructureToPtr(flagsOpt, _orgList.pOptions, false);\r
94             }\r
95             var listSize = _orgList.dwSize;\r
96             var listBuff = Marshal.AllocCoTaskMem(listSize);\r
97             Marshal.StructureToPtr(_orgList, listBuff, false);\r
98             InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, listBuff, listSize);\r
99             Refresh();\r
100 \r
101             Marshal.FreeCoTaskMem(listBuff);\r
102             Marshal.FreeHGlobal(urlOpt.Value.pszValue);\r
103             Marshal.FreeCoTaskMem(_orgList.pOptions);\r
104             _orgList.dwSize = 0;\r
105         }\r
106 \r
107         private IntPtr MarshalOptions(InternetPerConnOption[] opts)\r
108         {\r
109             var buff = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(InternetPerConnOption)) * opts.Length);\r
110             var size = Marshal.SizeOf(typeof(InternetPerConnOption));\r
111             for (var i = 0; i < opts.Length; i++)\r
112             {\r
113                 var ptr = (IntPtr)((long)buff + (i * size));\r
114                 Marshal.StructureToPtr(opts[i], ptr, false);\r
115             }\r
116             return buff;\r
117         }\r
118 \r
119         public static void Refresh()\r
120         {\r
121             InternetSetOption(IntPtr.Zero, InternetOption.INTERNET_OPTION_PROXY_SETTINGS_CHANGED, IntPtr.Zero, 0);\r
122         }\r
123 \r
124         [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]\r
125         private static extern bool InternetQueryOption(IntPtr hInternet, InternetOption dwOption,\r
126             ref InternetPerConnOptionList optionList, ref int lpdwBufferLength);\r
127 \r
128         [DllImport("WinInet.dll", CharSet = CharSet.Unicode)]\r
129         private static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption,\r
130             IntPtr lpBuffer, int dwBufferLength);\r
131 \r
132         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\r
133         private struct InternetPerConnOptionList\r
134         {\r
135             public int dwSize;\r
136             public IntPtr pszConnection;\r
137             public int dwOptionCount;\r
138             public int dwOptionError;\r
139             public IntPtr pOptions;\r
140         }\r
141 \r
142         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\r
143         private struct InternetPerConnOption\r
144         {\r
145             public PerConnOption dwOption;\r
146             public InternetPerConnOptionValue Value;\r
147         }\r
148 \r
149         [StructLayout(LayoutKind.Explicit)]\r
150         public struct InternetPerConnOptionValue\r
151         {\r
152             [FieldOffset(0)] public int dwValue;\r
153             [FieldOffset(0)] public IntPtr pszValue;\r
154             [FieldOffset(0)] public FILETIME ftValue;\r
155         }\r
156 \r
157 // ReSharper disable UnusedMember.Local\r
158 // ReSharper disable InconsistentNaming\r
159 \r
160         private enum InternetOption : uint\r
161         {\r
162             INTERNET_OPTION_REFRESH = 0x00000025,\r
163             INTERNET_OPTION_PER_CONNECTION_OPTION = 0x0000004B,\r
164             INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 0x0000005F\r
165         }\r
166 \r
167         private enum PerConnOption\r
168         {\r
169             INTERNET_PER_CONN_FLAGS = 1,\r
170             INTERNET_PER_CONN_PROXY_SERVER = 2,\r
171             INTERNET_PER_CONN_PROXY_BYPASS = 3,\r
172             INTERNET_PER_CONN_AUTOCONFIG_URL = 4,\r
173             INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5\r
174         }\r
175 \r
176         [Flags]\r
177         private enum PerConnFlags\r
178         {\r
179             PROXY_TYPE_DIRECT = 0x00000001,\r
180             PROXY_TYPE_PROXY = 0x00000002,\r
181             PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,\r
182             PROXY_TYPE_AUTO_DETECT = 0x00000008\r
183         }\r
184     }\r
185 }