internal static extern bool CreateProcess(string applicationPath, string commandLineArgs, ref SecurityAttributes processSecurityAttributes, ref SecurityAttributes threadSecurityAttributes, bool inheritHandle, ProcessCreationFlags creationFlags, IntPtr environment, string currentDirectory, ref StartupInfo startupInfo, out ProcessInformation processInformation);
void PatchClient(ProcessInformation process, ClientVersion version, out ClientLoadResult result) { var patchMultipleInstances = UserSettingsManager.Instance.Settings.AllowMultipleInstances; var patchIntroVideo = UserSettingsManager.Instance.Settings.SkipIntroVideo; var patchNoWalls = UserSettingsManager.Instance.Settings.NoWalls; // Patch Process ProcessMemoryAccessor accessor = null; Stream patchStream = null; BinaryReader reader = null; BinaryWriter writer = null; try { accessor = new ProcessMemoryAccessor(process.ProcessId, ProcessAccess.ReadWrite); patchStream = accessor.GetStream(); reader = new BinaryReader(patchStream); writer = new BinaryWriter(patchStream); if (patchMultipleInstances && version.MultipleInstanceAddress > 0) { patchStream.Position = version.MultipleInstanceAddress; writer.Write((byte)0x31); // XOR writer.Write((byte)0xC0); // EAX, EAX writer.Write((byte)0x90); // NOP writer.Write((byte)0x90); // NOP writer.Write((byte)0x90); // NOP writer.Write((byte)0x90); // NOP } if (patchIntroVideo && version.IntroVideoAddress > 0) { patchStream.Position = version.IntroVideoAddress; writer.Write((byte)0x83); // CMP writer.Write((byte)0xFA); // EDX writer.Write((byte)0x00); // 0 writer.Write((byte)0x90); // NOP writer.Write((byte)0x90); // NOP writer.Write((byte)0x90); // NOP } if (patchNoWalls && version.NoWallAddress > 0) { patchStream.Position = version.NoWallAddress; writer.Write((byte)0xEB); // JMP SHORT writer.Write((byte)0x17); // +0x17 writer.Write((byte)0x90); // NOP } result = ClientLoadResult.Success; } catch { result = ClientLoadResult.PatchingFailed; } finally { reader?.Dispose(); writer?.Dispose(); accessor?.Dispose(); patchStream?.Dispose(); // Resume and close handles. NativeMethods.ResumeThread(process.ThreadHandle); NativeMethods.CloseHandle(process.ThreadHandle); NativeMethods.CloseHandle(process.ProcessHandle); } }