[C++]Sending Keydowns to Aion

11/14/2012 17:03 jackicola#1
Hey,
I'm trying to send Keydowns to Aion, I tried a few methods but nothing worked yet:
Code:
#include <windows.h>

int main()
{
	INPUT ip;
	Sleep(5000);

	ip.type = INPUT_KEYBOARD;
	ip.ki.wScan = 0; 
	ip.ki.time = 0;
	ip.ki.dwExtraInfo = 0;
	ip.ki.wVk = 0x41; 
	ip.ki.dwFlags = 0;
	SendInput(1, &ip, sizeof(INPUT));

	Sleep(1000);

	ip.ki.dwFlags = KEYEVENTF_KEYUP;
	SendInput(1, &ip, sizeof(INPUT));
	return 0;
}
Code:
#include <iostream>
#include <Windows.h>

using namespace std;

int main()
{

	HWND hWnd = FindWindowA(NULL, "AION Client");
	if(!hWnd)
	{
		cout << "HWND Failed" << endl;
		getchar();
		getchar();
		exit(1);
	}


	Sleep(5000);

	PostMessage(hWnd, WM_LBUTTONDOWN, NULL, NULL);
	Sleep(100);
	PostMessage(hWnd, WM_LBUTTONUP, NULL, NULL);
}
Both doesn't work... Can someone help me please?

Greets!
11/14/2012 22:01 lucid#2
Foreground
SendInput can be used if the window is active. There are a few things worth noting about this implementation: A real-world use case will need to be more complex for extended/system keys. SendInput also sends the Low Level Keyboard Hook Flag: INJECTED ([Only registered and activated users can see links. Click Here To Register...]), which will give the target application an opportunity to detect the injected input. There are bots out there which use SendInput and have not caught a ban, but I don't personally feel comfortable doing this.

As for specifically why your example isn't working, some of the properties of ip might be overwritten when it is passed into SendInput, try setting wVk, type and ki after the first call to SendInput is made; every example I can find explicitly sets each property before each call.

Background
There are many restrictions to sending input to background/minimized windows (or active windows) with SendMessage/PostMessage.

First, when sending input with SendMessage or PostMessage the physical state of the device persists and receives priority in some cases. This means if you emulate input and the target application calls GetKeyState it will return a negative result unless the user happens to be pressing the key at the time the input is emulated.

Similarly, if you try to emulate movement such as running, turning (like your SendInput example), backpedaling or strafing by sending multiple WM_CHAR messages as you would see with Spy++ or a similar message loop monitoring tool, it will not work. You cannot emulate repeat/"held down" buttons.

This problem also manifests itself with emulation of mouse input. I believe the mouse position will always reflect the actual position even if you have crafted the messages to specify otherwise, because of the same physical status problem.

So you can emulate keyboard keypresses to background windows, but as for holding keys or mouse manipulation, you're pretty much out of luck.

There only appear to be a few possible solutions, none of which are straightforward, easy and background compatible:
  • DDK: A filter (to manipulate emulated messages)
  • DDK: A driver (to emulate them closer to the kernel, instead of via WINAPI)
Both of those are fairly heavy topics and don't appear to be well-documented openly on the Internet. You can check out [Only registered and activated users can see links. Click Here To Register...] if you're interested in digging deeper.
  • SendInput to active window, possibly with LLKHF_INJECTED/LLMHF_INJECTED patched out of kernel (heh)


Hopefully this is helpful to you.
11/15/2012 12:06 jackicola#3
Wow, Wow, Wow! Great answer! I have it like this now:
Code:
#include <windows.h>

int main()
{
	INPUT ip;


	Sleep(5000);

	ip.type = INPUT_KEYBOARD;
	ip.ki.wScan = 0; 
	ip.ki.time = 0;
	ip.ki.dwExtraInfo = 0;

	
	ip.ki.wVk = 0x41; 
	ip.ki.dwFlags = 0; 
	SendInput(1, &ip, sizeof(INPUT));

	ip.ki.wVk = 0x41; 
	ip.type = INPUT_KEYBOARD;
	ip.ki.dwFlags = KEYEVENTF_KEYUP; 


	Sleep(1000);

	SendInput(1, &ip, sizeof(INPUT));

	return 0;
}
But it's still not working... Can you please help me again?
11/15/2012 13:16 lucid#4
Probably because you're not setting a scan code.

Check out [Only registered and activated users can see links. Click Here To Register...]
11/15/2012 14:45 jackicola#5
Can you please say me where and how I have to implement this in my code?
11/15/2012 16:21 lucid#6
I don't program in C so I can't test the code.

You must map the Virtual Key code (set here)
Code:
ip.ki.wVk = 0x41;
...to a scan code (set to 0 here)
Code:
ip.ki.wScan = 0;
...in referencing the documentation...
Quote:
Originally Posted by MapVirtualKey Documentation
MAPVK_VK_TO_VSC
0

uCode is a virtual-key code and is translated into a scan code. If it is a virtual-key code that does not distinguish between left- and right-hand keys, the left-hand scan code is returned. If there is no translation, the function returns 0.
...it might look like this:
Code:
ip.ki.wScan = MapVirtualKey(ip.ki.wVk, 0)
If it still doesn't work it might be worth taking a look through documentation for each of these elements to verify everything.

Function reference:
Input Structures: