Use wininet API to setup system proxy
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>
This commit is contained in:
@@ -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 );
|
||||
}
|
||||
|
||||
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)
|
||||
if (enabled)
|
||||
{
|
||||
if (global)
|
||||
{
|
||||
try {
|
||||
registry.Close();
|
||||
registry.Dispose();
|
||||
} catch (Exception e)
|
||||
{ Logging.LogUsefulException(e); }
|
||||
WinINet.SetIEProxy(true, true, "127.0.0.1:" + config.localPort.ToString(), "");
|
||||
}
|
||||
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)}";
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user