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

ghandler.c File Reference

#include "nt.h"

Go to the source code of this file.

Defines

#define IS_EXCEPT(Seb)   ((Seb)->JumpTarget != 0)
#define IS_FINALLY(Seb)   ((Seb)->JumpTarget == 0)
#define MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord, Seb)

Functions

LONG __C_ExecuteExceptionFilter (PEXCEPTION_POINTERS ExceptionPointers, EXCEPTION_FILTER ExceptionFilter, ULONG_PTR EstablisherFrame)
ULONG_PTR __C_ExecuteTerminationHandler (BOOLEAN AbnormalTermination, TERMINATION_HANDLER TerminationHandler, ULONG_PTR EstablisherFrame)
EXCEPTION_DISPOSITION _OtsCSpecificHandler (IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PDISPATCHER_CONTEXT DispatcherContext)
ULONG_PTR _OtsLocalFinallyUnwind (IN PSEH_CONTEXT SehContext, IN PSEH_BLOCK TargetSeb, IN PVOID RealFramePointer)


Define Documentation

#define IS_EXCEPT Seb   )     ((Seb)->JumpTarget != 0)
 

Definition at line 71 of file ghandler.c.

Referenced by _OtsCSpecificHandler().

#define IS_FINALLY Seb   )     ((Seb)->JumpTarget == 0)
 

Definition at line 72 of file ghandler.c.

Referenced by _OtsCSpecificHandler(), and _OtsLocalFinallyUnwind().

#define MODIFY_UNWIND_EXCEPTION_RECORD ExceptionRecord,
Seb   ) 
 

Value:

{ \ ExceptionRecord->ExceptionCode = STATUS_UNWIND; \ ExceptionRecord->ExceptionFlags = EXCEPTION_UNWINDING; \ ExceptionRecord->ExceptionRecord = NULL; \ ExceptionRecord->ExceptionAddress = 0; \ ExceptionRecord->NumberParameters = 1; \ ExceptionRecord->ExceptionInformation[0] = (ULONG_PTR)(Seb); \ }

Definition at line 81 of file ghandler.c.

Referenced by _OtsCSpecificHandler().


Function Documentation

LONG __C_ExecuteExceptionFilter PEXCEPTION_POINTERS  ExceptionPointers,
EXCEPTION_FILTER  ExceptionFilter,
ULONG_PTR  EstablisherFrame
 

ULONG_PTR __C_ExecuteTerminationHandler BOOLEAN  AbnormalTermination,
TERMINATION_HANDLER  TerminationHandler,
ULONG_PTR  EstablisherFrame
 

EXCEPTION_DISPOSITION _OtsCSpecificHandler IN PEXCEPTION_RECORD  ExceptionRecord,
IN PVOID  EstablisherFrame,
IN OUT PCONTEXT  ContextRecord,
IN OUT PDISPATCHER_CONTEXT  DispatcherContext
 

Definition at line 91 of file ghandler.c.

References __C_ExecuteExceptionFilter(), __C_ExecuteTerminationHandler(), _OtsLocalFinallyUnwind(), ExceptionContinueExecution, ExceptionContinueSearch, IS_EXCEPT, IS_FINALLY, MODIFY_UNWIND_EXCEPTION_RECORD, NULL, RtlUnwind(), RtlUnwind2(), and TRUE.

00100 : 00101 00102 This function walks up the list of SEB's associated with the specified 00103 procedure and calls except filters and finally handlers as necessary. 00104 00105 It is called in two different contexts: 00106 (i) by the exception dispatcher after an exception is raised 00107 (ii) by the unwinder during an unwind operation 00108 00109 In the first case, is searches the SEB list for except filters to evaluate. 00110 In the second case, it searches for finally handlers to execute. 00111 00112 Arguments: 00113 00114 ExceptionRecord - Supplies a pointer to an exception record. 00115 00116 EstablisherFrame - Supplies a (virtual frame) pointer to the frame of the 00117 establisher function. 00118 00119 ContextRecord - Supplies a pointer to a context record. 00120 00121 DispatcherContext - Supplies a pointer to the exception dispatcher or 00122 unwind dispatcher context. 00123 00124 Return Value: 00125 00126 If the exception is handled by one of the exception filter routines, then 00127 there is no return from this routine and RtlUnwind is called. Otherwise, 00128 an exception disposition value of continue execution or continue search is 00129 returned. 00130 00131 Notes: 00132 In context (i) there are 3 possibilities: 00133 00134 (a) If an exception filter returns a value greater that 0 (meaning 00135 that the associated handler should be invoked) there is no 00136 return from this function. RtlUnwind is called to unwind the 00137 stack to the exception handler corresponding to that filter. 00138 00139 (b) If an exception filter returns a value less than 0 (meaning 00140 that the exception should be dismissed), this routine returns 00141 value ExceptionContinueExecution. 00142 00143 (c) If every filter returns value 0 (meaning that the search for a 00144 handler should continue elsewhere), this function returns 00145 ExceptionContinueSearch. 00146 00147 In context (ii) there are 2 possibilities: 00148 00149 (d) If no branches are detected out of finally handlers, this 00150 function returns ExceptionContinueSearch. 00151 00152 (e) If a branch is detected out of a finally handler, there is no 00153 return from this routine. RtlUnwind is called to unwind to the 00154 branch target (and cancel the current unwind). 00155 00156 There may be long jumps out of both except filters and finally handlers 00157 in which case this routine will be peeled off the stack without returning. 00158 00159 --*/ 00160 00161 { 00162 00163 ULONG_PTR ContinuationAddress; 00164 EXCEPTION_FILTER ExceptionFilter; 00165 PVOID ExceptionHandler; 00166 EXCEPTION_POINTERS ExceptionPointers; 00167 LONG FilterValue; 00168 ULONG_PTR RealFramePointer; 00169 PSEH_BLOCK Seb; 00170 PSEH_CONTEXT SehContext; 00171 PSEH_BLOCK TargetSeb; 00172 TERMINATION_HANDLER TerminationHandler; 00173 00174 // 00175 // Get the address of the SEH context which is at some negative offset 00176 // from the virtual frame pointer. For GEM, the handler data field of 00177 // the function entry contains that offset. The current SEB pointer and 00178 // the RFP (static link) are obtained from the SEH context. 00179 // 00180 00181 SehContext = (PSEH_CONTEXT)((ULONG_PTR)EstablisherFrame + 00182 (LONG_PTR)DispatcherContext->FunctionEntry->HandlerData); 00183 RealFramePointer = SehContext->RealFramePointer; 00184 00185 // 00186 // If this is a dispatching context, walk up the list of SEBs evaluating 00187 // except filters. 00188 // 00189 00190 if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) { 00191 00192 // 00193 // Set up the ExceptionPointers structure that is used by except 00194 // filters to obtain data for the GetExceptionInformation intrinsic 00195 // function. Copy the current SEB pointer into a local variable 00196 // because the real SEB pointer is only modified in unwind contexts. 00197 // 00198 00199 ExceptionPointers.ExceptionRecord = ExceptionRecord; 00200 ExceptionPointers.ContextRecord = ContextRecord; 00201 00202 for (Seb = SehContext->CurrentSeb; Seb != NULL; Seb = Seb->ParentSeb) { 00203 if (IS_EXCEPT(Seb)) { 00204 00205 // 00206 // This is an except filter. Get the addresses of the filter 00207 // and exception handler from the SEB, then call the except 00208 // filter. 00209 // 00210 00211 ExceptionFilter = (EXCEPTION_FILTER)Seb->HandlerAddress; 00212 ExceptionHandler = (PVOID)Seb->JumpTarget; 00213 00214 FilterValue = __C_ExecuteExceptionFilter(&ExceptionPointers, 00215 ExceptionFilter, 00216 RealFramePointer); 00217 00218 // 00219 // If the except filter < 0, dismiss the exception. If > 0, 00220 // store the exception code on the stack for the except 00221 // handler, modify the given ExceptionRecord so that finally 00222 // handlers will be called properly during the unwind, then 00223 // unwind down to the except handler. If = 0, resume the 00224 // search for except filters. 00225 // 00226 00227 if (FilterValue < 0) { 00228 return ExceptionContinueExecution; 00229 00230 } else if (FilterValue > 0) { 00231 SehContext->ExceptionCode = ExceptionRecord->ExceptionCode; 00232 MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord, 00233 Seb->ParentSeb); 00234 RtlUnwind2(EstablisherFrame, 00235 ExceptionHandler, 00236 ExceptionRecord, 00237 0, 00238 ContextRecord); 00239 } 00240 } 00241 } 00242 00243 } else if (!IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags)) { 00244 00245 // 00246 // This is an unwind but is not the target frame. Since the function 00247 // is being terminated, finally handlers for all try bodies that are 00248 // presently in scope must be executed. Walk up the SEB list all the 00249 // way to the top executing finally handlers. This corresponds to 00250 // exiting all try bodies that are presently in scope. 00251 // 00252 00253 while (SehContext->CurrentSeb != NULL) { 00254 00255 // 00256 // Get the address of the SEB and then update the SEH context. 00257 // 00258 00259 Seb = SehContext->CurrentSeb; 00260 SehContext->CurrentSeb = Seb->ParentSeb; 00261 00262 if (IS_FINALLY(Seb)) { 00263 00264 // 00265 // This is a finally handler. Get the address of the handler 00266 // from the SEB and call the finally handler. 00267 // 00268 00269 TerminationHandler = (TERMINATION_HANDLER)Seb->HandlerAddress; 00270 ContinuationAddress = 00271 __C_ExecuteTerminationHandler(TRUE, 00272 TerminationHandler, 00273 RealFramePointer); 00274 00275 // 00276 // If the finally handler returns a non-zero result, there 00277 // was a branch out of the handler (to that address) and this 00278 // routine should unwind to that target. 00279 // 00280 00281 if (ContinuationAddress != 0) { 00282 MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord, 00283 SehContext->CurrentSeb); 00284 RtlUnwind(EstablisherFrame, 00285 (PVOID)ContinuationAddress, 00286 ExceptionRecord, 00287 0); 00288 } 00289 } 00290 } 00291 00292 } else { 00293 00294 // 00295 // This is the target frame of an unwind. Since the target may be 00296 // in a different try scope than the one defined by the current SEB 00297 // pointer, finally handlers between the two scopes must execute. 00298 // Walk up the SEB list from the current SEB to the target SEB and 00299 // execute all finally handlers encountered. 00300 // 00301 00302 TargetSeb = (PSEH_BLOCK)ExceptionRecord->ExceptionInformation[0]; 00303 ContinuationAddress = _OtsLocalFinallyUnwind(SehContext, 00304 TargetSeb, 00305 (PVOID)RealFramePointer); 00306 if (ContinuationAddress != 0) { 00307 00308 // 00309 // A non-zero result indicates there was a branch out of a 00310 // finally handler that was being executed during the unwind. 00311 // This routine should unwind to that address. 00312 // 00313 00314 MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord, 00315 SehContext->CurrentSeb); 00316 RtlUnwind(EstablisherFrame, 00317 (PVOID)ContinuationAddress, 00318 ExceptionRecord, 00319 0); 00320 } 00321 } 00322 00323 // 00324 // Continue search for exception or termination handlers. 00325 // 00326 00327 return ExceptionContinueSearch; 00328 }

ULONG_PTR _OtsLocalFinallyUnwind IN PSEH_CONTEXT  SehContext,
IN PSEH_BLOCK  TargetSeb,
IN PVOID  RealFramePointer
 

Definition at line 331 of file ghandler.c.

References __C_ExecuteTerminationHandler(), FALSE, IS_FINALLY, NULL, and TRUE.

Referenced by _OtsCSpecificHandler().

00339 : 00340 00341 This function walks up the SEB tree of the current procedure from the 00342 current SEB to the target SEB and executes all the finally handlers it 00343 encounters. 00344 00345 Calls to this function are inserted into user code by the compiler when 00346 there are branches out of guarded regions that may require finally 00347 handlers to execute. 00348 00349 This function is also called from _OtsCSpecificHandler when the target 00350 frame is reached during an unwind operation. There may be finally handlers 00351 that should execute before resuming execution at the unwind target. 00352 00353 Arguments: 00354 00355 SehContext - Supplies the address of the SEH context structure which is 00356 located in the stack frame. 00357 00358 TargetSeb - Supplies the address of the SEB corresponding to the branch 00359 target address. 00360 00361 RealFramePointer - Supplies the (real frame) pointer of the establisher 00362 frame, which is the current stack frame. This is used to set up the 00363 static link if a finally handler is invoked. 00364 00365 Return Value: 00366 00367 If a branch out of a finally handler is detected, the function value is 00368 the address of the branch target. Otherwise, the function value is zero. 00369 00370 --*/ 00371 00372 { 00373 00374 ULONG_PTR ContinuationAddress; 00375 BOOLEAN Nested; 00376 PSEH_BLOCK Seb; 00377 TERMINATION_HANDLER TerminationHandler; 00378 00379 // 00380 // If the SEB pointers are the same, no finally handlers need to execute. 00381 // The branch is to a target location in the same guarded scope. 00382 // 00383 00384 if (SehContext->CurrentSeb == TargetSeb) { 00385 return 0; 00386 } 00387 00388 // 00389 // If the current SEB scope is not nested within the target SEB scope, no 00390 // finally handlers need to execute. Reset the current SEB pointer to the 00391 // target SEB pointer and return. 00392 // 00393 00394 Nested = FALSE; 00395 Seb = SehContext->CurrentSeb; 00396 00397 while (Seb != NULL) { 00398 Seb = Seb->ParentSeb; 00399 if (Seb == TargetSeb) { 00400 Nested = TRUE; 00401 break; 00402 } 00403 } 00404 if (Nested == FALSE) { 00405 SehContext->CurrentSeb = TargetSeb; 00406 return 0; 00407 } 00408 00409 // 00410 // Walk up the list of SEB blocks executing finally handlers. If a branch 00411 // out of a finally is encountered along the way, return the target 00412 // address, otherwise return 0. 00413 // 00414 00415 while (SehContext->CurrentSeb != TargetSeb) { 00416 00417 // 00418 // Get the address of the SEB and then update the SEH context. 00419 // 00420 00421 Seb = SehContext->CurrentSeb; 00422 SehContext->CurrentSeb = Seb->ParentSeb; 00423 00424 if (IS_FINALLY(Seb)) { 00425 TerminationHandler = (TERMINATION_HANDLER)Seb->HandlerAddress; 00426 ContinuationAddress = 00427 __C_ExecuteTerminationHandler(TRUE, 00428 TerminationHandler, 00429 (ULONG_PTR)RealFramePointer); 00430 if (ContinuationAddress != 0) { 00431 return ContinuationAddress; 00432 } 00433 } 00434 } 00435 return 0; 00436 } }


Generated on Sat May 15 19:43:54 2004 for test by doxygen 1.3.7