mirror of
https://github.com/jie65535/GrasscutterCommandGenerator.git
synced 2025-10-21 19:59:48 +08:00
Add HTTP(S) proxy (#208)
This commit is contained in:
241
Source/GrasscutterTools/Eavesdrop/Internals/INETOptions.cs
Normal file
241
Source/GrasscutterTools/Eavesdrop/Internals/INETOptions.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Eavesdrop
|
||||
{
|
||||
public static class INETOptions
|
||||
{
|
||||
private static readonly object _stateLock;
|
||||
private static readonly int _iNetOptionSize;
|
||||
private static readonly int _iNetPackageSize;
|
||||
private static readonly RegistryKey _proxyKey;
|
||||
|
||||
public static List<string> Overrides { get; }
|
||||
|
||||
public static string HTTPAddress { get; set; }
|
||||
public static string HTTPSAddress { get; set; }
|
||||
|
||||
public static bool IsProxyEnabled { get; set; }
|
||||
public static bool IsIgnoringLocalTraffic { get; set; }
|
||||
|
||||
static INETOptions()
|
||||
{
|
||||
_stateLock = new object();
|
||||
_iNetOptionSize = Marshal.SizeOf(typeof(INETOption));
|
||||
_iNetPackageSize = Marshal.SizeOf(typeof(INETPackage));
|
||||
_proxyKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
|
||||
|
||||
Overrides = new List<string>();
|
||||
Load();
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
var options = new List<INETOption>(3);
|
||||
string joinedAddresses = (IsProxyEnabled ? GetJoinedAddresses() : null);
|
||||
string joinedOverrides = (IsProxyEnabled ? GetJoinedOverrides() : null);
|
||||
|
||||
var kind = ProxyKind.PROXY_TYPE_DIRECT;
|
||||
if (!string.IsNullOrWhiteSpace(joinedAddresses))
|
||||
{
|
||||
options.Add(new INETOption(OptionKind.INTERNET_PER_CONN_PROXY_SERVER, joinedAddresses));
|
||||
if (!string.IsNullOrWhiteSpace(joinedOverrides))
|
||||
{
|
||||
options.Add(new INETOption(OptionKind.INTERNET_PER_CONN_PROXY_BYPASS, joinedOverrides));
|
||||
}
|
||||
kind |= ProxyKind.PROXY_TYPE_PROXY;
|
||||
}
|
||||
options.Insert(0, new INETOption(OptionKind.INTERNET_PER_CONN_FLAGS, (int)kind));
|
||||
|
||||
var inetPackage = new INETPackage
|
||||
{
|
||||
_optionError = 0,
|
||||
_size = _iNetPackageSize,
|
||||
_connection = IntPtr.Zero,
|
||||
_optionCount = options.Count
|
||||
};
|
||||
|
||||
IntPtr optionsPtr = Marshal.AllocCoTaskMem(_iNetOptionSize * options.Count);
|
||||
for (int i = 0; i < options.Count; ++i)
|
||||
{
|
||||
var optionPtr = new IntPtr((IntPtr.Size == 4 ? optionsPtr.ToInt32() : optionsPtr.ToInt64()) + (i * _iNetOptionSize));
|
||||
Marshal.StructureToPtr(options[i], optionPtr, false);
|
||||
}
|
||||
inetPackage._optionsPtr = optionsPtr;
|
||||
|
||||
IntPtr iNetPackagePtr = Marshal.AllocCoTaskMem(_iNetPackageSize);
|
||||
Marshal.StructureToPtr(inetPackage, iNetPackagePtr, false);
|
||||
|
||||
int returnvalue = (NativeMethods.InternetSetOption(IntPtr.Zero, 75, iNetPackagePtr, _iNetPackageSize) ? -1 : 0);
|
||||
if (returnvalue == 0)
|
||||
{
|
||||
returnvalue = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
Marshal.FreeCoTaskMem(optionsPtr);
|
||||
Marshal.FreeCoTaskMem(iNetPackagePtr);
|
||||
if (returnvalue > 0)
|
||||
{
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
NativeMethods.InternetSetOption(IntPtr.Zero, 39, iNetPackagePtr, _iNetPackageSize);
|
||||
NativeMethods.InternetSetOption(IntPtr.Zero, 37, iNetPackagePtr, _iNetPackageSize);
|
||||
}
|
||||
}
|
||||
public static void Load()
|
||||
{
|
||||
lock (_stateLock)
|
||||
{
|
||||
LoadAddresses();
|
||||
LoadOverrides();
|
||||
IsProxyEnabled = (_proxyKey.GetValue("ProxyEnable")?.ToString() == "1");
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadOverrides()
|
||||
{
|
||||
string proxyOverride = _proxyKey.GetValue("ProxyOverride")?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(proxyOverride)) return;
|
||||
|
||||
string[] overrides = proxyOverride.Split(';');
|
||||
foreach (string @override in overrides)
|
||||
{
|
||||
if (@override == "<local>")
|
||||
{
|
||||
IsIgnoringLocalTraffic = true;
|
||||
}
|
||||
else if (!Overrides.Contains(@override))
|
||||
{
|
||||
Overrides.Add(@override);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void LoadAddresses()
|
||||
{
|
||||
string proxyServer = _proxyKey.GetValue("ProxyServer")?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(proxyServer)) return;
|
||||
|
||||
string[] values = proxyServer.Split(';');
|
||||
foreach (string value in values)
|
||||
{
|
||||
string[] pair = value.Split('=');
|
||||
if (pair.Length != 2)
|
||||
{
|
||||
HTTPAddress = value;
|
||||
HTTPSAddress = value;
|
||||
return;
|
||||
}
|
||||
|
||||
string address = pair[1];
|
||||
string protocol = pair[0];
|
||||
switch (protocol)
|
||||
{
|
||||
case "http": HTTPAddress = address; break;
|
||||
case "https": HTTPSAddress = address; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetJoinedAddresses()
|
||||
{
|
||||
var addresses = new List<string>(2);
|
||||
if (!string.IsNullOrWhiteSpace(HTTPAddress))
|
||||
{
|
||||
addresses.Add("http=" + HTTPAddress);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(HTTPSAddress))
|
||||
{
|
||||
addresses.Add("https=" + HTTPSAddress);
|
||||
}
|
||||
return string.Join(";", addresses);
|
||||
}
|
||||
private static string GetJoinedOverrides()
|
||||
{
|
||||
var overrides = new List<string>(Overrides);
|
||||
if (IsIgnoringLocalTraffic)
|
||||
{
|
||||
overrides.Add("<local>");
|
||||
}
|
||||
return string.Join(";", overrides);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
private struct INETOption
|
||||
{
|
||||
private readonly OptionKind _kind;
|
||||
private readonly INETOptionValue _value;
|
||||
|
||||
public INETOption(OptionKind kind, int value)
|
||||
{
|
||||
_kind = kind;
|
||||
_value = CreateValue(value);
|
||||
}
|
||||
public INETOption(OptionKind kind, string value)
|
||||
{
|
||||
_kind = kind;
|
||||
_value = CreateValue(value);
|
||||
}
|
||||
|
||||
private static INETOptionValue CreateValue(int value)
|
||||
{
|
||||
return new INETOptionValue
|
||||
{
|
||||
_intValue = value
|
||||
};
|
||||
}
|
||||
private static INETOptionValue CreateValue(string value)
|
||||
{
|
||||
return new INETOptionValue
|
||||
{
|
||||
_stringPointer = Marshal.StringToHGlobalAuto(value)
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct INETOptionValue
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public int _intValue;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public IntPtr _stringPointer;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public System.Runtime.InteropServices.ComTypes.FILETIME _fileTime;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
private struct INETPackage
|
||||
{
|
||||
public int _size;
|
||||
public IntPtr _connection;
|
||||
public int _optionCount;
|
||||
public int _optionError;
|
||||
public IntPtr _optionsPtr;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum ProxyKind
|
||||
{
|
||||
PROXY_TYPE_DIRECT = 1,
|
||||
PROXY_TYPE_PROXY = 2,
|
||||
PROXY_TYPE_AUTO_PROXY_URL = 4,
|
||||
PROXY_TYPE_AUTO_DETECT = 8
|
||||
}
|
||||
private enum OptionKind
|
||||
{
|
||||
INTERNET_PER_CONN_FLAGS = 1,
|
||||
INTERNET_PER_CONN_PROXY_SERVER = 2,
|
||||
INTERNET_PER_CONN_PROXY_BYPASS = 3,
|
||||
INTERNET_PER_CONN_AUTOCONFIG_URL = 4
|
||||
}
|
||||
}
|
||||
}
|
12
Source/GrasscutterTools/Eavesdrop/Internals/NativeMethods.cs
Normal file
12
Source/GrasscutterTools/Eavesdrop/Internals/NativeMethods.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Eavesdrop
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user