Home > Net >  Cannot capture user input from within an old game. Using user32.dll
Cannot capture user input from within an old game. Using user32.dll

Time:12-31

I am trying to make a program that runs in the background when activated by a hotkey, it captures keyboard and mouse inputs then you can replay thoose inputs if another hotkey is pressed.

The concept works perfectly fine on Windows, chrome, and newer games, even like Overwatch or Rocket League (even tho I don't care about those). The problem is that I am trying to capture Call of Duty Modern Warfare (2007) inputs and replay them, but nor capturing the inputs nor replaying them works. The only thing that works is mouse movement CAPTURE.

I am using user32.dll for capture and replay. I tried multiple ways of simulating keyboard inputs which all of them worked everywhere except this specific game.

keybd_event((byte)Key, 0, KEYEVENTF_KEYDOWN, UIntPtr.Zero);
//or
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(Input)));

Trying to imitate keyboard inputs. I tried the SendInput from user32.dll because I read that DirectX games handle input differently, but this did not work either. The implementation of inputs for the SendInput is coming from this stackoverflow question

Regarding the keyboard reading, I used normally GetAsyncKeyState to read the keyboard

[DllImport("user32.dll")]
static extern short GetAsyncKeyState(Keys vKey);
//....
GetAsyncKeyState(key)

GetAsyncKeyState is 0 constantly, no matter the actual situation

I also tried windows hooks for the keyboard capture with no effect

    private static ListBox lb1;
    public Form1()
    {
        InitializeComponent();

        lb1 = listBox1;
        InstallHook();
    }

    private const int WH_KEYBOARD_LL = 13;
    // The callback function that will be called by the hook
    public delegate int KeyboardHookProc(int code, int wParam, ref KeyboardHookStruct lParam);

    public struct KeyboardHookStruct
    {
        public int vkCode;
        public int scanCode;
        public int flags;
        public int time;
        public int dwExtraInfo;
    }

    // Import the SetWindowsHookEx function from the Windows API
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc lpfn, IntPtr hMod, uint dwThreadId);

    // Import the UnhookWindowsHookEx function from the Windows API
    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    // Import the CallNextHookEx function from the Windows API
    [DllImport("user32.dll", SetLastError = true)]
    private static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, ref KeyboardHookStruct lParam);

    // The hook handle
    private static IntPtr hookHandle = IntPtr.Zero;

    // The hook procedure
    private static KeyboardHookProc hookProc = hookProcFunc;

    // Install the hook
    public static void InstallHook()
    {
        hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, IntPtr.Zero, 0);
    }

    // Uninstall the hook
    public static void UninstallHook()
    {
        UnhookWindowsHookEx(hookHandle);
    }

    // The hook function
    private static int hookProcFunc(int code, int wParam, ref KeyboardHookStruct lParam)
    {
        if (code >= 0)
        {
            // Handle the keystroke here
            lb1.Items.Add("Keystroke: "   lParam.vkCode);
        }

        // Pass the keystroke on to the next hook in the chain
        return CallNextHookEx(hookHandle, code, wParam, ref lParam);
    }

mouse_event(MOUSEEVENTF_MOVE, movementX, movementY, 0, UIntPtr.Zero);

mouse_event also has no effect.

The only part that works in this one specific game is:

[DllImport("user32.dll")]
static extern bool GetCursorPos(out Point lpPoint);

It's worth mentioning that AHK (AutoHotkey) and Logitech HUB macros both work in this game. Also, the fact that this game is the only one I noticed where nor capturing nor raising keyboard events work.

I would need some ideas if the issue is in my approach of how I read and fire keyboard (and mouse) inputs, or if I misunderstand something of how to use the previously mentioned functions? Can I achieve a "universal" macro with user32.dll that will work with any application without oddities? If it's not capable then what are better alternatives that will work almost in any case even if it's not possible in c# but let's say C ?

CodePudding user response:

Windows will for obvious security reasons by default block most communication (Windows messages, accessing each other's handles, input signals, ...) between elevated and non-elevated processes.

From the point of view of a non-elevated process, the elevated process runs like in a different Windows session.

In order to be able to communicate with an elevated process from your own process, your own process has to run elevated (with admin privileges) as well. This includes reading and simulating input events that happen in the context of the elevated process.

  • Related