First things first.
- Yes, this is injection.
- No, it isn't currently detected.
- No, I don't plan to give some sort of way to do it out of process.
- No, I won't hold your hand, or answer stupid questions.
- Yes, it's C#. Get over it.
Now then, we've got the stupid questions dealt with. We can move on to the good stuff.
Alot of people seem to think that enumerating the object list is the best approach to keeping track of current objects in WoW. While this is a great way to do it, you need to keep track of quite a few things.
- g_clientConnection
- s_curMgr
- nextObj
- curObj
- localGuid
- etc
I prefer to keep track of only 3 things.
- EnumVisibleObjects
- ClntObjMgrGetObjectPtr (GetObjectByGuid)
- ClntObjMgrGetActivePlayer
A whole 3 functions is all I ever need to update in order to get my object manager working for a new patch. Since PatchDiff2 can handle the work of finding these functions for me, it makes life that much easier between patches.
Now for the rundown of the functions... shall we?
EnumVisibleObjects
Signature:
Code:
signed int __cdecl EnumVisibleObjects(int (__cdecl *pCallback)(WGUID, DWORD), eWOWOBJECTTYPE filter)
C# Signature:
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int EnumVisibleObjectsDelegate(IntPtr callback, int filter);
Use: This function allows you to enumerate over WoW's list of objects, and also base that enumeration around a filter. (Object type) Using the callback passed in, it will allow you to retrieve the GUID, and type of each object. (Note: Inheritance does work here! Object = 0, so passing 0 will retrieve every object possible.)
Params: A callback to be used to let WoW know when to stop, or continue to call your callback with objects.
A filter of WoWObjectType. Basically; to narrow down the 'search' to specific types of objects.
EnumVisibleObjectsCallback
Signature:
Code:
int __cdecl EnumVisibleObjectsCallback(WGUID guid, eWOWOBJECTTYPE filter)
C# Signature:
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int EnumObjectsCallback(ulong guid, int filter);
Use: Acts as the callback from WoW. This function will be called for each object during the enumeration. (Think EnumWindows API) A GUID will be passed back that you can then use in the ClntObjMgrGetObjectPtr function to get the actual pointer.
Params: A GUID to use, and a filter for the object type. Nothing really special here.
Notes: Returning 0 will stop the enumeration. Returning 1 will continue to the next object. If no objects are left to enumerate, the function will no longer be called.
ClntObjMgrGetObjectPtr
Signature:
Code:
WoWObject *__cdecl ClntObjMgrObjectPtr(WGUID guid, eWOWOBJECTTYPE filter)
C# Signature:
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr ClntObjMgrGetObjectPtrDelegate(ulong guid, int filter);
Use: The typical GetObjectByGuid function. Returns a pointer to an object based on GUID. NULL if no object exists.
Params: The GUID of the object, and a filter, if any.
Notes: This function works from the Object descriptor GUID. (OBJECT_FIELD_GUID) Not the typical obj+0x30 GUID. (They can be, and usually are different.)
ClntObjMgrGetActivePlayer
Signature:
Code:
WGUID __cdecl ClntObjMgrGetActivePlayer()
C# Signature:
Code:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate ulong ClntObjMgrGetActivePlayer();
Use: Retrieves the GUID of the active player (ourselves) which can then be passed to the ClntObjMgrGetObjectPtr function.
Params: None.
Putting it all together...
We need a small building block to work from. The basic WoWObject class, and it's descendants.
Code:
public class WoWObject
{
protected IntPtr ObjPtr;
internal WoWObject(IntPtr objPtr)
{
ObjPtr = objPtr;
}
public ulong Guid { get { return 0; /*Add your code here to grab the OBJECT_FIELD_GUID descriptor*/ } }
public bool IsValid { get { return ObjPtr != IntPtr.Zero; } }
internal void UpdateObjectPointer(IntPtr ptr)
{
ObjPtr = ptr;
}
public static implicit operator IntPtr(WoWObject obj)
{
// Allows us to implicitly cast a WoWObject to an IntPtr (objBase)
return obj.ObjPtr;
}
}
(I'll leave creating the descendant classes to you. WoWUnit, WoWItem, etc)
Firstly; it is ALWAYS better to manage a list of objects in your project, rather than rely on WoW's. We will use WoW's to grab the objects only. All the other management of the objects, will be done internally in our project.
Since the best way to keep a correlation of non-sequential things with a key/value is obviously a Dictionary, we'll use that. (It uses a HashTable-esque implementation internally, so it's very fast to use.) This part is very simple. Assuming you already have your WoWObject class (and descendants), we can dive right in.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace ObjMgrDemo
{
public class ObjectManager
{
private static readonly EnumObjectsCallback Callback = EnumObjectsCallbackHandler;
private static readonly IntPtr CallbackPtr;
private static readonly ClntObjMgrGetObjectPtrDelegate ClntObjMgrGetObjectPtrWoW;
private static readonly EnumVisibleObjectsDelegate EnumObjs;
private static readonly ClntObjMgrGetActivePlayerDelegate GetActivePlayerDelegate;
private static readonly Dictionary<ulong, WoWObject> RealObjects = new Dictionary<ulong, WoWObject>();
private static ulong _frameCounter = 1;
static ObjectManager()
{
Me = new WoWActivePlayer(IntPtr.Zero);
CallbackPtr = Marshal.GetFunctionPointerForDelegate(Callback);
GetActivePlayerDelegate =
Utilities.RegisterDelegate<ClntObjMgrGetActivePlayerDelegate>((uint) 0x00476A90);
EnumObjs = Utilities.RegisterDelegate<EnumVisibleObjectsDelegate>((uint) 0x004780A0);
ClntObjMgrGetObjectPtrWoW =
Utilities.RegisterDelegate<ClntObjMgrGetObjectPtrDelegate>((uint) 0x00478320);
}
internal static WoWActivePlayer Me { get; private set; }
public static List<WoWObject> ObjectList { get { return RealObjects.Values.Where(o => o.IsValid).ToList(); } }
public static void Pulse()
{
_frameCounter++;
}
private static int EnumObjectsCallbackHandler(ulong guid, int filter)
{
return 1;
}
#region Nested type: ClntObjMgrGetActivePlayerDelegate
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate ulong ClntObjMgrGetActivePlayerDelegate();
#endregion
#region Nested type: ClntObjMgrGetObjectPtrDelegate
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr ClntObjMgrGetObjectPtrDelegate(ulong guid, int filter);
#endregion
#region Nested type: EnumObjectsCallback
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int EnumObjectsCallback(ulong guid, int filter);
#endregion
#region Nested type: EnumVisibleObjectsDelegate
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int EnumVisibleObjectsDelegate(IntPtr callback, int filter);
#endregion
}
}
As you can see, I filled in a good bit of the required stuff. This is mostly boilerplate code. I'm keeping a static reference to 'Me', as we should never 'not be there'. We'll simply update a single instance of that object. The frame counter will be explained later, as we'll need it for some optimizations. You'll also notice how I have the RealObjects dictionary, and then the public ObjectList... List. This is so we're not handing off a Dictionary of values to other areas. Instead, we simply return only valid objects, so you can easily enumerate over it. (It makes it feel more natural, I swear!)
Pulse should be called on every frame (Yes, it's perfectly safe, and viable to do this, WoW does it many times over.) We'll be using the FrameCounter to do some 'trickery' to keep resources to a minimum.
Now, we just need to wrap the typical GetObjectByGuid function. Note though, we'll actually be wrapping TWO functions. Our internal one, and then WoW's. I'll just hand the source over here, so it's easier to understand.
Code:
/// <summary>
/// Uses our current internal list of objects to retrieve a WoWObject. This is much faster
/// if the object is known to be in the current object list. USE THIS FUNCTION!
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
internal static WoWObject GetObjectByGuid(ulong guid)
{
WoWObject ret;
RealObjects.TryGetValue(guid, out ret);
return ret ?? new WoWObject(IntPtr.Zero);
}
/// <summary>
/// Calls WoW's internal ClntObjPtr (or whatever it's called) to retrieve an object pointer
/// based on the specified GUID.
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
internal static IntPtr InternalGetObjectByGuid(ulong guid)
{
return ClntObjMgrGetObjectPtrWoW(guid, -1);
}
Notice how our 'public' (which isn't actually public) GetObjectByGuid function only checks the dictionary. If no valid GUIDs are present, it returns an INVALID WoWObject. This is very important!
Also note, we're passing -1 to WoW's ClntObjMgrGetObjectPtr function. This just tells WoW we want to search every type of object. (Feel free to overload this)
Now we have the basics for getting an object via GUID, we can get into more complicated things. Firstly, we need a way to invalidate the current object list, without 'nulling' it out. (Think what happens when you keep a reference to an object, and all the sudden, it no longer exists, but the reference says otherwise.)
Code:
public static void Pulse()
{
// Reset all the pointers.
// This is faster than instantiating the class hundreds of times...
foreach (WoWObject o in RealObjects.Values)
{
o.UpdateObjectPointer(IntPtr.Zero);
}
_frameCounter++;
}
Pretty simple. Since our IsValid check in WoWObject checks that ObjPtr != IntPtr.Zero, this 'invalidates' every object.
Next, we'll tell WoW to start enumerating. This part is fairly simple, so stay with me.
Code:
public static void Pulse()
{
// Reset all the pointers.
// This is faster than instantiating the class hundreds of times...
foreach (WoWObject o in RealObjects.Values)
{
o.UpdateObjectPointer(IntPtr.Zero);
}
// Enum all object types.
EnumObjs(CallbackPtr, 0);
_frameCounter++;
}
Our EnumObjectsCallbackHandler will now be called constantly until the entire object list is iterated. Pretty simple, yet very effective. 
We'll get back to the callback handler in a moment, we still need to do some quick optimizations. kynox and I had a conversation a while back about how to best handle removing invalid entries, and keeping track of those invalid entries. (As you can tell, our IsValid property handles most of it.) Now, we just need to physically remove those entries. Since we don't want to do it each frame, as that's quite intensive, we do it every 10th frame. (Still 3-6 times per second, which is plenty.)
Code:
public static void Pulse()
{
// Reset all the pointers.
// This is faster than instantiating the class hundreds of times...
foreach (WoWObject o in RealObjects.Values)
{
o.UpdateObjectPointer(IntPtr.Zero);
}
// Enum all object types.
EnumObjs(CallbackPtr, 0);
// Every 10th frame, lets clear out the invalid entries in the object list
// to conserve resources
if (_frameCounter++ % 10 == 0)
{
RemoveInvalidEntries();
}
}
/// <summary>
/// Clears out any invalid objects from our list.
/// </summary>
private static void RemoveInvalidEntries()
{
// Yes, this is pretty damned simple. Just clear out any invalid
// objects. (IsValid is just ObjPtr != IntPtr.Zero)
IEnumerable<KeyValuePair<ulong, WoWObject>> r = from o in RealObjects
where !o.Value.IsValid
select o;
foreach (var pair in r)
{
RealObjects.Remove(pair.Key);
}
}
It's not the prettiest solution, but it works great for me.
Now, we've got the list basically managing valid/invalid, and all that stuff. Now we can do the fun things. 
Code:
private static int EnumObjectsCallbackHandler(ulong guid, int filter)
{
// Note: Filter is actually a WoWObjectType enum value.
// If we decide to call EVO with a filter set; we will only receive objects of that type!
// Get the objects pointer, and move forward!
IntPtr objPtr = InternalGetObjectByGuid(guid);
if (!RealObjects.ContainsKey(guid))
{
var tmp = new WoWObject(objPtr);
switch (tmp.Type)
{
case WoWObjectType.Item:
tmp = new WoWItem(objPtr);
break;
case WoWObjectType.Container:
tmp = new WoWContainer(objPtr);
break;
case WoWObjectType.Unit:
tmp = new WoWUnit(objPtr);
break;
case WoWObjectType.Player:
// Skip ourselves
//if (tmp.Guid == Me.Guid)
// return 1;
tmp = new WoWPlayer(objPtr);
break;
case WoWObjectType.GameObject:
tmp = new WoWGameObject(objPtr);
break;
case WoWObjectType.Corpse:
tmp = new WoWCorpse(objPtr);
break;
default:
// Maybe in the future we'll support the rest of the types
// for now however, we'll just skip over them completely.
return 1;
}
RealObjects.Add(guid, tmp);
}
else if (RealObjects[guid] != objPtr)
{
RealObjects[guid].UpdateObjectPointer(objPtr);
}
return 1;
}
That's pretty much it. The RealObjects dictionary is filled with the type-specific objects. Which can then be used however you wish.
So with this, call Pulse each frame -> Do whatever you want with your current list of objects. 
Enjoy folks.
Credits:
kynox - Being awesome, and helping debug some stupid shit.
jjaa - Being awesome, and doing the updates for me. (I'm lazy, shoot me!)
Cypher - Jew.
Somebody else I forgot - Tough shit.
2dgreengiant - cos hes fking hot
Disclaimer:
This is written entirely by me, with some help from the above credited people. This is NOT to be used in commercial products for any reason whatsoever.
JuJu is herein, BANNED from any of said code. Period.
Jay (AkA KRYPTON) is also BANNED from any of said code. Period. (You little twat)
All others; please ask before ripping this code. All I ask for is a simple 'thanks' somewhere.