#include #include #define MAKESOFTWAREEXCEPTION(Severity, Facility, Exception) \ ((DWORD) ( \ /* Severity code */ (Severity << 0) | \ /* MS(0) or Cust(1) */ (1 << 29) | \ /* Reserved(0) */ (0 << 28) | \ /* Facility code */ (Facility << 16) | \ /* Exception code */ (Exception << 0))) struct Alarm { static const DWORD ExceptionCode; Alarm(DWORD timeOut) : m_hStopEvent(NULL), m_hThread(NULL), m_dwTimeOut(timeOut), m_hAlarmThread(NULL) { m_hStopEvent =::CreateEvent(NULL, TRUE, FALSE, NULL); DWORD dwThreadId; ::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentThread(), ::GetCurrentProcess(), &m_hAlarmThread, THREAD_ALL_ACCESS, FALSE, 0); m_hThread = ::CreateThread(NULL,0,AlarmThread,this,0,&dwThreadId); } void Reset() { HANDLE handles[2]; handles[0] = m_hStopEvent; handles[1] = m_hThread; ::SetEvent(m_hStopEvent); ::WaitForMultipleObjects(2,handles,TRUE,INFINITE); CloseHandles(); } private: static void WINAPI RaiseAlarm (void) { ::RaiseException(ExceptionCode, EXCEPTION_NONCONTINUABLE, 0, NULL); } static DWORD WINAPI AlarmThread(LPVOID lpParameter) { Alarm* me = (Alarm*)lpParameter; if(::WaitForSingleObject(me->m_hStopEvent,me->m_dwTimeOut) == WAIT_TIMEOUT) { ::SuspendThread(me->m_hAlarmThread); CONTEXT ctx; ctx.ContextFlags = CONTEXT_CONTROL; ::GetThreadContext(me->m_hAlarmThread, &ctx); ctx.Eip = (DWORD)RaiseAlarm; ::SetThreadContext(me->m_hAlarmThread, &ctx); ::ResumeThread(me->m_hAlarmThread); me->CloseHandles(); }; return TRUE; } void CloseHandles() { ::CloseHandle(m_hAlarmThread); ::CloseHandle(m_hThread); ::CloseHandle(m_hStopEvent); } HANDLE m_hStopEvent; HANDLE m_hThread; DWORD m_dwTimeOut; HANDLE m_hAlarmThread; }; const DWORD Alarm::ExceptionCode = MAKESOFTWAREEXCEPTION(ERROR_SEVERITY_ERROR, FACILITY_NULL, 1); int func(int lpParameter) { while(1) ; } int main(int argc, char* argv[]) { __try { Alarm alarm(1000); int result = func(0); alarm.Reset(); } __except (true) { switch (GetExceptionCode()) { case EXCEPTION_ACCESS_VIOLATION: std::cout << "Access violation" << std::endl; break; case EXCEPTION_INT_DIVIDE_BY_ZERO: std::cout << "Division by zero" << std::endl; break; case Alarm::ExceptionCode: std::cout << "Alarm fired" << std::endl; break; default: break; }; return 1; } return 0; }