Get rid of tricky registry handling Several files come from https://code.msdn.microsoft.com/windowsapps/CSWebBrowserWithProxy-c8535715/view/SourceCode Signed-off-by: Syrone Wong <wong.syrone@gmail.com>tags/3.3.3
@@ -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); } | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Checks or unchecks the IE Options Connection setting of "Automatically detect Proxy" | |||
/// </summary> | |||
/// <param name="set">Provide 'true' if you want to check the 'Automatically detect Proxy' check box. To uncheck, pass 'false'</param> | |||
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, "", ""); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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 | |||
{ | |||
/// <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 | |||
{ | |||
// 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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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 | |||
{ | |||
/// <summary> | |||
/// Sets an Internet option. | |||
/// </summary> | |||
[DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)] | |||
internal static extern bool InternetSetOption( | |||
IntPtr hInternet, | |||
INTERNET_OPTION dwOption, | |||
IntPtr lpBuffer, | |||
int lpdwBufferLength); | |||
} | |||
} |
@@ -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 | |||
{ | |||
/// <summary> | |||
/// Set IE settings for LAN connection. | |||
/// </summary> | |||
public static void SetIEProxy(bool enable, bool global, string proxyServer, string pacURL) | |||
{ | |||
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 } | |||
}); | |||
_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("<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.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); | |||
} | |||
} | |||
} |
@@ -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() { | |||
@@ -190,6 +190,11 @@ | |||
<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\WinINet.cs" /> | |||
<Compile Include="Util\Util.cs" /> | |||
<Compile Include="View\ConfigForm.cs"> | |||
<SubType>Form</SubType> | |||