HOWTO: Avoid Crashes When Debugging System-wide HooksLast reviewed: January 27, 1998Article ID: Q179905 |
The information in this article applies to:
SUMMARYDebugging a system-wide hook can be very difficult because the debugger is also being hooked. It is not uncommon to lock up the system, thus requiring a reboot. This article shows you how to avoid locking up the system. Basically, the hook procedure must check to see if the process being hooked is the debugger. If it is, the hook procedure bypasses the debugger code.
MORE INFORMATIONFirst, your hook procedure needs to check to see if the current process is the debugger. If it is not, proceed to your code. If it is, simply call the CallNextHookEx function. Because this is a system-wide hook, the procedure for determining if you are in the debugger should be kept to a minimum, or else it could slow the process down tremendously.
Sample CodeUse the following sample code to debug a keyboard hook:
#ifdef _DEBUG #define PATHSIZE 256 BOOL IsCurProcDebugger(); #endif // Shared DATA #pragma data_seg("HOOKVARS") // Other variables should be in here (for example, hhookKeyboard). // Add this variable to the shared data segment. #ifdef _DEBUG DWORD dwDebuggerProcId = 0; #endif #pragma data_seg() // Filter function for the WH_KEYBOARD. LRESULT CALLBACK KeyboardFunc (int nCode, WPARAM wParam, LPARAM lParam ) { if ( nCode >= 0 ) { // Add this if-block to your code. //*** You should put breakpoints ONLY inside this if-block *** #ifdef _DEBUG if ( !IsCurProcDebugger() ) // If you are not in the debugger... { #endif // Your hook code goes here. #ifdef _DEBUG } #endif } return( CallNextHookEx(hhookKeyboard, nCode, wParam, lParam)); } #ifdef _DEBUG // *** DO NOT PUT ANY BREAKPOINTS IN THIS CODE!!! BOOL IsCurProcDebugger() { // In Visual C++, declare these three variables after the // following if-block to speed things up. char szPathName[PATHSIZE]; char *szFileName = szPathName; char *tcp; // Do this first for speed. // If there is only one debugger present // and you have already found it. if ( dwDebuggerProcId ) { return ( GetCurrentProcessId() == dwDebuggerProcId ); } // If only one debugger is running, then the rest of this code // should be entered only until the debugger is first hooked. // After that, the preceding code should catch it every time. GetModuleFileName( NULL, szPathName, PATHSIZE ); // Only check the file name, not the full path. // A co-worker's path may be different. for ( tcp = szPathName; *tcp; tcp++ ) { if ( *tcp == '/' || *tcp == '\\' ) szFileName = tcp + 1; } // Use "MSDEV.EXE" for the Visual C++ debugger, or // else use YOUR debugger's name. if ( !strcmp( _strupr(szFileName), "MSDEV.EXE") ) { // It's the debugger! dwDebuggerProcId = GetCurrentProcessId(); return TRUE; } return FALSE; } #endif // #ifdef _DEBUG Important Caveats
REFERENCESFor additional information, please see the following articles in the Microsoft Knowledge Base:
ARTICLE-ID: Q125677 TITLE : HOWTO: Share Data Between Different Mappings of a DLL ARTICLE-ID: Q100292 TITLE : PRB: Data Section Names Limited to Eight Characters ARTICLE-ID: Q100634 TITLE : HOWTO: Specify Shared and Nonshared Data in a DLL ARTICLE-ID: Q102428 TITLE : HOWTO: Debug a System-Wide Hook Keywords : UsrHks Version : WINNT:4.0 Platform : winnt Issue type : kbhowto |
================================================================================
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |