00240 :
00241
00242 This function
is called to dispatch an exception to
the proper mode and
00243 to cause
the exception dispatcher to be called.
00244
00245 If
the exception
is a data misalignment,
this is the first chance
for
00246 handling
the exception, and
the current thread has enabled automatic
00247 alignment fixup, then an attempt
is made to emulate
the unaligned
00248 reference.
00249
00250 If
the exception
is a floating exception (N.B. the pseudo status
00251 STATUS_FLOAT_STACK_CHECK is used to signify
this and is converted to the
00252 proper code by examiningg the main status field of the floating point
00253 status
register).
00254
00255 If
the exception
is neither a data misalignment nor a floating point
00256 exception and
the the previous mode
is kernel, then
the exception
00257 dispatcher
is called directly to process
the exception. Otherwise
the
00258 exception record, exception frame, and trap frame contents are copied
00259 to
the user mode stack. The contents of
the exception frame and trap
00260 are then modified such that when
control is returned, execution will
00261 commense in user mode in a routine which will call
the exception
00262 dispatcher.
00263
00264 Arguments:
00265
00266 ExceptionRecord - Supplies a pointer to an exception record.
00267
00268 ExceptionFrame - Supplies a pointer to an exception frame.
00269
00270 TrapFrame - Supplies a pointer to a trap frame.
00271
00272 PreviousMode - Supplies
the previous processor mode.
00273
00274 FirstChance - Supplies a
boolean variable that specifies whether
this
00275
is the first (TRUE) or second (FALSE) time that this exception has
00276 been processed.
00277
00278 Return Value:
00279
00280 None.
00281
00282 --*/
00283
00284 {
00285
00286 CONTEXT ContextFrame;
00287 EXCEPTION_RECORD ExceptionRecord1;
00288 PPLABEL_DESCRIPTOR Plabel;
00289 BOOLEAN UserApcPending;
00290
00291
00292
00293
00294
00295
00296
00297
00298
#if DBG
00299
if (KiBreakOnAlignmentFault !=
FALSE) {
00300
00301
if (ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) {
00302
00303
DbgPrint(
"KI: Alignment fault exr = %p Pc = %p Address = %p\n",
00304 ExceptionRecord,
00305 ExceptionRecord->ExceptionAddress,
00306 ExceptionRecord->ExceptionInformation[2]);
00307
00308 DbgBreakPoint();
00309 }
00310 }
00311
#endif
00312
00313
if ((ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) &&
00314 (FirstChance !=
FALSE)) {
00315
00316
#if DBG
00317
00318
00319
00320
00321
00322
if (PreviousMode ==
KernelMode) {
00323 KiKernelFixupCount += 1;
00324
if ((KiKernelFixupCount & KiKernelFixupMask) == 0) {
00325
DbgPrint(
"KI: Kernel Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n",
00326
PsGetCurrentProcess()->UniqueProcessId,
00327 ExceptionRecord->ExceptionAddress,
00328 ExceptionRecord->ExceptionInformation[1],
00329 KiKernelFixupCount);
00330 }
00331
00332 }
else {
00333 KiUserFixupCount += 1;
00334
if ((KiUserFixupCount & KiUserFixupMask) == 0) {
00335
DbgPrint(
"KI: User Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n",
00336
PsGetCurrentProcess()->UniqueProcessId,
00337 ExceptionRecord->ExceptionAddress,
00338 ExceptionRecord->ExceptionInformation[1],
00339 KiUserFixupCount);
00340 }
00341 }
00342
00343
#endif
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
if ( (
KiEnableAlignmentFaultExceptions == 0) ||
00356
00357 ((
KeGetCurrentThread()->AutoAlignment !=
FALSE) ||
00358 (
KeGetCurrentThread()->ApcState.Process->AutoAlignment !=
FALSE)) ||
00359
00360 (((
PsGetCurrentProcess()->DebugPort ==
NULL) || (PreviousMode ==
KernelMode)) &&
00361 (
KiEnableAlignmentFaultExceptions == 2)) ) {
00362
00363
if (
KiEmulateReference(ExceptionRecord,
00364 ExceptionFrame,
00365 TrapFrame) !=
FALSE)
00366 {
00367
KeGetCurrentPrcb()->KeAlignmentFixupCount += 1;
00368
goto Handled2;
00369 }
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
if ((ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS) ||
00384 (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS)) {
00385
00386
if (
KiEmulateFloat(ExceptionRecord, ExceptionFrame, TrapFrame)) {
00387
00388
00389
00390
00391
00392
return;
00393 }
00394 }
00395
00396
00397
00398
00399
00400
00401 ContextFrame.ContextFlags =
CONTEXT_FULL;
00402
KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame);
00403
KeGetCurrentPrcb()->KeExceptionDispatchCount += 1;
00404
00405
00406
00407
00408
00409
if (PreviousMode ==
KernelMode) {
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
if (FirstChance !=
FALSE) {
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
RtlpCaptureRnats(&ContextFrame);
00439 TrapFrame->RsRNAT = ContextFrame.RsRNAT;
00440
00441
00442
00443
00444
00445
00446
00447
if ((
KiDebugRoutine !=
NULL) &&
00448 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
00449 (
KdIsThisAKdTrap(ExceptionRecord,
00450 &ContextFrame,
00451 KernelMode) !=
FALSE)) {
00452
00453
if (((
KiDebugRoutine) (TrapFrame,
00454 ExceptionFrame,
00455 ExceptionRecord,
00456 &ContextFrame,
00457
KernelMode,
00458
FALSE)) !=
FALSE) {
00459
00460
goto Handled1;
00461 }
00462 }
00463
00464
if (
RtlDispatchException(ExceptionRecord, &ContextFrame) !=
FALSE) {
00465
goto Handled1;
00466 }
00467 }
00468
00469
00470
00471
00472
00473
if (
KiDebugRoutine !=
NULL) {
00474
if (((
KiDebugRoutine) (TrapFrame,
00475 ExceptionFrame,
00476 ExceptionRecord,
00477 &ContextFrame,
00478 PreviousMode,
00479
TRUE)) !=
FALSE) {
00480
goto Handled1;
00481 }
00482 }
00483
00484
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
00485 ExceptionRecord->ExceptionCode,
00486 (ULONG_PTR)ExceptionRecord->ExceptionAddress,
00487 ExceptionRecord->ExceptionInformation[0],
00488 ExceptionRecord->ExceptionInformation[1]);
00489
00490 }
else {
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
if (FirstChance !=
FALSE) {
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
if ((
KiDebugRoutine !=
NULL) &&
00529 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
00530 (
KdIsThisAKdTrap(ExceptionRecord,
00531 &ContextFrame,
00532 UserMode) !=
FALSE) &&
00533 ((
PsGetCurrentProcess()->DebugPort ==
NULL) ||
00534 ((
PsGetCurrentProcess()->DebugPort !=
NULL) &&
00535 (ExceptionRecord->ExceptionInformation[0] !=
00536 DEBUG_STOP_BREAKPOINT)))) {
00537
00538
if (((
KiDebugRoutine) (TrapFrame,
00539 ExceptionFrame,
00540 ExceptionRecord,
00541 &ContextFrame,
00542
UserMode,
00543
FALSE)) !=
FALSE) {
00544
00545
goto Handled1;
00546 }
00547 }
00548
00549
00550
00551
00552
00553
if (
DbgkForwardException(ExceptionRecord, TRUE, FALSE)) {
00554 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode);
00555
goto Handled2;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 repeat:
00594
try {
00595
00596
00597
00598
00599
00600
00601 ULONG Length = (STACK_SCRATCH_AREA + 15 +
00602
sizeof(EXCEPTION_REGISTRATION_RECORD) +
00603
sizeof(EXCEPTION_RECORD) +
sizeof(CONTEXT)) & ~(15);
00604 ULONGLONG UserStack = (ContextFrame.IntSp & (~15)) - Length;
00605 ULONGLONG ContextSlot = UserStack + STACK_SCRATCH_AREA;
00606 ULONGLONG ExceptSlot = ContextSlot +
sizeof(CONTEXT);
00607 PULONGLONG PUserStack = (PULONGLONG) UserStack;
00608
00609
00610
00611
00612
00613
00614
ProbeForWrite((PCHAR)UserStack, Length,
sizeof(QUAD));
00615 RtlMoveMemory((PVOID)ContextSlot, &ContextFrame,
00616
sizeof(CONTEXT));
00617 RtlMoveMemory((PVOID)ExceptSlot, ExceptionRecord,
00618
sizeof(EXCEPTION_RECORD));
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 TrapFrame->RsPFS = TrapFrame->StIFS;
00631 TrapFrame->StIFS &= 0xffffffc000000000;
00632 TrapFrame->StIPSR &= ~((0x3i64 << PSR_RI) | (0x1i64 << PSR_IS));
00633 TrapFrame->IntSp = UserStack;
00634 TrapFrame->IntNats = 0;
00635
00636 ExceptionFrame->IntS0 = ExceptSlot;
00637 ExceptionFrame->IntS1 = ContextSlot;
00638 ExceptionFrame->IntNats = 0;
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 Plabel = (PPLABEL_DESCRIPTOR)
KeUserExceptionDispatcher;
00649 TrapFrame->StIIP = Plabel->EntryPoint;
00650 TrapFrame->IntGp = Plabel->GlobalPointer;
00651
00652
return;
00653
00654
00655
00656
00657
00658
00659 } except (
KiCopyInformation(&ExceptionRecord1,
00660 (GetExceptionInformation())->ExceptionRecord)) {
00661
00662
00663
00664
00665
00666
00667
00668
00669
if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) {
00670 ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress;
00671 RtlMoveMemory((PVOID)ExceptionRecord,
00672 &ExceptionRecord1,
sizeof(EXCEPTION_RECORD));
00673
goto repeat;
00674 }
00675 }
00676 }
00677
00678
00679
00680
00681
00682 UserApcPending =
KeGetCurrentThread()->ApcState.UserApcPending;
00683
if (
DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
00684 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode);
00685
goto Handled2;
00686
00687 }
else if (
DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
00688 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode);
00689
goto Handled2;
00690
00691 }
else {
00692 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
00693
KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
00694 ExceptionRecord->ExceptionCode,
00695 (ULONG_PTR)ExceptionRecord->ExceptionAddress,
00696 ExceptionRecord->ExceptionInformation[0],
00697 ExceptionRecord->ExceptionInformation[1]);
00698 }
00699 }
00700
00701
00702
00703
00704
00705
00706 Handled1:
00707
KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame,
00708 ContextFrame.ContextFlags, PreviousMode);
00709
00710
00711
00712
00713
00714
00715
00716
00717 Handled2:
00718
return;
00719 }