Browse Source

platform and required service check for wininet

pull/2874/head
Student Main 5 years ago
parent
commit
fc2285b0c6
1 changed files with 61 additions and 17 deletions
  1. +61
    -17
      shadowsocks-csharp/Util/SystemProxy/WinINet.cs

+ 61
- 17
shadowsocks-csharp/Util/SystemProxy/WinINet.cs View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Shadowsocks.Model;
using NLog;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -92,7 +92,7 @@ namespace Shadowsocks.Util.SystemProxy
public int OptionError; public int OptionError;


// List of INTERNET_PER_CONN_OPTIONs. // List of INTERNET_PER_CONN_OPTIONs.
public System.IntPtr pOptions;
public IntPtr pOptions;


public void Dispose() public void Dispose()
{ {
@@ -128,11 +128,37 @@ namespace Shadowsocks.Util.SystemProxy


public class WinINet public class WinINet
{ {
private static readonly Logger logger = LogManager.GetCurrentClassLogger();

private const string SettingFile = "wininet-setting.json"; private const string SettingFile = "wininet-setting.json";
private static WinINetSetting initialSetting; private static WinINetSetting initialSetting;


public static bool operational { get; private set; } = true;
static WinINet() static WinINet()
{ {
try
{
Query();
}
catch (DllNotFoundException)
{
operational = false;
// Not on windows
logger.Info("You are not running on Windows platform, system proxy will disable");
}
catch (Win32Exception we)
{
if (we.NativeErrorCode == 12178)
{
logger.Warn("WPAD service is not running, system proxy will disable");
// WPAD not running
}
else
{
throw we;
}
}

Load(); Load();
} }


@@ -191,7 +217,7 @@ namespace Shadowsocks.Util.SystemProxy
sw.Flush(); sw.Flush();
} }
} }
catch (IOException e)
catch (IOException)
{ {
// logger.LogUsefulException(e); // logger.LogUsefulException(e);
} }
@@ -229,6 +255,11 @@ namespace Shadowsocks.Util.SystemProxy


public static WinINetSetting Query() public static WinINetSetting Query()
{ {
if (!operational)
{
return new WinINetSetting();
}

List<InternetPerConnectionOption> options = new List<InternetPerConnectionOption> List<InternetPerConnectionOption> options = new List<InternetPerConnectionOption>
{ {
new InternetPerConnectionOption{dwOption = (int)InternetPerConnectionOptionEnum.FlagsUI}, new InternetPerConnectionOption{dwOption = (int)InternetPerConnectionOptionEnum.FlagsUI},
@@ -237,11 +268,14 @@ namespace Shadowsocks.Util.SystemProxy
new InternetPerConnectionOption{dwOption = (int)InternetPerConnectionOptionEnum.AutoConfigUrl}, new InternetPerConnectionOption{dwOption = (int)InternetPerConnectionOptionEnum.AutoConfigUrl},
}; };


var (unmanagedList, listSize) = PrepareOptionList(options, null);
(IntPtr unmanagedList, int listSize) = PrepareOptionList(options, null);
bool ok = InternetQueryOption(IntPtr.Zero, (int)InternetOptions.PerConnectionOption, unmanagedList, ref listSize); bool ok = InternetQueryOption(IntPtr.Zero, (int)InternetOptions.PerConnectionOption, unmanagedList, ref listSize);
if (!ok) throw new Exception();
if (!ok)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}


var proxy = new WinINetSetting();
WinINetSetting proxy = new WinINetSetting();


InternetPerConnectionOptionList ret = Marshal.PtrToStructure<InternetPerConnectionOptionList>(unmanagedList); InternetPerConnectionOptionList ret = Marshal.PtrToStructure<InternetPerConnectionOptionList>(unmanagedList);
IntPtr p = ret.pOptions; IntPtr p = ret.pOptions;
@@ -249,12 +283,12 @@ namespace Shadowsocks.Util.SystemProxy
List<InternetPerConnectionOption> outOptions = new List<InternetPerConnectionOption>(); List<InternetPerConnectionOption> outOptions = new List<InternetPerConnectionOption>();
for (int i = 0; i < nOption; i++) for (int i = 0; i < nOption; i++)
{ {
var o = Marshal.PtrToStructure<InternetPerConnectionOption>(p);
InternetPerConnectionOption o = Marshal.PtrToStructure<InternetPerConnectionOption>(p);
outOptions.Add(o); outOptions.Add(o);
p += Marshal.SizeOf(o); p += Marshal.SizeOf(o);
} }


foreach (var o in outOptions)
foreach (InternetPerConnectionOption o in outOptions)
{ {
switch ((InternetPerConnectionOptionEnum)o.dwOption) switch ((InternetPerConnectionOptionEnum)o.dwOption)
{ {
@@ -315,7 +349,7 @@ namespace Shadowsocks.Util.SystemProxy
IntPtr buf = Marshal.AllocCoTaskMem(len); IntPtr buf = Marshal.AllocCoTaskMem(len);
IntPtr cur = buf; IntPtr cur = buf;


foreach (var o in options)
foreach (InternetPerConnectionOption o in options)
{ {
Marshal.StructureToPtr(o, cur, false); Marshal.StructureToPtr(o, cur, false);
cur += Marshal.SizeOf(o); cur += Marshal.SizeOf(o);
@@ -351,7 +385,7 @@ namespace Shadowsocks.Util.SystemProxy
Record(); Record();


Exec(options, null); Exec(options, null);
foreach (var conn in RAS.GetAllConnections())
foreach (string conn in RAS.GetAllConnections())
{ {
Exec(options, conn); Exec(options, conn);
} }
@@ -361,7 +395,12 @@ namespace Shadowsocks.Util.SystemProxy


private static void Exec(List<InternetPerConnectionOption> options, string connName) private static void Exec(List<InternetPerConnectionOption> options, string connName)
{ {
var (unmanagedList, listSize) = PrepareOptionList(options, connName);
if (!operational)
{
return;
}

(IntPtr unmanagedList, int listSize) = PrepareOptionList(options, connName);


bool ok = InternetSetOption( bool ok = InternetSetOption(
IntPtr.Zero, IntPtr.Zero,
@@ -372,8 +411,7 @@ namespace Shadowsocks.Util.SystemProxy


if (!ok) if (!ok)
{ {
int errno = Marshal.GetLastWin32Error();
throw new Win32Exception(errno);
throw new Win32Exception(Marshal.GetLastWin32Error());
} }
ClearOptionList(unmanagedList); ClearOptionList(unmanagedList);
ok = InternetSetOption( ok = InternetSetOption(
@@ -382,22 +420,28 @@ namespace Shadowsocks.Util.SystemProxy
IntPtr.Zero, IntPtr.Zero,
0 0
); );
if (!ok) throw new Exception();
if (!ok)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}

ok = InternetSetOption( ok = InternetSetOption(
IntPtr.Zero, IntPtr.Zero,
(int)InternetOptions.Refresh, (int)InternetOptions.Refresh,
IntPtr.Zero, IntPtr.Zero,
0 0
); );
if (!ok) throw new Exception();

if (!ok)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
} }


[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);


[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool InternetQueryOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, ref int lpdwBufferLength);
private static extern bool InternetQueryOption(IntPtr hInternet, uint dwOption, IntPtr lpBuffer, ref int lpdwBufferLength);


} }
} }

Loading…
Cancel
Save