Browse Source

Use external agents to set system proxy.

This fix the proxy issue on win10 insider preview.
tags/3.4.0
noisyfox 7 years ago
parent
commit
5c5f753721
13 changed files with 163 additions and 644 deletions
  1. +3
    -3
      shadowsocks-csharp/Controller/System/SystemProxy.cs
  2. BIN
      shadowsocks-csharp/Data/sysproxy.exe.gz
  3. BIN
      shadowsocks-csharp/Data/sysproxy64.exe.gz
  4. +43
    -23
      shadowsocks-csharp/Properties/Resources.Designer.cs
  5. +6
    -0
      shadowsocks-csharp/Properties/Resources.resx
  6. +0
    -42
      shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs
  7. +0
    -115
      shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs
  8. +0
    -63
      shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs
  9. +0
    -36
      shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs
  10. +0
    -148
      shadowsocks-csharp/Util/SystemProxy/RAS.cs
  11. +83
    -0
      shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs
  12. +0
    -183
      shadowsocks-csharp/Util/SystemProxy/WinINet.cs
  13. +28
    -31
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 3
- 3
shadowsocks-csharp/Controller/System/SystemProxy.cs View File

@@ -27,7 +27,7 @@ namespace Shadowsocks.Controller
{
if (global)
{
WinINet.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
Sysproxy.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
}
else
{
@@ -36,12 +36,12 @@ namespace Shadowsocks.Controller
pacUrl = config.pacUrl;
else
pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}{pacSrv.PacSecret}";
WinINet.SetIEProxy(true, false, "", pacUrl);
Sysproxy.SetIEProxy(true, false, "", pacUrl);
}
}
else
{
WinINet.SetIEProxy(false, false, "", "");
Sysproxy.SetIEProxy(false, false, "", "");
}
}
catch (ProxyException ex)


BIN
shadowsocks-csharp/Data/sysproxy.exe.gz View File


BIN
shadowsocks-csharp/Data/sysproxy64.exe.gz View File


+ 43
- 23
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -215,6 +215,26 @@ namespace Shadowsocks.Properties {
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy_exe {
get {
object obj = ResourceManager.GetObject("sysproxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] sysproxy64_exe {
get {
object obj = ResourceManager.GetObject("sysproxy64_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找类似 ! Put user rules line by line in this file.
///! See https://adblockplus.org/en/filter-cheatsheet
@@ -227,29 +247,29 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// 查找类似 # translation for Traditional Chinese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=啟用系統代理
///Mode=系統代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=伺服器
///Edit Servers...=編輯伺服器...
///Statistics Config...=統計配置...
///Start on Boot=開機啟動
///Forward Proxy...=正向代理設置...
///Allow Clients from LAN=允許來自區域網路的連接
///Local PAC=使用本地 PAC
///Online PAC=使用在線 PAC
///Edit Local PAC File...=編輯本地 PAC 文件...
///Update Local PAC from GFWList=從 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
///Show QRCode...=顯示 QR 碼...
///Scan QRCode from Screen [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// 查找类似 # translation for Traditional Chinese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=啟用系統代理
///Mode=系統代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=伺服器
///Edit Servers...=編輯伺服器...
///Statistics Config...=統計配置...
///Start on Boot=開機啟動
///Forward Proxy...=正向代理設置...
///Allow Clients from LAN=允許來自區域網路的連接
///Local PAC=使用本地 PAC
///Online PAC=使用在線 PAC
///Edit Local PAC File...=編輯本地 PAC 文件...
///Update Local PAC from GFWList=從 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
///Show QRCode...=顯示 QR 碼...
///S [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string zh_tw {
get {


+ 6
- 0
shadowsocks-csharp/Properties/Resources.resx View File

@@ -157,6 +157,12 @@
<data name="ssw128" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ssw128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="sysproxy64_exe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\sysproxy64.exe.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="sysproxy_exe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\sysproxy.exe.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="user_rule" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\user-rule.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>


+ 0
- 42
shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs View File

@@ -1,42 +0,0 @@
/****************************** Module Header ******************************\
Module Name: INTERNET_OPTION.cs
Project: CSWebBrowserWithProxy
Copyright (c) Microsoft Corporation.
This enum contains 4 WinINet constants used in method InternetQueryOption and
InternetSetOption functions.
Visit http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx to get the
whole constants list.
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
namespace Shadowsocks.Util.SystemProxy
{
public enum INTERNET_OPTION
{
// Sets or retrieves an INTERNET_PER_CONN_OPTION_LIST structure that specifies
// a list of options for a particular connection.
INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
// Notify the system that the registry settings have been changed so that
// it verifies the settings on the next call to InternetConnect.
INTERNET_OPTION_SETTINGS_CHANGED = 39,
// Causes the proxy data to be reread from the registry for a handle.
INTERNET_OPTION_REFRESH = 37,
// Alerts the current WinInet instance that proxy settings have changed
// and that they must update with the new settings.
// To alert all available WinInet instances, set the Buffer parameter of
// InternetSetOption to NULL and BufferLength to 0 when passing this option.
INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95
}
}

+ 0
- 115
shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs View File

@@ -1,115 +0,0 @@
/****************************** Module Header ******************************\
Module Name: INTERNET_PER_CONN_OPTION.cs
Project: CSWebBrowserWithProxy
Copyright (c) Microsoft Corporation.
This file defines the struct INTERNET_PER_CONN_OPTION and constants used by it.
The struct INTERNET_PER_CONN_OPTION contains the value of an option that to be
set to internet settings.
Visit http://msdn.microsoft.com/en-us/library/aa385145(VS.85).aspx to get the
detailed description.
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
using System;
using System.Runtime.InteropServices;
namespace Shadowsocks.Util.SystemProxy
{
/// <summary>
/// Constants used in INTERNET_PER_CONN_OPTION_OptionUnion struct.
/// </summary>
public enum INTERNET_PER_CONN_OptionEnum
{
INTERNET_PER_CONN_FLAGS = 1,
INTERNET_PER_CONN_PROXY_SERVER = 2,
INTERNET_PER_CONN_PROXY_BYPASS = 3,
INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6,
INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7,
INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8,
INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9,
INTERNET_PER_CONN_FLAGS_UI = 10
}
/// <summary>
/// Constants used in INTERNET_PER_CONN_OPTON struct.
/// </summary>
[Flags]
public enum INTERNET_OPTION_PER_CONN_FLAGS
{
PROXY_TYPE_DIRECT = 0x00000001, // direct to net
PROXY_TYPE_PROXY = 0x00000002, // via named proxy
PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL
PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
}
/// <summary>
/// Constants used in INTERNET_PER_CONN_OPTON struct.
/// Windows 7 and later:
/// Clients that support Internet Explorer 8 should query the connection type using INTERNET_PER_CONN_FLAGS_UI.
/// If this query fails, then the system is running a previous version of Internet Explorer and the client should
/// query again with INTERNET_PER_CONN_FLAGS.
/// Restore the connection type using INTERNET_PER_CONN_FLAGS regardless of the version of Internet Explorer.
/// XXX: If fails, notify user to upgrade Internet Explorer
/// </summary>
[Flags]
public enum INTERNET_OPTION_PER_CONN_FLAGS_UI
{
PROXY_TYPE_DIRECT = 0x00000001, // direct to net
PROXY_TYPE_PROXY = 0x00000002, // via named proxy
PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL
PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
}
/// <summary>
/// Used in INTERNET_PER_CONN_OPTION.
/// When create a instance of OptionUnion, only one filed will be used.
/// The StructLayout and FieldOffset attributes could help to decrease the struct size.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct INTERNET_PER_CONN_OPTION_OptionUnion : IDisposable
{
// A value in INTERNET_OPTION_PER_CONN_FLAGS.
[FieldOffset(0)]
public int dwValue;
[FieldOffset(0)]
public System.IntPtr pszValue;
[FieldOffset(0)]
public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
if (pszValue != IntPtr.Zero)
{
Marshal.FreeHGlobal(pszValue);
pszValue = IntPtr.Zero;
}
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct INTERNET_PER_CONN_OPTION
{
// A value in INTERNET_PER_CONN_OptionEnum.
public int dwOption;
public INTERNET_PER_CONN_OPTION_OptionUnion Value;
}
}

+ 0
- 63
shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs View File

@@ -1,63 +0,0 @@
/****************************** Module Header ******************************\
Module Name: INTERNET_PER_CONN_OPTION_LIST.cs
Project: CSWebBrowserWithProxy
Copyright (c) Microsoft Corporation.
The struct INTERNET_PER_CONN_OPTION contains a list of options that to be
set to internet connection.
Visit http://msdn.microsoft.com/en-us/library/aa385146(VS.85).aspx to get the
detailed description.
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
using System;
using System.Runtime.InteropServices;
namespace Shadowsocks.Util.SystemProxy
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct INTERNET_PER_CONN_OPTION_LIST : IDisposable
{
public int Size;
// The connection to be set. NULL means LAN.
public System.IntPtr Connection;
public int OptionCount;
public int OptionError;
// List of INTERNET_PER_CONN_OPTIONs.
public System.IntPtr pOptions;
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
private void Dispose( bool disposing )
{
if ( disposing )
{
if ( Connection != IntPtr.Zero )
{
Marshal.FreeHGlobal( Connection );
Connection = IntPtr.Zero;
}
if ( pOptions != IntPtr.Zero )
{
Marshal.FreeHGlobal( pOptions );
pOptions = IntPtr.Zero;
}
}
}
}
}

+ 0
- 36
shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs View File

@@ -1,36 +0,0 @@
/****************************** Module Header ******************************\
Module Name: NativeMethods.cs
Project: CSWebBrowserWithProxy
Copyright (c) Microsoft Corporation.
This class is a simple .NET wrapper of wininet.dll. It contains 4 extern
methods in wininet.dll. They are InternetOpen, InternetCloseHandle,
InternetSetOption and InternetQueryOption.
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
using System;
using System.Runtime.InteropServices;
namespace Shadowsocks.Util.SystemProxy
{
internal static class NativeMethods
{
/// <summary>
/// Sets an Internet option.
/// </summary>
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool InternetSetOption(
IntPtr hInternet,
INTERNET_OPTION dwOption,
IntPtr lpBuffer,
int lpdwBufferLength);
}
}

+ 0
- 148
shadowsocks-csharp/Util/SystemProxy/RAS.cs View File

@@ -1,148 +0,0 @@
using System.Runtime.InteropServices;
namespace Shadowsocks.Util.SystemProxy
{
internal static class RemoteAccessService
{
private enum RasFieldSizeConstants
{
#region original header
//#if (WINVER >= 0x400)
//#define RAS_MaxEntryName 256
//#define RAS_MaxDeviceName 128
//#define RAS_MaxCallbackNumber RAS_MaxPhoneNumber
//#else
//#define RAS_MaxEntryName 20
//#define RAS_MaxDeviceName 32
//#define RAS_MaxCallbackNumber 48
//#endif
#endregion
RAS_MaxEntryName = 256,
RAS_MaxPath = 260
}
private const int ERROR_SUCCESS = 0;
private const int RASBASE = 600;
private const int ERROR_BUFFER_TOO_SMALL = RASBASE + 3;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct RasEntryName
{
#region original header
//#define RASENTRYNAMEW struct tagRASENTRYNAMEW
//RASENTRYNAMEW
//{
// DWORD dwSize;
// WCHAR szEntryName[RAS_MaxEntryName + 1];
//
//#if (WINVER >= 0x500)
// //
// // If this flag is REN_AllUsers then its a
// // system phonebook.
// //
// DWORD dwFlags;
// WCHAR szPhonebookPath[MAX_PATH + 1];
//#endif
//};
//
//#define RASENTRYNAMEA struct tagRASENTRYNAMEA
//RASENTRYNAMEA
//{
// DWORD dwSize;
// CHAR szEntryName[RAS_MaxEntryName + 1];
//
//#if (WINVER >= 0x500)
// DWORD dwFlags;
// CHAR szPhonebookPath[MAX_PATH + 1];
//#endif
//};
#endregion
public int dwSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName + 1)]
public string szEntryName;
public int dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=(int)RasFieldSizeConstants.RAS_MaxPath + 1)]
public string szPhonebookPath;
}
[DllImport("rasapi32.dll", CharSet = CharSet.Auto)]
private static extern uint RasEnumEntries(
// reserved, must be NULL
string reserved,
// pointer to full path and file name of phone-book file
string lpszPhonebook,
// buffer to receive phone-book entries
[In, Out] RasEntryName[] lprasentryname,
// size in bytes of buffer
ref int lpcb,
// number of entries written to buffer
out int lpcEntries
);
/// <summary>
/// Get all entries from RAS
/// </summary>
/// <param name="allConns"></param>
/// <returns>
/// 0: success with entries
/// 1: success but no entries found
/// 2: failed
/// </returns>
public static uint GetAllConns(ref string[] allConns)
{
int lpNames = 0;
int entryNameSize = 0;
int lpSize = 0;
uint retval = ERROR_SUCCESS;
RasEntryName[] names = null;
entryNameSize = Marshal.SizeOf(typeof(RasEntryName));
// Windows Vista or later: To determine the required buffer size, call RasEnumEntries
// with lprasentryname set to NULL. The variable pointed to by lpcb should be set to zero.
// The function will return the required buffer size in lpcb and an error code of ERROR_BUFFER_TOO_SMALL.
retval = RasEnumEntries(null, null, null, ref lpSize, out lpNames);
if (retval == ERROR_BUFFER_TOO_SMALL)
{
names = new RasEntryName[lpNames];
for (int i = 0; i < names.Length; i++)
{
names[i].dwSize = entryNameSize;
}
retval = RasEnumEntries(null, null, names, ref lpSize, out lpNames);
}
if (retval == ERROR_SUCCESS)
{
if (lpNames == 0)
{
// no entries found.
return 1;
}
allConns = new string[names.Length];
for (int i = 0; i < names.Length; i++)
{
allConns[i] = names[i].szEntryName;
}
return 0;
}
else
{
return 2;
}
}
}
}

+ 83
- 0
shadowsocks-csharp/Util/SystemProxy/Sysproxy.cs View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shadowsocks.Controller;
using Shadowsocks.Properties;

namespace Shadowsocks.Util.SystemProxy
{
public static class Sysproxy
{

enum RET_ERRORS : int
{
RET_NO_ERROR = 0,
INVALID_FORMAT = 1,
NO_PERMISSION = 2,
SYSCALL_FAILED = 3,
NO_MEMORY = 4,
INVAILD_OPTION_COUNT = 5,
};

static Sysproxy()
{
try
{
FileManager.UncompressFile(Utils.GetTempPath("sysproxy.exe"),
Environment.Is64BitOperatingSystem ? Resources.sysproxy64_exe : Resources.sysproxy_exe);
}
catch (IOException e)
{
Logging.LogUsefulException(e);
}
}

public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
{
string arguments;

if (enable)
{
if (global)
{
arguments = "global " + proxyServer;
}
else
{
arguments = "pac " + pacURL;
}
}
else
{
arguments = "off";
}

using (var process = new Process())
{
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = Utils.GetTempPath("sysproxy.exe");
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Utils.GetTempPath();
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.Start();

var error = process.StandardError.ReadToEnd();

process.WaitForExit();

var exitCode = process.ExitCode;
if (exitCode != (int) RET_ERRORS.RET_NO_ERROR)
{
throw new ProxyException(error);
}
}
}
}
}

+ 0
- 183
shadowsocks-csharp/Util/SystemProxy/WinINet.cs View File

@@ -1,183 +0,0 @@
/****************************** Module Header ******************************\
Module Name: WinINet.cs
Project: CSWebBrowserWithProxy
Copyright (c) Microsoft Corporation.
This class is used to set the proxy. or restore to the system proxy for the
current application
This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using Shadowsocks.Controller;
namespace Shadowsocks.Util.SystemProxy
{
public static class WinINet
{
/// <summary>
/// Set IE settings.
/// </summary>
private static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL, string connName)
{
List<INTERNET_PER_CONN_OPTION> _optionlist = new List<INTERNET_PER_CONN_OPTION>();
if (enable)
{
if (global)
{
// global proxy
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
Value = { dwValue = (int)(INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_PROXY
| INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_DIRECT) }
});
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER,
Value = { pszValue = Marshal.StringToHGlobalAuto(proxyServer) }
});
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS,
Value = { pszValue = Marshal.StringToHGlobalAuto("<local>") }
});
}
else
{
// pac
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
Value = { dwValue = (int)INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_AUTO_PROXY_URL }
});
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_AUTOCONFIG_URL,
Value = { pszValue = Marshal.StringToHGlobalAuto(pacURL) }
});
}
}
else
{
// direct
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_FLAGS_UI,
Value = { dwValue = (int)(INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_AUTO_DETECT
| INTERNET_OPTION_PER_CONN_FLAGS_UI.PROXY_TYPE_DIRECT) }
});
}
// Get total length of INTERNET_PER_CONN_OPTIONs
var len = _optionlist.Sum(each => Marshal.SizeOf(each));
// Allocate a block of memory of the options.
IntPtr buffer = Marshal.AllocCoTaskMem(len);
IntPtr current = buffer;
// Marshal data from a managed object to an unmanaged block of memory.
foreach (INTERNET_PER_CONN_OPTION eachOption in _optionlist)
{
Marshal.StructureToPtr(eachOption, current, false);
current = (IntPtr)((int)current + Marshal.SizeOf(eachOption));
}
// Initialize a INTERNET_PER_CONN_OPTION_LIST instance.
INTERNET_PER_CONN_OPTION_LIST optionList = new INTERNET_PER_CONN_OPTION_LIST();
// Point to the allocated memory.
optionList.pOptions = buffer;
// Return the unmanaged size of an object in bytes.
optionList.Size = Marshal.SizeOf(optionList);
optionList.Connection = connName.IsNullOrEmpty()
? IntPtr.Zero // NULL means LAN
: Marshal.StringToHGlobalAuto(connName); // TODO: not working if contains Chinese
optionList.OptionCount = _optionlist.Count;
optionList.OptionError = 0;
int optionListSize = Marshal.SizeOf(optionList);
// Allocate memory for the INTERNET_PER_CONN_OPTION_LIST instance.
IntPtr intptrStruct = Marshal.AllocCoTaskMem(optionListSize);
// Marshal data from a managed object to an unmanaged block of memory.
Marshal.StructureToPtr(optionList, intptrStruct, true);
// Set internet settings.
bool bReturn = NativeMethods.InternetSetOption(
IntPtr.Zero,
INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
intptrStruct, optionListSize);
// Free the allocated memory.
Marshal.FreeCoTaskMem(buffer);
Marshal.FreeCoTaskMem(intptrStruct);
// Throw an exception if this operation failed.
if (!bReturn)
{
throw new ProxyException("InternetSetOption failed.", new Win32Exception());
}
// Notify the system that the registry settings have been changed and cause
// the proxy data to be reread from the registry for a handle.
bReturn = NativeMethods.InternetSetOption(
IntPtr.Zero,
INTERNET_OPTION.INTERNET_OPTION_PROXY_SETTINGS_CHANGED,
IntPtr.Zero, 0);
if (!bReturn)
{
Logging.Error("InternetSetOption:INTERNET_OPTION_PROXY_SETTINGS_CHANGED");
}
bReturn = NativeMethods.InternetSetOption(
IntPtr.Zero,
INTERNET_OPTION.INTERNET_OPTION_REFRESH,
IntPtr.Zero, 0);
if (!bReturn)
{
Logging.Error("InternetSetOption:INTERNET_OPTION_REFRESH");
}
}
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
{
string[] allConnections = null;
var ret = RemoteAccessService.GetAllConns(ref allConnections);
if (ret == 2)
throw new ProxyException("Cannot get all connections");
if (ret == 1)
{
// no entries, only set LAN
SetIEProxy(enable, global, proxyServer, pacURL, null);
}
else if (ret == 0)
{
// found entries, set LAN and each connection
SetIEProxy(enable, global, proxyServer, pacURL, null);
foreach (string connName in allConnections)
{
SetIEProxy(enable, global, proxyServer, pacURL, connName);
}
}
}
}
}

+ 28
- 31
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -195,13 +195,8 @@
<Compile Include="Util\Sockets\LineReader.cs" />
<Compile Include="Util\Sockets\SocketUtil.cs" />
<Compile Include="Util\Sockets\WrappedSocket.cs" />
<Compile Include="Util\SystemProxy\INTERNET_OPTION.cs" />
<Compile Include="Util\SystemProxy\INTERNET_PER_CONN_OPTION.cs" />
<Compile Include="Util\SystemProxy\INTERNET_PER_CONN_OPTION_LIST.cs" />
<Compile Include="Util\SystemProxy\NativeMethods.cs" />
<Compile Include="Util\SystemProxy\ProxyException.cs" />
<Compile Include="Util\SystemProxy\RAS.cs" />
<Compile Include="Util\SystemProxy\WinINet.cs" />
<Compile Include="Util\SystemProxy\Sysproxy.cs" />
<Compile Include="Util\Util.cs" />
<Compile Include="Util\ViewUtils.cs" />
<Compile Include="View\ConfigForm.cs">
@@ -294,6 +289,8 @@
<None Include="Data\proxy.pac.txt.gz" />
</ItemGroup>
<ItemGroup>
<None Include="Data\sysproxy.exe.gz" />
<None Include="Data\sysproxy64.exe.gz" />
<None Include="packages.config" />
<None Include="Properties\DataSources\Shadowsocks.Model.StatisticsStrategyConfiguration.datasource" />
<None Include="Properties\Settings.settings">
@@ -359,25 +356,25 @@
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System" />
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.IO" />
<Using xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Namespace="System.Xml.Linq" />
<Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
if (config == null) return true;
var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
foreach (var item in filesToCleanup)
File.Delete(item);
<Code xmlns="http://schemas.microsoft.com/developer/msbuild/2003" Type="Fragment" Language="cs"><![CDATA[
var config = XElement.Load(Config.ItemSpec).Elements("Costura").FirstOrDefault();
if (config == null) return true;
var excludedAssemblies = new List<string>();
var attribute = config.Attribute("ExcludeAssemblies");
if (attribute != null)
foreach (var item in attribute.Value.Split('|').Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var element = config.Element("ExcludeAssemblies");
if (element != null)
foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).Where(x => x != string.Empty))
excludedAssemblies.Add(item);
var filesToCleanup = Files.Select(f => f.ItemSpec).Where(f => !excludedAssemblies.Contains(Path.GetFileNameWithoutExtension(f), StringComparer.InvariantCultureIgnoreCase));
foreach (var item in filesToCleanup)
File.Delete(item);
]]></Code>
</Task>
</UsingTask>
@@ -391,11 +388,11 @@ foreach (var item in filesToCleanup)
</PropertyGroup>
<Error Condition="!Exists('3rd\Fody.1.29.4\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '3rd\Fody.1.29.4\build\dotnet\Fody.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Loading…
Cancel
Save