Thread: Simulating keypress

  1. #1
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220

    Simulating keypress

    Hi, how can i "simulate" a keypress on a directX programmed game?

  2. #2
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    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

  3. #3
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Does this method works for system-wide input simulation? As i can see this function receives no "target" like a window handle...

  4. #4
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    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

  5. #5
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    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.

  6. #6
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    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

  7. #7
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    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?

  8. #8
    Codebot
    Join Date
    Jun 2004
    Location
    Toronto
    Posts
    195
    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

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    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.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No easy solution I know of. It's tricky because DirectInput works on a low level with hardware and bypasses Windows keyboard handling.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I think that BobS0327 method is pretty good but i don't know how to implement it... some help would be welcome =)
    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.

    The next step will be open for discussion when you have this code working reliably.

  13. #13
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Ok, im working on that, soon i should post my code here...

  14. #14
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Ok, this is the code so far:
    Process.h
    Code:
    #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();
    };
    Process.cpp
    Code:
    #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.h
    Code:
    #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);
    };
    ProcessEnumerator.cpp
    Code:
    #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;
    	}
    }
    main.cpp
    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;
    }
    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?

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    They're basically just wrapper, but I guess that's fine... You could make them more useful, but still...
    You need to set debug privilege for your app in order to inject code into an executable.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Allegro input keypress
    By CaliJoe in forum C++ Programming
    Replies: 1
    Last Post: 05-26-2009, 09:51 PM
  2. (MFC, Visual C++) Keypress Detection in a dialog...
    By guitarist809 in forum Windows Programming
    Replies: 4
    Last Post: 08-31-2008, 01:13 PM
  3. Replies: 6
    Last Post: 08-28-2008, 08:10 PM
  4. Detecting keypress
    By dandago in forum C Programming
    Replies: 4
    Last Post: 06-10-2007, 09:34 AM
  5. ahhh help....rapid keypress detection
    By technoXavage in forum Game Programming
    Replies: 1
    Last Post: 12-18-2003, 01:00 PM