Compare commits

...
10 Commits
Author SHA1 Message Date
Syrone Wong 89b7043a4e Update CHANGES and bump version
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-21 09:57:08 +08:00
Syrone Wong 9c438ee745 Misc
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-21 08:17:28 +08:00
Syrone Wong ce26bc15a9 Refine random generator handling
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-20 08:15:47 +08:00
Syrone Wong 4b99a5c210 Make registry opening more generic
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-20 08:05:25 +08:00
Syrone Wong 5721769c6d Refine Remote Access Service query for WinVista and later
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-16 16:43:11 +08:00
Syrone Wong 1c1cc62235 System proxy support for Remote Access Service
e.g. Dial-up connection and VPN

- use INTERNET_OPTION_PROXY_SETTINGS_CHANGED instead of INTERNET_OPTION_SETTINGS_CHANGED

Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-16 12:36:12 +08:00
Jiangzhuo 3fe8484b8b Fix link to GFWList (#793)
Thanks to @jiangzhuo
2016-10-14 19:46:20 +08:00
Syrone Wong 131114f0c2 Fix #779
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-12 09:36:17 +08:00
Syrone Wong 74ad98d9ce Distinguish unhandled error type
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-12 07:40:42 +08:00
Syrone Wong 90ae73057e Misc
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-10-11 17:00:19 +08:00
15 changed files with 285 additions and 75 deletions
+5
View File
@@ -1,3 +1,8 @@
3.3.4 2016-10-21
- Fix IE dial-up and VPN connection proxy settings
not changed since release 3.3.3.
- Fix a UI bug
3.3.3 2016-10-10
- Add timeout support for server and forward proxy,
only integer is allowed
+1 -1
View File
@@ -32,7 +32,7 @@ port in `Servers -> Edit Servers`
1. You can change PAC rules by editing the PAC file. When you save the PAC file
with any editor, Shadowsocks will notify browsers about the change automatically
2. You can also update PAC file from [GFWList] (maintained by 3rd party)
2. You can also update PAC file from [GFWList] \(maintained by 3rd party)
3. You can also use online PAC URL
#### Server Auto Switching
@@ -23,7 +23,7 @@ namespace Shadowsocks.Controller
public string LatestVersionLocalName;
public event EventHandler CheckUpdateCompleted;
public const string Version = "3.3.3";
public const string Version = "3.3.4";
private class CheckUpdateTimer : System.Timers.Timer
{
@@ -15,7 +15,7 @@ namespace Shadowsocks.Controller
try
{
string path = Application.ExecutablePath;
runKey = Utils.OpenUserRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if ( runKey == null ) {
Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run" );
return false;
@@ -54,7 +54,7 @@ namespace Shadowsocks.Controller
try
{
string path = Application.ExecutablePath;
runKey = Utils.OpenUserRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
runKey = Utils.OpenRegKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (runKey == null) {
Logging.Error(@"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Run");
return false;
+4 -4
View File
@@ -237,10 +237,10 @@ namespace Shadowsocks.Encryption
protected static void randBytes(byte[] buf, int length)
{
byte[] temp = new byte[length];
RNGCryptoServiceProvider rngServiceProvider = new RNGCryptoServiceProvider();
rngServiceProvider.GetBytes(temp);
temp.CopyTo(buf, 0);
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(buf, 0, length);
}
}
public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength)
+3 -3
View File
@@ -43,7 +43,6 @@ namespace Shadowsocks
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ApplicationExit += (sender, args) => HotKeys.Destroy();
if (!mutex.WaitOne(0, false))
{
@@ -85,7 +84,7 @@ namespace Shadowsocks
Logging.Error(e.ExceptionObject?.ToString());
MessageBox.Show(
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{e.ExceptionObject?.ToString()}",
"Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
"Shadowsocks non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
@@ -96,7 +95,7 @@ namespace Shadowsocks
Logging.Error(errorMsg);
MessageBox.Show(
$"{I18N.GetString("Unexpected error, shadowsocks will exit. Please report to")} https://github.com/shadowsocks/shadowsocks-windows/issues {Environment.NewLine}{errorMsg}",
"Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
"Shadowsocks UI Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
@@ -150,6 +149,7 @@ namespace Shadowsocks
private static void Application_ApplicationExit(object sender, EventArgs e)
{
HotKeys.Destroy();
if (_controller != null)
{
_controller.Stop();
@@ -11,21 +11,7 @@ namespace Shadowsocks.Util.ProcessManagement
*/
public class Job : IDisposable
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
private IntPtr handle = IntPtr.Zero;
private bool disposed;
public Job()
{
@@ -62,36 +48,6 @@ namespace Shadowsocks.Util.ProcessManagement
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
if (disposing) { }
Close();
}
private void Close()
{
if (handle != IntPtr.Zero)
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
}
~Job()
{
Dispose(false);
}
public bool AddProcess(IntPtr processHandle)
{
var succ = AssignProcessToJobObject(handle, processHandle);
@@ -109,6 +65,56 @@ namespace Shadowsocks.Util.ProcessManagement
return AddProcess(Process.GetProcessById(processId).Handle);
}
#region IDisposable
private bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
if (disposing)
{
// no managed objects to free
}
if (handle != IntPtr.Zero)
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
}
~Job()
{
Dispose(false);
}
#endregion
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
#endregion
}
#region Helper classes
@@ -30,7 +30,13 @@ namespace Shadowsocks.Util.SystemProxy
INTERNET_OPTION_SETTINGS_CHANGED = 39,
// Causes the proxy data to be reread from the registry for a handle.
INTERNET_OPTION_REFRESH = 37
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
}
}
@@ -22,7 +22,7 @@ using System.Runtime.InteropServices;
namespace Shadowsocks.Util.SystemProxy
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct INTERNET_PER_CONN_OPTION_LIST : IDisposable
{
public int Size;
@@ -26,7 +26,7 @@ namespace Shadowsocks.Util.SystemProxy
/// <summary>
/// Sets an Internet option.
/// </summary>
[DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool InternetSetOption(
IntPtr hInternet,
INTERNET_OPTION dwOption,
+147
View File
@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Shadowsocks.Util.SystemProxy
{
public static class RAS
{
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(
string reserved, // reserved, must be NULL
string lpszPhonebook, // pointer to full path and file name of phone-book file
[In, Out] RasEntryName[] lprasentryname, // buffer to receive phone-book entries
ref int lpcb, // size in bytes of buffer
out int lpcEntries // number of entries written to buffer
);
/// <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;
}
}
}
}
+58 -13
View File
@@ -19,17 +19,19 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Shadowsocks.Controller;
namespace Shadowsocks.Util.SystemProxy
{
public static class WinINet
{
/// <summary>
/// Set IE settings for LAN connection.
/// Set IE settings.
/// </summary>
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
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)
@@ -38,17 +40,18 @@ namespace Shadowsocks.Util.SystemProxy
_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 }
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.StringToHGlobalAnsi(proxyServer) }
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.StringToHGlobalAnsi("<local>") }
Value = { pszValue = Marshal.StringToHGlobalAuto("<local>") }
});
}
else
@@ -62,7 +65,7 @@ namespace Shadowsocks.Util.SystemProxy
_optionlist.Add(new INTERNET_PER_CONN_OPTION
{
dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_AUTOCONFIG_URL,
Value = { pszValue = Marshal.StringToHGlobalAnsi(pacURL) }
Value = { pszValue = Marshal.StringToHGlobalAuto(pacURL) }
});
}
}
@@ -101,8 +104,9 @@ namespace Shadowsocks.Util.SystemProxy
// Return the unmanaged size of an object in bytes.
optionList.Size = Marshal.SizeOf(optionList);
// IntPtr.Zero means LAN connection.
optionList.Connection = IntPtr.Zero;
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;
@@ -132,15 +136,56 @@ namespace Shadowsocks.Util.SystemProxy
// Notify the system that the registry settings have been changed and cause
// the proxy data to be reread from the registry for a handle.
NativeMethods.InternetSetOption(
IntPtr.Zero,
INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
IntPtr.Zero, 0);
// bReturn = NativeMethods.InternetSetOption(
// IntPtr.Zero,
// INTERNET_OPTION.INTERNET_OPTION_SETTINGS_CHANGED,
// IntPtr.Zero, 0);
// if ( ! bReturn )
// {
// Logging.Error("InternetSetOption:INTERNET_OPTION_SETTINGS_CHANGED");
// }
NativeMethods.InternetSetOption(
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 = RAS.GetAllConns(ref allConnections);
if (ret == 2)
throw new Exception("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);
}
}
}
}
}
+3 -3
View File
@@ -211,7 +211,7 @@ namespace Shadowsocks.Util
return new BandwidthScaleInfo(f, unit, scale);
}
public static RegistryKey OpenUserRegKey( string name, bool writable )
public static RegistryKey OpenRegKey( string name, bool writable, RegistryHive hive = RegistryHive.CurrentUser )
{
// we are building x86 binary for both x86 and x64, which will
// cause problem when opening registry key
@@ -219,7 +219,7 @@ namespace Shadowsocks.Util
if (name.IsNullOrEmpty()) throw new ArgumentException(nameof(name));
try
{
RegistryKey userKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser,
RegistryKey userKey = RegistryKey.OpenBaseKey(hive,
Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32)
.OpenSubKey(name, writable);
return userKey;
@@ -236,7 +236,7 @@ namespace Shadowsocks.Util
}
catch (ArgumentException ae)
{
MessageBox.Show("OpenUserRegKey: " + ae.ToString());
MessageBox.Show("OpenRegKey: " + ae.ToString());
return null;
}
}
+1 -1
View File
@@ -296,7 +296,7 @@ namespace Shadowsocks.View
{
int index = ServersListBox.SelectedIndex;
Server server = _modifiedConfiguration.configs[index];
object item = ServersListBox.SelectedItem;
object item = ServersListBox.Items[index];
_modifiedConfiguration.configs.Remove(server);
_modifiedConfiguration.configs.Insert(index + step, server);
@@ -190,6 +190,7 @@
<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\RAS.cs" />
<Compile Include="Util\SystemProxy\WinINet.cs" />
<Compile Include="Util\Util.cs" />
<Compile Include="View\ConfigForm.cs">