Listing 1: fdbgbrk.cpp Implementation of ForceDebugBreak()
/* disable unnecessary level-4 warnings */ #pragma warning(disable : 4201) //nameless struct/union #pragma warning(disable : 4214) //bit field types other than int #pragma warning(disable : 4514) //unreferenced inline function /* include files */ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <tchar.h> #include <regstr.h> #include "IsDbgEx.h" #include "FDbgBrk.h" /* required link libraries */ #pragma comment(lib, "kernel32") #pragma comment(lib, "user32") #pragma comment(lib, "advapi32") /* private macros */ #ifndef CountOf #define CountOf(array) (sizeof(array)/sizeof((array)[0])) #endif /* private type definitions */ typedef BOOL (WINAPI * ISDEBUGGERPRESENTPROC)(VOID); /* private function prototypes */ BOOL LocateAeDebugger(LPTSTR lpszDest, const UINT cchDest); //------------------------------------------------------------------ //ForceDebugBreak() //------------------------------------------------------------------ VOID WINAPI ForceDebugBreak(VOID) { /* TEMPORARY VARIABLES */ PROCESS_INFORMATION pi = { NULL }; SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) }; STARTUPINFO si = { sizeof(STARTUPINFO) }; const DWORD dwProcessId = GetCurrentProcessId(); HANDLE hEventDebuggerReady = NULL; TCHAR szDebugger[MAX_PATH+1] = TEXT(""); TCHAR szCmdLine[MAX_PATH+1] = TEXT(""); DWORD cbData = 0; HKEY hkeyDebugger = NULL; LONG lResult = 0; /* continue if not currently being debugged */ if (!IsDebuggerPresentEx()) { /* determine the installed debugger */ if (LocateAeDebugger(szDebugger, CountOf(szDebugger))) { /* create the debugger ready signaling event */ sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; //handle must be inheritable hEventDebuggerReady = CreateEvent(&sa, TRUE, FALSE, NULL); /* format the command line and execute */ wsprintf( szCmdLine, szDebugger, (unsigned long)dwProcessId, (unsigned long)hEventDebuggerReady); if (CreateProcess( NULL, szCmdLine, NULL, NULL, TRUE, //debugger must inherit handles 0, NULL, NULL, &si, &pi)) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); /* wait for debugger */ WaitForSingleObject(hEventDebuggerReady, INFINITE); } /* clean up */ CloseHandle(hEventDebuggerReady); hEventDebuggerReady = NULL; } } /* break */ #ifndef _M_IX86 DebugBreak(); #else //_M_IX86 __asm { int 3 } #endif //_M_IX86 /* done */ return; } //------------------------------------------------------------------ //LocateAeDebugger() // Attempt to locate the registed AeDebugger: first search // the registry, then search win.ini. //------------------------------------------------------------------ BOOL LocateAeDebugger(LPTSTR lpszDest, const UINT cchDest) { /* TEMPORARY VARIABLES */ DWORD cbData = 0; HKEY hkeyDebugger = NULL; LONG lResult = ERROR_GEN_FAILURE; BOOL fSuccess = FALSE; /* determine the installed debugger */ lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_AEDEBUG, 0, KEY_READ, &hkeyDebugger); if (lResult == ERROR_SUCCESS) { cbData = cchDest * sizeof(TCHAR); lResult = RegQueryValueEx( hkeyDebugger, REGSTR_VAL_AEDEBUG_DEBUGGER, NULL, NULL, (LPBYTE)lpszDest, &cbData); RegCloseKey(hkeyDebugger); hkeyDebugger = NULL; fSuccess = lResult == ERROR_SUCCESS; } /* search win.ini if not found */ if (lResult != ERROR_SUCCESS) { fSuccess = GetProfileString( TEXT("AeDebug"), TEXT("Debugger"), TEXT(""), lpszDest, cchDest) > 0; } /* done */ return fSuccess; } /* End of file */