|
|
|
| |
|
First off I would like to say that researching hooks is not an easy subject to find information out about. To their credit, the vast majority of information
that I have on hooks, other than trial and error, came from the MicroSoft Knowledge base. I am by no means a fan of MicroSoft, but I will give credit
to where credit is due. The MicroSoft Knowledge base is an excellent source of information to program in Windows. I have found that the older versions
of code that is available is usually more stable, more reliable, and much more complete than the newer versions. The older versions is for 3.1 so
you will have to do a little bit of tweaking to make it work, but in the long run I think that it is worth it. So anyway, on with the show.
|
| |
|
Hooks are a user defined function that can be used to monitor system events like mouse movements or clicks, key strokes, or messages. This
function can monitor these actions and perform steps depending upon what the developer wants. The developer can, in some cases, modify or even
discard the actions. Of course there are limits on what the function can do and most of them are beyond the scope of this page. I will give out
the links that I have where you can view and/or download more information on hooks at the end of this page.
|
| |
|
Hooks are used when you need to monitor or change an action that happens inside or outside the scope of your program. There are 2 types of hooks
that a developer can use, Thread or System. A thread hook is speicific to the application that called it and can be contained with in the program.
A system hook is a dll and can monitor all activity on a PC.
|
|
Hooks use four functions:
- SetWindowsHookEx. This function takes 4 arguments and is used to set/start the hook.
- Integer code of the hook to set.
- Address of the hook function.
- The instance handle to the module that contains the hook function.
- The thread for which the hook is to be installed. If it is a system hook this is set to zero.
- Example:
HHOOK hkKeyHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)hkProcKeyHook, hPrintInstDLL, 0);
- User defined hook function. This means that function name can be called anything that you would like, but it has to have the correct parameters, which are 3.
- Integer code telling the function to process the message or to let it pass. Usually anything less than zero, the hook function should pass on.
- WPARAM will pass information that is needed by the hook function to process a message.
- LPARAM will pass information that is needed by the hook function to process a message.
- Example:
LRESULT CALLBACK setWTPSKeyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
- UnhookWindowsHookEx: This function takes one parameter and is used to stop the hook.
- Example:
UnhookWindowsHookEx(hkPlayBackJournal)
Note: hkPlayBackJournal is the handle to HHOOK of hook function
- CallNextHookEx: This function takes four parameters and is used to pass the message to the next hook in the chain.
- HHOOK is the handle to the current hook
- Integer code telling the function to process the message or to let it pass. Usually anything less than zero, the hook function
should pass on.
- WPARAM will pass information that is needed by the hook function to process a message.
- LPARAM will pass information that is needed by the hook function to process a message.
- Example:
CallNextHookEx(HHOOK hkPlayBackJournal, int nCode, WPARAM wParam, LPARAM lParam)
|
Below is one possible way of setting a WH_MOUSE hook, monitoring the movements, writing the movements to a file, and closing the hook.
This is down by loading the DLL dynamically so I can get the handles that I need to load the hook. To save space I took out all error checking, in the real program I checked to make sure that the DLL and
all of it's functions loaded properly.
Note: There are a few different ways that this program can be done and I choose to use files to maintain state. I used files for a different
reasons. The main reason is that I am more comfortable with files and I was unable to find a great deal of information concerning sharing
memory between applications.
//In the DLL itself declare the mouse hook function and get it's address
// This is the keyboard hook method
LRESULT CALLBACK setWTPSKeyboardHook(int nCode, WPARAM wParam, LPARAM lParam);
// Address of the keyboard hook procedure that will monitor the keyboard
FARPROC hkProcKeyHook = {
(FARPROC)setWTPSKeyboardHook
};
// In the calling application
inst.dllInstance = LoadLibrary(load);
startWTPSMouseHook = (startMouse)GetProcAddress(inst.dllInstance, "startWTPSMouseHook");
startWTPSMouseHook();
// Back in the DLL at startWTPSMouseHook()
extern "C" __declspec(dllexport)
__stdcall void startWTPSMouseHook()
{
if (hPrintInstDLL)
{
getHomePath(); // Registry entry with home path
getDLLInstance(); // Registry entry with DLL instance
}
if (hPrintInstDLL)
{
if (!hkProcMouseHook)
writeWTInfoMessage(WT_MESSAGE_WARN, "Mouse hook NOT set. Region not working");
else
{
hkMouseHook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC)hkProcMouseHook, hPrintInstDLL, 0);
writeHook(MOUSE_HOOK_INDEX, hkMouseHook);
writeMonitorMouse(false);
writeWTInfoMessage(WT_MESSAGE_INFO, "Mouse hook set. Region working");
} // End the else
} // End the if
else
writeWTInfoMessage(WT_MESSAGE_WARN, "Mouse hook NOT set. hPrintInstDLL is NULL");
} // End the startMouseHook function
// At SetWindowsHookEx
// In Windows every time an application is started, a copy of this DLL will be loaded into it's memory space.
// When this happens all variables in the DLL are brand new and contain no values. Because of this, I wrote the
// the values of variables that I needed to the registry so I could retrieve them latter. There are other ways of
// doing this such as FileMapping, but I choose this way
LRESULT CALLBACK setWTPSMouseHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if (!hPrintInstDLL || !hkMouseHook) // Another process started, fill in the values
{
getHomePath();
getDLLInstance();
hkMouseHook = getHook(MOUSE_HOOK_INDEX);
readMonitorMouse();
} // End the else
LPMOUSEHOOKSTRUCT mouseCoords;
static bool bCapture = true;
if ((nCode >= 0) && (bDoMouseClick))
{
mouseCoords = (MOUSEHOOKSTRUCT *)lParam;
if (wParam == WM_LBUTTONDOWN)
{
if (bCapture)
{
::RECT rcClip;
rcClip.left = rcClip.right = mouseCoords->pt.x;
rcClip.top = rcClip.bottom = mouseCoords->pt.y;
char fPath[MAXPATH + 20];
sprintf(fPath, "%s%s", hDir.homePath, CFGFileName[RECT_SIZE_INDEX]);
ofstream outfile(fPath, ios::out | ios::trunc | ios::binary | ios::beg);
if (outfile)
{
outfile.write((char *)&rcClip, sizeof(::RECT));
outfile.close();
} // End the if
writeWTInfoMessage(WT_MESSAGE_INFO, "Captured left mouse button DOWN");
bCapture = false;
} // End the if
} // End the if
if (wParam == WM_LBUTTONUP)
{
writeMonitorMouse(false);
bCapture = true; // Reset if for the next one
::RECT endClip;
char fPath[MAXPATH + 20];
sprintf(fPath, "%s%s", hDir.homePath, CFGFileName[RECT_SIZE_INDEX]);
ifstream infile(fPath, ios::beg | ios::binary | ios::in);
if (infile)
{
infile.read((char *)&endClip, sizeof(::RECT));
infile.close();
} // End the if
else
endClip.left = endClip.top = 0;
endClip.right = mouseCoords->pt.x;
endClip.bottom = mouseCoords->pt.y;
ofstream outfile(fPath, ios::out | ios::trunc | ios::binary | ios::beg);
if (outfile)
{
outfile.write((char *)&endClip, sizeof(::RECT));
outfile.close();
} // End the if
sendWTPSMessage(DO_REGION_INDEX);
writeWTInfoMessage(WT_MESSAGE_INFO, "Captured left mouse button UP");
} // End the if
} // End the if
return (CallNextHookEx(hkMouseHook, nCode, wParam, lParam));
} // End the setWTPSMouseHook function
// Back at the calling application, the user is terminating the application
unHookWTPSMouseHook = (shutMouse)GetProcAddress(inst.dllInstance, "unHookWTPSMouseHook");
if (unHookWTPSMouseHook)
{
unHookWTPSMouseHook();
writeWTInfoMessage(WT_MESSAGE_INFO, "Shut down, UnHooking the mouse hook");
} // End the if
else
writeWTInfoMessage(WT_MESSAGE_INFO, "Shut down, Could not unhooking mouse hook");
// Back at the DLL, the mouse hook shuts down
extern "C" __declspec(dllexport)
__stdcall void unHookWTPSMouseHook()
{
if (!hPrintInstDLL || !hkMouseHook) // Another process started, fill in the values
{
getHomePath();
getDLLInstance();
hkMouseHook = getHook(MOUSE_HOOK_INDEX);
} // End the else
if (UnhookWindowsHookEx(hkMouseHook)) // Get rid of the hook
writeWTInfoMessage(WT_MESSAGE_INFO, "Unhook Mouse hook");
else
writeWTInfoMessage(WT_MESSAGE_WARN, "Unhook Mouse hook NOT");
} // End the clearMouseHook function
|