00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
#include "ntrtlp.h"
00031
00032
00033
00034
00035
00036
00037 typedef struct _DISPATCHER_CONTEXT {
00038 PEXCEPTION_REGISTRATION_RECORD
RegistrationPointer;
00039 }
DISPATCHER_CONTEXT;
00040
00041
00042
00043
00044
00045 EXCEPTION_DISPOSITION
00046
RtlpExecuteHandlerForException (
00047 IN PEXCEPTION_RECORD ExceptionRecord,
00048 IN PVOID EstablisherFrame,
00049 IN OUT PCONTEXT ContextRecord,
00050 IN OUT PVOID DispatcherContext,
00051 IN PEXCEPTION_ROUTINE ExceptionRoutine
00052 );
00053
00054
00055
00056
00057
00058 EXCEPTION_DISPOSITION
00059
RtlpExecuteHandlerForUnwind (
00060 IN PEXCEPTION_RECORD ExceptionRecord,
00061 IN PVOID EstablisherFrame,
00062 IN OUT PCONTEXT ContextRecord,
00063 IN OUT PVOID DispatcherContext,
00064 IN PEXCEPTION_ROUTINE ExceptionRoutine
00065 );
00066
00067
00068
00069 BOOLEAN
00070 RtlDispatchException (
00071 IN PEXCEPTION_RECORD ExceptionRecord,
00072 IN PCONTEXT ContextRecord
00073 )
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 {
00100
00101
DISPATCHER_CONTEXT DispatcherContext;
00102 EXCEPTION_DISPOSITION Disposition;
00103 PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
00104 PEXCEPTION_REGISTRATION_RECORD NestedRegistration;
00105 ULONG HighAddress;
00106 ULONG HighLimit;
00107 ULONG LowLimit;
00108 EXCEPTION_RECORD ExceptionRecord1;
00109
00110
#if !defined(WX86_i386)
00111
00112 ULONG
Index;
00113
00114
#endif
00115
00116
00117
00118
00119
00120
RtlpGetStackLimits(&LowLimit, &HighLimit);
00121
00122
00123
00124
00125
00126
00127
00128 RegistrationPointer =
RtlpGetRegistrationHead();
00129 NestedRegistration = 0;
00130
00131
while (RegistrationPointer != EXCEPTION_CHAIN_END) {
00132
00133
00134
00135
00136
00137
00138
00139
00140 HighAddress = (ULONG)RegistrationPointer +
00141
sizeof(EXCEPTION_REGISTRATION_RECORD);
00142
00143
if ( ((ULONG)RegistrationPointer < LowLimit) ||
00144 (HighAddress > HighLimit) ||
00145 (((ULONG)RegistrationPointer & 0x3) != 0) ) {
00146
00147
#if defined(NTOS_KERNEL_RUNTIME)
00148
00149
00150
00151
00152
00153
00154 ULONG TestAddress = (ULONG)RegistrationPointer;
00155
00156
if (((TestAddress & 0x3) == 0) &&
00157 KeGetCurrentIrql() >=
DISPATCH_LEVEL) {
00158
00159 PKPRCB Prcb =
KeGetCurrentPrcb();
00160 ULONG DpcStack = (ULONG)Prcb->DpcStack;
00161
00162
if ((Prcb->DpcRoutineActive) &&
00163 (HighAddress <= DpcStack) &&
00164 (TestAddress >= DpcStack - KERNEL_STACK_SIZE)) {
00165
00166
00167
00168
00169
00170
00171
00172 HighLimit = DpcStack;
00173 LowLimit = DpcStack - KERNEL_STACK_SIZE;
00174
continue;
00175 }
00176 }
00177
00178
#endif
00179
00180 ExceptionRecord->ExceptionFlags |=
EXCEPTION_STACK_INVALID;
00181
return FALSE;
00182 }
00183
00184
#if !defined(WX86_i386)
00185
00186
00187
00188
00189
00190
00191
00192
00193
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00194
Index =
RtlpLogExceptionHandler(
00195 ExceptionRecord,
00196 ContextRecord,
00197 0,
00198 (PULONG)RegistrationPointer,
00199 4 *
sizeof(ULONG));
00200
00201
00202 }
00203
#endif
00204
00205 Disposition =
RtlpExecuteHandlerForException(
00206 ExceptionRecord,
00207 (PVOID)RegistrationPointer,
00208 ContextRecord,
00209 (PVOID)&DispatcherContext,
00210 (PEXCEPTION_ROUTINE)RegistrationPointer->Handler);
00211
00212
#if !defined(WX86_i386)
00213
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00214
RtlpLogLastExceptionDisposition(
Index, Disposition);
00215 }
00216
#endif
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
if (NestedRegistration == RegistrationPointer) {
00227 ExceptionRecord->ExceptionFlags &= (~
EXCEPTION_NESTED_CALL);
00228 NestedRegistration = 0;
00229 }
00230
00231
00232
00233
00234
00235
switch (Disposition) {
00236
00237
00238
00239
00240
00241
00242
00243
00244
case ExceptionContinueExecution :
00245
if ((ExceptionRecord->ExceptionFlags &
00246
EXCEPTION_NONCONTINUABLE) != 0) {
00247 ExceptionRecord1.ExceptionCode =
00248 STATUS_NONCONTINUABLE_EXCEPTION;
00249 ExceptionRecord1.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00250 ExceptionRecord1.ExceptionRecord = ExceptionRecord;
00251 ExceptionRecord1.NumberParameters = 0;
00252
RtlRaiseException(&ExceptionRecord1);
00253 }
else {
00254
return TRUE;
00255 }
00256
00257
00258
00259
00260
00261
00262
case ExceptionContinueSearch :
00263
break;
00264
00265
00266
00267
00268
00269
00270
00271
case ExceptionNestedException :
00272 ExceptionRecord->ExceptionFlags |=
EXCEPTION_NESTED_CALL;
00273
if (DispatcherContext.RegistrationPointer > NestedRegistration) {
00274 NestedRegistration = DispatcherContext.RegistrationPointer;
00275 }
00276
break;
00277
00278
00279
00280
00281
00282
00283
default :
00284 ExceptionRecord1.ExceptionCode = STATUS_INVALID_DISPOSITION;
00285 ExceptionRecord1.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00286 ExceptionRecord1.ExceptionRecord = ExceptionRecord;
00287 ExceptionRecord1.NumberParameters = 0;
00288
RtlRaiseException(&ExceptionRecord1);
00289
break;
00290 }
00291
00292
00293
00294
00295
00296
00297 RegistrationPointer = RegistrationPointer->Next;
00298 }
00299
return FALSE;
00300 }
00301
00302
VOID
00303 RtlUnwind (
00304 IN PVOID TargetFrame OPTIONAL,
00305 IN PVOID TargetIp OPTIONAL,
00306 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
00307 IN PVOID ReturnValue
00308 )
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 {
00356 PCONTEXT ContextRecord;
00357 CONTEXT ContextRecord1;
00358
DISPATCHER_CONTEXT DispatcherContext;
00359 EXCEPTION_DISPOSITION Disposition;
00360 PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
00361 PEXCEPTION_REGISTRATION_RECORD PriorPointer;
00362 ULONG HighAddress;
00363 ULONG HighLimit;
00364 ULONG LowLimit;
00365 EXCEPTION_RECORD ExceptionRecord1;
00366 EXCEPTION_RECORD ExceptionRecord2;
00367
00368
00369
00370
00371
00372
RtlpGetStackLimits(&LowLimit, &HighLimit);
00373
00374
00375
00376
00377
00378
00379
if (ARGUMENT_PRESENT(ExceptionRecord) ==
FALSE) {
00380 ExceptionRecord = &ExceptionRecord1;
00381 ExceptionRecord1.ExceptionCode = STATUS_UNWIND;
00382 ExceptionRecord1.ExceptionFlags = 0;
00383 ExceptionRecord1.ExceptionRecord =
NULL;
00384 ExceptionRecord1.ExceptionAddress =
RtlpGetReturnAddress();
00385 ExceptionRecord1.NumberParameters = 0;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
if (ARGUMENT_PRESENT(TargetFrame) ==
TRUE) {
00395 ExceptionRecord->ExceptionFlags |=
EXCEPTION_UNWINDING;
00396 }
else {
00397 ExceptionRecord->ExceptionFlags |= (
EXCEPTION_UNWINDING |
00398
EXCEPTION_EXIT_UNWIND);
00399 }
00400
00401
00402
00403
00404
00405 ContextRecord = &ContextRecord1;
00406 ContextRecord1.ContextFlags =
CONTEXT_INTEGER |
CONTEXT_CONTROL | CONTEXT_SEGMENTS;
00407
RtlpCaptureContext(ContextRecord);
00408
00409
#ifdef STD_CALL
00410
00411
00412
00413 ContextRecord->Esp +=
sizeof(TargetFrame) +
00414
sizeof(TargetIp) +
00415
sizeof(ExceptionRecord) +
00416
sizeof(ReturnValue);
00417
#endif
00418
ContextRecord->Eax = (ULONG)ReturnValue;
00419
00420
00421
00422
00423
00424
00425
00426 RegistrationPointer =
RtlpGetRegistrationHead();
00427
while (RegistrationPointer != EXCEPTION_CHAIN_END) {
00428
00429
00430
00431
00432
00433
00434
if ((ULONG)RegistrationPointer == (ULONG)TargetFrame) {
00435 ZwContinue(ContextRecord,
FALSE);
00436
00437
00438
00439
00440
00441
00442 }
else if ( (ARGUMENT_PRESENT(TargetFrame) ==
TRUE) &&
00443 ((ULONG)TargetFrame < (ULONG)RegistrationPointer) ) {
00444 ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
00445 ExceptionRecord2.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00446 ExceptionRecord2.ExceptionRecord = ExceptionRecord;
00447 ExceptionRecord2.NumberParameters = 0;
00448
RtlRaiseException(&ExceptionRecord2);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458 HighAddress = (ULONG)RegistrationPointer +
00459
sizeof(EXCEPTION_REGISTRATION_RECORD);
00460
00461
if ( ((ULONG)RegistrationPointer < LowLimit) ||
00462 (HighAddress > HighLimit) ||
00463 (((ULONG)RegistrationPointer & 0x3) != 0) ) {
00464
00465
#if defined(NTOS_KERNEL_RUNTIME)
00466
00467
00468
00469
00470
00471
00472 ULONG TestAddress = (ULONG)RegistrationPointer;
00473
00474
if (((TestAddress & 0x3) == 0) &&
00475 KeGetCurrentIrql() >=
DISPATCH_LEVEL) {
00476
00477 PKPRCB Prcb =
KeGetCurrentPrcb();
00478 ULONG DpcStack = (ULONG)Prcb->DpcStack;
00479
00480
if ((Prcb->DpcRoutineActive) &&
00481 (HighAddress <= DpcStack) &&
00482 (TestAddress >= DpcStack - KERNEL_STACK_SIZE)) {
00483
00484
00485
00486
00487
00488
00489
00490 HighLimit = DpcStack;
00491 LowLimit = DpcStack - KERNEL_STACK_SIZE;
00492
continue;
00493 }
00494 }
00495
00496
#endif
00497
00498 ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK;
00499 ExceptionRecord2.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00500 ExceptionRecord2.ExceptionRecord = ExceptionRecord;
00501 ExceptionRecord2.NumberParameters = 0;
00502
RtlRaiseException(&ExceptionRecord2);
00503 }
else {
00504
00505
00506
00507
00508
00509
00510
00511
00512 Disposition =
RtlpExecuteHandlerForUnwind(
00513 ExceptionRecord,
00514 (PVOID)RegistrationPointer,
00515 ContextRecord,
00516 (PVOID)&DispatcherContext,
00517 RegistrationPointer->Handler);
00518
00519
00520
00521
00522
00523
switch (Disposition) {
00524
00525
00526
00527
00528
00529
00530
case ExceptionContinueSearch :
00531
break;
00532
00533
00534
00535
00536
00537
00538
case ExceptionCollidedUnwind :
00539
00540
00541
00542
00543
00544
00545 RegistrationPointer = DispatcherContext.RegistrationPointer;
00546
break;
00547
00548
00549
00550
00551
00552
00553
00554
default :
00555 ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
00556 ExceptionRecord2.ExceptionFlags =
EXCEPTION_NONCONTINUABLE;
00557 ExceptionRecord2.ExceptionRecord = ExceptionRecord;
00558 ExceptionRecord2.NumberParameters = 0;
00559
RtlRaiseException(&ExceptionRecord2);
00560
break;
00561 }
00562
00563
00564
00565
00566
00567 PriorPointer = RegistrationPointer;
00568 RegistrationPointer = RegistrationPointer->Next;
00569
00570
00571
00572
00573
00574
RtlpUnlinkHandler(PriorPointer);
00575
00576
00577
00578
00579
00580
00581 }
00582 }
00583
00584
if (TargetFrame == EXCEPTION_CHAIN_END) {
00585
00586
00587
00588
00589
00590
00591
00592
00593 ZwContinue(ContextRecord,
FALSE);
00594
00595 }
else {
00596
00597
00598
00599
00600
00601
00602
00603
00604 ZwRaiseException(ExceptionRecord, ContextRecord,
FALSE);
00605
00606 }
00607
return;
00608 }