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>
153 lines
6.3 KiB
C#
153 lines
6.3 KiB
C#
/****************************** 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);
|
|
}
|
|
}
|
|
}
|