test: chandler.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# chandler.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     chandler.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the C specific exception handler that provides
    00012     structured condition handling for the C language.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 11-Sep-1990
    00017
    00018 Environment:
    00019
    00020     Any mode.
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026 #include "nt.h"
    00027
    00028
    00029 //
    00030 // Define procedure prototypes for exception filter and termination handler
    00031 // execution routines defined in jmpunwnd.s
    00032 //
    00033
    00034 LONG
    00035 __C_ExecuteExceptionFilter (
    00036     PEXCEPTION_POINTERS ExceptionPointers,
    00037     EXCEPTION_FILTER ExceptionFilter,
    00038     ULONG EstablisherFrame
    00039     );
    00040
    00041 VOID
    00042 __C_ExecuteTerminationHandler (
    00043     BOOLEAN AbnormalTermination,
    00044     TERMINATION_HANDLER TerminationHandler,
    00045     ULONG EstablisherFrame
    00046     );
    00047
    00048 EXCEPTION_DISPOSITION
    00049 __C_specific_handler (
    00050     IN PEXCEPTION_RECORD ExceptionRecord,
    00051     IN PVOID EstablisherFrame,
    00052     IN OUT PCONTEXT ContextRecord,
    00053     IN OUT PDISPATCHER_CONTEXT DispatcherContext
    00054     )
    00055
    00056 /*++
    00057
    00058 Routine Description:
    00059
    00060     This function scans the scope tables associated with the specified
    00061     procedure and calls exception and termination handlers as necessary.
    00062
    00063 Arguments:
    00064
    00065     ExceptionRecord - Supplies a pointer to an exception record.
    00066
    00067     EstablisherFrame - Supplies a pointer to frame of the establisher function.
    00068
    00069     ContextRecord - Supplies a pointer to a context record.
    00070
    00071     DispatcherContext - Supplies a pointer to the exception dispatcher or
    00072         unwind dispatcher context.
    00073
    00074 Return Value:
    00075
    00076     If the exception is handled by one of the exception filter routines, then
    00077     there is no return from this routine and RtlUnwind is called. Otherwise,
    00078     an exception disposition value of continue execution or continue search is
    00079     returned.
    00080
    00081 --*/
    00082
    00083 {
    00084
    00085     ULONG ControlPc;
    00086     EXCEPTION_FILTER ExceptionFilter;
    00087     EXCEPTION_POINTERS ExceptionPointers;
    00088     PRUNTIME_FUNCTION FunctionEntry;
    00089     ULONG Index;
    00090     PSCOPE_TABLE ScopeTable;
    00091     ULONG TargetPc;
    00092     TERMINATION_HANDLER TerminationHandler;
    00093     LONG Value;
    00094
    00095     //
    00096     // Get address of where control left the establisher, the address of the
    00097     // function table entry that describes the function, and the address of
    00098     // the scope table.
    00099     //
    00100
    00101     ControlPc = DispatcherContext->ControlPc;
    00102     FunctionEntry = DispatcherContext->FunctionEntry;
    00103     ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
    00104
    00105     //
    00106     // If an unwind is not in progress, then scan the scope table and call
    00107     // the appropriate exception filter routines. Otherwise, scan the scope
    00108     // table and call the appropriate termination handlers using the target
    00109     // PC obtained from the context record.
    00110     // are called.
    00111     //
    00112
    00113     if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
    00114
    00115         //
    00116         // Scan the scope table and call the appropriate exception filter
    00117         // routines.
    00118         //
    00119
    00120         ExceptionPointers.ExceptionRecord = ExceptionRecord;
    00121         ExceptionPointers.ContextRecord = ContextRecord;
    00122         for (Index = 0; Index < ScopeTable->Count; Index += 1) {
    00123             if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
    00124                 (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
    00125                 (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
    00126
    00127                 //
    00128                 // Call the exception filter routine.
    00129                 //
    00130
    00131                 ExceptionFilter =
    00132                     (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
    00133                 Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
    00134                                                    ExceptionFilter,
    00135                                                    (ULONG)EstablisherFrame);
    00136
    00137                 //
    00138                 // If the return value is less than zero, then dismiss the
    00139                 // exception. Otherwise, if the value is greater than zero,
    00140                 // then unwind to the target exception handler. Otherwise,
    00141                 // continue the search for an exception filter.
    00142                 //
    00143
    00144                 if (Value < 0) {
    00145                     return ExceptionContinueExecution;
    00146
    00147                 } else if (Value > 0) {
    00148                     RtlUnwind2(EstablisherFrame,
    00149                                (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
    00150                                ExceptionRecord,
    00151                                (PVOID)ExceptionRecord->ExceptionCode,
    00152                                ContextRecord);
    00153                 }
    00154             }
    00155         }
    00156
    00157     } else {
    00158
    00159         //
    00160         // Scan the scope table and call the appropriate termination handler
    00161         // routines.
    00162         //
    00163
    00164         TargetPc = ContextRecord->Fir;
    00165         for (Index = 0; Index < ScopeTable->Count; Index += 1) {
    00166             if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
    00167                 (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
    00168
    00169                 //
    00170                 // If the target PC is within the same scope the control PC
    00171                 // is within, then this is an uplevel goto out of an inner try
    00172                 // scope or a long jump back into a try scope. Terminate the
    00173                 // scan termination handlers.
    00174                 //
    00175                 // N.B. The target PC can be just beyond the end of the scope,
    00176                 //      in which case it is a leave from the scope.
    00177                 //
    00178
    00179
    00180                 if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
    00181                    (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
    00182                     break;
    00183
    00184                 } else {
    00185
    00186                     //
    00187                     // If the scope table entry describes an exception filter
    00188                     // and the associated exception handler is the target of
    00189                     // the unwind, then terminate the scan for termination
    00190                     // handlers. Otherwise, if the scope table entry describes
    00191                     // a termination handler, then record the address of the
    00192                     // end of the scope as the new control PC address and call
    00193                     // the termination handler.
    00194                     //
    00195
    00196                     if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
    00197                         if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
    00198                             break;
    00199                         }
    00200
    00201                     } else {
    00202                         DispatcherContext->ControlPc =
    00203                                 ScopeTable->ScopeRecord[Index].EndAddress + 4;
    00204                         TerminationHandler =
    00205                             (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
    00206                         __C_ExecuteTerminationHandler(TRUE,
    00207                                                       TerminationHandler,
    00208                                                       (ULONG)EstablisherFrame);
    00209                     }
    00210                 }
    00211             }
    00212         }
    00213     }
    00214
    00215     //
    00216     // Continue search for exception or termination handlers.
    00217     //
    00218
    00219     return ExceptionContinueSearch;
    00220 }