Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenexcept.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Run-Time Library 00004 * PURPOSE: User-mode exception support for IA-32 00005 * FILE: lib/rtl/i386/exception.c 00006 * PROGRAMERS: Alex Ionescu (alex@relsoft.net) 00007 * Casper S. Hornstrup (chorns@users.sourceforge.net) 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <rtl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* PUBLIC FUNCTIONS **********************************************************/ 00017 00018 /* 00019 * @implemented 00020 */ 00021 VOID 00022 NTAPI 00023 RtlGetCallersAddress(OUT PVOID *CallersAddress, 00024 OUT PVOID *CallersCaller) 00025 { 00026 USHORT FrameCount; 00027 PVOID BackTrace[2]; 00028 PULONG BackTraceHash = NULL; 00029 00030 /* Get the tow back trace address */ 00031 FrameCount = RtlCaptureStackBackTrace(2, 2, &BackTrace[0],BackTraceHash); 00032 00033 /* Only if user want it */ 00034 if (*CallersAddress != NULL) 00035 { 00036 /* only when first frames exist */ 00037 if (FrameCount >= 1) 00038 { 00039 *CallersAddress = BackTrace[0]; 00040 } 00041 else 00042 { 00043 *CallersAddress = NULL; 00044 } 00045 } 00046 00047 /* Only if user want it */ 00048 if (*CallersCaller != NULL) 00049 { 00050 /* only when second frames exist */ 00051 if (FrameCount >= 2) 00052 { 00053 *CallersCaller = BackTrace[1]; 00054 } 00055 else 00056 { 00057 *CallersCaller = NULL; 00058 } 00059 } 00060 } 00061 00062 /* 00063 * @implemented 00064 */ 00065 BOOLEAN 00066 NTAPI 00067 RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, 00068 IN PCONTEXT Context) 00069 { 00070 PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL; 00071 DISPATCHER_CONTEXT DispatcherContext; 00072 EXCEPTION_RECORD ExceptionRecord2; 00073 EXCEPTION_DISPOSITION Disposition; 00074 ULONG_PTR StackLow, StackHigh; 00075 ULONG_PTR RegistrationFrameEnd; 00076 00077 /* Perform vectored exception handling if we are in user mode */ 00078 if (RtlpGetMode() != KernelMode) 00079 { 00080 /* Call any registered vectored handlers */ 00081 if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context)) 00082 { 00083 /* Exception handled, continue execution */ 00084 return TRUE; 00085 } 00086 } 00087 00088 /* Get the current stack limits and registration frame */ 00089 RtlpGetStackLimits(&StackLow, &StackHigh); 00090 RegistrationFrame = RtlpGetExceptionList(); 00091 00092 /* Now loop every frame */ 00093 while (RegistrationFrame != EXCEPTION_CHAIN_END) 00094 { 00095 /* Find out where it ends */ 00096 RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame + 00097 sizeof(EXCEPTION_REGISTRATION_RECORD); 00098 00099 /* Make sure the registration frame is located within the stack */ 00100 if ((RegistrationFrameEnd > StackHigh) || 00101 ((ULONG_PTR)RegistrationFrame < StackLow) || 00102 ((ULONG_PTR)RegistrationFrame & 0x3)) 00103 { 00104 /* Check if this happened in the DPC Stack */ 00105 if (RtlpHandleDpcStackException(RegistrationFrame, 00106 RegistrationFrameEnd, 00107 &StackLow, 00108 &StackHigh)) 00109 { 00110 /* Use DPC Stack Limits and restart */ 00111 continue; 00112 } 00113 00114 /* Set invalid stack and return false */ 00115 ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; 00116 return FALSE; 00117 } 00118 00119 /* Check if logging is enabled */ 00120 RtlpCheckLogException(ExceptionRecord, 00121 Context, 00122 RegistrationFrame, 00123 sizeof(*RegistrationFrame)); 00124 00125 /* Call the handler */ 00126 Disposition = RtlpExecuteHandlerForException(ExceptionRecord, 00127 RegistrationFrame, 00128 Context, 00129 &DispatcherContext, 00130 RegistrationFrame-> 00131 Handler); 00132 00133 /* Check if this is a nested frame */ 00134 if (RegistrationFrame == NestedFrame) 00135 { 00136 /* Mask out the flag and the nested frame */ 00137 ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; 00138 NestedFrame = NULL; 00139 } 00140 00141 /* Handle the dispositions */ 00142 switch (Disposition) 00143 { 00144 /* Continue searching */ 00145 case ExceptionContinueExecution: 00146 00147 /* Check if it was non-continuable */ 00148 if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) 00149 { 00150 /* Set up the exception record */ 00151 ExceptionRecord2.ExceptionRecord = ExceptionRecord; 00152 ExceptionRecord2.ExceptionCode = 00153 STATUS_NONCONTINUABLE_EXCEPTION; 00154 ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 00155 ExceptionRecord2.NumberParameters = 0; 00156 00157 /* Raise the exception */ 00158 RtlRaiseException(&ExceptionRecord2); 00159 } 00160 else 00161 { 00162 /* Return to caller */ 00163 return TRUE; 00164 } 00165 00166 /* Continue searching */ 00167 case ExceptionContinueSearch: 00168 break; 00169 00170 /* Nested exception */ 00171 case ExceptionNestedException: 00172 00173 /* Turn the nested flag on */ 00174 ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL; 00175 00176 /* Update the current nested frame */ 00177 if (DispatcherContext.RegistrationPointer > NestedFrame) 00178 { 00179 /* Get the frame from the dispatcher context */ 00180 NestedFrame = DispatcherContext.RegistrationPointer; 00181 } 00182 break; 00183 00184 /* Anything else */ 00185 default: 00186 00187 /* Set up the exception record */ 00188 ExceptionRecord2.ExceptionRecord = ExceptionRecord; 00189 ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; 00190 ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 00191 ExceptionRecord2.NumberParameters = 0; 00192 00193 /* Raise the exception */ 00194 RtlRaiseException(&ExceptionRecord2); 00195 break; 00196 } 00197 00198 /* Go to the next frame */ 00199 RegistrationFrame = RegistrationFrame->Next; 00200 } 00201 00202 /* Unhandled, return false */ 00203 return FALSE; 00204 } 00205 00206 /* 00207 * @implemented 00208 */ 00209 VOID 00210 NTAPI 00211 RtlUnwind(IN PVOID TargetFrame OPTIONAL, 00212 IN PVOID TargetIp OPTIONAL, 00213 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, 00214 IN PVOID ReturnValue) 00215 { 00216 PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame; 00217 DISPATCHER_CONTEXT DispatcherContext; 00218 EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3; 00219 EXCEPTION_DISPOSITION Disposition; 00220 ULONG_PTR StackLow, StackHigh; 00221 ULONG_PTR RegistrationFrameEnd; 00222 CONTEXT LocalContext; 00223 PCONTEXT Context; 00224 00225 /* Get the current stack limits */ 00226 RtlpGetStackLimits(&StackLow, &StackHigh); 00227 00228 /* Check if we don't have an exception record */ 00229 if (!ExceptionRecord) 00230 { 00231 /* Overwrite the argument */ 00232 ExceptionRecord = &ExceptionRecord3; 00233 00234 /* Setup a local one */ 00235 ExceptionRecord3.ExceptionFlags = 0; 00236 ExceptionRecord3.ExceptionCode = STATUS_UNWIND; 00237 ExceptionRecord3.ExceptionRecord = NULL; 00238 ExceptionRecord3.ExceptionAddress = _ReturnAddress(); 00239 ExceptionRecord3.NumberParameters = 0; 00240 } 00241 00242 /* Check if we have a frame */ 00243 if (TargetFrame) 00244 { 00245 /* Set it as unwinding */ 00246 ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING; 00247 } 00248 else 00249 { 00250 /* Set the Exit Unwind flag as well */ 00251 ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING | 00252 EXCEPTION_EXIT_UNWIND); 00253 } 00254 00255 /* Now capture the context */ 00256 Context = &LocalContext; 00257 LocalContext.ContextFlags = CONTEXT_INTEGER | 00258 CONTEXT_CONTROL | 00259 CONTEXT_SEGMENTS; 00260 RtlpCaptureContext(Context); 00261 00262 /* Pop the current arguments off */ 00263 Context->Esp += sizeof(TargetFrame) + 00264 sizeof(TargetIp) + 00265 sizeof(ExceptionRecord) + 00266 sizeof(ReturnValue); 00267 00268 /* Set the new value for EAX */ 00269 Context->Eax = (ULONG)ReturnValue; 00270 00271 /* Get the current frame */ 00272 RegistrationFrame = RtlpGetExceptionList(); 00273 00274 /* Now loop every frame */ 00275 while (RegistrationFrame != EXCEPTION_CHAIN_END) 00276 { 00277 /* If this is the target */ 00278 if (RegistrationFrame == TargetFrame) ZwContinue(Context, FALSE); 00279 00280 /* Check if the frame is too low */ 00281 if ((TargetFrame) && 00282 ((ULONG_PTR)TargetFrame < (ULONG_PTR)RegistrationFrame)) 00283 { 00284 /* Create an invalid unwind exception */ 00285 ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; 00286 ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 00287 ExceptionRecord2.ExceptionRecord = ExceptionRecord; 00288 ExceptionRecord2.NumberParameters = 0; 00289 00290 /* Raise the exception */ 00291 RtlRaiseException(&ExceptionRecord2); 00292 } 00293 00294 /* Find out where it ends */ 00295 RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame + 00296 sizeof(EXCEPTION_REGISTRATION_RECORD); 00297 00298 /* Make sure the registration frame is located within the stack */ 00299 if ((RegistrationFrameEnd > StackHigh) || 00300 ((ULONG_PTR)RegistrationFrame < StackLow) || 00301 ((ULONG_PTR)RegistrationFrame & 0x3)) 00302 { 00303 /* Check if this happened in the DPC Stack */ 00304 if (RtlpHandleDpcStackException(RegistrationFrame, 00305 RegistrationFrameEnd, 00306 &StackLow, 00307 &StackHigh)) 00308 { 00309 /* Use DPC Stack Limits and restart */ 00310 continue; 00311 } 00312 00313 /* Create an invalid stack exception */ 00314 ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK; 00315 ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 00316 ExceptionRecord2.ExceptionRecord = ExceptionRecord; 00317 ExceptionRecord2.NumberParameters = 0; 00318 00319 /* Raise the exception */ 00320 RtlRaiseException(&ExceptionRecord2); 00321 } 00322 else 00323 { 00324 /* Call the handler */ 00325 Disposition = RtlpExecuteHandlerForUnwind(ExceptionRecord, 00326 RegistrationFrame, 00327 Context, 00328 &DispatcherContext, 00329 RegistrationFrame-> 00330 Handler); 00331 switch(Disposition) 00332 { 00333 /* Continue searching */ 00334 case ExceptionContinueSearch: 00335 break; 00336 00337 /* Collission */ 00338 case ExceptionCollidedUnwind : 00339 00340 /* Get the original frame */ 00341 RegistrationFrame = DispatcherContext.RegistrationPointer; 00342 break; 00343 00344 /* Anything else */ 00345 default: 00346 00347 /* Set up the exception record */ 00348 ExceptionRecord2.ExceptionRecord = ExceptionRecord; 00349 ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; 00350 ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 00351 ExceptionRecord2.NumberParameters = 0; 00352 00353 /* Raise the exception */ 00354 RtlRaiseException(&ExceptionRecord2); 00355 break; 00356 } 00357 00358 /* Go to the next frame */ 00359 OldFrame = RegistrationFrame; 00360 RegistrationFrame = RegistrationFrame->Next; 00361 00362 /* Remove this handler */ 00363 RtlpSetExceptionList(OldFrame); 00364 } 00365 } 00366 00367 /* Check if we reached the end */ 00368 if (TargetFrame == EXCEPTION_CHAIN_END) 00369 { 00370 /* Unwind completed, so we don't exit */ 00371 ZwContinue(Context, FALSE); 00372 } 00373 else 00374 { 00375 /* This is an exit_unwind or the frame wasn't present in the list */ 00376 ZwRaiseException(ExceptionRecord, Context, FALSE); 00377 } 00378 } 00379 00380 /* EOF */ Generated on Thu May 24 2012 04:24:40 for ReactOS by
1.7.6.1
|