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
00176
00177
00178
00179
00180
00181 SehContext = (PSEH_CONTEXT)((ULONG_PTR)EstablisherFrame +
00182 (LONG_PTR)DispatcherContext->FunctionEntry->HandlerData);
00183 RealFramePointer = SehContext->RealFramePointer;
00184
00185
00186
00187
00188
00189
00190
if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
00191
00192
00193
00194
00195
00196
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
00207
00208
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
00220
00221
00222
00223
00224
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
00247
00248
00249
00250
00251
00252
00253
while (SehContext->CurrentSeb !=
NULL) {
00254
00255
00256
00257
00258
00259 Seb = SehContext->CurrentSeb;
00260 SehContext->CurrentSeb = Seb->ParentSeb;
00261
00262
if (
IS_FINALLY(Seb)) {
00263
00264
00265
00266
00267
00268
00269 TerminationHandler = (TERMINATION_HANDLER)Seb->HandlerAddress;
00270 ContinuationAddress =
00271
__C_ExecuteTerminationHandler(TRUE,
00272 TerminationHandler,
00273 RealFramePointer);
00274
00275
00276
00277
00278
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
00296
00297
00298
00299
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
00310
00311
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
00325
00326
00327
return ExceptionContinueSearch;
00328 }