3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/except.c
6 * PURPOSE: Exception functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
16 #include "../include/debug.h"
18 UINT GlobalErrMode
= 0;
19 LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter
= UnhandledExceptionFilter
;
21 UINT
GetErrorMode(void)
32 SetErrorMode( UINT uMode
)
34 UINT OldErrMode
= GetErrorMode();
35 GlobalErrMode
= uMode
;
43 LPTOP_LEVEL_EXCEPTION_FILTER
45 SetUnhandledExceptionFilter(
46 LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
49 return InterlockedExchangePointer(&GlobalTopLevelExceptionFilter
,
50 lpTopLevelExceptionFilter
);
55 * Private helper function to lookup the module name from a given address.
56 * The address can point to anywhere within the module.
59 _module_name_from_addr(const void* addr
, char* psz
, size_t nChars
)
61 MEMORY_BASIC_INFORMATION mbi
;
62 if (VirtualQuery(addr
, &mbi
, sizeof(mbi
)) != sizeof(mbi
) ||
63 !GetModuleFileNameA((HMODULE
)mbi
.AllocationBase
, psz
, nChars
))
71 _dump_context(PCONTEXT pc
)
74 * Print out the CPU registers
76 DbgPrint("CS:EIP %x:%x\n", pc
->SegCs
&0xffff, pc
->Eip
);
77 DbgPrint("DS %x ES %x FS %x GS %x\n", pc
->SegDs
&0xffff, pc
->SegEs
&0xffff,
78 pc
->SegFs
&0xffff, pc
->SegGs
&0xfff);
79 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", pc
->Eax
, pc
->Ebx
, pc
->Ecx
);
80 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", pc
->Edx
,
81 pc
->Ebp
, pc
->Esi
, pc
->Esp
);
82 DbgPrint("EDI: %.8x EFLAGS: %.8x\n", pc
->Edi
, pc
->EFlags
);
89 UnhandledExceptionFilter(struct _EXCEPTION_POINTERS
*ExceptionInfo
)
94 HANDLE DebugPort
= NULL
;
98 if (ExceptionInfo
->ExceptionRecord
->ExceptionCode
== STATUS_ACCESS_VIOLATION
&&
99 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[0])
101 RetValue
= _BasepCheckForReadOnlyResource(
102 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[1]);
103 if (RetValue
== EXCEPTION_CONTINUE_EXECUTION
)
104 return EXCEPTION_CONTINUE_EXECUTION
;
108 /* Is there a debugger running ? */
109 ErrCode
= NtQueryInformationProcess(NtCurrentProcess(), ProcessDebugPort
,
110 &DebugPort
, sizeof(HANDLE
), NULL
);
111 if (!NT_SUCCESS(ErrCode
) && ErrCode
!= STATUS_NOT_IMPLEMENTED
)
113 SetLastErrorByStatus(ErrCode
);
114 return EXCEPTION_EXECUTE_HANDLER
;
119 /* Pass the exception to debugger. */
120 DPRINT("Passing exception to debugger\n");
121 return EXCEPTION_CONTINUE_SEARCH
;
124 if ((GetErrorMode() & SEM_NOGPFAULTERRORBOX
) == 0)
128 CHAR szMod
[128] = "";
131 /* Print a stack trace. */
132 DPRINT1("Unhandled exception\n");
133 DPRINT1("Address:\n");
135 ExceptionInfo
->ExceptionRecord
->ExceptionAddress
,
136 _module_name_from_addr(ExceptionInfo
->ExceptionRecord
->ExceptionAddress
, szMod
, sizeof(szMod
)));
137 _dump_context ( ExceptionInfo
->ContextRecord
);
139 DPRINT1("Frames:\n");
140 Frame
= (PULONG
)ExceptionInfo
->ContextRecord
->Ebp
;
141 while (Frame
[1] != 0 && Frame
[1] != 0xdeadbeef)
143 if (IsBadReadPtr((PVOID
)Frame
[1], 4)) {
144 DPRINT1(" %8x %s\n", Frame
[1], "<invalid address>");
146 _module_name_from_addr((const void*)Frame
[1], szMod
, sizeof(szMod
));
147 DPRINT1(" %8x %s\n", Frame
[1], szMod
);
149 if (IsBadReadPtr((PVOID
)Frame
[0], sizeof(*Frame
) * 2)) {
152 Frame
= (PULONG
)Frame
[0];
158 * Returning EXCEPTION_EXECUTE_HANDLER means that the code in
159 * the __except block will be executed. Normally this will end up in a
163 return EXCEPTION_EXECUTE_HANDLER
;
173 DWORD dwExceptionCode
,
174 DWORD dwExceptionFlags
,
175 DWORD nNumberOfArguments
,
176 CONST DWORD
* lpArguments OPTIONAL
179 EXCEPTION_RECORD ExceptionRecord
;
181 /* Do NOT normalize dwExceptionCode: it will be done in
182 * NTDLL.RtlRaiseException().
184 ExceptionRecord
.ExceptionCode
= dwExceptionCode
;
185 ExceptionRecord
.ExceptionRecord
= NULL
;
186 ExceptionRecord
.ExceptionAddress
= (PVOID
) RaiseException
;
188 * Normalize dwExceptionFlags.
190 ExceptionRecord
.ExceptionFlags
= (dwExceptionFlags
& EXCEPTION_NONCONTINUABLE
);
192 * Normalize nNumberOfArguments.
194 if (EXCEPTION_MAXIMUM_PARAMETERS
< nNumberOfArguments
)
196 nNumberOfArguments
= EXCEPTION_MAXIMUM_PARAMETERS
;
199 * If the exception has no argument,
200 * ignore nNumberOfArguments and lpArguments.
202 if (NULL
== lpArguments
)
204 ExceptionRecord
.NumberParameters
= 0;
208 ExceptionRecord
.NumberParameters
= nNumberOfArguments
;
209 for ( nNumberOfArguments
= 0;
210 (nNumberOfArguments
< ExceptionRecord
.NumberParameters
);
211 nNumberOfArguments
++
214 ExceptionRecord
.ExceptionInformation
[nNumberOfArguments
]
218 RtlRaiseException (& ExceptionRecord
);