From a0ccd3ffa8f09676b9c44dcf360db76bcc490d4e Mon Sep 17 00:00:00 2001 From: "raidmax@live.com" Date: Fri, 24 Jul 2015 14:46:32 -0500 Subject: [PATCH] Downgraded external lib to VS 2010 --- Admin/IW4M ADMIN.csproj | 13 ++- Admin/Main.cs | 6 +- Admin/Manager.cs | 10 +-- Admin/Properties/Settings.Designer.cs | 26 ++++++ Admin/Server.cs | 20 ++++- Admin/Utilities.cs | 124 ++++++++++++++++++++------ Admin/app.config | 3 + Admin/lib/AdminInterface.dll | Bin 10752 -> 6656 bytes IW4M Admin.sln | 4 +- 9 files changed, 165 insertions(+), 41 deletions(-) create mode 100644 Admin/Properties/Settings.Designer.cs create mode 100644 Admin/app.config diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj index 37ff7161c..6b03bf237 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 dd6b0029f..dde1a54d2 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 7f79f67ce..36b9e001f 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 000000000..304482d79 --- /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 3a44098dc..988d4d3da 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 3f17bdb6a..226870c30 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 000000000..fcd0c9373 --- /dev/null +++ b/Admin/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Admin/lib/AdminInterface.dll b/Admin/lib/AdminInterface.dll index c237df605e54c8a4b85959d607c936340db4725d..b6dd3012f4cc2b6b29d1cae27b3b703972f46f35 100644 GIT binary patch literal 6656 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