[How To] Hooking functions in WoW with variable arguments.. from C# menu

User Tag List

Results 1 to 1 of 1
  1. #1
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [How To] Hooking functions in WoW with variable arguments.. from C#

    Note: You won't probably ever need this. The example provided here is completely bogus. FrameScript__SignalEvent wraps around a function which takes a pointer as the third argument. If you just hook this, you will have a pointer to the stack at runtime anyway without any weird types like RuntimeArgumentHandle. This was more a "cool!" moment when I realized this worked.

    So anyways, some time ago Apoc told me about the __arglist keyword. Eager to see if it worked, I tried it on FrameScript__SignalEvent and it turned out you can't use the keyword in delegates.
    To my surprise, I discovered that __arglist translates directly into a structure. This structure is a special structure and is called RuntimeArgumentHandle. This structure can not be boxed into an object, which means you won't be able to call the original function if you use a late bound delegate, like WhiteMagic does. Fortunately I wrote my own library that uses generics and it works with that.

    RuntimeArgumentHandle was originally thought to be used together with ArgIterator to iterate through arguments. This, however, throws an exception when you do it in WoW (?!? why?). Fortunately RuntimeArgumentHandle contains a single member which is an IntPtr and points to the first argument on the stack. Unfortunately Microsoft made this member internal, so my first thought was to use Reflection. But oops, RuntimeArgumentHandle can not be boxed to an object, so you can't get the value on the instance! I fixed this by simply casting a pointer to it to an IntPtr* and dereferencing that.
    Code:
    IntPtr ptr = *(IntPtr*)&args;
    Embrace yourself for code:

    Code:
    public static class Lua
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void FrameScript__SignalEventDelegate(uint id, string fmt, RuntimeArgumentHandle args);
    
        private static readonly RoutedDetour<FrameScript__SignalEventDelegate> _signalEventDetour;
    
        static Lua()
        {
            _signalEventDetour = Memory.CreateAndApplyRoutedDetour<FrameScript__SignalEventDelegate>((IntPtr)GlobalOffsets.FrameScript__SignalEvent, FrameScript__SignalEventHk, 6);
        }
    
        internal static void Init()
        {
        }
    
        private static unsafe void FrameScript__SignalEventHk(uint id, string fmt, RuntimeArgumentHandle args)
        {
            _signalEventDetour.Original(id, fmt, args);
            if (fmt == null)
                return;
    
            IntPtr ptr = *(IntPtr*)&args;
            var vals = new List<object>(fmt.Length / 2);
            for (int i = 1; i < fmt.Length; i += 2)
            {
                switch (fmt[i])
                {
                    case 'b':
                        vals.Add(Memory.Read<uint>(ptr) != 0);
                        ptr += 4;
                        break;
                    case 'd':
                        vals.Add(Memory.Read<int>(ptr));
                        ptr += 4;
                        break;
                    case 'f':
                        vals.Add(Memory.Read<double>(ptr));
                        ptr += 8;
                        break;
                    case 'u':
                        vals.Add(Memory.Read<uint>(ptr));
                        ptr += 4;
                        break;
                    case 's':
                        vals.Add(Memory.Read<string>((uint)ptr, 0));
                        ptr += 4;
                        break;
                }
            }
    
            LuaEventDispatcher.Dispatch(id, vals);
        }
    }
    So yeah.. Not so useful but still fun that C# (more like .NET) actually supports this after all.
    Last edited by MaiN; 07-26-2010 at 10:24 AM. Reason: Fixed a typo.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

    [How To] Hooking functions in WoW with variable arguments.. from C#

Similar Threads

  1. [Help] How i can hook function with debug/PTR build ?
    By Woweur in forum WoW Memory Editing
    Replies: 3
    Last Post: 07-11-2010, 12:20 PM
  2. How to log in on wow with another ip?
    By hellshunter in forum World of Warcraft General
    Replies: 3
    Last Post: 05-19-2009, 11:16 AM
  3. Replies: 6
    Last Post: 06-21-2008, 03:20 PM
  4. How to: Play WoW with a wiimote
    By clamsd101 in forum World of Warcraft General
    Replies: 7
    Last Post: 04-12-2008, 12:15 PM
  5. How do you run a wow server with out editing wow?
    By Mike3667 in forum World of Warcraft General
    Replies: 2
    Last Post: 09-24-2006, 05:37 PM
All times are GMT -5. The time now is 01:02 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search