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->Iar; 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 } 00221 

Generated on Sat May 15 19:39:23 2004 for test by doxygen 1.3.7