Listing 3 Logging an exception
void PreviewException(void * pObject, void * pThrowAddress, const type_info * pObjectInfo) { pObject; //reference parameter if (pObjectInfo) std::cout << "Exception of type \"" << pObjectInfo->name() << "\" occured at " << pThrowAddress << "\n"; } // this processor-specific function returns // the return address of the caller // assuming that callers frame was not optimized __declspec(naked) void * GetReturnAddress() { __asm { mov eax, [ebp + 4] ret } } // this processor-specific function returns // the stack frame of the caller's caller // assuming that frames were not optimized __declspec(naked) void * GetCallerFrame() { __asm { mov eax, [ebp] ret } } // imhibit optimization of frames #pragma optimize("y",off) extern "C" void __stdcall _CxxThrowException(void * pObject, _s__ThrowInfo const * pObjectInfo) { void * paddr = GetReturnAddress(); // call __CxxThrowException@8 is 5 bytes // long on i386. Subtracting 5 from return address // gives us the address of call instruction paddr = (void*)((DWORD_PTR)paddr - 5); void * pframe = GetCallerFrame(); type_info * pti = 0; // since we can get here when an exception is rethrown // pObjectInfo could be 0. Also it is a good idea to // make a sanity check if (pObjectInfo && pObjectInfo->pCatchableTypeArray && pObjectInfo->pCatchableTypeArray->nCatchableTypes > 0) { const _s__CatchableTypeArray * pTypes = pObjectInfo->pCatchableTypeArray; pti = (type_info*) ((*(pTypes->arrayOfCatchableTypes))[0].pType); } //call the hook function PreviewException(pObject,paddr,pti); const ULONG_PTR args[] = {MS_MAGIC, (ULONG_PTR)pObject, (ULONG_PTR)pObjectInfo}; RaiseException(CPP_EXCEPTION, EXCEPTION_NONCONTINUABLE, sizeof(args)/sizeof(args[0]), args); } //restore optimization settings #pragma optimize("",on)