About Hooks
First, the basic concept:
Hooks, a platform for Windows message processing, where an application can set a subroutine to monitor a message of a specified form, and the form being monitored can be created by another process. When the message arrives, it is processed before the target form processing function. The hook mechanism agrees that the application intercepts the processing of window messages or specific events.
A hook is actually a program segment that processes messages, and it is put into the system by a system call. Whenever a particular message is issued, the hook program captures the message before the destination form is reached, i.e. the hook function gets control first. The hook function is then able to process (change) the message, to continue to pass the message without processing, and to force the end of the message delivery.
Second, the implementation mechanism:
1. Hook link list and hook path:
Each hook has a list of pointers associated with it, called a chain of hooks, which is maintained by the system. The pointer to this list points to the specified, application-defined, callback function called by the hook, which is the various processing routines for the hooks. When the message associated with the specified hook type occurs, the system passes the message to the hook thread. Some hooks can only monitor messages, or change messages, or stop the progress of messages, to prevent these messages from being passed to the next hook or destination form. Recently installed hooks are placed at the beginning of the chain, and the first installed hooks are placed at the end, that is, after the addition of the first gain control.
Windows does not require that the order of the hooks be unloaded in the reverse order of installation. Whenever a hook is unloaded, Windows frees up its occupied memory and updates the entire hook list. Suppose the program installs a hook, but before the hook has not been uninstalled, then the system will take the initiative to do the uninstall hook operation.
A hook thread is an application-defined callback (CALLBACK function) that cannot be defined as a member function of a class, but can only be defined as a normal C function. Used to monitor a system or a specific type of event that can be associated with a particular thread, or it can be an event for all threads in the system.
The hook path must follow the following syntax:
LRESULT CALLBACK HookProc
(
int NCode,
WPARAM WPARAM,
LPARAM LPARAM
);
HookProc is the name of the application definition.
The ncode reference is the hook code, which is used by the hook to determine the task. The value of this parameter depends on the hook type, and each hook has its own hook code feature character set.
The values of the wparam and lparam parameters depend on the hook code, but their typical value is to include information about sending or receiving messages.
2, the hook installation and release:
Use the API function SetWindowsHookEx () to load an application-defined hook Shuo into the list of hooks. The SetWindowsHookEx function always installs the hook path at the beginning of the hook chain. When a specified type of hook is monitored by an event that occurs, the system invokes the hook path at the beginning of the hook chain associated with the hook. The hook in each hook routine decides whether to pass the event to the next hook. The CallNextHookEx function needs to be called when the hook passes the event to the next hook path.
Hhook SetWindowsHookEx (
The type of int idhook,//hook, that is, the type of message it handles
HOOKPROC LPFN,//The address pointer of the hook path. Suppose dwThreadID is 0
Or the identity of a thread created by another process,
LPFN must point to the hook in the DLL.
In addition, LPFN can point to the current process of a section of the hook code.
The entry address of the hook function, which is called when the hook is hooked to whatever message.
HINSTANCE Hmod,//handle to the application instance. Identifies the DLL that includes the Cheng referred to by LPFN.
Suppose dwThreadID identifies a thread created by the current process,
And the subroutine code is in the current process, hmod must be null.
It is very easy to set its instance handle for this application.
DWORD dwThreadID//identifier of the thread associated with the installed hook child threads.
Assuming 0, the hook path is associated with all threads, which is the global hook.
);
The function succeeds to return the handle of the hook, and the failure returns NULL.
The above-mentioned hook path and line Threads Association refers to the message sent to the thread in a chain list is sent to the hook at the same time, and is handled by the hook enters upgradeable.
The hook function that calls control in the hook is completed after processing the message, assuming that the message continues to be passed, it must call the API function CallNextHookEx in the other SDK to pass it to run the next hook that the hook list refers to. When this function succeeds, it returns the return value of the next hook procedure in the hook chain, and the type of the return value depends on the type of hook. The prototype for this function is as follows:
LRESULT CallNextHookEx
(
Hhook hhk;
int NCode;
WPARAM WPARAM;
LPARAM LPARAM;
);
HHK is the handle of the current hook, returned by the SetWindowsHookEx () function.
Ncode is the event code passed to the hook procedure.
WPARAM and lparam are respectively wparam values passed to the hook, and their detailed meanings are related to the hook type.
The hook function can also discard the message by returning true directly, and prevent the message from being passed. Otherwise, other applications that have hooks installed will not receive notification of the hooks and may produce incorrect results.
Hooks need to be unloaded with UnhookWindowsHookEx () after use, otherwise it will cause trouble. Easy to release hooks, UnhookWindowsHookEx () has only one parameter. function prototypes such as the following:
UnhookWindowsHookEx
(
Hhook hhk;
);
The function returns true successfully, otherwise false is returned.
3, some implementation mechanisms:
In a WIN16 environment, the global data for a DLL is the same for every process that loads it, and in a Win32 environment, the situation changes, and the code in the DLL function creates whatever object (including the variable) is called to its thread or process. When a process loads a DLL, the operating system itself proactively maps the DLL address to the private space of the process, that is, the virtual address space of the process, and copies a copy of the DLL's global data to that process space. That is, each process has the same DLL's global data, their name is the same, but its value is not necessarily the same, and is non-interfering with each other.
Therefore, in a Win32 environment, if you want to share data across multiple processes, you must make the necessary settings. The shared memory between the processes of the same DLL is realized through the memory map file technology. You can also isolate the data that needs to be shared, place it in a separate data segment, and set the attribute of that segment to be shared. These variables must be assigned an initial value, or the compiler will place a variable with no initial values in a data segment called uninitialized.
#pragma data_seg preprocessing directives are used to set up shared data segments. Like what:
#pragma data_seg ("Shareddataname")
Hhook Hhook=null;
#pragma data_seg ()
All variables between #pragma data_seg ("shareddataname") and #pragma data_seg () will be visited and shared by all the processes of the DLL.
When a process implicitly or explicitly invokes a function in a dynamic library, the system maps the dynamic library to the virtual address space of the process (hereinafter referred to as the "address space"). This makes the DLL a part of the process, running as the process, using the stack of the process.
4. System hooks and Thread hooks:
The last parameter of the SetWindowsHookEx () function determines whether the hook is a system hook or a thread hook.
The line Cheng is used to monitor event messages for a specified thread. A line Cheng is typically within a thread that is derived from the current thread or when it is active.
The system hook monitors the event messages for all threads in the system. Because the system hook affects all applications in the system, the hook function must be placed in a separate dynamic-link library (DLL). The system itself proactively maps the DLL that includes the "Hook callback function" to the address space of all processes affected by the hook function, injecting the DLL into those processes.
A few notes:
(1) Assuming that the same event (such as a mouse message) has both a line Cheng and a system hook installed, then the system will call the line Cheng itself, and then call the system hook.
(2) Multiple hook processes can be installed on the same event message, and these hook processes form the hook chain. The hook information should be passed to the next hook function at the end of the current hook processing.
(3) Hooks, especially system hooks, consume message processing time and reduce system performance. Only install hooks when necessary, and uninstall them when the use is complete.
Three, Hook type
Each type of hook enables applications to monitor different types of system message handling mechanisms. The following description describes all the types of hooks that can be used.
1, Wh_callwndproc and Wh_callwndprocret Hooks
Wh_callwndproc and Wh_callwndprocret hooks enable you to monitor messages sent to the form process. The system calls the Wh_callwndproc hook thread before the message is sent to the Receive form procedure, and calls the Wh_callwndprocret hook after the form process finishes processing the message.
The Wh_callwndprocret hook passes the pointer to the CWPRETSTRUCT structure, which is then passed to the hook path. The CWPRETSTRUCT structure includes the return value of the form procedure from which the message was processed, and the same number of message parameters associated with the message.
2, WH_CBT Hook
The system calls the WH_CBT hook thread before the following event, which contains:
1. Activate, build, destroy, minimize, maximize, move, resize, etc. form events;
2. Complete the system instructions;
3. Mobile mouse, keyboard events from the system message queue;
4. Set input focus events;
5. Synchronize system Message Queuing events.
The return value of the hook determines whether the system agrees or prevents one of these operations.
3, Wh_debug Hook
The system calls the Wh_debug hook before the hook thread that is associated with the other hooks in the system call system. You can use this hook to decide whether or not to agree to the system calling the hooks associated with other hooks.
4, Wh_foregroundidle Hook
When the foreground thread of an application is in the spare state, a low-priority task can be run with wh_foregroundidle hooks. When the foreground thread of the application is about to become spare state, the system calls the Wh_foregroundidle hook thread.
5, Wh_getmessage Hook
The application uses wh_getmessage hooks to monitor the messages returned from the GETMESSAGE or PeekMessage function. You can use the Wh_getmessage hook to monitor mouse and keyboard input, as well as other messages sent to the message queue.
6, Wh_journalplayback Hook
Wh_journalplayback hooks enable applications to insert messages into the system message queue. The ability to use this hook to replay successive mouse and keyboard events recorded by using the Wh_journalrecord hook. Only the Wh_journalplayback hook has been installed, the normal mouse and keyboard events are invalid. The Wh_journalplayback Hook is a global hook that cannot be used as a thread-specific hook. Wh_journalplayback Hook returns the timeout value, which tells the system how long (in milliseconds) to wait before processing the current message from the playback hook. This enables the hook to control the playback of real-time events. Wh_journalplayback are system-wide local hooks and they will not be injected into any of the travel address spaces.
7, Wh_journalrecord Hook
Wh_journalrecord hooks are used to monitor and record input events. Typically, you can use this hook to record continuous mouse and keyboard events, and then back and forth by using the Wh_journalplayback hook. The Wh_journalrecord Hook is a global hook that cannot be used as a thread-specific hook. Wh_journalrecord are system-wide local hooks and they will not be injected into any of the travel address spaces.
8, Wh_keyboard Hook
In the application, Wh_keyboard hooks are used to monitor wm_keydown and WM_KEYUP messages, which are returned by GetMessage or PeekMessage function. The ability to use this hook to monitor keyboard messages entered into the message queue.
9, Wh_keyboard_ll Hook
The Wh_keyboard_ll hook monitors the keyboard messages entered into the thread message queue.
10, Wh_mouse Hook
Wh_mouse Hooks monitor Mouse messages returned from the GetMessage or PeekMessage functions. Use this hook to monitor mouse messages entered into the message queue.
11, Wh_mouse_ll Hook
WH_MOUSE_LL Hooks monitor Mouse messages that are entered into the thread message queue.
12, Wh_msgfilter and Wh_sysmsgfilter Hooks
Wh_msgfilter and Wh_sysmsgfilter hooks enable us to monitor menus, scroll bars, message boxes, dialog box messages and find that users use ALT + TAB or ALT+ESC key combinations to switch forms. Wh_msgfilter hooks can only monitor messages that are passed to menus, scroll bars, message boxes, and messages that are passed to a dialog box created by an application that has a hook thread installed. Wh_sysmsgfilter Hooks monitor all application messages.
Wh_msgfilter and Wh_sysmsgfilter hooks enable us to filter messages during the pattern cycle, which is equivalent to filtering messages in the main message loop.
The Wh_msgfilter Hook can be called directly by calling Callmsgfilter function. By using this function, the application can use the same code to filter the message during the pattern loop, as in the main message loop.
13, Wh_shell Hook
The shell application can use the Wh_shell hook to receive important notifications. When the shell application is active and the When top layer form is established or destroyed, the system calls the Wh_shell hook thread.
Wh_shell has 5 in common:
1. Only a top-level, unowned form is created, acted on, or destroyed;
2. When taskbar need to redraw a button;
3. When the system needs to display a minimal form of a program about taskbar;
4. When the current keyboard layout state changes;
5. When the user presses CTRL+ESC to run task Manager (or the same level of program).
As a rule, shell applications do not receive Wh_shell messages. Therefore, before an application can receive Wh_shell messages, the application must call the SystemParametersInfo function to register itself.
Rivershan original on September 18, 2002
My Hook study notes