A Simple keyboard hook ProgramMonitors the keyboard in a timely manner, and stores the key information in the TXT file. The Windows system is based on the event-driven mechanism. To put it bluntly, the entire system is implemented through message transmission. Hooks are very important system interfaces in Windows systems. They can be used to intercept and process messages sent to other applications to implement functions that are hard to implement in common applications. There are many types of hooks. Each Hook can intercept and process corresponding messages. For example, a keyboard Hook can intercept keyboard messages, and a shell Hook can intercept, start, and close application messages. In this article, a simple keyboard hook program is implemented in the vc6 programming environment, the running mechanism of Win32 global hooks, the characteristics of Win32 DLL, the mfc dll in vc6 environment, and sharing data are briefly described. 1. Win32 global hook Operation Mechanism A hook is actually a program segment for message processing. It is called by the system and mounted to the system. When a specific message is sent, the hook program captures the message before it reaches the target window, that is, the hook function gets control of the message first. In this case, the hook function can process (Change) the message, continue to transmit the message without processing it, and forcibly end the message transmission. For each type of Hook, the system maintains a hook chain. The recently installed hook is placed at the beginning of the chain, and the first installed hook is put at the end, that is, the first added hook gets control. To implement a Win32 system hook, you must call the SDK's API function setwindowshookex to install the hook function. The prototype of this function is Hhook setwindowshookex (INT idhook, hookproc lpfn, hinstance hmod, DWORD dwthreadid ); The first parameter is the hook type, the second parameter is the hook function address, the third parameter is the module handle containing the hook function, and the fourth parameter specifies the monitored thread. If a specific thread is specified, it is a dedicated hook. If it is specified as null, it is a global hook. Among them, the global hook function must be included in the DLL (Dynamic Link Library), and the thread-specific Hook can also be included in the executable file. After the hook function obtains control, if you want to continue transmitting the message after processing the message, it must call the API function callnexthookex in another SDK to transmit it. The hook function can also directly return true to discard the message and prevent the message from being transmitted. Ii. Win32 DLL features Win32 DLL differs greatly from Win16 DLL, which is mainly determined by the operating system design philosophy. On the one hand, in Win16 DLL, the program entry point function and exit point function (libmain and WEP) are implemented respectively, but in Win32 DLL, the same function is implemented by dllmain. This function is called whenever a process or thread loads and detaches a DLL. Its prototype is Bool winapi dllmain (hinstance hinstdll, DWORD fdwreason, lpvoid lpvreserved ); The first parameter indicates the DLL instance handle, and the third parameter is retained. Here we mainly introduce the second parameter, which has four possible values: dll_process_attach (process loading ), dll_thread_attach (thread loading), dll_thread_detach (thread detaching), and dll_process_detach (process detaching). In the dllmain function, you can identify the value of this parameter passed in, perform necessary initialization or cleanup for the DLL based on different parameter values. For example, when a process loads a DLL, the second parameter assigned to the DLL by the system is dll_process_attach. In this case, you can initialize specific data based on this parameter. In Win16, all applications are in the same address space. In Win32, all applications have their own private space, the space of each process is independent of each other, which reduces the interaction between applications, but also increases the programming difficulty. As you know, in the Win16 environment, the global data of DLL is the same for every process that loads it. In the Win32 environment, the situation has changed, when a process loads a DLL, the system automatically maps the DLL address to the private space of the process and copies the global data of the DLL to the process space, that is to say, the global data values of the same DLL owned by each process are not necessarily the same. Therefore, to share data among multiple processes in a Win32 environment, you must make necessary settings. That is, the data to be shared is separated and placed in an independent data segment, and the attribute of this segment is set to share. Iii. Classification and features of mfc dll in vc6 There are three forms of mfc dll in vc6 (which can be used and inherit from existing MFC classes in this DLL) to choose from, that is, regular statically linked to mfc dll (Standard 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 type of DLL is that the MFC code used is added to the DLL during compilation. Therefore, when using this program, no other MFC dynamic link library is required, however, the occupied disk space is relatively large. The second DLL is characterized by dynamic link to the MFC class library during runtime, which reduces the occupied space, however, the runtime depends on the Dynamic Link class library of MFC. These two DLL types can be used by both the MFC program and Win32 program. The third type of DLL is similar to the second type. As an extension of the MFC class library, it can only be used by the MFC program. 4. Global data sharing in vc6 In the main file, use # pragma data_seg to create a new data segment and define shared data. The specific format is: # Pragma data_seg ("shareddata ") Hwnd sharedwnd = NULL; // share data # Pragma data_seg () Defining only one data segment can not achieve the purpose of sharing data, but also tell the compiler the attributes of this segment, there are two ways to achieve this (the effect is the same ), one way is in. add the following statement to the def file: Setctions Shareddata read write shared Another method is to add the following statement to the project setting link option: /Section: shareddata, RWS 5. Specific implementation steps Because the global hook function must be included in the dynamic link library, this example is implemented by two program bodies. 1. Create hook keyboardhook. dll (1) Select MFC Appwizard (DLL) to create the project mousehook; (2) Select the MFC extension DLL (shared MFC copy) type; (3) because vc6 does not have a ready-made hook class, you must create a keyboardhook. h file in the project directory and create a hook class in it: Class afx_ext_class ckeyboardhook: Public cobject { Public: Ckeyboardhook (); // constructor of the hook class Virtual ~ Ckeyboardhook (); // destructor of the hook class Public: Bool starthook (); // install the hook function Bool stophook (); // uninstall the hook function }; (4) Add the # include "keyboardhook. H" statement at the top of the keyboardhook. cpp file; (5) Add the global shared data variable to the top of the keyboardhook. cpp file: # Pragma data_seg ("mydata ") Hhook glhhook = NULL; // installed mouse hook handle Hinstance glhinstance = NULL; // DLL instance handle # Pragma data_seg () (6) define the segment attribute in the def file: Sections Mydata read write shared (7) Add the statement for saving the DLL instance handle to the dllmain function of keyboardhook. cpp in the main file: Glhinstance = hinstance; // insert and save the DLL instance handle (8) Implementation of the keyboard hook function: // Keyboard Hook Function Lresult callback keyboardproc (INT ncode, wparam, lparam) { Char CH = 0; File * FL; If (DWORD) lparam & 0x40000000) & (hc_action = ncode) // Press { If (wparam = vk_space) | (wparam = vk_return) | (wparam> = 0x2f) & (wparam <= 0x100 )) { FL = fopen ("key.txt", "A +"); // output to the key.txt File If (wparam = vk_return) { Ch = '/N '; } Else { Byte KS [256]; Getkeyboardstate (KS ); Word W; Uint scan = 0; Toascii (wparam, scan, KS, & W, 0 ); // CH = mapvirtualkey (wparam, 2); // convert the virtual key code into a character Ch = char (w ); } Fwrite (& Ch, sizeof (char), 1, FL ); } Fclose (FL ); } Return callnexthookex (glhhook, ncode, wparam, lparam ); } (9) Implementation of member functions of ckeyboardhook: Ckeyboardhook: ckeyboardhook () { } Ckeyboardhook ::~ Ckeyboardhook () { If (glhhook) Unhookwindowshookex (glhhook ); } // Install the hook and set the handle for receiving the display window Bool ckeyboardhook: starthook () { Bool bresult = false; Glhhook = setwindowshookex (wh_keyboard, keyboardproc, glhinstance, 0 ); /* ===================================================== ====================================== Hhook setwindowshookex (INT idhook, hookproc lpfn, instance hmod, DWORD dwthreadid) The idhook parameter indicates the hook type, which corresponds to the hook function type one by one. For example, wh_keyboard indicates that the keyboard hook is installed, and wh_mouse indicates that the mouse hook is installed. Lpfn is the address of the hook function. Hmod is the handle of the instance where the hook function is located. This parameter is null for thread hooks. For system hooks, This parameter is the DLL handle of the hook function. Dwthreadid specifies the thread number monitored by the hook. For global hooks, this parameter is null. Setwindowshookex returns the mounted hook handle. It is worth noting that the location of the hook function varies greatly between the thread hook and the system hook. Thread hooks are generally within the current thread or the thread derived from the current thread, However, system hooks must be placed in an independent dynamic link library, which may be difficult to implement. ========================================================== ================================= */ If (glhhook! = NULL) Bresult = true; Return bresult; } // Uninstall the hook Bool ckeyboardhook: stophook () { Bool bresult = false; If (glhhook) { Bresult = unhookwindowshookex (glhhook ); If (bresult) Glhhook = NULL; } Return bresult; } (10) compile the project to generate keyboardhook. dll. 2. Create a hook executable program (1) Use the Appwizard (exe) of MFC to create the project keyhook; (2) Select "Application Based on dialog" and press "finish; (3) Add the include statement # include "keyboardhook. H" to keyhookdlg. h "; (4) Add a private data member in keyhookdlg. h: Ckeyboardhook m_hook; // Add the hook class as a data member (5) link the dll library to add ../keyboardhook. lib to the project setting link tag; (6) change the OK button ID to id_hook and write the implementation code: Void ckeyhookdlg: onhook () { M_hook.starthook (); } (7) Close button implementation: Void ckeyhookdlg: oncancel () { M_hook.stophook (); Cdialog: oncancel (); } (8) compile the project to generate executable files; Run the generated keyhook.exe program and press hook! Click the button next to the hook and click a button on the keyboard to find that a key.txt file is automatically generated under the exedirectory, which records your key information. |