Hello!
I want to write a program, which will read addon messages from chat (f.e. DBM messages) and output them to console.
I've got this:
Code:
//MemoryReader.cs
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
[StructLayout(LayoutKind.Sequential)]
public struct WowChatMsg
{
public ulong SenderGuid;
public uint Unknown;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
public byte[] _SenderName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3000)]
public byte[] _FormattedMessage;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3000)]
public byte[] _Text;
public uint MessageType;
public uint ChannelNumber;
public uint Sequence;
uint _Time;
static readonly DateTime UnixEpochStart = new DateTime(1970, 1, 1, 0, 0, 0, 0);
public string SenderName
{
get
{
return Encoding.UTF8.GetString(_SenderName.TakeWhile(b => b != 0).ToArray());
}
}
public string FormattedMessage
{
get
{
return Encoding.UTF8.GetString(_Text.TakeWhile(b => b != 0).ToArray());
}
}
public string Text
{
get
{
return Encoding.UTF8.GetString(_Text.TakeWhile(b => b != 0).ToArray());
}
}
public DateTime Time
{
get
{
return UnixEpochStart.AddSeconds(_Time);
}
}
public static int Size
{
get
{
return Marshal.SizeOf(typeof(WowChatMsg));
}
}
}
class MemoryReader : IDisposable
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, IntPtr nSize, IntPtr lpNumberOfBytesRead);
Process process;
public IntPtr BaseAddress
{
get
{
return process.MainModule.BaseAddress;
}
}
public MemoryReader()
{
var tempP = Process.GetProcessesByName("Wow-64");
if (tempP.Length == 0)
{
Console.WriteLine("Couldn't find working process");
Console.ReadKey();
Process.GetCurrentProcess().Kill();
}
process = tempP[0];
}
~MemoryReader()
{
process.Close();
process.Dispose();
}
public void Dispose()
{
process.Close();
process.Dispose();
GC.SuppressFinalize(this);
}
public T ReadStruct<T>(IntPtr offset) where T : struct
{
byte[] result = new byte[Marshal.SizeOf(typeof(T))];
ReadProcessMemory(process.Handle, offset, result, new IntPtr(result.Length), IntPtr.Zero);
GCHandle handle = GCHandle.Alloc(result, GCHandleType.Pinned);
var returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return returnObject;
}
}
Code:
//Program.cs
using System;
class Program
{
static int Main(string[] args)
{
ChatReadWorkaround crw = new ChatReadWorkaround();
crw.Init();
return 0;
}
}
class ChatReadWorkaround
{
const int ChatBufferStart_x64 = 0x1007AD0;
const int ChatBufferPos_x64 = 0x1061068;
const int ChatBufferSize = 60;
int Pos;
MemoryReader mr;
public void Init()
{
mr = new MemoryReader();
Pos = mr.ReadStruct<int>(mr.BaseAddress + ChatBufferPos_x64);
BeginRead();
}
void ReadMessages()
{
int newPos = mr.ReadStruct<int>(mr.BaseAddress + ChatBufferPos_x64);
if (newPos == Pos)
return;
if (newPos < Pos)
{
for (; Pos < ChatBufferSize; Pos++)
AddChatMessage();
Pos = 0;
}
for (; Pos < newPos; Pos++)
AddChatMessage();
}
void AddChatMessage()
{
IntPtr msgPtr = mr.BaseAddress + ChatBufferStart_x64 + WowChatMsg.Size * Pos;
WowChatMsg msg = mr.ReadStruct<WowChatMsg>(msgPtr);
Console.WriteLine("[{0:HH:mm:ss}][{1}]: {2}", msg.Time, msg.SenderName, msg.Text);
}
void BeginRead()
{
for (; ; )
ReadMessages();
}
}
It fails with reading only players' messages (whispers, lfg messages etc.), but ignoring npc yells and addons' messages, which i need.
Any thoughts on how to fix it?