158 lines
4.9 KiB
C#
158 lines
4.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Net;
|
|
using System.Threading;
|
|
|
|
namespace IW4MAdmin
|
|
{
|
|
class Manager
|
|
{
|
|
private List<Server> Servers;
|
|
private SortedDictionary<int, Thread> ThreadList;
|
|
private List<int> activePIDs;
|
|
|
|
public Manager()
|
|
{
|
|
ThreadList = new SortedDictionary<int, Thread>();
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
activePIDs = getCurrentIW4MProcesses();
|
|
Servers = loadServers();
|
|
|
|
foreach (Server S in Servers)
|
|
{
|
|
Server IW4MServer = S;
|
|
Thread IW4MServerThread = new Thread(IW4MServer.Monitor);
|
|
ThreadList.Add(IW4MServer.pID(), IW4MServerThread);
|
|
IW4MServerThread.Start();
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
lock (Servers)
|
|
{
|
|
foreach (Server S in Servers)
|
|
{
|
|
if (S == null)
|
|
continue;
|
|
|
|
if (!isIW4MStillRunning(S.pID()))
|
|
{
|
|
Thread Defunct = ThreadList[S.pID()];
|
|
if (Defunct != null)
|
|
{
|
|
Defunct.Abort();
|
|
ThreadList[S.pID()] = null;
|
|
}
|
|
activePIDs.Remove(S.pID());
|
|
}
|
|
}
|
|
}
|
|
scanForNewServers();
|
|
Utilities.Wait(5);
|
|
}
|
|
}
|
|
|
|
private void scanForNewServers()
|
|
{
|
|
List<int> newProcesses = getCurrentIW4MProcesses();
|
|
foreach (int pID in activePIDs)
|
|
{
|
|
bool newProcess = true;
|
|
foreach (int I in newProcesses)
|
|
{
|
|
if (I == pID)
|
|
newProcess = false;
|
|
}
|
|
|
|
if (newProcess)
|
|
{
|
|
Server S = loadIndividualServer(pID);
|
|
Servers.Add(S);
|
|
Thread IW4MServerThread = new Thread(S.Monitor);
|
|
ThreadList.Add(pID, IW4MServerThread);
|
|
|
|
IW4MServerThread.Start();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private bool isIW4MStillRunning(int pID)
|
|
{
|
|
if (pID > 0)
|
|
{
|
|
Process P = Process.GetProcessById(pID);
|
|
if (P.ProcessName.Length == 0)
|
|
{
|
|
return false;
|
|
Console.WriteLine("Server with PID #" + pID + " doesn't seem to be running anymore");
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
[DllImport("kernel32.dll")]
|
|
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
|
|
|
|
private List<int> getCurrentIW4MProcesses()
|
|
{
|
|
List<int> PIDs = new List<int>();
|
|
foreach (Process P in Process.GetProcessesByName("iw4m"))
|
|
{
|
|
IntPtr Handle = OpenProcess(0x10, false, P.Id);
|
|
Byte[] isClient = new Byte[1];
|
|
int numberRead = 0;
|
|
ReadProcessMemory((int)Handle, 0x5DEC04, isClient, 1, ref numberRead);
|
|
|
|
if (isClient[0] == 0)
|
|
PIDs.Add(P.Id);
|
|
}
|
|
|
|
return PIDs;
|
|
}
|
|
|
|
private List<Server> loadServers()
|
|
{
|
|
List<Server> activeServers = new List<Server>();
|
|
foreach (int pID in activePIDs)
|
|
{
|
|
Server S = loadIndividualServer(pID);
|
|
if (S != null)
|
|
activeServers.Add(S);
|
|
}
|
|
return activeServers;
|
|
}
|
|
|
|
private Server loadIndividualServer(int pID)
|
|
{
|
|
if (pID > 0)
|
|
{
|
|
IntPtr Handle = OpenProcess(0x10, false, pID);
|
|
if (Handle != null)
|
|
{
|
|
dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle);
|
|
dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle);
|
|
// unfortunately this needs to be updated for every iw4m build :/
|
|
dvar rcon_password = Utilities.getDvar(0x1120CC3C, (int)Handle);
|
|
|
|
return new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle, pID);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|