ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

except.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.