Use hooks to intercept messages in Windows

Source: Internet
Author: User

I. Preface

As we all know, running Windows programs is driven by events. In other words, the program keeps waiting for a message to occur, then judges the message type, and then processes it properly. After processing the message, it returns to the waiting status. From the analysis of Windows program running mechanism, it is not difficult to find that messages play an intermediate "language" role in communication between users and programs. The main character of receiving and processing messages in a program is the window, which receives messages through the message pump, and then processes the messages through a window process.

Message interception is implemented by intercepting a message before the window process processes the message and then sending it to the original window after relevant processing. Generally, programmers can process received messages in the window process, which requires that the window process must be completed during program development, however, in some applications, messages in other applications or other unit modules are often required to be obtained and processed. The technology for implementing such functions is also the topic to be discussed in this article-message interception technology.

2. Understand WINDOWS Message Mechanism

Before going into the implementation principles of message interception technology, let's take a look at the principles of Windows message mechanism.

1. Message generation

As a "language" for the program to communicate with the outside world, the message is generated naturally from the outside world. However, the outside world is not simply outside the program or outside the software system, it refers to modules other than message processing modules, Windows systems, other applications, and hardware. Generally, messages are divided into two categories: hardware messages and software messages. A hardware message is usually an event (such as a mouse or a keyboard being pressed) generated by a hardware device and placed in a system message queue, then, the system message processing organization sends messages to the application message queue. A software Message is usually sent by a Windows system or other applications. It is directly put into an application Message Queue (application ).
And then the application message processing organization sends the message to the corresponding window.

2. Message Composition

A Message consists of a message name (uint) and two parameters (wparam, lparam ). When the user enters the window or the window status changes, the system will send a message to a window. For example, after the menu is converted, A wm_command message is sent. hiword (wparam) in the wparam is the command ID, and the menu is the menu ID. Of course, you can also define your own message name, or use custom messages to send notifications and send data.

3. Message Receiver

A message must be received in a window. In the window process (wndproc), you can analyze messages and process the messages that the application requires to process, for messages that do not need to be processed by the application, the default processing can be called. For example, if you want to process the menu selection, you can define the code to process wm_command. If you want to output graphics in the window, you must process wm_paint.

4. Message Processing

After the window receives the message sent to itself, it processes the message as a parameter call window. You can regard the Window Process as a collection of Message Processing code. The prototype of the window process function is:

Long Far Pascal wndproc (hwnd, word message, word wparam, long lparam );
Hwnd is the window handle, message is the message name, wparam, and lparam are two parameters.

In Windows, the application does not directly call any window function, but waits for Windows to call the window function and request to complete the task or return information. To ensure that Windows calls this window function, this function must first register with windows and then callback when performing corresponding operations in windows. Therefore, window function is also called a callback function. Wndproc is a primary callback function. Windows has at least one callback function. It registers with windows when the application registers window classes.

3. Use hooks to intercept messages

1. What is a hook )?

The hook mechanism allows applications to intercept and process window messages or specific events. It is similar to the DOS interrupt interception processing mechanism. A hook is a platform for Windows message processing. Applications can set sub-processes on the top to monitor a message in a specified window, And the monitored window can be created by other processes. When a message arrives, the hook can process it before the target window processing function and prevent message transmission. Each Hook has an associated pointer list, which is called a hook linked list. The pointer in the linked list points to each processing child of the hook. There are many types of hooks. Each Hook can intercept and process messages of the corresponding type. When a message monitored by a hook appears, Windows calls the first hook sub-program in the linked list. After the first process is completed, the next hook sub-program in the linked list is transmitted, until all hook sub-processes in the linked list are completed (Note: if one of the hooks does not execute message transmission before execution is completed, the subsequent hook process and the original window process will not receive messages .) And then return the message to the window.

2. Hook sub-functions

A hook is a callback function defined by an application. It is used to monitor the system or a specific type of events. These events can be associated with a specific thread or all threads in the system. Its function prototype is:

Lresult callback hookproc (INT ncode, wparam, lparam );

The ncode parameter is the hook code, which is used by the hook child to determine the task. The value of this parameter depends on the hook type. Each Hook has its own hook code feature character set. Windows provides multiple types of hooks, each of which enables applications to monitor different types of system message processing mechanisms.

The values of wparam and lparam parameters depend on the hook code, but their typical values contain information about sending or receiving messages.

3. hook installation and uninstallation

The hook is installed through sdk api setwindowshookex (), which installs the hook program in the system hook list. Its function prototype
Hhook setwindowshookex (INT idhook, hookproc lpfn, hinstance hmod, DWORD dwthreadid );
Idhook refers to the hook type. Table 1 lists the types and descriptions of some hooks.

Type
Description

Wh_callwndproc
The system calls this sub-process before the message is sent to the receiving window.

Wh_callwndprocret hooks
This sub-process is called after the message is processed in the window Process

Wh_getmessage
Monitor messages returned from the getmessage/peekmessage Function

Wh_keyboard
Monitor keyboard messages entered into the Message Queue

Wh_mouse
Monitor mouse messages entered in the Message Queue

Due to space limitations, other message types are not listed one by one. For more information, see msdn.

Lpfn refers to the address pointer of the hook Child Program. If the dwthreadid parameter is 0 or is identified by a thread created by another process, lpfn must point to the hook Child Program in the DLL. In addition, lpfn can point to a hook sub-program code of the current process.

Hmod refers to the handle of the application instance. Identifies the DLL that contains the Child Program referred to by lpfn. If dwthreadid identifies a thread created by the current process and the Child Code is in the current process, hmod must be null.

Dwthreadid refers to the identifier of the Thread associated with the installed hook sup. If it is 0, the hook sup is associated with all threads.

If the function succeeds, the hook handle is returned. If the function fails, null is returned.

After the hook is used, unhookwindowshookex () must be used to uninstall the hook. Otherwise, it may cause trouble. Unhookwindowshookex () has only one parameter. The function prototype is as follows:

Unhookwindowshookex (hhook HHK)

Among them, the HHK parameter is the hook handle returned by the setwindowshookex () function. Therefore, you must save this handle when designing the program for use during uninstallation. If the function is successful, true is returned. Otherwise, false is returned.

4. System hooks and thread hooks

In Windows, hooks are classified into system hooks (Global hooks) and thread hooks (local hooks) based on the range of hook monitoring events. The last parameter of the setwindowshookex () function determines whether the hook is a system hook or a thread hook. The thread hook is used to monitor the event messages of a specified thread. The thread hooks are generally within the current thread or the thread derived from the current thread. The system hooks the event messages of all threads in the system. Because the system hooks will affect all applications in the system, the hooks must be placed in an independent dynamic link library (DLL. The system automatically maps the DLL containing the "hook callback function" to the address space of all processes affected by the hook function, which injects the DLL into those processes.

5. Implementation of hooks

This document intercepts the wm_char message function of the program (notepad.exe. If you want to implement other functions, you can directly add code to the hook sub-function.

(1) Select MFC Appwizard (DLL) to create the project notepadhook and select the MFC extension DLL (shared MFC copy) type.

(2) create a notepadhook. h file and create a hook class in it:

Class afx_ext_class cnotepadhook: Public cobject

{

Public:

Cnotepadhook (); // constructor of the hook class

~ Cnotepadhook (); // hook class destructor

Bool starthook (hwnd); // install the hook function

Bool stophook (); uninstall Hook Function

};

(3) add # include "notepadhook. H" to notepadhook. cpp ".

(4) Add the shared data segment to notepadhook. cpp:

# Pragma data_seg ("external data") // share data segments. Variables in these segments can be shared by all hook instances.

Hhook glhhook = NULL; // hook handle.

Hinstance glhinstance = NULL; // DLL instance handle.

# Pragma data_seg ()

(5) define only one data segment to share data, and notify the compiler of its attributes. To set the segment attribute in the. Def file, open the. Def file and add the following code:

Setctions

Sharedata read write shared

(6) Add the DLL instance handle to the dllmain function of notepadhook. cpp in the main file:

Dllmain (hinstance, DWORD dwreason, lpvoid lpreserved)

{

// If the lpreserved parameter is used, delete the following line.

Unreferenced_parameter (lpreserved );

If (dwreason = dll_process_attach)

{

Trace0 ("notepadhook. dll initializing! \ N ");

// The extension DLL is initialized only once.

If (! Afxinitextensionmodule (notepadhookdll, hinstance ))

Return 0;

New cdynlinklibrary (notepadhookdll );

// Add the DLL to the dynamic MFC class library

Glhinstance = hinstance;

// Insert and save the DLL instance handle

}

Else if (dwreason = dll_process_detach)

{

Trace0 ("notepadhook. dll terminating! \ N ");

// Call this library before terminating it

Afxtermextensionmodule (notepadhookdll );

}

Return 1;

}

(7) Implementation of the member functions of the class cnotepadhook:

Cnotepadhook: cnotepadhook (){}

Cnotepadhook ::~ Cnotepadhook () {stophook ();}

Bool cnotepadhook: starthook (hwnd) // install the hook.

{

Bool bresult = false;

Glhhook = setwindowshookex (wh_callwndproc, notepadproc, glhinstance, 0 );

If (glhhook! = NULL) bresult = true;

Return bresult;

}

Cnotepadhook: stophook ()

{

Bool bresult = false;

If (glhhook ){

Bresult = unhookwindowshookex (glhhook );

If (bresult) glhhook = NULL;

Return bresult;

}

(8) Implementation of hook sub-processes:

Lresult winapi notepadproc (INT ncode, wparam, lparam)

{

Pcwpstruct PCs = NULL;

PCS = (pcwpstruct) lparam;

If (PCs & PCs-> hwnd! = NULL)

{

Tchar szclass [256];

Getclassname (PCs-> hwnd, szclass, 255); // obtain the name of the blocked window class.

If (strcmp (szclass, "Notepad") = 0)

{

If (PCs-> message = wm_char)

{

Afxmessagebox ("hook notepad wm_char OK !!! ");

}

}

}

Return callnexthookex (glhhook, ncode, wparam, lparam); // continue to transmit messages.

}

(9) compile the project to generate notepadhook. dll.

Although the hook class has been completed, the hook function cannot be implemented yet. We must write a program to start the hook, inject the hook DLL into the memory space of other programs, and add the hook to the system hook linked list. Due to the limited length, this article will not detail the examples of hook-started programs, but the precautions for writing startup programs are described as follows:

(1) Add debug \ notepadhook. Lib in the notepadhook project to the project setting link tag.

(2) include the notepadhook. h file in the notepadhook project to stdafx. h.

(3) create a cnotepadhook class instance, call the class member starthook () when starting the hook, and call the class member stophook () When uninstalling the hook ().

4. intercept messages using window subclass (subclass)

As mentioned above, each window has a window process defined in its window class. This window process processes each message sent to the window. If you want to write the Window Process by yourself, it is no problem to modify its behavior. However, if the window process belongs to someone else, no source code will be modified. For example, every button in an application is created by the button window provided by the system, and it has its own window process. If you want to change the appearance of the window, you cannot change its wm_paint processing function because it is not necessary. So how can we change the appearance of these buttons without re-writing the original controls? You only need to replace the address of the initial window process of the window object with the address of your window process. This technology is also the topic discussed in this section.
-Window subclass technology.

1. Principle of window subclass

Before creating a new window, an application must register the window class with the Windows system. First, enter a wndclass structure. The structure parameter lpfnwndproc is the address of the window function, then, call the registerclass () function to apply to the Windows system for registering this window class. In this case, Windows allocates a piece of memory for it to store all the information about the class. This memory block is called a window memory block.

The window subclass technology actually changes the parameters in the window memory block. This modification only involves the window memory block of a window, so it does not affect the functions and performance of other windows belonging to the same window class. The most common thing in window subclass is to modify the window function address (lpfnwndproc) in the window memory block so that it points to a new window function, thus changing the processing method of the original window function, to modify the window.

2. Implementation of window subclass

The core of window subclass implementation is to change the address of the window process, which can be achieved through several functions provided by the sdk api. The procedure is as follows:

A. Compile a subclass window process function. This function must be in the standard window procedure Function Format:

Lresult callback subclasswndproc (hwnd, uint, wparam, lparam );

The parameter meanings of this function are similar to the window procedure function parameters described above.

B. Call the getwindowlong (hwnd, gwl_wndproc) function to obtain and save the address of the original window function. The hwnd parameter is the window handle to be subclass.

C. Call setwindowlong (hwnd, gwl_wndproc, subclasswndproc) to set the window function to subclass the window function.

To reduce the tedious work in the subclass process, MFC provides support for subclass. It simplifies the subclass process and uses the cwnd subclasswindows () function to implement subclass. To give readers an intuitive understanding of the subclass process, we will use MFC to subclass an edit control.

(1) create a new control class csubedit derived from the MFC control class cedit.

(2) Add csubedit: pretranslatemessage (MSG * PMSG)

Bool csubedit: pretranslatemessage (MSG * PMSG)

{

If (PMSG-> message = wm_keydown & PMSG-> wparam = vk_return)

{

// When you press the Enter key on the Edit Control...

.....

// The processing content is limited to space.

Return true;

}

Cedit: pretranslatemessage (PMSG );

}

(3) change the control variable type from cedit to csubedit in the dialog box Class header file that contains the control.

(4) subclass the Edit Control in the dialog box class file that contains the control. The Code is as follows:

Hwnd;

Getdlgitem (idc_sub_edit, & hwnd); // Where idc_sub_edit is the Control ID.

M_subedit.subclasswindow (hwnd); // m_subedit is the control variable name.

V. Summary

This article discusses two methods to intercept messages. The hook technique is widely used. It not only intercepts messages in the same process, but also intercepts messages in other processes. Subclass technology is mainly used to intercept window messages in the same process unit module. Programmers can choose one of them based on their actual application needs to block messages.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.