Browse Source

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>
tags/3.3.3
Syrone Wong 8 years ago
parent
commit
70bff7d7cc
8 changed files with 409 additions and 159 deletions
  1. +19
    -154
      shadowsocks-csharp/Controller/System/SystemProxy.cs
  2. +36
    -0
      shadowsocks-csharp/Util/SystemProxy/INTERNET_OPTION.cs
  3. +97
    -0
      shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION.cs
  4. +38
    -0
      shadowsocks-csharp/Util/SystemProxy/INTERNET_PER_CONN_OPTION_LIST.cs
  5. +36
    -0
      shadowsocks-csharp/Util/SystemProxy/NativeMethods.cs
  6. +152
    -0
      shadowsocks-csharp/Util/SystemProxy/WinINet.cs
  7. +26
    -5
      shadowsocks-csharp/Util/Util.cs
  8. +5
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj

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

@@ -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.Model;
using Shadowsocks.Util;
using Shadowsocks.Util.SystemProxy;
namespace Shadowsocks.Controller namespace Shadowsocks.Controller
{ {
public static class SystemProxy 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) private static string GetTimestamp(DateTime value)
{ {
return value.ToString("yyyyMMddHHmmssfff"); return value.ToString("yyyyMMddHHmmssfff");
@@ -43,139 +20,27 @@ namespace Shadowsocks.Controller
{ {
enabled = false; 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, "", "");
}
} }
} }
}
}

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

@@ -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
}
}

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

@@ -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;
}
}

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

@@ -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;
}
}

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

@@ -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);
}
}

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

@@ -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);
}
}
}

+ 26
- 5
shadowsocks-csharp/Util/Util.cs View File

@@ -5,6 +5,7 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Win32; using Microsoft.Win32;
using Shadowsocks.Controller; using Shadowsocks.Controller;
@@ -210,14 +211,34 @@ namespace Shadowsocks.Util
return new BandwidthScaleInfo(f, unit, scale); 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 // we are building x86 binary for both x86 and x64, which will
// cause problem when opening registry key // cause problem when opening registry key
// detect operating system instead of CPU // 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() { public static bool IsWinVistaOrHigher() {


+ 5
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -190,6 +190,11 @@
<Compile Include="Util\Sockets\LineReader.cs" /> <Compile Include="Util\Sockets\LineReader.cs" />
<Compile Include="Util\Sockets\SocketUtil.cs" /> <Compile Include="Util\Sockets\SocketUtil.cs" />
<Compile Include="Util\Sockets\WrappedSocket.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="Util\Util.cs" />
<Compile Include="View\ConfigForm.cs"> <Compile Include="View\ConfigForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>


Loading…
Cancel
Save