A program that defeats AutoHotKey???
After playing with it a bit, I found the script language relatively easy to learn, so I wanted to try it with a game my brother plays called Priston Tale.
So far, most if not all attempts to interact with the game have failed. I tried AutoHotKey, I setup a simple hotkey to rightclick once upon control-tab. It works fine in windows on the desktop. Furthermore, I added the #UseHook directive just for extra measure.
Upon entering the game and pressing control-tab, nothing happens. The expected action of an ability being used does not occur. When I drop back and check the key history, it shows control-tab was pressed, but it appears the events are never reaching the game.
I happen to be a relatively experienced programmer, and I have tried checking something I thought might be causing the problem. I wrote a program in VB.NET which checks to see if the right click from the mouse is the same as a right click from the script. According to Microsoft, mouse_event calls and the like will produce events tagged with an INJECTED bit. This bit didn't seem to be set. More accurately, the flag values were the same.
So what I'm trying to figure out is how this program is defeating AutoHotKey without causing the mouse itself not to work?
I would love any feedback on this, I've been trying to write my own simple program to feed right clicks into the game and have had no success. Everquest doesn't seem nearly as well protected, I can't seem to figure out how Priston Tale is avoiding these events and not real mouse events.
It's also important to distinguish between two things:
1) Is the game somehow suppressing hotkeys entirely, so that AutoHotkey doesn't even know that's you've pressed a hotkey? If this is the case, using mouse or joystick hotkeys might work around the issue.
2) Or are the hotkeys firing but their use of the Send and Mouse commands is being ignored? This would be more difficult to work around, but there is some info below.
I once tried modifying the keyboard hook to change the "injected" flag before it passed the event on to the rest of the system. I don't think it had any effect for what I was testing, but it might be worth experimenting with. I can send you a test version with this enabled if you'd like to try it.
Here is some info from a previous post:
You could also try using joystick hotkeys and/or mouse hotkeys. But that won't help if the game blocks artificial input entirely (i.e. the Send command).
If that isn't suitable, there are some other topics that discuss this issue, and may be of help. They mention ControlSend and PostMessage:
Other related posts:
http://www.autohotke... ... rect input
http://www.autohotke... ... rect input
Please let me know if you make any further discoveries in this area.
Thanks for your quick reply, I thought I was going to be suffering through this on my own.
Turns out I did exactly what you recommended trying. I created a program which added a low level global mouse hook, and checked for any RBUTTONDOWN and RBUTTONUP events. Then, I checked to see if any of them had the INJECTED bit set.
The results were that both real mouse, and AutoHotKey are sending identical flag values, and further more neither are set with the INJECTED bit.
The problem is the second one you mentioned. I have confirmed that the HotKey's are getting run by AutoHotKey. When I hit control-tab, then exit the game, it shows in the key history that it was pressed. This tells me that AutoHotKey has received and run the script. However, the game never receives the event.
I am not 100% certain, but very close that this program does not make use of DirectX whatsoever, and so I REALLY doubt it uses DirectInput either.
So, despite looking at the LLMSHOOKSTRUCT contents of a real mouse event, and a hotkey generated event, there seemed to be no difference in the data the structures contained. So how would the program be filtering out generated events?
Is it possible the game has hooked into the IO port directly somehow, and is actively reading from the IO port and not a message queue? If that is the case, is there a way to figure this out by throwing simulated data into the IO port stream?
It seems like supporting such a thing would be seriously disadvantageous to the programmer, because they'd have to figure out which device is the mouse, figure out it's IO port, the bind to it somehow. I'm really baffled how they have managed to avoid all the events.
Of all the information you pointed me to, only 1 was something I hadn't read and it lead me to try something new. Keyboard strokes don't do anything, but if I try using WinGet, PTID, ID, A... then use ControlClick, , %PTID%, , right... Sometimes I will get a right click menu pop up for a moment in front of the game, with grey'd out "Undo" "Cut" "Copy" "Paste" entries. Is it possible WinGet is getting a parent window ID instead of maybe a child ID where the drawing/processing of mouse/keyboard occurs?
So bottom line, from my experiences, it doesn't seem like the INJECTED flag is the issue, and it's not DirectInput either I don't think. But it may be something to do with OpenGL, as I think that's the rendering standard being used.
The poster in those other posts you mentioned, trying to get Everquest working, sounds like his problem was a bit different. He wanted to minimize EQ while the hotkeys ran, but I think Everquest ignores most messages while minimized. However, the fact remains that everquest does still process windows messages. I'm not sure what's going on with Priston Tale, but it's like they have somehow managed to ignore window messages altogether.
Unfortunately, it's been hell trying to get much information as PristonTale runs full screen and has no known way of breaking free without crashing the program. The use of WinMinimizeAll didn't do anything either.
I am really confused by this problem, I'd love to know how they are processing mouse events, and filtering anything except REAL TRUE mouse events.
B. Once upon a time I wrote a program similar to AHK, and I was using a windows api call that iinjected the scan codes and such directly into the IO stream, instead of sending a message. I seem to recall this was somewhat hazardous to do because it could break up keydown-keyup pairs. However, it might be worth looking into, because I successfuly used this method to control Diablo 2.
AutoHotkey uses low-level keyboard and mouse hooks, which are slightly more powerful than the old type of hook (but they do not work on Win9x). With these low-level hooks, the injected flag is clear when physical input occurs, but not so for artificial events. This is the means by which features such as GetKeyState and A_TimeIdlePhysical can discern between physical and artificial events.
I created a program which added a low level global mouse hook, and checked for any RBUTTONDOWN and RBUTTONUP events. Then, I checked to see if any of them had the INJECTED bit set.
The results were that both real mouse, and AutoHotKey are sending identical flag values, and further more neither are set with the INJECTED bit.
the game never receives the event.
I REALLY doubt it uses DirectInput either.
how would the program be filtering out generated events?
The game is using a low-level hook too, and if you launch the game after launching AutoHotkey, the game's hook gets first shot at deciding whether the keystrokes and clicks should be hidden from the other hooks (you could try reversing the startup order).
You could try sending WM_CHAR messages directly to the window as described here:
http://www.autohotke... ... ght=wmchar
Note: I think PostMessage vs. SendMessage can sometimes have a different effect depending on the nature of the target window.
Alternatively, you could try ControlSend, which posts WM_KEYDOWN and WM_KEYUP messages. For both ControlSend and WM_CHAR, different results might occur if you send to the parent window vs. topmost control vs. focused control (though most games probably lack the OS's concept of "focus"). The help file mentions how to send to the parent window directly vs. a specific or top control.
Maybe, but probably only if (dynamically?) installes a VXD or makes some other low-level change to the OS (at least for NT/2k/XP). There's also a thing similar to hooks called WM_INPUT, but it only exists in XP and beyond. It's described at MSDN.
Is it possible the game has hooked into the IO port directly somehow
WinGet always gets parent window IDs. I don't use terms like "parent window" and "child window" too often in the help file because it's intended for an audience of non-programmers. So usually, when it says "window" it means "parent window" and when it says control it mean "child window".
Is it possible WinGet is getting a parent window ID instead of maybe a child ID where the drawing/processing of mouse/keyboard occurs?
That internally uses a feature of the Explorer shell. Maybe Explorer knows not to minimize-all when there is a full-screen game running.
The use of WinMinimizeAll didn't do anything either.
I searched on Google newsgroups for relevant info and have included below some relevant quotes:
The only way to send a DirectInput application keystrokes is to inject them into the keyboard driver. You can write a very simple dyna-load VxD that can send the data to *vkd. Note: the above only applies to DirectInput running on Win9x. For Windows NT, you will have to do things a bit differently.
The great thing about window messages is every app gets them the same way. If it is a VB application the VB engine translates it into a OnKeyDown event or whatever else is valid for the message. If it is a C++ app it is sent to a function defined by the programmer to be processed or a function in a system dll if it is a common control. This means that no matter what the window is it will respond to a windows message you send it (except keyboard and mouse input to apps that are using DirectInput exclusively, they get there user input from a different source).
I want to emulate mouse clicks in DirectInput application from an external application. I tried mouse_event (or
SendInput), but it has no effect on Win 98. (It is interesting that on Win 2000 it works fine.)
Actually, it depends on the OS. On Win9x, you are right, DirectInput is lower level than the keyboard event stuff, so you cannot inject keystrokes into an app that is using DirectInput on 9x, short of rewriting the keyboard device driver. On Win2K you can inject keystrokes, because the input pipeline happens slightly differently.
How can I send keystrokes (for example macros) to another application that uses DirectInput? I tried some message generating functions like "keybd_event" (Delphi 3), but it won't work when the target application uses DirectInput to detect keyboard informations.
I wrote a VxD to interface directly to the keyboard driver (VxD_ForceKeys). All the other methods were ignored by DirectX (like WM_CHAR or keyd_event). 'keybd_event' works with some games but I can only conclude they are not using DirectInput exclusively.
You have to write a VxD that hooks the keyboard processing. It's not as bad as it sounds
From: Jason ([email protected])
Subject: Re: Generating keyboard input to games
I will send you the source to the VxD to your e-mail. It is a commercial product but there is nothing "secret" about what I am doing I just pieced it together from the DDK. You basically do a 'CreateFile' to load the VxD dynamically and
'DeviceIoControl' to send it commands. Look in the documentation regarding 'dynamically loadable VxDs'.
Could you post the links you found this information at and any other relevant information you found? I've been looking all night, and sometimes it just takes someone elses search to find the right thing
I'm going to take a stab at this VXD as soon as I can find some information on how it works, I'll keep searching. Thanks a lot for the help, and I hope maybe another directive can be added into AutoHotKeys when this is figured out. #SuperLowLevelHook
Thanks for the lead.
Once upon a time I wrote a program similar to AHK, and I was using a windows api call that iinjected the scan codes and such directly into the IO stream, instead of sending a message.
Sounds good. If you get such a thing working, I'd be quite interested since it might allow interaction with all games that use DirectInput (I'm talking about legitimate, non-cheating uses, such as ways to reduce clicking and keypresses for those who suffer from RSI).
I am going to do some more research on creating a VXD to hook into keyboard and mouse input. It is more important for me to hook the mouse at this time.
I found the info by searching for keywords -- such as keybd_event, ignore, games, directinput -- at Google's newsgroup archives: http://groups.google...ed_group_search
Could you post the links you found this information at and any other relevant information you found?
As for the VXD hook Chris described, I've found the articles mentioned, and they are as short as posted here unfortunately. And I've had little luck in finding much else. I did some extensive research on DeviceIoControl, and this might be the right direction, but information is erratic at best. Was this the API call you happened to use Savage?
Savage, I'd appreciate any code snippet you might be able to provide on how you injected data directly into the mouse and keyboard streams. With a few tests, I'm sure Chris would be willing to add the extra low level support to his todo list for AHK too. Hope I'm not breaking any rules posting my email but feel free to contact me at [email protected], I'd like to see how you did it if you're willing.
In particular, I THINK DeviceIoControl is going to solve the problem. In specific, I found this an interesting read:
Now, I'm far from a genius, but I think that tells me I can inject a set of bytes right into the mouse IO stream once I use CreateFile to open it.
Another bit of information I found interesting (unfortunately unlinkable, so I pasted it here, sorry).
Mouse Messaging Services
A mouse minidriver is a small VxD that supports mouse hardware that is not automatically supported by VMOUSE. A minidriver uses the VMD_Set_Mouse_Data service to pass information about the mouse hardware to VMOUSE, including the mouse-type identifier, the number of the interrupt request line (IRQ) the mouse is using, the number of buttons on the mouse, and the number of the port the mouse is using. A mouse minidriver's interrupt handler converts raw input from the mouse into event messages and uses the VMD_Post_Pointer_Message or VMD_Post_Absolute_Pointer_Message service to post the messages to VMOUSE.
By hooking the VMD_Manipulate_Pointer_Message service, a virtual device can install a hook procedure that manipulates mouse pointer data. VMOUSE passes raw mouse data to the hook procedure before it is posted to an application. The data includes the x and y delta values, and the status of the mouse buttons. The hook procedure can manipulate the mouse data as needed. A virtual device that needs to manipulate pointer data should hook the VMD_Manipulate_Pointer_Message service instead of the VMD_Post_Pointer_Message service. A virtual device uses the Hook_Device_Service VMM service to install the hook procedure.
VMOUSE does not automatically support the middle mouse button. Instead, a mouse minidriver can support the middle button by hooking the VMD_Set_Middle_Button service. To hook the service, a mouse minidriver calls the Hook_Device_Service VMM service, specifying the address of a programmer-defined callback function. VMOUSE calls the callback function whenever a mouse event occurs, allowing the callback function to set the status of the middle mouse button.
See also VMD_Manipulate_Pointer_Message, VMD_Post_Pointer_Message, VMD_Set_Middle_Button, VMD_Set_Mouse_Data
Built on Friday, April 11, 2003
I have never written a VxD before, but I bolded the piece here that was of particular interest. Maybe someone can help me decipher this stuff and we can get a virtual driver written to include with AutoHotKey. It would be very cool if we could actually manipulate, and post our own events from this VxD hook, and it sounds like we can do exactly that. By using the VMD_Post_Pointer_Message I think we can basically use AutoHotKey to hook into the VxD and call this to create low level events. What do you think Chris? I'm still struggling to understand how this works, I've only written .NET DLL's, and never written device drivers before, this is certainly jumping head first for me... But live and let learn
If anyone wants to contribute any of their experience with what I've mentioned here, please do. Take nothing for granted, I won't bite your head off for noobish suggestions
If we can get this VxD working, I think it'll fool every possible program, and could even afford to do away with AutoHotKey's current #UseHook, as the VxD I'm certain written in C, would have a smaller overhead at a lower level too.
Once the VxD is hooking the mouse events (and eventually keyboard), the strategy of how it can be implemented into AutoHotKey is simple... On each event, pass the raw data to AutoHotKey, and have some new methods for allowing AutoHotKey to manipulate the data (or choose to ignore, or do nothing), and reinject any changes as appropriate back into the DLL. If AutoHotKey never sends back the mouse packet, then the DLL will effectively never post it to the system.
Okay, getting a little overboard here. I'm off to investigate the DDK and VxD's a little more. But I'm still hoping Savage will post his solution even if it's just a snippet of code
For the moment, I'm going to leave this most up to you and anyone else who wants to research and experiment with it. I have a list of other enhancements -- especially the GUI features -- that I want to focus on over the next few weeks.
Maybe someone can help me decipher this stuff and we can get a virtual driver written to include with AutoHotKey.
By using the VMD_Post_Pointer_Message I think we can basically use AutoHotKey to hook into the VxD and call this to create low level events. What do you think Chris?
Join the club
never written device drivers before
That would be a good thing because I know a lot of gamers have have RSI or are in danger of developing it. Even something that frees a gamer from having to hold down a key or mouse button can be a great asset.
If we can get this VxD working, I think it'll fool every possible program
In time, perhaps. But the hooks are a fairly complex part of the program, having required a great deal of testing and refinement from the beginning.
and could even afford to do away with AutoHotKey's current #UseHook
If you get any kind of prototype working -- or even just some framework written -- I'd be quite interested in seeing it. I'm especially interested in things that can be dynamically loaded and that don't permanently alter the system in any way. Anything that does install a driver or alter the system in some way (i.e. resident even while AutoHotkey isn't even running) I would not want to make a built-in part of the program, though it could of course be an optional add-on.
I'd be happy to share it with anyone who wants to try and figure it out with me, otherwise I guess this is a dead subject. I can only pray that Chris will take a serious interest in this, as it would make AutoHotKey lightyears ahead of similar products, even though it's already a few steps ahead in most cases.
Truly, until AutoHotKey can feed DirectInput without the use of WM_KEYDOWN, etc, it's uses are limited to the sore-wristed gamer.
Best of luck, hope you will turn some attention to this limitation in the future.
Here's what I think.
HRESULT GetDeviceState( DWORD cbData, LPVOID lpvData );
This method is used by DirectInput applications to retreive the state of a device during it's game loop. While not ALL DirectX games used this method, most do. The other option is that with the release of DirectX 9 you can specify callbacks to achieve events like windows, through DirectInput.
Anyways, let's assume (and hope) that the game in question uses the game loop method.
Here are the parameter descriptions for the above method:
cbData Size of the buffer in the lpvData parameter, in bytes. lpvData Address of a structure that receives the current state of the device. The format of the data is established by a prior call to the IDirectInputDevice8::SetDataFormat method.
Now, my thinking is that if you created an API hook to this method (See: http://www.madshi.net for a library usable for non-commercial uses, written in Delphi, but has a C++ library as well), you could then have this method hooked to return whatever you wanted to.
So, if you hooked GetDeviceState in DINPUT.DLL, and had AutoHotKey able to run code in these hooks to change the state of the mouse or keyboard, the next loop the game runs will pick up the change of state. At least, that's my thinking. Basically, we just call the Next hook (the one the game would have), have it do it's work on the pointers, and when it's done, before returning from our hook, we can manipulate the data at the pointers location. I've been running some tests with Madshi's madCodeHook, but so far haven't had a whole lot of success. Anyone here familiar with hooking API functions themselves?
What do you guys think?
By the way, Priston Tale is a perfect game to do this testing on. As it currently stands, the game costs around $10 CDN funds. The biggest hassle is in getting setup on the game, but the software is a free download. So, for about 7-8 USD a month you could have a game that doesn't work with AutoHotKey currently to test with. I think the US servers for Priston Tale cost a bit more, but if you use the Thailand servers, and go through the hassle of getting through the thaiwan website, most of the game itself is converted to english already even for Thaiwan. I can't read or speak a stitch of Thai and I was able to figure it out.
Keep in mind, I can get AutoHotKey's to trigger, so the events are still passed to AutoHotKey, I just can't get Send to actually present changes to the game. So hopefully if we can figure this out, then a simple directive like #DIHook before using Send would cause Send to use the GetDeviceState hook instead. Using Madshi's code, you can install and uninstall the hook's at will. And as I said, for non-commercial uses (like this OpenSource product) the library is free to use the dynamic version.
None the less, I HAVE an account I can test with, I would be happy to test anything for anyone. I'm available almost 24/7 on MSN/ICQ if you want to get into a real-time chat and try to figure this out... I could really use another mind to bash heads with
Email me at [email protected] with your ICQ or MSN info and we'll get in touch.
For the next 4 weeks or I won't be able to devote much time to this area since the I'm committed to adding more GUI features and high priority items that have been on the to-do list for a long time.
What of course would be the ultimate windfall is some kind of prototype or demonstration that proves the concept. For example, it's hard to justify spending a lot of time trying to integrate something like this if it only works with 30% of DirectInput games. It's also hard to justify building in this component if it adds a signficant size to the installer (which is currently about 1.0 meg). That could be worked around by making it an optional accessory available as a separate download.
So basically, in the short-term I'm avoiding any large commitment to this, leaving it up to you and anyone else who wants to look into it further. I still continue to benefit from what you posted so far; even if you give up on this task, this info well prove valuable to myself or others in the coming months.