Browse Source

Revert "Remove privoxy"

This reverts commit 0d4d01af3b.
tags/3.4.2
noisyfox 7 years ago
parent
commit
dd269ac89d
12 changed files with 783 additions and 49 deletions
  1. +0
    -23
      shadowsocks-csharp/Controller/Service/Http2Socks5.cs
  2. +261
    -0
      shadowsocks-csharp/Controller/Service/PortForwarder.cs
  3. +216
    -0
      shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs
  4. +18
    -2
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  5. BIN
      shadowsocks-csharp/Data/mgwz.dll.gz
  6. BIN
      shadowsocks-csharp/Data/privoxy.exe.gz
  7. +5
    -0
      shadowsocks-csharp/Data/privoxy_conf.txt
  8. +57
    -23
      shadowsocks-csharp/Properties/Resources.Designer.cs
  9. +9
    -0
      shadowsocks-csharp/Properties/Resources.resx
  10. +179
    -0
      shadowsocks-csharp/Util/ProcessManagement/Job.cs
  11. +31
    -0
      shadowsocks-csharp/Util/ProcessManagement/ThreadUtil.cs
  12. +7
    -1
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 0
- 23
shadowsocks-csharp/Controller/Service/Http2Socks5.cs View File

@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Shadowsocks.Util.Sockets;

namespace Shadowsocks.Controller.Service
{
class Http2Socks5 : Listener.Service
{
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
{
if (socket.ProtocolType != ProtocolType.Tcp)
{
return false;
}

return true;
}
}
}

+ 261
- 0
shadowsocks-csharp/Controller/Service/PortForwarder.cs View File

@@ -0,0 +1,261 @@
using System;
using System.Net;
using System.Net.Sockets;
using Shadowsocks.Util.Sockets;
namespace Shadowsocks.Controller
{
class PortForwarder : Listener.Service
{
int _targetPort;
public PortForwarder(int targetPort)
{
this._targetPort = targetPort;
}
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state)
{
if (socket.ProtocolType != ProtocolType.Tcp)
{
return false;
}
new Handler().Start(firstPacket, length, socket, this._targetPort);
return true;
}
class Handler
{
private byte[] _firstPacket;
private int _firstPacketLength;
private Socket _local;
private WrappedSocket _remote;
private bool _closed = false;
private bool _localShutdown = false;
private bool _remoteShutdown = false;
public const int RecvSize = 16384;
// remote receive buffer
private byte[] remoteRecvBuffer = new byte[RecvSize];
// connection receive buffer
private byte[] connetionRecvBuffer = new byte[RecvSize];
// instance-based lock
private readonly object _Lock = new object();
public void Start(byte[] firstPacket, int length, Socket socket, int targetPort)
{
this._firstPacket = firstPacket;
this._firstPacketLength = length;
this._local = socket;
try
{
EndPoint remoteEP = SocketUtil.GetEndPoint("127.0.0.1", targetPort);
// Connect to the remote endpoint.
_remote = new WrappedSocket();
_remote.BeginConnect(remoteEP, ConnectCallback, null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void ConnectCallback(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
_remote.EndConnect(ar);
_remote.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
HandshakeReceive();
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void HandshakeReceive()
{
if (_closed)
{
return;
}
try
{
_remote.BeginSend(_firstPacket, 0, _firstPacketLength, 0, new AsyncCallback(StartPipe), null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void StartPipe(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
_remote.EndSend(ar);
_remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeRemoteReceiveCallback), null);
_local.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeConnectionReceiveCallback), null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void PipeRemoteReceiveCallback(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
int bytesRead = _remote.EndReceive(ar);
if (bytesRead > 0)
{
_local.BeginSend(remoteRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeConnectionSendCallback), null);
}
else
{
_local.Shutdown(SocketShutdown.Send);
_localShutdown = true;
CheckClose();
}
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void PipeConnectionReceiveCallback(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
int bytesRead = _local.EndReceive(ar);
if (bytesRead > 0)
{
_remote.BeginSend(connetionRecvBuffer, 0, bytesRead, 0, new AsyncCallback(PipeRemoteSendCallback), null);
}
else
{
_remote.Shutdown(SocketShutdown.Send);
_remoteShutdown = true;
CheckClose();
}
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void PipeRemoteSendCallback(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
_remote.EndSend(ar);
_local.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeConnectionReceiveCallback), null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void PipeConnectionSendCallback(IAsyncResult ar)
{
if (_closed)
{
return;
}
try
{
_local.EndSend(ar);
_remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0,
new AsyncCallback(PipeRemoteReceiveCallback), null);
}
catch (Exception e)
{
Logging.LogUsefulException(e);
this.Close();
}
}
private void CheckClose()
{
if (_localShutdown && _remoteShutdown)
{
this.Close();
}
}
public void Close()
{
lock (_Lock)
{
if (_closed)
{
return;
}
_closed = true;
}
if (_local != null)
{
try
{
_local.Shutdown(SocketShutdown.Both);
_local.Close();
}
catch (Exception e)
{
Logging.LogUsefulException(e);
}
}
if (_remote != null)
{
try
{
_remote.Shutdown(SocketShutdown.Both);
_remote.Dispose();
}
catch (SocketException e)
{
Logging.LogUsefulException(e);
}
}
}
}
}
}

+ 216
- 0
shadowsocks-csharp/Controller/Service/PrivoxyRunner.cs View File

@@ -0,0 +1,216 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using Shadowsocks.Util.ProcessManagement;
namespace Shadowsocks.Controller
{
class PrivoxyRunner
{
private static int Uid;
private static string UniqueConfigFile;
private static Job PrivoxyJob;
private Process _process;
private int _runningPort;
static PrivoxyRunner()
{
try
{
Uid = Application.StartupPath.GetHashCode(); // Currently we use ss's StartupPath to identify different Privoxy instance.
UniqueConfigFile = $"privoxy_{Uid}.conf";
PrivoxyJob = new Job();
FileManager.UncompressFile(Utils.GetTempPath("ss_privoxy.exe"), Resources.privoxy_exe);
FileManager.UncompressFile(Utils.GetTempPath("mgwz.dll"), Resources.mgwz_dll);
}
catch (IOException e)
{
Logging.LogUsefulException(e);
}
}
public int RunningPort => _runningPort;
public void Start(Configuration configuration)
{
if (_process == null)
{
Process[] existingPrivoxy = Process.GetProcessesByName("ss_privoxy");
foreach (Process p in existingPrivoxy.Where(IsChildProcess))
{
KillProcess(p);
}
string privoxyConfig = Resources.privoxy_conf;
_runningPort = this.GetFreePort();
privoxyConfig = privoxyConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString());
privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_PORT__", _runningPort.ToString());
privoxyConfig = privoxyConfig.Replace("__PRIVOXY_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1");
FileManager.ByteArrayToFile(Utils.GetTempPath(UniqueConfigFile), Encoding.UTF8.GetBytes(privoxyConfig));
_process = new Process();
// Configure the process using the StartInfo properties.
_process.StartInfo.FileName = "ss_privoxy.exe";
_process.StartInfo.Arguments = UniqueConfigFile;
_process.StartInfo.WorkingDirectory = Utils.GetTempPath();
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_process.StartInfo.UseShellExecute = true;
_process.StartInfo.CreateNoWindow = true;
_process.Start();
/*
* Add this process to job obj associated with this ss process, so that
* when ss exit unexpectedly, this process will be forced killed by system.
*/
PrivoxyJob.AddProcess(_process.Handle);
}
RefreshTrayArea();
}
public void Stop()
{
if (_process != null)
{
KillProcess(_process);
_process.Dispose();
_process = null;
}
RefreshTrayArea();
}
private static void KillProcess(Process p)
{
try
{
p.CloseMainWindow();
p.WaitForExit(100);
if (!p.HasExited)
{
p.Kill();
p.WaitForExit();
}
}
catch (Exception e)
{
Logging.LogUsefulException(e);
}
}
/*
* We won't like to kill other ss instances' ss_privoxy.exe.
* This function will check whether the given process is created
* by this process by checking the module path or command line.
*
* Since it's required to put ss in different dirs to run muti instances,
* different instance will create their unique "privoxy_UID.conf" where
* UID is hash of ss's location.
*/
private static bool IsChildProcess(Process process)
{
try
{
if (Utils.IsPortableMode())
{
/*
* Under PortableMode, we could identify it by the path of ss_privoxy.exe.
*/
var path = process.MainModule.FileName;
return Utils.GetTempPath("ss_privoxy.exe").Equals(path);
}
else
{
var cmd = process.GetCommandLine();
return cmd.Contains(UniqueConfigFile);
}
}
catch (Exception ex)
{
/*
* Sometimes Process.GetProcessesByName will return some processes that
* are already dead, and that will cause exceptions here.
* We could simply ignore those exceptions.
*/
Logging.LogUsefulException(ex);
return false;
}
}
private int GetFreePort()
{
int defaultPort = 8123;
try
{
// TCP stack please do me a favor
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
var port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
catch (Exception e)
{
// in case access denied
Logging.LogUsefulException(e);
return defaultPort;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public void RefreshTrayArea()
{
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
if (notificationAreaHandle == IntPtr.Zero)
{
notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null);
IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
RefreshTrayArea(overflowNotificationAreaHandle);
}
RefreshTrayArea(notificationAreaHandle);
}
private static void RefreshTrayArea(IntPtr windowHandle)
{
const uint wmMousemove = 0x0200;
RECT rect;
GetClientRect(windowHandle, out rect);
for (var x = 0; x < rect.right; x += 5)
for (var y = 0; y < rect.bottom; y += 5)
SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x);
}
}
}

+ 18
- 2
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -30,6 +30,7 @@ namespace Shadowsocks.Controller
private PACServer _pacServer;
private Configuration _config;
private StrategyManager _strategyManager;
private PrivoxyRunner privoxyRunner;
private GFWListUpdater gfwListUpdater;
public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance;
public StatisticsStrategyConfiguration StatisticsConfiguration { get; private set; }
@@ -264,6 +265,10 @@ namespace Shadowsocks.Controller
{
_listener.Stop();
}
if (privoxyRunner != null)
{
privoxyRunner.Stop();
}
if (_config.enabled)
{
SystemProxy.Update(_config, true, null);
@@ -427,7 +432,11 @@ namespace Shadowsocks.Controller
// some logic in configuration updated the config when saving, we need to read it again
_config = Configuration.Load();
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
if (privoxyRunner == null)
{
privoxyRunner = new PrivoxyRunner();
}
if (_pacServer == null)
{
_pacServer = new PACServer();
@@ -448,7 +457,11 @@ namespace Shadowsocks.Controller
{
_listener.Stop();
}
// don't put PrivoxyRunner.Start() before pacServer.Stop()
// or bind will fail when switching bind address from 0.0.0.0 to 127.0.0.1
// though UseShellExecute is set to true now
// http://stackoverflow.com/questions/10235093/socket-doesnt-close-after-application-exits-if-a-launched-process-is-open
privoxyRunner.Stop();
try
{
var strategy = GetCurrentStrategy();
@@ -457,12 +470,15 @@ namespace Shadowsocks.Controller
strategy.ReloadServers();
}
privoxyRunner.Start(_config);
TCPRelay tcpRelay = new TCPRelay(this, _config);
UDPRelay udpRelay = new UDPRelay(this);
List<Listener.IService> services = new List<Listener.IService>();
services.Add(tcpRelay);
services.Add(udpRelay);
services.Add(_pacServer);
services.Add(new PortForwarder(privoxyRunner.RunningPort));
_listener = new Listener(services);
_listener.Start(_config);
}


BIN
shadowsocks-csharp/Data/mgwz.dll.gz View File


BIN
shadowsocks-csharp/Data/privoxy.exe.gz View File


+ 5
- 0
shadowsocks-csharp/Data/privoxy_conf.txt View File

@@ -0,0 +1,5 @@
listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__
show-on-task-bar 0
activity-animation 0
forward-socks5 / 127.0.0.1:__SOCKS_PORT__ .
hide-console

+ 57
- 23
shadowsocks-csharp/Properties/Resources.Designer.cs View File

@@ -111,6 +111,40 @@ namespace Shadowsocks.Properties {
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] mgwz_dll {
get {
object obj = ResourceManager.GetObject("mgwz_dll", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找类似 listen-address __PRIVOXY_BIND_IP__:__PRIVOXY_BIND_PORT__
///show-on-task-bar 0
///activity-animation 0
///forward-socks5 / 127.0.0.1:__SOCKS_PORT__ .
///hide-console
/// 的本地化字符串。
/// </summary>
internal static string privoxy_conf {
get {
return ResourceManager.GetString("privoxy_conf", resourceCulture);
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] privoxy_exe {
get {
object obj = ResourceManager.GetObject("privoxy_exe", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
@@ -213,29 +247,29 @@ namespace Shadowsocks.Properties {
}
/// <summary>
/// 查找类似 # translation for Traditional Chinese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=啟用系統代理
///Mode=系統代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=伺服器
///Edit Servers...=編輯伺服器...
///Statistics Config...=統計配置...
///Start on Boot=開機啟動
///Forward Proxy...=正向代理設置...
///Allow Clients from LAN=允許來自區域網路的連接
///Local PAC=使用本地 PAC
///Online PAC=使用在線 PAC
///Edit Local PAC File...=編輯本地 PAC 文件...
///Update Local PAC from GFWList=從 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
///Show QRCode...=顯示 QR 碼...
///S [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// 查找类似 # translation for Traditional Chinese
///
///Shadowsocks=Shadowsocks
///
///# Menu items
///
///Enable System Proxy=啟用系統代理
///Mode=系統代理模式
///PAC=PAC 模式
///Global=全局模式
///Servers=伺服器
///Edit Servers...=編輯伺服器...
///Statistics Config...=統計配置...
///Start on Boot=開機啟動
///Forward Proxy...=正向代理設置...
///Allow Clients from LAN=允許來自區域網路的連接
///Local PAC=使用本地 PAC
///Online PAC=使用在線 PAC
///Edit Local PAC File...=編輯本地 PAC 文件...
///Update Local PAC from GFWList=從 GFWList 更新本地 PAC
///Edit User Rule for GFWList...=編輯 GFWList 的用戶規則...
///Show QRCode...=顯示 QR 碼...
///Scan QRCode from Screen [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string zh_tw {
get {


+ 9
- 0
shadowsocks-csharp/Properties/Resources.resx View File

@@ -127,6 +127,15 @@
<data name="libsscrypto_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="mgwz_dll" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\mgwz.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="privoxy_conf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\privoxy_conf.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="privoxy_exe" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\data\privoxy.exe.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="proxy_pac_txt" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Data\proxy.pac.txt.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>


+ 179
- 0
shadowsocks-csharp/Util/ProcessManagement/Job.cs View File

@@ -0,0 +1,179 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Shadowsocks.Controller;

namespace Shadowsocks.Util.ProcessManagement
{
/*
* See:
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
*/
public class Job : IDisposable
{
private IntPtr handle = IntPtr.Zero;

public Job()
{
handle = CreateJobObject(IntPtr.Zero, null);
var extendedInfoPtr = IntPtr.Zero;
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
LimitFlags = 0x2000
};

var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};

try
{
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
(uint) length))
throw new Exception(string.Format("Unable to set information. Error: {0}",
Marshal.GetLastWin32Error()));
}
finally
{
if (extendedInfoPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(extendedInfoPtr);
extendedInfoPtr = IntPtr.Zero;
}
}
}

public bool AddProcess(IntPtr processHandle)
{
var succ = AssignProcessToJobObject(handle, processHandle);

if (!succ)
{
Logging.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
}

return succ;
}

public bool AddProcess(int processId)
{
return AddProcess(Process.GetProcessById(processId).Handle);
}

#region IDisposable

private bool disposed;

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;

if (disposing)
{
// no managed objects to free
}

if (handle != IntPtr.Zero)
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
}

~Job()
{
Dispose(false);
}

#endregion

#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);

#endregion
}

#region Helper classes

[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}


[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public UInt32 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public UIntPtr Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}

[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public Int32 bInheritHandle;
}

[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}

public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}

#endregion
}

+ 31
- 0
shadowsocks-csharp/Util/ProcessManagement/ThreadUtil.cs View File

@@ -0,0 +1,31 @@
using System.Diagnostics;
using System.Management;
using System.Text;

namespace Shadowsocks.Util.ProcessManagement
{
static class ThreadUtil
{

/*
* See:
* http://stackoverflow.com/questions/2633628/can-i-get-command-line-arguments-of-other-processes-from-net-c
*/
public static string GetCommandLine(this Process process)
{
var commandLine = new StringBuilder(process.MainModule.FileName);

commandLine.Append(" ");
using (var searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id))
{
foreach (var @object in searcher.Get())
{
commandLine.Append(@object["CommandLine"]);
commandLine.Append(" ");
}
}

return commandLine.ToString();
}
}
}

+ 7
- 1
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -140,7 +140,6 @@
<Compile Include="3rd\zxing\ResultPoint.cs" />
<Compile Include="3rd\zxing\ResultPointCallback.cs" />
<Compile Include="3rd\zxing\WriterException.cs" />
<Compile Include="Controller\Service\Http2Socks5.cs" />
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" />
<Compile Include="Model\HotKeyConfig.cs" />
<Compile Include="Model\ProxyConfig.cs" />
@@ -161,6 +160,7 @@
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Service\Listener.cs" />
<Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\Service\PortForwarder.cs" />
<Compile Include="Controller\Service\UDPRelay.cs" />
<Compile Include="Controller\Service\UpdateChecker.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
@@ -189,6 +189,8 @@
<Compile Include="Settings.cs" />
<Compile Include="StringEx.cs" />
<Compile Include="Controller\System\Hotkeys\Hotkeys.cs" />
<Compile Include="Util\ProcessManagement\Job.cs" />
<Compile Include="Util\ProcessManagement\ThreadUtil.cs" />
<Compile Include="Encryption\RNG.cs" />
<Compile Include="Util\Sockets\LineReader.cs" />
<Compile Include="Util\Sockets\SocketUtil.cs" />
@@ -204,6 +206,7 @@
<DependentUpon>ConfigForm.cs</DependentUpon>
</Compile>
<Compile Include="Controller\Service\TCPRelay.cs" />
<Compile Include="Controller\Service\PrivoxyRunner.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Controller\ShadowsocksController.cs" />
@@ -281,6 +284,8 @@
</None>
<None Include="Data\abp.js.gz" />
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\mgwz.dll.gz" />
<None Include="Data\privoxy.exe.gz" />
<None Include="Data\proxy.pac.txt.gz" />
</ItemGroup>
<ItemGroup>
@@ -297,6 +302,7 @@
<None Include="Resources\ss24.png" />
<None Include="Resources\ssw128.png" />
<Content Include="Data\cn.txt" />
<Content Include="Data\privoxy_conf.txt" />
<Content Include="Data\user-rule.txt" />
<Content Include="Data\zh_tw.txt" />
<Content Include="FodyWeavers.xml">


Loading…
Cancel
Save