1 /* $Id: except.c,v 1.16 2004/08/22 18:49:11 tamlin Exp $
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
= NULL
;
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 LPTOP_LEVEL_EXCEPTION_FILTER OldTopLevelExceptionFilter
=
50 GlobalTopLevelExceptionFilter
;
51 GlobalTopLevelExceptionFilter
= lpTopLevelExceptionFilter
;
52 return OldTopLevelExceptionFilter
;
57 * Private helper function to lookup the module name from a given address.
58 * The address can point to anywhere within the module.
61 _module_name_from_addr(const void* addr
, char* psz
, size_t nChars
)
63 MEMORY_BASIC_INFORMATION mbi
;
64 if (VirtualQuery(addr
, &mbi
, sizeof(mbi
)) != sizeof(mbi
) ||
65 !GetModuleFileNameA((HMODULE
)mbi
.AllocationBase
, psz
, nChars
))
77 UnhandledExceptionFilter(struct _EXCEPTION_POINTERS
*ExceptionInfo
)
80 HANDLE DebugPort
= NULL
;
82 static int RescursionTrap
= 3;
85 if (ExceptionInfo
->ExceptionRecord
->ExceptionCode
== STATUS_ACCESS_VIOLATION
&&
86 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[0])
88 RetValue
= _BasepCheckForReadOnlyResource(
89 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[1]);
90 if (RetValue
== EXCEPTION_CONTINUE_EXECUTION
)
91 return EXCEPTION_CONTINUE_EXECUTION
;
95 if (--RescursionTrap
> 0)
97 /* Is there a debugger running ? */
98 ErrCode
= NtQueryInformationProcess(NtCurrentProcess(), ProcessDebugPort
,
99 &DebugPort
, sizeof(HANDLE
), NULL
);
100 if (!NT_SUCCESS(ErrCode
) && ErrCode
!= STATUS_NOT_IMPLEMENTED
)
102 SetLastErrorByStatus(ErrCode
);
103 return EXCEPTION_EXECUTE_HANDLER
;
108 /* Pass the exception to debugger. */
109 DPRINT("Passing exception to debugger\n");
110 return EXCEPTION_CONTINUE_SEARCH
;
113 /* Run unhandled exception handler. */
114 if (GlobalTopLevelExceptionFilter
!= NULL
)
116 RetValue
= GlobalTopLevelExceptionFilter(ExceptionInfo
);
117 if (RetValue
== EXCEPTION_EXECUTE_HANDLER
)
118 return EXCEPTION_EXECUTE_HANDLER
;
119 if (RetValue
== EXCEPTION_CONTINUE_EXECUTION
)
120 return EXCEPTION_CONTINUE_EXECUTION
;
124 if (RescursionTrap
>= 0 && (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
)));
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
);