I have been working on a soon to be open sourced application for tracking how much time a person spends on the computer (and limits them depending on many factors that an administrator can configure). This time my QA team consists of my family members (all 7).
The idea behind this application is that we allow our children a certain amount of time on the computer each day and would like to ensure it is followed. ‘TimeTracker’ as it is called thus far employs a number of techniques to limit a person’s access to one or more computers. I’ll blog about this more as the application matures, but the point of this blog is all about Windows hooks and trapping keyboard and mouse events using the Windows API SetWindowsHookEx() when using a Codegear compiler (I currently use Borland C++ Builder 6).
This was my first Windows Hook application I ever wrote so I had lots to learn. When using the hook APIs ensure that you:
1. Use cross-process shared memory for data that needs to be shared (remember the hook API loads your DLL into all processes, meaning even if the variable(s) are static they won’t be shared across process boundaries). So if explorer.exe sends a mouse event, then media player sends a keyboard event and you want to keep track of the last activity in som kind of datetime variable, you need to use a cross-process memory buffer. VC++ allows for shared segments (i could not get it to work in the Borland environment), but I chose to use memory mapped files via the CreateFileMapping() and MapViewOfFile() API calls. You could use sockets or some other IPC mechanism as well.
2. Guard access to the shared memory via some kind of synchronizers (i chose mutexes via CreateMutex() API’s). If you don’t you may end up getting memory corruption and trash windows itself (hook api’s are delicate).
3. For Codegear specific compilers you MUST employ special floating point behaviour because the Hook DLL may attach to a DirectX application and eventually the directX / OpenGL application will crash randomly. This one took me a while to figure out! MAKE SURE you call the following method in the hook DLL as the first thing you do:
// Borland floating point initialization
// Disable floating point exceptions
Now add this method declaration to your DLL hook project:
int _matherr(struct _exception *e)
e; // Dummy reference to catch the warning
return 1; // Error has been handled
and voila, no more crashing when graphics applications are running and you are hooked into them.
Believe it or not here is an MSDN article giving a brief mention of this requirement. I would say this is ALWAYS required when hooking via the API’s because you will never know what program is running while you are hooked in.
Till next time, cya.