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.

WinINet.cs 6.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /****************************** Module Header ******************************\
  2. Module Name: WinINet.cs
  3. Project: CSWebBrowserWithProxy
  4. Copyright (c) Microsoft Corporation.
  5. This class is used to set the proxy. or restore to the system proxy for the
  6. current application
  7. This source is subject to the Microsoft Public License.
  8. See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  9. All other rights reserved.
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  11. EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  12. WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  13. \***************************************************************************/
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Linq;
  17. using System.Runtime.InteropServices;
  18. namespace Shadowsocks.Util.SystemProxy
  19. {
  20. public static class WinINet
  21. {
  22. /// <summary>
  23. /// Set IE settings for LAN connection.
  24. /// </summary>
  25. public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
  26. {
  27. List<INTERNET_PER_CONN_OPTION> _optionlist = new List<INTERNET_PER_CONN_OPTION>();
  28. if (enable)
  29. {
  30. if (global)
  31. {
  32. // global proxy
  33. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  34. {
  35. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
  36. Value = { dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_PROXY }
  37. });
  38. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  39. {
  40. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER,
  41. Value = { pszValue = Marshal.StringToHGlobalAnsi(proxyServer) }
  42. });
  43. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  44. {
  45. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS,
  46. Value = { pszValue = Marshal.StringToHGlobalAnsi("<local>") }
  47. });
  48. }
  49. else
  50. {
  51. // pac
  52. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  53. {
  54. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
  55. Value = { dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_AUTO_PROXY_URL }
  56. });
  57. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  58. {
  59. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_AUTOCONFIG_URL,
  60. Value = { pszValue = Marshal.StringToHGlobalAnsi(pacURL) }
  61. });
  62. }
  63. }
  64. else
  65. {
  66. // direct
  67. _optionlist.Add(new INTERNET_PER_CONN_OPTION
  68. {
  69. dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
  70. Value = { dwValue = (int)(INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_AUTO_DETECT
  71. | INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_DIRECT) }
  72. });
  73. }
  74. // Get total length of INTERNET_PER_CONN_OPTIONs
  75. var len = _optionlist.Sum(each => Marshal.SizeOf(each));
  76. // Allocate a block of memory of the options.
  77. IntPtr buffer = Marshal.AllocCoTaskMem(len);
  78. IntPtr current = buffer;
  79. // Marshal data from a managed object to an unmanaged block of memory.
  80. foreach (INTERNET_PER_CONN_OPTION eachOption in _optionlist)
  81. {
  82. Marshal.StructureToPtr(eachOption, current, false);
  83. current = (IntPtr)((int)current + Marshal.SizeOf(eachOption));
  84. }
  85. // Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
  86. INTERNET_PER_CONN_OPTION_LIST optionList = new INTERNET_PER_CONN_OPTION_LIST();
  87. // Point to the allocated memory.
  88. optionList.pOptions = buffer;
  89. // Return the unmanaged size of an object in bytes.
  90. optionList.Size = Marshal.SizeOf(optionList);
  91. // IntPtr.Zero means LAN connection.
  92. optionList.Connection = IntPtr.Zero;
  93. optionList.OptionCount = _optionlist.Count;
  94. optionList.OptionError = 0;
  95. int optionListSize = Marshal.SizeOf(optionList);
  96. // Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
  97. IntPtr intptrStruct = Marshal.AllocCoTaskMem(optionListSize);
  98. // Marshal data from a managed object to an unmanaged block of memory.
  99. Marshal.StructureToPtr(optionList, intptrStruct, true);
  100. // Set internet settings.
  101. bool bReturn = NativeMethods.InternetSetOption(
  102. IntPtr.Zero,
  103. INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
  104. intptrStruct, optionListSize);
  105. // Free the allocated memory.
  106. foreach (var v in _optionlist)
  107. {
  108. // free strings
  109. if (v.Value.pszValue != IntPtr.Zero)
  110. Marshal.FreeHGlobal(v.Value.pszValue);
  111. }
  112. Marshal.FreeCoTaskMem(buffer);
  113. Marshal.FreeCoTaskMem(intptrStruct);
  114. // Throw an exception if this operation failed.
  115. if (!bReturn)
  116. {
  117. throw new Exception("InternetSetOption: " + Marshal.GetLastWin32Error());
  118. }
  119. // Notify the system that the registry settings have been changed and cause
  120. // the proxy data to be reread from the registry for a handle.
  121. NativeMethods.InternetSetOption(
  122. IntPtr.Zero,
  123. INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
  124. IntPtr.Zero, 0);
  125. NativeMethods.InternetSetOption(
  126. IntPtr.Zero,
  127. INTERNET_OPTION.INTERNET_OPTION_REFRESH,
  128. IntPtr.Zero, 0);
  129. }
  130. }
  131. }