diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj index 37ff7161..6b03bf23 100644 --- a/Admin/IW4M ADMIN.csproj +++ b/Admin/IW4M ADMIN.csproj @@ -1,5 +1,5 @@  - + Debug @@ -11,7 +11,8 @@ IW4MAdmin v4.0 512 - + + true ftp://raidmax.org/ true @@ -44,6 +45,7 @@ prompt 4 true + false x86 @@ -55,6 +57,7 @@ 0 true On + false LocalIntranet @@ -106,6 +109,11 @@ + + True + True + Settings.settings + @@ -166,6 +174,7 @@ PreserveNewest + PreserveNewest diff --git a/Admin/Main.cs b/Admin/Main.cs index dd6b0029..dde1a54d 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -24,7 +24,7 @@ namespace IW4MAdmin else Console.WriteLine(" Version " + Version + " (unable to retrieve latest)"); Console.WriteLine("====================================================="); -#if DEBUG +#if DEBUG2 if (viableServers.Count < 1) viableServers = checkConfig(); // fall back to config Servers = viableServers; @@ -56,7 +56,7 @@ namespace IW4MAdmin frontEnd.Init(); } } -#if DEBUG +#if DEBUG2 static void setupConfig() { bool validPort = false; @@ -91,7 +91,7 @@ namespace IW4MAdmin return serverManager.getServers().ToArray(); } -#if DEBUG +#if DEBUG2 static List checkConfig() { diff --git a/Admin/Manager.cs b/Admin/Manager.cs index 7f79f67c..36b9e001 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -26,15 +26,13 @@ namespace IW4MAdmin public void Init() { - activePIDs = getCurrentIW4MProcesses(); - - if (activePIDs.Count == 0) + while (getCurrentIW4MProcesses().Count == 0) { mainLog.Write("No viable IW4M instances detected.", Log.Level.All); - Utilities.Wait(5); - return; + Utilities.Wait(10); } + activePIDs = getCurrentIW4MProcesses(); Servers = loadServers(); foreach (Server S in Servers) @@ -108,7 +106,7 @@ namespace IW4MAdmin Servers.Add(S); Thread IW4MServerThread = new Thread(S.Monitor); ThreadList.Add(pID, IW4MServerThread); - mainLog.Write("New server dectected on port " + S.getPort(), Log.Level.All); + mainLog.Write("New server detected on port " + S.getPort(), Log.Level.All); IW4MServerThread.Start(); } } diff --git a/Admin/Properties/Settings.Designer.cs b/Admin/Properties/Settings.Designer.cs new file mode 100644 index 00000000..304482d7 --- /dev/null +++ b/Admin/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.18408 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace IW4MAdmin.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Admin/Server.cs b/Admin/Server.cs index 3a44098d..988d4d3d 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -804,18 +804,34 @@ namespace IW4MAdmin Log.Write("Could not load IW4MAdmin interface!", IW4MAdmin.Log.Level.Debug); return false; } + // basic info dvars hostname = Utilities.stripColors(getDvar("sv_hostname").current); mapname = getDvar("mapname").current; IW_Ver = getDvar("shortversion").current; - maxClients = Convert.ToInt32(getDvar("party_maxplayers").current); + maxClients = -1; + Int32.TryParse(getDvar("party_maxplayers").current, out maxClients); + + if (maxClients == -1) + { + Log.Write("Could not get iw4m_onelog value", IW4MAdmin.Log.Level.Debug); + return false; + } + Gametype = getDvar("g_gametype").current; // important log variables Basepath = getDvar("fs_basepath").current; Mod = getDvar("fs_game").current; logPath = getDvar("g_log").current; - int oneLog = Convert.ToInt32(getDvar("iw4m_onelog").current); + int oneLog = -1; + Int32.TryParse(getDvar("iw4m_onelog").current, out oneLog); + + if (oneLog == -1) + { + Log.Write("Could not get iw4m_onelog value", IW4MAdmin.Log.Level.Debug); + return false; + } // our settings setDvar("sv_kickBanTime", "3600"); // 1 hour diff --git a/Admin/Utilities.cs b/Admin/Utilities.cs index 3f17bdb6..226870c3 100644 --- a/Admin/Utilities.cs +++ b/Admin/Utilities.cs @@ -316,6 +316,12 @@ namespace IW4MAdmin return "a very long time"; } + const int PROCESS_CREATE_THREAD = 0x0002; + const int PROCESS_QUERY_INFORMATION = 0x0400; + const int PROCESS_VM_OPERATION = 0x0008; + const int PROCESS_VM_WRITE = 0x0020; + const int PROCESS_VM_READ = 0x0010; + [Flags] public enum ProcessAccessFlags : uint { @@ -364,6 +370,9 @@ namespace IW4MAdmin [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); + [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); @@ -376,7 +385,7 @@ namespace IW4MAdmin [DllImport("kernel32.dll")] public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); - [DllImport("kernel32.dll")] + [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] @@ -385,15 +394,45 @@ namespace IW4MAdmin [DllImport("kernel32.dll", SetLastError = true)] static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); - [DllImport("kernel32.dll", SetLastError = true)] + [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); - [DllImport("kernel32.dll", SetLastError = true)] + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("kernel32.dll", SetLastError = true)] static extern int CloseHandle(IntPtr hObject); + [DllImport("ntdll.dll")] + public static extern uint RtlCreateUserThread( + [In] IntPtr Process, + [In] IntPtr ThreadSecurityDescriptor, + [In] bool CreateSuspended, + [In] int StackZeroBits, + uint MaximumStackSize, + [In] [Optional] IntPtr InitialStackSize, + [In] IntPtr StartAddress, + [In] IntPtr Parameter, + [Out] out IntPtr Thread, + [Out] out ClientId ClientId + ); + + [StructLayout(LayoutKind.Sequential)] + public struct ClientId + { + public ClientId(int processId, int threadId) + { + this.UniqueProcess = new IntPtr(processId); + this.UniqueThread = new IntPtr(threadId); + } + + public IntPtr UniqueProcess; + public IntPtr UniqueThread; + + public int ProcessId { get { return this.UniqueProcess.ToInt32(); } } + public int ThreadId { get { return this.UniqueThread.ToInt32(); } } + } + public static dvar getDvar(int Location, IntPtr Handle) { int numberRead = 0; @@ -550,8 +589,10 @@ namespace IW4MAdmin setDvarCurrentPtr(0x2098D9C, memoryForDvarName, ProcessHandle); - // if (!VirtualFreeEx(ProcessHandle, memoryForDvarName, 0, AllocationType.Release)) - // Console.WriteLine("Virtual Free Failed -- Error #" + Marshal.GetLastWin32Error()); + Utilities.Wait(.3); + + if (!VirtualFreeEx(ProcessHandle, memoryForDvarName, 0, AllocationType.Release)) + Console.WriteLine("Virtual Free Failed -- Error #" + Marshal.GetLastWin32Error()); CloseHandle(ProcessHandle); @@ -590,57 +631,88 @@ namespace IW4MAdmin String Path = AppDomain.CurrentDomain.BaseDirectory + "lib\\AdminInterface.dll"; if (!File.Exists(Path)) + { + Console.WriteLine("AdminInterface DLL does not exist!"); return false; + } UIntPtr bytesWritten; - uint threadID; + IntPtr threadID; IntPtr ProcessHandle = OpenProcess(ProcessAccessFlags.All, false, pID); +#if DEBUG + Console.WriteLine("Process handle is: " + ProcessHandle); +#endif if (ProcessHandle == IntPtr.Zero) + { + Console.WriteLine("Unable to open target process"); return false; + } IntPtr lpLLAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (lpLLAddress == IntPtr.Zero) + { + Console.WriteLine("Could not obtain address of function address"); return false; + } + +#if DEBUG + Console.WriteLine("LoadLibraryA location is 0x" + lpLLAddress.ToString("X8")); +#endif IntPtr pathAllocation = VirtualAllocEx(ProcessHandle, IntPtr.Zero, (uint)Path.Length + 1, AllocationType.Commit, MemoryProtection.ExecuteReadWrite); if (pathAllocation == IntPtr.Zero) + { + Console.WriteLine("Could not allocate memory for path location"); return false; + } +#if DEBUG + Console.WriteLine("Allocated DLL path address is 0x" + pathAllocation.ToString("X8")); +#endif byte[] pathBytes = Encoding.ASCII.GetBytes(Path); if (!WriteProcessMemory(ProcessHandle, pathAllocation, pathBytes, (uint)pathBytes.Length, out bytesWritten)) + { + Console.WriteLine("Could not write process memory"); return false; + } + + ClientId clientid = new ClientId(); + threadID = new IntPtr(); + RtlCreateUserThread(ProcessHandle, IntPtr.Zero, false, 0, (uint)0, IntPtr.Zero, lpLLAddress, pathAllocation, out threadID, out clientid); - if (CreateRemoteThread(ProcessHandle, IntPtr.Zero, 0, lpLLAddress, pathAllocation, 0, out threadID) == IntPtr.Zero) + if (threadID == IntPtr.Zero) + { + Console.WriteLine("Could not create remote thread"); return false; + } +#if DEBUG + //Console.WriteLine("Thread Status is " + threadStatus); + Console.WriteLine("Thread ID is " + threadID); +#endif + uint responseCode = WaitForSingleObject (threadID, 3000); + + if (responseCode != 0x00000000L) + { + Console.WriteLine("Thread did not finish in a timely manner!"); + Console.WriteLine("Last error is: " + Marshal.GetLastWin32Error()); + return false; + } + + if (!VirtualFreeEx(ProcessHandle, pathAllocation, 0, AllocationType.Decommit)) + Console.WriteLine("Could not free memory allocated for DLL name"); CloseHandle(ProcessHandle); +#if DEBUG + Console.WriteLine("Initialization finished -- last error : " + Marshal.GetLastWin32Error()); +#endif return true; } - public static void setDvar(int pID, String Name, String Value) - { - /* IntPtr ProcessHandle = OpenProcess(ProcessAccessFlags.All, false, pID); - IntPtr memoryForDvarName = allocateAndWrite(Encoding.ASCII.GetBytes(Name + " " + Value + "\0"), ProcessHandle); - - if (memoryForDvarName == IntPtr.Zero) - { - Console.WriteLine("UNABLE TO ALLOCATE MEMORY FOR DVAR NAME"); - return; - } - - setDvarCurrentPtr(0x2098D9C, memoryForDvarName, ProcessHandle); - - if (!VirtualFreeEx(ProcessHandle, memoryForDvarName, 0, AllocationType.Release)) - Console.WriteLine("Virtual Free Failed -- Error #" + Marshal.GetLastWin32Error()); - - CloseHandle(ProcessHandle);*/ - } - public static dvar getDvar(int pID, String DVAR) { dvar requestedDvar = new dvar(); diff --git a/Admin/app.config b/Admin/app.config new file mode 100644 index 00000000..fcd0c937 --- /dev/null +++ b/Admin/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Admin/lib/AdminInterface.dll b/Admin/lib/AdminInterface.dll index c237df60..b6dd3012 100644 Binary files a/Admin/lib/AdminInterface.dll and b/Admin/lib/AdminInterface.dll differ diff --git a/IW4M Admin.sln b/IW4M Admin.sln index a4117879..da90d349 100644 --- a/IW4M Admin.sln +++ b/IW4M Admin.sln @@ -11,8 +11,8 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.ActiveCfg = Release|Any CPU - {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.Build.0 = Release|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection