diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs
index b53f4a65..b932b240 100644
--- a/shadowsocks-csharp/Controller/System/SystemProxy.cs
+++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs
@@ -1,34 +1,11 @@
-using System.Windows.Forms;
-using Microsoft.Win32;
-using System;
-using System.Runtime.InteropServices;
-using System.IO;
+using System;
using Shadowsocks.Model;
-using Shadowsocks.Util;
+using Shadowsocks.Util.SystemProxy;
namespace Shadowsocks.Controller
{
public static class SystemProxy
{
-
- [DllImport("wininet.dll")]
- public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
- public const int INTERNET_OPTION_SETTINGS_CHANGED = 39;
- public const int INTERNET_OPTION_REFRESH = 37;
- static bool _settingsReturn, _refreshReturn;
-
- public static void NotifyIE()
- {
- // These lines implement the Interface in the beginning of program
- // They cause the OS to refresh the settings, causing IP to realy update
- _settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
- _refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
- }
-
- private static readonly DateTime UnixEpoch
- = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- public static long ToUnixEpochMilliseconds(this DateTime dt)
- => (long)(dt - UnixEpoch).TotalMilliseconds;
private static string GetTimestamp(DateTime value)
{
return value.ToString("yyyyMMddHHmmssfff");
@@ -43,139 +20,27 @@ namespace Shadowsocks.Controller
{
enabled = false;
}
- RegistryKey registry = null;
- try {
- registry = Utils.OpenUserRegKey( @"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true );
- if ( registry == null ) {
- Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" );
- return;
- }
- if ( enabled ) {
- if ( global ) {
- registry.SetValue( "ProxyEnable", 1 );
- registry.SetValue( "ProxyServer", "127.0.0.1:" + config.localPort.ToString() );
- registry.SetValue( "AutoConfigURL", "" );
- } else {
- string pacUrl;
- if ( config.useOnlinePac && ! config.pacUrl.IsNullOrEmpty() )
- pacUrl = config.pacUrl;
- else
- pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp( DateTime.Now )}";
- registry.SetValue( "ProxyEnable", 0 );
- var readProxyServer = registry.GetValue( "ProxyServer" );
- registry.SetValue( "ProxyServer", "" );
- registry.SetValue( "AutoConfigURL", pacUrl );
- }
- } else {
- registry.SetValue( "ProxyEnable", 0 );
- registry.SetValue( "ProxyServer", "" );
- registry.SetValue( "AutoConfigURL", "" );
- }
-
- //Set AutoDetectProxy
- IEAutoDetectProxy( ! enabled );
- NotifyIE();
- //Must Notify IE first, or the connections do not chanage
- CopyProxySettingFromLan();
- } catch ( Exception e ) {
- Logging.LogUsefulException( e );
- // TODO this should be moved into views
- MessageBox.Show( I18N.GetString( "Failed to update registry" ) );
- } finally {
- if ( registry != null ) {
- try {
- registry.Close();
- registry.Dispose();
- } catch (Exception e)
- { Logging.LogUsefulException(e); }
- }
- }
- }
-
- private static void CopyProxySettingFromLan()
- {
- RegistryKey registry = null;
- try {
- registry = Utils.OpenUserRegKey( @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections", true );
- if ( registry == null ) {
- Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections" );
- return;
- }
- var defaultValue = registry.GetValue( "DefaultConnectionSettings" );
- var connections = registry.GetValueNames();
- foreach ( var each in connections ) {
- switch ( each.ToUpperInvariant() ) {
- case "DEFAULTCONNECTIONSETTINGS":
- case "LAN CONNECTION":
- case "SAVEDLEGACYSETTINGS":
- continue;
- default:
- //set all the connections's proxy as the lan
- registry.SetValue( each, defaultValue );
- continue;
- }
- }
- NotifyIE();
- } catch ( IOException e ) {
- Logging.LogUsefulException( e );
- } finally {
- if ( registry != null ) {
- try {
- registry.Close();
- registry.Dispose();
- } catch (Exception e)
- { Logging.LogUsefulException(e); }
- }
- }
- }
-
- ///
- /// Checks or unchecks the IE Options Connection setting of "Automatically detect Proxy"
- ///
- /// Provide 'true' if you want to check the 'Automatically detect Proxy' check box. To uncheck, pass 'false'
- private static void IEAutoDetectProxy(bool set)
- {
- RegistryKey registry = null;
- try {
- registry = Utils.OpenUserRegKey( @"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections", true );
- if ( registry == null ) {
- Logging.Error( @"Cannot find HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections" );
- return;
- }
- var defConnection = ( byte[] ) registry.GetValue( "DefaultConnectionSettings" );
- var savedLegacySetting = ( byte[] ) registry.GetValue( "SavedLegacySettings" );
-
- const int versionOffset = 4;
- const int optionsOffset = 8;
-
- if ( set ) {
- defConnection[ optionsOffset ] = ( byte ) ( defConnection[ optionsOffset ] | 8 );
- savedLegacySetting[ optionsOffset ] = ( byte ) ( savedLegacySetting[ optionsOffset ] | 8 );
- } else {
- defConnection[ optionsOffset ] = ( byte ) ( defConnection[ optionsOffset ] & ~8 );
- savedLegacySetting[ optionsOffset ] = ( byte ) ( savedLegacySetting[ optionsOffset ] & ~8 );
+ if (enabled)
+ {
+ if (global)
+ {
+ WinINet.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
}
-
- BitConverter.GetBytes(unchecked( BitConverter.ToUInt32( defConnection, versionOffset ) + 1 ) )
- .CopyTo( defConnection, versionOffset );
- BitConverter.GetBytes(unchecked( BitConverter.ToUInt32( savedLegacySetting, versionOffset ) + 1 ) )
- .CopyTo( savedLegacySetting, versionOffset );
-
- registry.SetValue( "DefaultConnectionSettings", defConnection );
- registry.SetValue( "SavedLegacySettings", savedLegacySetting );
- } catch ( Exception e ) {
- Logging.LogUsefulException( e );
- } finally {
- if (registry != null)
+ else
{
- try {
- registry.Close();
- registry.Dispose();
- } catch (Exception e)
- { Logging.LogUsefulException(e); }
+ string pacUrl;
+ if (config.useOnlinePac && !config.pacUrl.IsNullOrEmpty())
+ pacUrl = config.pacUrl;
+ else
+ pacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}";
+ WinINet.SetIEProxy(true, false, "", pacUrl);
}
}
+ else
+ {
+ WinINet.SetIEProxy(false, false, "", "");
+ }
}
}
-}
+}
\ No newline at end of file
diff --git a/shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs b/shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs
new file mode 100644
index 00000000..584b8e97
--- /dev/null
+++ b/shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs
@@ -0,0 +1,36 @@
+/****************************** 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
+
+ }
+}
diff --git a/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs b/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs
new file mode 100644
index 00000000..351aa1ca
--- /dev/null
+++ b/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs
@@ -0,0 +1,97 @@
+/****************************** 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
+{
+ ///
+ /// Constants used in INTERNET_PER_CONN_OPTION_OptionUnion struct.
+ ///
+ 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
+ }
+
+ ///
+ /// Constants used in INTERNET_PER_CONN_OPTON struct.
+ ///
+ [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
+ }
+
+ ///
+ /// 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
+ ///
+ [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
+ }
+
+ ///
+ /// 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.
+ ///
+ [StructLayout(LayoutKind.Explicit)]
+ public struct INTERNET_PER_CONN_OPTION_OptionUnion
+ {
+ // 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;
+ }
+
+ [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;
+ }
+}
diff --git a/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs b/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs
new file mode 100644
index 00000000..b15870ce
--- /dev/null
+++ b/shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs
@@ -0,0 +1,38 @@
+/****************************** 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.Runtime.InteropServices;
+
+namespace Shadowsocks.Util.SystemProxy
+{
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct INTERNET_PER_CONN_OPTION_LIST
+ {
+ 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;
+ }
+}
diff --git a/shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs b/shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs
new file mode 100644
index 00000000..ab90c569
--- /dev/null
+++ b/shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs
@@ -0,0 +1,36 @@
+/****************************** 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
+ {
+ ///
+ /// Sets an Internet option.
+ ///
+ [DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
+ internal static extern bool InternetSetOption(
+ IntPtr hInternet,
+ INTERNET_OPTION dwOption,
+ IntPtr lpBuffer,
+ int lpdwBufferLength);
+ }
+}
diff --git a/shadowsocks-csharp/Util/SystemProxy/WinINet.cs b/shadowsocks-csharp/Util/SystemProxy/WinINet.cs
new file mode 100644
index 00000000..a1de566c
--- /dev/null
+++ b/shadowsocks-csharp/Util/SystemProxy/WinINet.cs
@@ -0,0 +1,152 @@
+/****************************** 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.Linq;
+using System.Runtime.InteropServices;
+
+namespace Shadowsocks.Util.SystemProxy
+{
+ public static class WinINet
+ {
+ ///
+ /// Set IE settings for LAN connection.
+ ///
+ public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL)
+ {
+ List _optionlist = new List();
+ 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 }
+ });
+ _optionlist.Add(new INTERNET_PER_CONN_OPTION
+ {
+ dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_SERVER,
+ Value = { pszValue = Marshal.StringToHGlobalAnsi(proxyServer) }
+ });
+ _optionlist.Add(new INTERNET_PER_CONN_OPTION
+ {
+ dwOption = (int)INTERNET_PER_CONN_OptionEnum.INTERNET_PER_CONN_PROXY_BYPASS,
+ Value = { pszValue = Marshal.StringToHGlobalAnsi("") }
+ });
+ }
+ 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.StringToHGlobalAnsi(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);
+
+ // IntPtr.Zero means LAN connection.
+ optionList.Connection = IntPtr.Zero;
+
+ 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.
+ foreach (var v in _optionlist)
+ {
+ // free strings
+ if (v.Value.pszValue != IntPtr.Zero)
+ Marshal.FreeHGlobal(v.Value.pszValue);
+ }
+ Marshal.FreeCoTaskMem(buffer);
+ Marshal.FreeCoTaskMem(intptrStruct);
+
+ // Throw an exception if this operation failed.
+ if (!bReturn)
+ {
+ throw new Exception("InternetSetOption: " + Marshal.GetLastWin32Error());
+ }
+
+ // 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);
+
+ NativeMethods.InternetSetOption(
+ IntPtr.Zero,
+ INTERNET_OPTION.INTERNET_OPTION_REFRESH,
+ IntPtr.Zero, 0);
+ }
+ }
+}
diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs
index d59cfaf1..e6017432 100755
--- a/shadowsocks-csharp/Util/Util.cs
+++ b/shadowsocks-csharp/Util/Util.cs
@@ -5,6 +5,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
+using System.Security;
using System.Windows.Forms;
using Microsoft.Win32;
using Shadowsocks.Controller;
@@ -210,14 +211,34 @@ namespace Shadowsocks.Util
return new BandwidthScaleInfo(f, unit, scale);
}
- public static RegistryKey OpenUserRegKey( string name, bool writable ) {
+ public static RegistryKey OpenUserRegKey( string name, bool writable )
+ {
// we are building x86 binary for both x86 and x64, which will
// cause problem when opening registry key
// detect operating system instead of CPU
- RegistryKey userKey = RegistryKey.OpenRemoteBaseKey( RegistryHive.CurrentUser, "",
- Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32 )
- .OpenSubKey( name, writable );
- return userKey;
+ if (name.IsNullOrEmpty()) throw new ArgumentException(nameof(name));
+ try
+ {
+ RegistryKey userKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser,
+ Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32)
+ .OpenSubKey(name, writable);
+ return userKey;
+ }
+ catch (UnauthorizedAccessException uae)
+ {
+ Logging.LogUsefulException(uae);
+ return null;
+ }
+ catch (SecurityException se)
+ {
+ Logging.LogUsefulException(se);
+ return null;
+ }
+ catch (ArgumentException ae)
+ {
+ MessageBox.Show("OpenUserRegKey: " + ae.ToString());
+ return null;
+ }
}
public static bool IsWinVistaOrHigher() {
diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj
index 36ef328d..92680f73 100644
--- a/shadowsocks-csharp/shadowsocks-csharp.csproj
+++ b/shadowsocks-csharp/shadowsocks-csharp.csproj
@@ -190,6 +190,11 @@
+
+
+
+
+
Form