Hooks
Hook pointed out the system message processing mechanism. With hook, you can install messaging between subroutine monitoring systems and processes in your application. This monitoring process is before the message reaches the window process. Next, Hook is briefly described, and explains how to use hook programming under Win32 system.
2. Bout Hooks Hook will reduce the program efficiency because they increase the total number of messages that the system must process. You should use it when you need it and remove it in time. I will describe the topic of the following topics.
Hook Chains systems support many different types of hooks; different HOOKs provide different message processing mechanisms. For example, the application can use WH_Mouse_hook to monitor the transfer of mouse messages. The system provides separate HOOK chains for different types of HOOK. The HOOK chain is a pointer list, which points to the specified, the application defined, the callback function called by the Hook process. When the message associated with the specified hook type occurs, the system passes this message to the HOOK process. Some hook processes can only monitor messages or modify messages, or to stop messages, avoiding these messages to the next hook process or destination window.
Hook Procedures (Hook Process)
In order to take advantage of special HOOK types, developers provide Hook processes, use the SetWindowsHooKex function to install the Hook process to the associated hook chain. The Hook process must follow the following grammar: LRESULT CALLBACK HOOKPROC (INT NCODE, WPARAM WPARAM, LPARAM LPARAM); HookProc is the name of the application definition. The ncode parameter is the hook code, the hook process uses this parameter 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 value of WPARAM and LPARAM parameters depends on the HOOK code, but their typical value is information about sending or receiving messages. The setWindowsHookex function is always installed at the beginning of the HOOK chain. When the hook monitored by the hook monitored by the specified type, the system is called the opening process of the opening associated with this hook. The Hook procedures in each hook chain decide whether this event is passed to the next HOOK process. The hook process pass event to the next hook process needs to call the CallNextHooKex function. Some types of Hook processes can only monitor messages, whether or not the CallNextHooKex function is called, the system passes the message to every hook process. Global Hook monitors all threads in the same table. The HOOK of a specific thread can only monitor a separate thread. The global hook process can be called by any application of the same desktop, just like calling threads, so this process must be separated from the DLL module. A specific thread hook process can only be called related threads. Only using the global hook only when there is a debug purpose, you should avoid use, the global HOOK harm system performance.
Hook Types
Each type of Hook allows applications to monitor different types of system messaging mechanisms. All of the hook types that can be utilized will be described below.
Wh_CallWndProc and wh_callwndprocret hooks
Wh_callwndproc and wh_callwndprocret hook allows you to monitor messages sent to the window process. The system calls the WH_CallWndProc hook process before the message is sent to the receiving window, and then call the WH_CallWndProcret Hook process after the window process is handled. The Wh_CallWndProcret Hook passes the pointer to the CWPRETSTRUCT structure and is passed to the HOOK process. The CWPRETSTRUCT structure contains the return value from the window process from the processing message, and also includes message parameters associated with this message. WH_CBT HOOK
Before the following events, the system calls the WH_CBT Hook process, including: activation, establishment, destruction, minimize window events such as, maximize, move, change sizes; complete system instructions; mobile mouse from the system message queue, keyboard Event; set input focus events; synchronous system message queue events. The return value of the HOOK process determines if the system allows or prevents one of these operations.
WH_Debug hook
The system will call the WH_Debug hook process before the HOOK process 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 procedure associated with other hooks.
Wh_ForegroundIdle Hook
When the foreground thread of the application is idle, you can perform a low priority task using the WH_ForeGroundIdle Hook. When the foreground thread of the application is about to become idle, the system calls the Wh_ForeGroundIdle Hook process.
WH_GetMessage Hook
The 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.
WH_Journalplayback Hook
The Wh_Journalplayback Hook enables the application to insert a 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_JournalRecord Hook
WH_JournalRecord hook is used to monitor and record an input event. 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_Keyboard Hook
In the application, the Wh_keyboard hook is used to monitor the WM_KEYDOWN AND WM_KEYUP message, which is returned by GetMessage or PeekMessage Function. You can use this hook to monitor the keyboard message input to the message queue.
Wh_keyboard_ll hook
WH_KEYBOARD_LL HOOK Monitor Enter the keyboard message in the thread message queue.
WH_Mouse Hook
WH_MOUSE Hook monitors the mouse message returned from the GetMessage or PeekMessage Function. Use this Hook monitor to enter mouse messages in the message queue. WH_MOUSE_LL HOOK
WH_MOUSE_LL HOOK Monitor Enter the mouse message in the thread message queue.
Wh_msgfilter and wh_sysmsgfilter hooks
WH_MSGFilter and wh_sysmsgfilter hooks allows us to monitor menu, scroll bars, message boxes, dialog messages, and find users to switch windows using the Alt Tab OR Alt ESC combination key. The WH_MSGFilter Hook can only monitor messages that are passed to the menu, scroll bar, message box, and the message passed to the dialog established by the application where the HOOK process is installed. WH_SYSMSGFILTER Hook Monitor all application messages. WH_MSGFilter and wh_sysmsgfilter hooks allows 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.
WH_SHELL HOOK
The 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 process. 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.
3.USING HOOKS
Installing and Releaseing Hook Procedures You can use the setWindowsHookex function to install the HOOK process and specify the hook type, specify whether you need to associate the Hook process with all threads, or associate the specified thread, and point to the HOOK process entry point. The global hook process must be placed in the DLL, and the HOOK process installed with the application is separated. Before the application is installed, it must have a handle to the DLL module. In order to get this handle, you can use the DLL name parameter when calling the LoadLibrary function. After getting this handle, you can call the getProcAddress function to get the pointer to the HOOK process. Finally, install the Hook Process Address Enter the application hook chain using the SetWindowsHookex function. This process can be illustrated by the following example:
HOOKPROC hkprcSysMsg; static HINSTANCE hinstDLL; static HHOOK hhookSysMsg; hinstDLL = LoadLibrary ((LPCTSTR) "c: //windows//sysmsg.dll"); file: // loading DLL hkprcSysMsg = (HOOKPROC) GetProcAddress (hinstDLL, "SysMessageProc" ); file: // get address hhookSysMsg = SetWindowsHookEx (WH_SYSMSGFILTER, hkprcSysMsg, hinstDLL, 0); file: // install hook when the application is no longer needed associated with a particular thread hook, call UnhookWindowsHookEx function removes the associated hook process. For global hook, you also need to call UNHOOKWINDOWSHOKEX functions, but this function cannot release the Hook process included in the DLL. This is because the global hook process is called by all application processes, which has caused all processes to call the LoadLibrary function. So you must call the FreeELibrary function to release the DLL. Monitoring System Events The following example uses different specific thread hook procedures to monitor system events. It demonstrates how to use the following hook procedure to process events: wh_callwndproc wh_CBT WH_DEBUG WH_GETMESSAGE WH_KEYBOARD WH_MOUSE WH_MSGFILTER users can install or remove hook processes by using menus. When the Hook process has been installed and the time of process monitoring occurs, the Hook process will write event information in the application main window customer area. The original code is as follows:
#define NUMHOOKS 7 // Global variables typedef struct _MYHOOKDATA {int nType; HOOKPROC hkprc; HHOOK hhook;} MYHOOKDATA; MYHOOKDATA myhookdata [NUMHOOKS]; LRESULT WINAPI MainWndProc (HWND hwndMain, UINT uMsg, WPARAM wParam, LPARAM lParam) {static BOOL afHooks [NUMHOOKS]; int index; static HMENU hmenu; switch (uMsg) {case WM_CREATE:.. // Save the menu handle hmenu = GetMenu (hwndMain); // Initialize structures with hook data The menu-item // identifiers are defined . as 0 through 6 in the // header file They can be used to identify array // elements both here and during the WM_COMMAND // message myhookdata [IDM_CALLWNDPROC] .nType = WH_CALLWNDPROC;. myhookdata [IDM_CALLWNDPROC] .hkprc = CallWndProc; myhookdata [IDM_CBT] .ntype = wh_cbt; myhookdata [IDM_CBT] .hkprc = CBTPROC; myhookdata [idm_debug] .ntype = WH_DEBUG; myhookdata [IDM_DEBUG] .hkprc = DebugProc; myhookdata [IDM_GETMESSAGE] .nType = WH_GETMESSAGE; myhookdata [IDM_GETMESSAGE] .hkprc = GetMsgProc; myhookdata [IDM_KEYBOARD] .nType = WH_KEYBOARD; myhookdata [IDM_KEYBOARD] .hkprc = KeyboardProc; myhookdata [ IDM_MOUSE] .nType = WH_MOUSE; myhookdata [IDM_MOUSE] .hkprc = MouseProc; myhookdata [IDM_MSGFILTER] .nType = WH_MSGFILTER; myhookdata [IDM_MSGFILTER] .hkprc = MessageProc;. // Initialize all flags in the array to FALSE memset (afHooks, FALSE Sizeof (Afhooks); Return 0;
case WM_COMMAND: switch (LOWORD (wParam)) {// The user selected a hook command from the menu case IDM_CALLWNDPROC:. case IDM_CBT: case IDM_DEBUG: case IDM_GETMESSAGE: case IDM_KEYBOARD: case IDM_MOUSE: case IDM_MSGFILTER: // Use the menu- item identifier as an index // into the array of structures with hook data index = LOWORD (wParam);. // If the selected type of hook procedure is not // installed yet, install it and check the // associated menu item IF (! Afhooks [index]) {myhookdata [index] .hook = setWindowshookex (myhookdata [index] .ntype, myhookdata [index] .hkprc, (Hi NSTANCE) NULL, GetCurrentThreadId ()); CheckMenuItem (hmenu, index, MF_BYCOMMAND | MF_CHECKED); afHooks [index] = TRUE;} // If the selected type of hook procedure is // already installed, remove it and remove the // Check Mark from The Associated Menu Item. Else {UNHOOKWINDOWSHOKEX (MyHOOKDATA [INDEX] .hook; CheckMenuItem (HMENU, INDEX, MF_BYCOMMAND | MF_UNCHECKED); afhook [index] = false;
} Default: return (DefWindowProc (hwndMain, uMsg, wParam, lParam));} break; // // Process other messages // default:. Return DefWindowProc (hwndMain, uMsg, wParam, lParam);} return NULL;} / *********************************************************** ************** WH_CALLWNDPROC HOOK Procedure ******************************************** ***************************************** / LRESULT WINAPI CallWndProc (int Ncode, WParam WParam, LParam lparam) {char szcwpbuf [256 ]; CHAR SZMSG [16]; HDC HDC; static int C = 0; int CCH; if (ncode <0) // do not process message returnch callnexthookex (MyHOOKDATA [CallWndProc] .hook, ncode, wparam, lparam; / / Call An Application-Defined Function That Converts A Message // Constant To A String and Copies It to A Buffer ((PMSG) LPARAM, SZMSG); HDC = GetDC (hwndmain); switch (ncode) {copy hc_action: cch = wsprintf (Szcwpbuf, "CallwndProc - TSK:% LD, MSG:% S,% D Times", WPARAM, SZMSG, C ); Textout (HDC, 2, 15 , SZCWPBUF, CCH; Break; Default: Break;} ReleaseDC (HWndMain, HDC); Return CallNexthookex (MyHOOKDATA [CallWndProc] .hook, ncode, wparam, lparam;} / ********** *********************************************************** *** WH_GETMESSAGE HOOK Procedure *********************************************************** ******************* / LRESULT CALLBACK GETMSGPROC (Int Ncode, WPARAM WPARAM, LPARAM LPARAM) {char Szmsgbuf [256];
Char Szrem [16]; CHAR SZMSG [16]; HDC HDC; Static Int C = 0; Int Cch; IF (Ncode <0) // Do Not Process Message Return CallnexThookex (MyHOOKDATA [GetMessage] .hook, ncode, wparam, lParam); switch (nCode) {case HC_ACTION: switch (wParam) {case PM_REMOVE: lstrcpy (szRem, "PM_REMOVE"); break; case PM_NOREMOVE: lstrcpy (szRem, "PM_NOREMOVE"); break; default: lstrcpy (szRem, "Unknown"); break;} // Call an application-defined function that converts a // message constant to a string and copies it to a // buffer LookUpTheMessage ((PMSG) lParam, szMsg);. hdc = GetDC (hwndMain ); Cch = wsprintf (Szmsgbuf, "GetMessage - WPARAM:% S, MSG:% S,% D Times", szRem, szMsg, c ); TextOut (hdc, 2, 35, szMSGBuf, cch); break; default: break;} ReleaseDC (hwndMain, hdc); return CallNextHookEx (myhookdata [GETMESSAGE] .hhook, nCode, wParam, lParam) } / ***************************************************** **************** WH_DEBUG HOOK Procedure ****************************************** ******************************************** / LRESULT CALLBACK DEBUGPROC (int Ncode, WPARAM WPARAM, LPARAM LPARAM) {char SZBUF [128]; HDC HDC; Static Int C = 0; INT CCH; IF (Ncode <
0) // do not process message return CallNextHookEx (myhookdata [DEBUG] .hhook, nCode, wParam, lParam); hdc = GetDC (hwndMain); switch (nCode) {case HC_ACTION: cch = wsprintf (szBuf, "DEBUG - nCode :% D, TSK:% LD,% D Times ", NCODE, WPARAM, C ); Textout (HDC, 2, 55, SZBUF, CCH); Break; Default: Break; RETURN CALLNEXTHOKEX (MyHOOKDATA [Debug] .hook, ncode, wparam, lparam);} / **************************************************** ***************************** Wh_CBT hook procedure ************************ ****************************************************************** / LRESULT Callback CBTPROC (INT NCODE, WPARAM WPARAM, LPAR SZBUF [128]; CHAR SZCODE [128]; HDC HDC; Static Int C = 0; int CCH; IF (Ncode <0) // do not process message return CallNexthookex (MyHOKDATA [CBT] .hook, Ncode, WPARAM, LPA ram); hdc = GetDC (hwndMain); switch (nCode) {case HCBT_ACTIVATE: lstrcpy (szCode, "HCBT_ACTIVATE"); break; case HCBT_CLICKSKIPPED: lstrcpy (szCode, "HCBT_CLICKSKIPPED"); break; case HCBT_CREATEWND: lstrcpy (szCode, "HCBT_CREATEWND"); break; case HCBT_DESTROYWND: lstrcpy (szCode, "HCBT_DESTROYWND"); break; case HCBT_KEYSKIPPED: lstrcpy (szCode, "HCBT_KEYSKIPPED"); break; case HCBT_MINMAX: lstrcpy (szCode, "HCBT_MINMAX"); break;
case HCBT_MOVESIZE: lstrcpy (szCode, "HCBT_MOVESIZE"); break; case HCBT_QS: lstrcpy (szCode, "HCBT_QS"); break; case HCBT_SETFOCUS: lstrcpy (szCode, "HCBT_SETFOCUS"); break; case HCBT_SYSCOMMAND: lstrcpy (szCode, " HCBT_SYSCOMMAND "); Break; default: lstrcpy (Szcode," Unknown "); Break;} cch = WSPrintf (SZBUF," CBT - NCODE:% S, TSK:% LD,% D Times ", Szcode, WPARAM, C ) Textout (HDC, 2, 75, SZBUF, CCH); ReleaseDC (HWndMain, HDC); Return CallNexthookex (MyHOOKDATA [CBT] .hook, ncode, wparam, lparam);} / ********** *********************************************************** **** WH_MOUSE HOOK Procedure *********************************************************** ********************* / LRESULT CALLBACK MOUSEPROC (int Ncode, WParam WParam, LParam Lparam) {char Szbuf [128]; char szmsg [16]; HDC HDC Static int C = 0; int cch; if (nCode <0) // do not process the message return CallNextHookEx (myhookdata [MOUSE] .hhook, nCode, wParam, lParam); // Call an application-defined function that converts a message // constant to a String and Copies It to a buffer. LookuptHeMessage ((PMSG) LPARAM, SZMSG); HDC = GetDC (HWndMain); cch = WSPrintf (SZBUF, "MOUSE - NCODE:% D, MSG:% S, X:% D, Y :% D,% D Times ", NCODE, SZMSG, LOWORD (LPARAM), HiWord (LPARAM), C ); Textout (HDC, 2, 95, SZBUF, CCH); ReleaseDC (HWndMain, HDC); Return CallNexthookex (MyHookData [Mouse] .hook, ncode, wparam, lparam;
} / ******************************************************* *************** WH_KEYBOARD HOOK Procedure ****************************************** ****************************************** / LRESULT CALLBACK KeyboardProc (int ncode, wparam wparam, lparam lparam) {char szbuf [128]; static int C = 0; int CCH; IF (ncode <0) // do not process message return callnexthookex (MyHOOKDATA [Keyboard] .hook, ncode, wparam, lpaam; hdc = getdc (hwndmain) ); Cch = wsprintf (SZBUF, "Keyboard - NCODE:% D, VK:% D,% D Times", NCODE, WPARAM, C ); Textout (HDC, 2, 115, SZBUF, CCH); ReleaseDC (HWndmain, HDC); Return CallNexthookex (MyHOOKDATA [Keyboard] .hook, ncode, wparam, lparam);} / ************************************* ********************************** Wh_MSGFilter hook procedure ********************* *********************************************************** *** / LRESULT CALLBACK MessageProc (int Ncode, WPARAM WPARAM, LPAR SZBUF [128]; Char SZ MSG [16]; char szcode [32]; hdc hdc; static int c = 0; int CCH; if (ncode <0) // do not process message returnch callnexThookex (MyHOOKDATA [MSGFilter] .hook, ncode, wparam, lparam ); switch (nCode) {case MSGF_DIALOGBOX: lstrcpy (szCode, "MSGF_DIALOGBOX"); break; case MSGF_MENU: lstrcpy (szCode, "MSGF_MENU"); break; case MSGF_SCROLLBAR: lstrcpy (szCode, "MSGF_SCROLLBAR"); break; default : WSPrintf (Szcode, "Unknown:% D", NCODE); Break;
} // Call an application-defined function that converts a message // constant to a string and copies it to a buffer LookUpTheMessage ((PMSG) lParam, szMsg);. Hdc = GetDC (hwndMain); cch = wsprintf (szBuf, " MSGFilter NCODE:% S, MSG:% S,% D Times ", SZCODE, SZMSG, C ); Textout (HDC, 2, 135, SZBUF, CCH); ReleaseDC (HWndmain, HDC); Return CallNexthookex (MyHOOKDATA [MSGFilter] . HHOOK, NCODE, WPARAM, LPARAM;}