The Windows system is built on the event-driven mechanism, saying that the entire system is implemented through the transfer of messages. The hook is a very important system interface in the Windows system, which can intercept and process messages that are given to other applications to complete the functionality of common applications. The hook can monitor the various event messages in the system or process, intercept messages to the target window and proceed. In this way, we can install custom hooks in the system, monitor the occurrence of specific events in the system, complete specific features, such as intercepting keyboard, mouse input, screen tether, log monitoring, etc. It can be seen that many special and useful features can be achieved by hooks. Therefore, it is necessary for advanced programmers to master the programming method of the hook.
Type of hooks. By event classification, there are several common types (1) Keyboard hooks and low-level keyboard hooks to monitor various keyboard messages. (2) Mouse hooks and low-level mouse hooks can monitor various mouse messages. (3) The hook hook can monitor various shell event messages. Such as startup and closing the app. (4) The log hook can record the various event messages removed from the system message queue. (5) Window Process Hook Monitor All messages from the system message queue to the target window. In addition, there are some of the hooks of some particular events to us, and they are not listed in one by one. The common HOOK types are described below: 1. WH_CallWndProc and WH_CallWndProcret Hooks WH_CallWndProcret Hooks WH_CallWndProcret and WH_CallWndProcret Hooks allow you to monitor messages sent to the window process. The system calls the WH_CallWndProc Hook subsess before the message is sent to the receiving window, and then call the WH_CallWndPro Cret Hook subsess after the window process is handled. The Wh_CallWndProcret Hook passes the pointer to the CWPRETSTRUCT structure, and then passes to the hook subsequence. The CWPRETSTRUCT structure contains the return value from the window process from the processing message, and also includes message parameters associated with this message. 2, WH_CBT Hook Before the following events, the system calls the WH_CBT Hook subsidiary, including: 1. Activation, establish, destroy, minimize, maximize, move, change the size, etc. 10, complete system instructions; . Mobile mouse, keyboard events in the system message queue; 4. Set input focus events; 5. Synchronize system message queue events. The return value of the Hook subsidiary determines whether the system allows or prevents one of these operations. 3, WH_Debug hook The system calls the WH_Debug hook subsessment before the HOOK subcrocesses associated with other hooks in the system call system. You can use this hook to determine if the system is allowed to call the Hook subtrace associated with other hooks. 4, WH_FOREGROUNDLE HOOK When the front desk thread is idle, you can use the wh_ForeGroundIdle Hook to perform a low priority task. When the front desk thread of the application is about to become an idle state, the system calls the Wh_ForegroundIdle Hook subtrace. 5, the Wh_getMessage hook application uses the WH_GetMessage Hook to monitor the message returned from the getMessage or PeekMessage function. You can use the WH_GetMessage Hook to monitor mouse and keyboard input, and other messages sent to the message queue. 6, WH_Journalplayback Hook WH_Journalplayback Hook enables the application to insert the message to the system message queue. You can use this hook playback through the continuous mouse and keyboard events recorded by using WH_Journalrord Hook. As long as the WH_JournalPlayback Hook has been installed, normal mouse and keyboard events are invalid. Wh_journalplayback Hook is a global HOOK, it cannot be used like thread specific HOOK. WH_JournalPlayback Hook Returns a timeout value, this value tells the system how long (milliseconds) will be taken before processing the current message from the playback hook. This makes hooks to control the playback of real-time events. WH_JournalPlayback is System-Wide Local Hooks that will not be injected to any stroke location space.
(Estimated button wizards are made with this Hook) 7, WH_JournalRecord Hook WH_JournalRecord hook is used to monitor and record input events. Typically, this Hook records continuous mouse and keyboard events, and then play back by using the Wh_Journalplayback Hook. Wh_JournalRecord Hook is a global hook, which cannot be used like thread specific HOOK. WH_JournalRecord is System-Wide Local Hooks that will not be injected to any stroke location space. 8, WH_KEYBOARD HOOK In the application, WH_KEYBOARD hook is used to monitor WM_KeyDown and WM_Keyup messages, which are returned via GetMessage or PeekMessage Function. You can use this hook to monitor the keyboard message input to the message queue. 9, WH_KEYBOARD_LL HOOK WH_KEYBOARD_LL Hook Monitor Enter the keyboard message in the thread message queue. 10, WH_MOUSE HOOK WH_MOUSE Hook Monitor the mouse message returned from the getMessage or PeekMessage function. Use this Hook monitor to enter mouse messages in the message queue. 11, WH_MOUSE_LL HOOK WH_MOUSE_LL Hook Monitor Enter the mouse message in the thread message queue. 12, WH_MSGFILTER and WH_SYSMSGFILTER HOOKS WH_MSGFILTER and WH_SYSMSGFILTER hooks allow us to monitor menus, scroll bars, message boxes, dialog messages and find users to switch windows using Alt Tab or Alt ESC combination keys. The WH_MSGFilter Hook can only monitor messages that are passed to the menu, scroll bar, message box, and the message that is passed to the dialog established by an application that has an Hook subtertaine. WH_SYSMSGFILTER Hook Monitor all application messages. WH_MSGFILTER and WH_SYSMSGFILTER hooks allow us to filter messages during the mode cycle, which is equivalent to filtering messages in the main message loop. WH_MSGFILTER HOOK can be called directly by calling CallMSGFilter Function. By using this function, the application can use the same code to filter messages during the mode cycle, just like the main message cycle. 13. The Wh_Shell hook shell application can use the wh_shell hook to receive important notifications. When the shell application is activated and when the top window is established or destroyed, the system calls the WH_Shell Hook subsess. WH_SHELL has a total of 5 minutes: 1. As long as there is a top-level, the Unowned window is generated, it works, or is destroyed; 2. When Taskbar needs to redraw a button; 3. When the system needs to display a program about Taskbar Minimize form; 4. When the current keyboard layout state changes; 5. When the user presses Ctrl ESC to perform Task Manager (or the same level program). According to conventions, both the shell application does not receive the WH_SHELL message. Therefore, before the application is able to receive the Wh_Shell message, the application must call the SystemParametersInfo Function to register itself. The above is a 10 common HOOK type! Two. According to the range of use, mainly thread hooks and system hooks (1) Thread hooks monitor the event message of the specified thread. (2) System hook monitoring event messages in 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). This is the difference between system hooks and thread hooks. A number of places that need to be explained: (1) If you install both the thread hook and install the system hook for the same event, the system will automatically call the thread hook, then call the system hook. (2) Multiple hook processing can be installed on the same event message, which form a hook chain. The hook information should be passed to the next hook function after the current hook processing ends. Moreover, the recently installed hooks are placed in the beginning of the chain, and the earliest installed hooks are finally added, and the control is obtained first. (3) Hooks, especially system hooks, will consume message processing time and reduce system performance. The hook is installed only when necessary, and then uninstall it after use. The steps to write hook programs to write hook programs are divided into three steps: define hook functions, install hooks and unload hooks. 1. Defining hook function hook functions is a special callback function. After the specific event of hook monitors, the system will call the hook function. The form of hook functions of different events is different. The prototype of the hook function is illustrated below: LRESULT CALLBACK HOOKPROC (INT NCODE, WPARAM WPARAM, LPARAM LPARAM) Parameters WPARAM and LPARAM include information of the hook message, such as mouse position, status, keyboard buttons, etc. Ncode contains information about the message itself, such as whether it is removed from the message queue. Let's implement custom features in the hook function, then call the function callnexthookex. Pass the hook information to the next hook function of the hook chain. The prototype of CallNexthooKex is as follows: LResult CallNexthookex (HHOOK HHK, INT NCODE, WPARAM WPARAM, LPARAM LPARAM) Parameters HHK is a hook handle. NCODE, WPARAM, and LPARAM are hook functions. Of course, it can also be discarded by directly returning True, blocking the passage of the message. 2. Installing the hook When the program is initialized, call the function setWindowshookex Install the hook. Its function prototype is: HHOOK SETWINDOWSHOKEX (Int IDHOK, HOOKPROC LPFN, Instance HMOD, DWORD DWTHREADID) Parameter IDHOOK represents the hook type, which corresponds to the hook function type. For example, wh_keyboard indicates that the keyboard hook is installed, wh_mouse is represented by a mouse hook, and the like. LPFN is the address of the hook function. HMOD is the handle of the instance of the hook function. For thread hooks, this parameter is null; for the system hook, this parameter is the DLL handle where the hook function is located. DWTHREADID Specifies the thread number of the thread monitored by the hook. For global hooks, this parameter is NULL. Setwindowshookex returns the installed hook handle. 3. Uninstalling hooks When the hook is no longer used, you must uninstall it in time. Simply call function BOOL UnHookWindowsHookex (HHOOK HHK). It is worth noting that the location of the hook function of the thread hook and the system hook has a big difference. Thread hooks are generally within the thread of current threads or current threads, and the system hook must be placed in a separate dynamic link library, and it is troublesome.
Programming Example of Thread Hook: A thread-level mouse hook is implemented in accordance with the method described above. The hook tracks the location change information of the current window mouse. And output to the window. (1) Generate a single document that uses MFC AppWizard (EXE) in VC 6.0 to apply Mousehook. Open the childview.cpp file, join the global variable: hHOOK hHOOK; // mouse hook handle cpoint point; // mouse location information cchildview * pView; // mouse hook function Used output window pointer in cchildview :: onpaint () Add below Code: CPAINTDC DC (this); Char Str [256]; Sprintf (STR, "X =% D, Y =% D", Point.x, Point.y); // Constructs string Dc.Textout (0, 0, STR); // Display string
(2) Define global mouse hook functions in childview.cpp files. LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam) {// mouse movement message if (wParam == WM_MOUSEMOVE || wParam == WM_NCMOUSEMOVE) {point = ((MOUSEHOOKSTRUCT *) lParam) -> pt; // get Mouse Information PView-> Invalide (); // Window Heavy Pictures Return CallNexthookex (HHOOK, NCODE, WPARAM, LPARAM); // Transfer hook information} (3) The cchildView class is installed in the constructor. Cchildview :: cchildview () {pView = this; // Get the output window pointer hHOOK = setWindowshookex (wh_mouse, mouseproc, 0, getCurrentThreadID ());} (4) Uninstall the hook in the destructor of the CchildView class. Cchildview :: ~ cchildview () {if (hhook) unhatlightwindowshookex (hHOOK);
System hook programming example: Since the system hook is used to use the DLL, first introduce the feature of Win32 DLL: Win32 DLL has a great difference from Win16 DLL, which is mainly determined by the design idea of the operating system. On the one hand, in the Win16 DLL in the process entry point function and the exit point function (libmain and WEP) are respectively implemented; in the Win32 DLL, it is implemented by the same function Dllmain. Whenever, when a process or thread loads and unresses the DLL, the function is called, and its prototype is Bool WinApi Dllmain (Hinstance Hinstdll, DWord FDWREASON, LPVOID LPVRESERVED); wherein the first parameter represents the DLL Example handle; the third parameter system is reserved; here mainly introduces the second parameters, it has four possible values: DLL_PROCESS_ATTACH (process load), DLL_THREAD_ATTACH (thread), DLL_THREAD_DETACH (thread uninstall), DLL_Process_Detach (process) Uninstall), in the DLLMAIN function, the value of the passing parameter can be discriminated, and the DLL is necessary to initialize or clean up according to different parameter values. For example, when a process is loaded into a DLL, the system assists the second parameter of the DLL is DLL_Process_attach, where you can initialize specific data based on this parameter. On the other hand, in the Win16 environment, all applications are in the same address space; and in the Win32 environment, all applications have their own private space, each process is independent, which reduces the application. Mutual influence, but also increased programming. Everyone knows that in the Win16 environment, the global data of the DLL is the same for each process loaded; in the Win32 environment, the situation has changed, and when the process is loaded, the system automatically The DLL address is mapped to the private space of the process, and a copy of the global data of the DLL is also copied to the process space, that is, the same DLL's global data owned by each process is not necessarily the same. of. Therefore, in the Win32 environment, you must share the data in multiple processes, you must make the necessary settings. That is, the data that needs to be shared is separated, placed in a separate data segment, and set the properties of the segment to sharing. There are three forms of MFC DLL in VC6 (available and inherited in this DLL) Alternative, ie Regular StaticLinked TO MFC DLL (Static Link MFC DLL) and Regular Using The Shared MFC DLL ( Standard Dynamic Link MFC DLL) and Extension MFC DLL (Extended MFC DLL). The first DLL is characterized by adding the MFC code used when compiling to the DLL, so there is no need to exist in other MFC dynamic link class libraries when using the program, but the space for the occupied disk is relatively large; second DLL The feature is that when running, dynamically link to the MFC class library, thereby reducing the occupation of space, but relies on the MFC dynamic link class library at runtime; these two DLLs can be used only by the MFC program or by Win32 program use.
The third DLL is similar to the second, as an extension of the MFC class library, can only be used by the MFC program. The implementation of the global shared data in VC6 is in the main file, with #pragma data_seg to create a new data segment and define shared data, the specific format is: #pragma data_seg ("shareddata) hWnd sharedwnd = null; / / Shared data #pragma data_seg () only defines a data segment that cannot reach the purpose of sharing data, but also tells the compiler that the properties of the segment can be implemented. There are two ways to achieve this (the effect is the same), one method Is the following statement in the .def file: Setctions SharedData Read Write Shared Another way to add the following statement in the project settings link option: / section: SharedData, RWS is good, ready knowledge has been completed, let us start writing a Global hook program! Since the global hook function must be included in the dynamic link library, this example is implemented by two programs.
1. Create a hook mousehook.dll (1) Select MFC AppWizard (DLL) Create a project mousehook; (2) Select the MFC Extension DLL type; (3) Because VC5 has no ready-made hook class, you have to create in the project directory. Mousehook.h file, built in it: Class AFX_EXT_CLASS CMOUSEHOOK: PUBLIC COBJECT {public: cmousehook (); // Hook class constructor ~ cmousehook (); // Hook class Destructure function Bool StartHook (hwnd hwnd) ; // Install the hook function bool stophook (); unload hook functions}; (4) Add to the #include "mousehook.h" statement at the top of the mousehook.app file; (5) Add global shared data variable: #pragma data_seg (" MyData ") HWND GLHPREVTARWND = NULL; // The window handle of the last mouse refers to HWND GLHDISPLAYWND = NULL; // Displays the HHOOK GLHHHOK = NULL; / / Installed Mouse Hook Hinstance Glhinstance = NULL; // DLL Example Handle #pragma data_seg () (6) Define segment attributes in the DEF file: Sections MyData Read Write Shared (7) Add Save DLL Equivation of Sector in the dllmain function of the main file mousehook.cpp: Dllmain (Hinstance hInstance, DWORD dwReason, LPVOID lpReserved) {// If the parameter lpReserved delete this line UNREFERENCED_PARAMETER (lpReserved); if (dwReason == DLL_PROCESS_ATTACH) {TRACE0 ( "MOUSEHOOK.DLL Initializing / n!"); // extension DLL Only initialization of IF (! AFXINITEXTENSIONMOD) ule (MousehookDLL, hInstance)) return 0; new CDynLinkLibrary (MousehookDLL); // Add the DLL dynamically MFC class libraries glhInstance = hInstance; // Insert a DLL instance handle} else if (dwReason == DLL_PROCESS_DETACH) {TRACE0 ( " Mousehook.dll Terminating! / N "); // Terminate this link library to call it AFXTERMEXTENSIONMODULE (mousehookdll);} Return 1;} (8) Specific implementation of member functions of class cmousehook: cmousehook :: cmousehook () // class Constructor {} cmousehook :: ~ cmousehook () // Category function {stophook ();} Bool cmousehook :: StartHOK (hwnd) // Install the hook and set the display window handle {bool Bresult = false; Glhhook =
SetWindowsHookEx (WH_MOUSE, MouseProc, glhInstance, 0); if (glhHook = NULL!) BResult = TRUE; glhDisplayWnd = hWnd; // set the title of the window displaying the edit box handle return bResult;} BOOL Cmousehook :: stophook () // unloading the hook {BOOL bResult = FALSE; if (glhHook) {bResult = UnhookWindowsHookEx (glhHook); if (bResult) {glhPrevTarWnd = NULL; glhDisplayWnd = NULL; // clear variable glhHook = NULL;}} return bResult;} (9) achieved hook function: LRESULT WINAPI MouseProc (int nCode, wPARAM wparam, lPARAM lparam) {LPMOUSEHOOKSTRUCT pMouseHook = (MOUSEHOOKSTRUCT FAR *) lparam; if (nCode> = 0) {HWND glhTargetWnd = pMouseHook-> hwnd; // get the target window handle HWND ParentWnd = glhTargetWnd; while (ParentWnd = NULL!) {glhTargetWnd = ParentWnd; ParentWnd = GetParent (glhTargetWnd); // get the main application window handle} if (glhTargetWnd = glhPrevTarWnd!) {char szCaption [100]; GetWindowText ( GLHTARGETWND, SZCAPTION, 100); // Take the target window title IF (iswindow (glhdisplaywnd) SendMessage (GLHDISPLAYWND, WM_SETTETTEXT, 0, (LPAram) (LPCTSTSTSTSTSTSTSTS); GLHP REVTARWND = GLHTARGETWND; / / Save Target Window}} Return CallNexthookex (Glhhook, Ncode, WPARAM, LPARAM); // Continue to pass message} (10) Compiling the project to generate mousehook.dll. 2. Creating a hook executor (1) Create a project mouse by an MFC's AppWizard (EXE); (2) Select "Dialog Application" and press "Finish" key; (3) Edit the dialog, delete two of them Button, add a static text box and edit box, right-click the static text box, select "Properties" in the pop-up menu, set its title "window title in the mouse";