Skip to content

Commit

Permalink
Add exe patcher
Browse files Browse the repository at this point in the history
Code is from the MaNGOS project, many thanks to them for making this easy to use. Source and binary are included. Place in game client directory and run.
  • Loading branch information
Niam5 committed Jun 19, 2023
1 parent 9d7baaa commit b50748a
Show file tree
Hide file tree
Showing 16 changed files with 3,033 additions and 0 deletions.
Binary file not shown.
20 changes: 20 additions & 0 deletions contrib/connection_patcher/Source/MaNGOSPatcher.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C# Express 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaNGOSPatcher", "Patcher\MaNGOSPatcher.csproj", "{1F50EA3B-6965-4AA8-ADAB-12ED51574C3C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F50EA3B-6965-4AA8-ADAB-12ED51574C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F50EA3B-6965-4AA8-ADAB-12ED51574C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F50EA3B-6965-4AA8-ADAB-12ED51574C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F50EA3B-6965-4AA8-ADAB-12ED51574C3C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
127 changes: 127 additions & 0 deletions contrib/connection_patcher/Source/Patcher/Form1.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

195 changes: 195 additions & 0 deletions contrib/connection_patcher/Source/Patcher/Form1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.IO;
using System.Windows.Forms;
using MaNGOSatcher;

namespace MaNGOSPatcher
{
public partial class Form1 : Form
{
byte[] wowExe = null;
Dictionary<int, List<PatchBytes>> Patches = new Dictionary<int, List<PatchBytes>>();
List<PatchBytes> patches = null;
const string FileWin = "Wow.exe";
const string BackupWin = "Wow_backup.exe";
const string FileMac = "World of Warcraft";
const string BackupMac = "World of Warcraft backup";
string FileName;
string BackupFile;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes())
{
if (t.IsSubclassOf(typeof(PatchInfo)))
{
PatchInfo pInfo = (PatchInfo)t.GetConstructor(new Type[] { }).Invoke(new Object[] { });
Patches.Add(pInfo.ExeLength, pInfo.Patches);
}
}
try
{
richTextBox1.AppendText("Loading Wow.exe into memory...\n");
wowExe = ReadByteArrayFromFile(FileWin);
if(!Patches.ContainsKey(wowExe.Length))
{
richTextBox1.AppendText("This Wow.exe version is not supported\n");
throw new Exception("Version not supported");
}
patches = Patches[wowExe.Length];
richTextBox1.AppendText("Success Windows 'wow.exe' loaded!\n");
BackupFile = BackupWin;
FileName = FileWin;
}
catch
{
try
{
richTextBox1.AppendText("Loading Mac 'World of Warcraft' binary into memory...\n");
wowExe = ReadByteArrayFromFile(FileMac);
richTextBox1.AppendText("Success Mac 'World of Warcraft' loaded!\n");
BackupFile = BackupMac;
FileName = FileMac;
if (!Patches.ContainsKey(wowExe.Length))
{
richTextBox1.AppendText("This Mac version is not supported\n");
throw new Exception("Version not supported");
}
patches = patches = Patches[wowExe.Length];
}
catch
{
richTextBox1.AppendText("Could not load Win 'Wow.exe' or Mac 'World of Warcraft' into memory. Make sure this program is in your WoW directory and that WoW is closed.\n");
label2.Text = "Error";
label2.ForeColor = Color.Red;
wowExe = null;
}
//filenotfound or fileinuse
}

if (wowExe != null)
{
byte[] testPatched = new byte[patches[0].Unpatched.Length];
System.Buffer.BlockCopy(wowExe, patches[0].Offset, testPatched, 0, patches[0].Unpatched.Length);

if (testPatched.SequenceEqual(patches[0].Unpatched))
{
richTextBox1.AppendText("Ready to patch " + FileName + ".\n");
label2.Text = "Ready!";
label2.ForeColor = Color.Orange;
button1.Text = "Patch";
button1.Enabled = true;
}
if (testPatched.SequenceEqual(patches[0].Patched))
{
richTextBox1.AppendText("To restore " + FileName + " click \"Unpatch\".\n");
label2.Text = "Ready!";
label2.ForeColor = Color.Orange;
button1.Text = "Unpatch";
button1.Enabled = true;
}
}
}

private void button1_Click(object sender, EventArgs e)
{
if (((Button)sender).Text == "Patch")
{
foreach (PatchBytes p in patches)
{
System.Buffer.BlockCopy(p.Patched, 0, wowExe, p.Offset, p.Patched.Length);
}
try { File.Delete(BackupFile); } catch { }
try { File.Move(FileName, BackupFile); } catch {}

if (WriteByteArrayToFile(wowExe, FileName) == true)
{
richTextBox1.AppendText("Successfully patched " + FileName + " and created a backup " + BackupFile +"!\n");
label2.Text = "Success!";
label2.ForeColor = Color.Green;
}
else
{
label2.Text = "Error!";
label2.ForeColor = Color.Red;
}
}
else
{
foreach (PatchBytes p in patches)
{
System.Buffer.BlockCopy(p.Unpatched, 0, wowExe, p.Offset, p.Unpatched.Length);
}
try { File.Delete(FileName); File.Delete(BackupFile); }
catch { };

if (WriteByteArrayToFile(wowExe, FileName) == true)
{
richTextBox1.AppendText("Successfully unpatched " + FileName + "!\n");
label2.Text = "Success!";
label2.ForeColor = Color.Green;
}
else
{
label2.Text = "Error!";
label2.ForeColor = Color.Red;
}
}
richTextBox1.AppendText("Done.\n");
button1.Enabled = false;
}

public byte[] ReadByteArrayFromFile(string fileName)
{
byte[] buff = null;
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(fileName).Length;
buff = br.ReadBytes((int)numBytes);
br.Close();
return buff;
}

public bool WriteByteArrayToFile(byte[] buff, string fileName)
{
bool response = false;

try
{
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(buff);
bw.Close();
response = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

return response;
}

private void richTextBox1_TextChanged(object sender, EventArgs e)
{

}

private void pictureBox1_Click(object sender, EventArgs e)
{

}
}
}
Loading

0 comments on commit b50748a

Please sign in to comment.