mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-24 17:44:44 +00:00
191 lines
6.5 KiB
C++
Vendored
191 lines
6.5 KiB
C++
Vendored
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Detours Test Program (firstexc.cpp of firstexc.lib)
|
|
//
|
|
// Microsoft Research Detours Package
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// For more information on exception handling, see "A Crash Course on the
|
|
// Depths of Win32 Structured Exception Handling," by Matt Pietrek in the
|
|
// January 1997 issue of Microsoft Systems Journal.
|
|
//
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include "detours.h"
|
|
#include "firstexc.h"
|
|
|
|
#if _MSC_VER > 1000
|
|
#pragma warning(disable: 4740)
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
static BOOL s_bExceptionDetourInstalled = FALSE;
|
|
static LPTOP_LEVEL_EXCEPTION_FILTER s_pFirstChanceFilter = NULL;
|
|
|
|
ULONG (NTAPI *Real_NtContinue)(IN PCONTEXT ContextRecord,
|
|
IN BOOLEAN TestAlerts) = NULL;
|
|
|
|
VOID (NTAPI *Real_KiUserExceptionDispatcher)(IN PEXCEPTION_RECORD ExceptionRecord,
|
|
IN PCONTEXT ContextFrame) = NULL;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// This function effectively removes all try..catch frames for the current
|
|
// stack. It forces all exceptions to be treated as unhandled exceptions.
|
|
//
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4733)
|
|
static VOID WINAPI RemoveAllExceptionHandlers(VOID)
|
|
{
|
|
// The basic, OS defined exception frame
|
|
struct EXCEPTION_REGISTRATION
|
|
{
|
|
EXCEPTION_REGISTRATION* prev;
|
|
FARPROC handler;
|
|
};
|
|
|
|
EXCEPTION_REGISTRATION * pVCExcRec = NULL;
|
|
EXCEPTION_REGISTRATION * pLastGood = NULL;
|
|
|
|
__asm mov eax, FS:[0];
|
|
__asm mov [pVCExcRec], eax;
|
|
|
|
for (pLastGood = pVCExcRec; (ULONG)pVCExcRec != ~0ul; ) {
|
|
if ((ULONG)pVCExcRec >= 0x30000000)
|
|
break;
|
|
|
|
pLastGood = pVCExcRec;
|
|
pVCExcRec = (EXCEPTION_REGISTRATION *)(pVCExcRec->prev);
|
|
}
|
|
|
|
__asm mov eax, [pLastGood];
|
|
__asm mov FS:[0], eax;
|
|
}
|
|
#pragma warning(pop)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Routine Description:
|
|
//
|
|
// This routine is entered on return from kernel mode to dispatch a user
|
|
// mode exception. If a frame based handler handles the exception, then
|
|
// the execution is continued. Else last chance processing is performed.
|
|
//
|
|
// NOTE: This procedure is not called, but rather dispatched to.
|
|
// It depends on there not being a return address on the stack
|
|
// (assumption w.r.t. argument offsets.)
|
|
//
|
|
// Arguments:
|
|
// ExceptionRecord (esp+0) - Supplies a pointer to an exception record.
|
|
// ContextRecord (esp+4) - Supplies a pointer to a context frame.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
static VOID __declspec(naked) NTAPI
|
|
Detour_KiUserExceptionDispatcher(PEXCEPTION_RECORD pExceptRec,
|
|
CONTEXT *pContext)
|
|
{
|
|
__asm {
|
|
xor eax, eax ; // Create fake return address on stack.
|
|
push eax ; // (Generally, we are called by the kernel.)
|
|
|
|
push ebp ; // Prolog
|
|
mov ebp, esp ;
|
|
sub esp, __LOCAL_SIZE ;
|
|
}
|
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER pFirstChanceFilter;
|
|
EXCEPTION_POINTERS ep;
|
|
DWORD dwReturn;
|
|
DWORD dwError;
|
|
|
|
ep.ExceptionRecord = pExceptRec;
|
|
ep.ContextRecord = pContext;
|
|
pFirstChanceFilter = s_pFirstChanceFilter;
|
|
dwReturn = EXCEPTION_CONTINUE_SEARCH;
|
|
dwError = 0;
|
|
|
|
if (s_pFirstChanceFilter) {
|
|
dwReturn = pFirstChanceFilter(&ep);
|
|
}
|
|
|
|
if (dwReturn == EXCEPTION_CONTINUE_EXECUTION) {
|
|
dwError = Real_NtContinue(pContext, 0);
|
|
// This call should *NEVER* return. If it does, we want to fail to the debugger.
|
|
RemoveAllExceptionHandlers();
|
|
}
|
|
|
|
if (dwReturn == EXCEPTION_EXECUTE_HANDLER) { // Special: Call debugger.
|
|
RemoveAllExceptionHandlers();
|
|
}
|
|
|
|
__asm {
|
|
mov ebx, pExceptRec ;
|
|
mov ecx, pContext ;
|
|
push ecx ;
|
|
push ebx ;
|
|
mov eax, [Real_KiUserExceptionDispatcher];
|
|
jmp eax ;
|
|
;
|
|
; The above code should never return.
|
|
;
|
|
int 3 ; // Break!
|
|
;
|
|
mov esp, ebp ; // Epilog
|
|
pop ebp ;
|
|
ret ;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Set the first-chance exception filter.
|
|
//
|
|
// Returns the pointer to the last first-chance exception filter if there
|
|
// was one. If this is the first first-chance exception filter, installs
|
|
// the necessary detour and acquires the appropriate function pointers.
|
|
// If the parameter is NULL, first-chance exception filtering is disabled.
|
|
//
|
|
// A first-chance exception filter should always return one of three
|
|
// possible codes:
|
|
//
|
|
// EXCEPTION_CONTINUE_SEARCH:
|
|
// The exception was not handled by this filter; continue the
|
|
// search for the appropriate exception handler.
|
|
//
|
|
// EXCEPTION_CONTINUE_EXECUTION:
|
|
// The exception was handled by this filter; continue execution
|
|
// at the point were the exception was thrown.
|
|
//
|
|
// EXCEPTION_EXECUTE_HANDLER:
|
|
// Drastic failure in the exception filter. Process the
|
|
// exception as if no exception handlers were installed.
|
|
// (i.e. Give the user a chance to invoke the debugger.)
|
|
//
|
|
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
|
|
DetourFirstChanceExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER pNewFirstChanceFilter)
|
|
{
|
|
if (!s_bExceptionDetourInstalled) {
|
|
s_bExceptionDetourInstalled = TRUE;
|
|
|
|
Real_NtContinue = (ULONG (NTAPI *)(IN PCONTEXT, IN BOOLEAN))
|
|
DetourFindFunction("ntdll.dll", "NtContinue");
|
|
Real_KiUserExceptionDispatcher =
|
|
(VOID (NTAPI *)(IN PEXCEPTION_RECORD, IN PCONTEXT))
|
|
DetourFindFunction("ntdll.dll", "KiUserExceptionDispatcher");
|
|
|
|
DetourTransactionBegin();
|
|
DetourUpdateThread(GetCurrentThread());
|
|
DetourAttach(&(PVOID&)Real_KiUserExceptionDispatcher,
|
|
Detour_KiUserExceptionDispatcher);
|
|
DetourTransactionCommit();
|
|
}
|
|
|
|
LPTOP_LEVEL_EXCEPTION_FILTER pOldFirstChanceFilter = s_pFirstChanceFilter;
|
|
s_pFirstChanceFilter = pNewFirstChanceFilter;
|
|
return pOldFirstChanceFilter;
|
|
}
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|