Hi, how can i "simulate" a keypress on a directX programmed game?
Hi, how can i "simulate" a keypress on a directX programmed game?
You can try using SendInput to simulate a keystroke. It also simulate mouse movements. If the game is using directInput for all of its input then this may not work.
Founder and avid member of the Internationsl Typo Associateion
Does this method works for system-wide input simulation? As i can see this function receives no "target" like a window handle...
Yes it works for system wide keyboard simulation. If you want to target specific keystrokes to an application, you might as well use SendMessage and specify the Windows Handle.
Again, if it uses DirectInput for the input then this approach wont work.
Last edited by Mastadex; 01-28-2008 at 09:24 AM.
Founder and avid member of the Internationsl Typo Associateion
If the target is using DirectInput, then you'll probably have use use a DLL which will review the names of all running processes in search of the targeted process. The DLL will then inject code into the targeted process to override DirectInput8Create. Your DLL will now intercept requests to create GUID_SysKeyboardDevices and will return it's own device.
Now when IDirectInputDevice8::GetdeviceState is used to retrieve the keyboard state in immediate mode, your custom keyboard can return a keyboard state containing your simulated keypress.
I haven't verifed the accuracy of this method using code. So, any non verified coding theory and $2.00 will get you nothing more than a cup of coffee.
A sure fire way would be to write a Virtual Device Driver (VxD) that inserts key strokes directly into the keyboard buffer, fooling DirectInput. Another way, like you said, is to write a DLL that injects code into the DirectInput memory space.
Looking through the Microsoft DDK, there are examples of custom VxD files. Under keyb\samples\Vkxd\ there is an example of an easy keyboard emulation VxD. But that might be outdated. DirectInput deals directly with the keyboard buffer (and other devices) and completely ignores all input that has been passed through windows and converted into WM_* messages. So any sort of WM_* simulation will not work.
Founder and avid member of the Internationsl Typo Associateion
I wasn't able to find that sample... Maybe i have download a wrong DDk version? I got it from here: http://www.microsoft.com/whdc/devtools/ddk/default.mspx.
I think that the virtual device driver is the best way to do it, but i got curious, how would i do it in BobS0327's way?
I'm most likely using a very very old version of the DDK. Mind you, in order to do this you will have to write a keyboard driver; Something that I have not done before. But before diving into that, try using the keybd_event function, and passing in some scan codes (NOT Virtual Key Codes!). If that fails, then you should write the VxD.
Founder and avid member of the Internationsl Typo Associateion
I recommend against doing that.
Drivers are very complex pieces of code and one wrong line of code can crash the entire system. Not to mention it would probably cause headaches since it's low level. Plus you need to ship that driver to anyone who uses the app. So that means they are left at exposure, too, and they need admin powers to install the driver.
No. Try to avoid drivers.
Oh, the keybd_event function worked just fine outside directX games... But in directX games simply nothing happened... I'm stuck here, any sugestions? I think that BobS0327 method is pretty good but i don't know how to implement it... some help would be welcome =)
Last edited by Scarvenger; 01-29-2008 at 01:39 PM.
I hope you realize that the description of my method gives the impression that this project is a simple task. It is definitely NOT going to be easy. It starts off somewhat easy but will become progressively more difficult as you near the end of the project. But for starters, the first order of business is to write the code to enumerate the tasks to find your targeted task. You should use CreateToolHelpSnapshot32 for this enumeration task. Also, you will have to set the debug privilege level using OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges. This privilege level has to be set first prior to querying the PID number for the targeted task to allow you to inject code into the process.I think that BobS0327 method is pretty good but i don't know how to implement it... some help would be welcome =)
The next step will be open for discussion when you have this code working reliably.
Ok, im working on that, soon i should post my code here...
Ok, this is the code so far:
Process.h
Process.cppCode:#pragma once #include <windows.h> #include <Tlhelp32.h> class Process { PROCESSENTRY32 processEntry; public: Process(const PROCESSENTRY32& processEntry); Process(); ~Process(); DWORD getPid(); DWORD getThreadsCount(); DWORD getParentPid(); DWORD getModuleId(); char* getExeFilename(); };
ProcessEnumerator.hCode:#include "Process.h" Process::Process(const PROCESSENTRY32& processEntry) { this->processEntry = processEntry; } Process::Process() { } Process::~Process() { } DWORD Process::getPid() { return processEntry.th32ProcessID; } DWORD Process::getParentPid() { return processEntry.th32ParentProcessID; } DWORD Process::getThreadsCount() { return processEntry.cntThreads; } DWORD Process::getModuleId() { return processEntry.th32ModuleID; } char* Process::getExeFilename() { return processEntry.szExeFile; }
ProcessEnumerator.cppCode:#pragma once #include <windows.h> #include <Tlhelp32.h> #include "Process.h" class ProcessEnumerator { HANDLE snapshot; PROCESSENTRY32 processEntry; public: ProcessEnumerator(); ~ProcessEnumerator(); bool getFirst(Process& process); bool getNext(Process& process); };
main.cppCode:#include "ProcessEnumerator.h" ProcessEnumerator::ProcessEnumerator() { snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); processEntry.dwSize = sizeof(PROCESSENTRY32); } ProcessEnumerator::~ProcessEnumerator() { CloseHandle(snapshot); } bool ProcessEnumerator::getFirst(Process& process) { if (Process32First(snapshot, &processEntry)) { process = Process(processEntry); return true; } else { return false; } } bool ProcessEnumerator::getNext(Process& process) { if (Process32Next(snapshot, &processEntry)) { process = Process(processEntry); return true; } else { return false; } }
It is worrking just fine, i can get any process and play with it, and get the PID too. I really dont know you indicated me those Token privileges functions, anything wrong with my code? If not, whats the next step?Code:#include <iostream> #include "ProcessEnumerator.h" int main() { ProcessEnumerator enumerator; Process actual; enumerator.getFirst(actual); do { std::cout << "Process Name: " << actual.getExeFilename() << '\n'; std::cout << "Process ID : " << actual.getPid() << '\n'; } while (enumerator.getNext(actual)); std::cin.get(); return 0; }