windows-nt/Source/XPSP1/NT/base/ntos/ke/amd64/xcpt4.c
2020-09-26 16:20:57 +08:00

2549 lines
46 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
xcpt4.c
Abstract:
This module implements user mode exception tests.
Author:
David N. Cutler (davec) 18-Sep-1990
Environment:
Kernel mode only.
Revision History:
--*/
#include "ki.h"
#pragma hdrstop
#include "setjmpex.h"
#include "float.h"
#pragma warning(disable:4532)
//
// Define switch constants.
//
#define BLUE 0
#define RED 1
//
// Define guaranteed fault.
//
#define FAULT *(volatile int *)0
//
// Define function prototypes.
//
VOID
addtwo (
IN LONG First,
IN LONG Second,
IN PLONG Place
);
VOID
bar1 (
IN NTSTATUS Status,
IN PLONG Counter
);
VOID
bar2 (
IN PLONG BlackHole,
IN PLONG BadAddress,
IN PLONG Counter
);
VOID
dojump (
IN jmp_buf JumpBuffer,
IN PLONG Counter
);
LONG
Echo(
IN LONG Value
);
VOID
eret (
IN NTSTATUS Status,
IN PLONG Counter
);
VOID
except1 (
IN PLONG Counter
);
ULONG
except2 (
IN PEXCEPTION_POINTERS ExceptionPointers,
IN PLONG Counter
);
ULONG
except3 (
IN PEXCEPTION_POINTERS ExceptionPointers,
IN PLONG Counter
);
VOID
foo1 (
IN NTSTATUS Status
);
VOID
foo2 (
IN PLONG BlackHole,
IN PLONG BadAddress
);
VOID
fret (
IN PLONG Counter
);
BOOLEAN
Tkm (
VOID
);
VOID
Test61Part2 (
IN OUT PULONG Counter
);
VOID
PerformFpTest(
VOID
);
double
SquareDouble (
IN double op
);
VOID
SquareDouble17E300 (
OUT PVOID ans
);
LONG
test66sub (
IN PLONG Counter
);
LONG
test67sub (
IN PLONG Counter
);
VOID
xcpt4 (
VOID
)
{
PLONG BadAddress;
PCHAR BadByte;
PLONG BlackHole;
ULONG Index1;
ULONG Index2 = RED;
jmp_buf JumpBuffer;
LONG Counter;
EXCEPTION_RECORD ExceptionRecord;
double doubleresult;
//
// Announce start of exception test.
//
DbgPrint("Start of exception test\n");
//
// Initialize exception record.
//
ExceptionRecord.ExceptionCode = STATUS_INTEGER_OVERFLOW;
ExceptionRecord.ExceptionFlags = 0;
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
//
// Initialize pointers.
//
BadAddress = (PLONG)NULL;
BadByte = (PCHAR)NULL;
BadByte += 1;
BlackHole = &Counter;
//
// Simply try statement with a finally clause that is entered sequentially.
//
DbgPrint(" test1...");
Counter = 0;
try {
Counter += 1;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 1;
}
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try statement with an exception clause that is never executed
// because there is no exception raised in the try clause.
//
DbgPrint(" test2...");
Counter = 0;
try {
Counter += 1;
} except (Counter) {
Counter += 1;
}
if (Counter != 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try statement with an exception handler that is never executed
// because the exception expression continues execution.
//
DbgPrint(" test3...");
Counter = 0;
try {
Counter -= 1;
RtlRaiseException(&ExceptionRecord);
} except (Counter) {
Counter -= 1;
}
if (Counter != - 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try statement with an exception clause that is always executed.
//
DbgPrint(" test4...");
Counter = 0;
try {
Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except (Counter) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try statement with an exception clause that is always executed.
//
DbgPrint(" test5...");
Counter = 0;
try {
Counter += 1;
*BlackHole += *BadAddress;
} except (Counter) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simply try statement with a finally clause that is entered as the
// result of an exception.
//
DbgPrint(" test6...");
Counter = 0;
try {
try {
Counter += 1;
RtlRaiseException(&ExceptionRecord);
} finally {
if (abnormal_termination() != FALSE) {
Counter += 1;
}
}
} except (Counter) {
if (Counter == 2) {
Counter += 1;
}
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simply try statement with a finally clause that is entered as the
// result of an exception.
//
DbgPrint(" test7...");
Counter = 0;
try {
try {
Counter += 1;
*BlackHole += *BadAddress;
} finally {
if (abnormal_termination() != FALSE) {
Counter += 1;
}
}
} except (Counter) {
if (Counter == 2) {
Counter += 1;
}
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that calls a function which raises an exception.
//
DbgPrint(" test8...");
Counter = 0;
try {
Counter += 1;
foo1(STATUS_ACCESS_VIOLATION);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that calls a function which raises an exception.
//
DbgPrint(" test9...");
Counter = 0;
try {
Counter += 1;
foo2(BlackHole, BadAddress);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that calls a function which calls a function that
// raises an exception. The first function has a finally clause
// that must be executed for this test to work.
//
DbgPrint(" test10...");
Counter = 0;
try {
bar1(STATUS_ACCESS_VIOLATION, &Counter);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter -= 1;
}
if (Counter != 98) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that calls a function which calls a function that
// raises an exception. The first function has a finally clause
// that must be executed for this test to work.
//
DbgPrint(" test11...");
Counter = 0;
try {
bar2(BlackHole, BadAddress, &Counter);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter -= 1;
}
if (Counter != 98) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A try within an except
//
DbgPrint(" test12...");
Counter = 0;
try {
foo1(STATUS_ACCESS_VIOLATION);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
try {
foo1(STATUS_SUCCESS);
} except ((GetExceptionCode() == STATUS_SUCCESS) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
if (Counter != 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded...");
}
Counter += 1;
}
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A try within an except
//
DbgPrint(" test13...");
Counter = 0;
try {
foo2(BlackHole, BadAddress);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
try {
foo1(STATUS_SUCCESS);
} except ((GetExceptionCode() == STATUS_SUCCESS) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
if (Counter != 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded...");
}
Counter += 1;
}
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A goto from an exception clause that needs to pass
// through a finally
//
DbgPrint(" test14...");
Counter = 0;
try {
try {
foo1(STATUS_ACCESS_VIOLATION);
} except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
goto t9;
}
} finally {
Counter += 1;
}
t9:;
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A goto from an finally clause that needs to pass
// through a finally
//
DbgPrint(" test15...");
Counter = 0;
try {
try {
Counter += 1;
} finally {
Counter += 1;
goto t10;
}
} finally {
Counter += 1;
}
t10:;
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A goto from an exception clause that needs to pass
// through a finally into the outer finally clause.
//
DbgPrint(" test16...");
Counter = 0;
try {
try {
try {
Counter += 1;
foo1(STATUS_INTEGER_OVERFLOW);
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 1;
goto t11;
}
} finally {
Counter += 1;
}
t11:;
} finally {
Counter += 1;
}
if (Counter != 4) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A goto from an finally clause that needs to pass
// through a finally into the outer finally clause.
//
DbgPrint(" test17...");
Counter = 0;
try {
try {
Counter += 1;
} finally {
Counter += 1;
goto t12;
}
t12:;
} finally {
Counter += 1;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A return from an except clause
//
DbgPrint(" test18...");
Counter = 0;
try {
Counter += 1;
eret(STATUS_ACCESS_VIOLATION, &Counter);
} finally {
Counter += 1;
}
if (Counter != 4) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A return from a finally clause
//
DbgPrint(" test19...");
Counter = 0;
try {
Counter += 1;
fret(&Counter);
} finally {
Counter += 1;
}
if (Counter != 5) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A simple set jump followed by a long jump.
//
DbgPrint(" test20...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
Counter += 1;
longjmp(JumpBuffer, 1);
} else {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump followed by a long jump out of a finally clause that is
// sequentially executed.
//
DbgPrint(" test21...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
try {
Counter += 1;
} finally {
Counter += 1;
longjmp(JumpBuffer, 1);
}
} else {
Counter += 1;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump within a try clause followed by a long jump out of a
// finally clause that is sequentially executed.
//
DbgPrint(" test22...");
Counter = 0;
try {
if (setjmp(JumpBuffer) == 0) {
Counter += 1;
} else {
Counter += 1;
}
} finally {
Counter += 1;
if (Counter == 2) {
Counter += 1;
longjmp(JumpBuffer, 1);
}
}
if (Counter != 5) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump followed by a try/except, followed by a try/finally where
// the try body of the try/finally raises an exception that is handled
// by the try/excecpt which causes the try/finally to do a long jump out
// of a finally clause. This will create a collided unwind.
//
DbgPrint(" test23...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
try {
try {
Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} finally {
Counter += 1;
longjmp(JumpBuffer, 1);
}
} except(EXCEPTION_EXECUTE_HANDLER) {
Counter += 1;
}
} else {
Counter += 1;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump followed by a try/except, followed by a several nested
// try/finally's where the inner try body of the try/finally raises an
// exception that is handled by the try/except which causes the
// try/finally to do a long jump out of a finally clause. This will
// create a collided unwind.
//
DbgPrint(" test24...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
try {
try {
try {
try {
Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} finally {
Counter += 1;
}
} finally {
Counter += 1;
longjmp(JumpBuffer, 1);
}
} finally {
Counter += 1;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
Counter += 1;
}
} else {
Counter += 1;
}
if (Counter != 5) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump followed by a try/except, followed by a try/finally which
// calls a subroutine which contains a try finally that raises an
// exception that is handled to the try/except.
//
DbgPrint(" test25...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
try {
try {
try {
Counter += 1;
dojump(JumpBuffer, &Counter);
} finally {
Counter += 1;
}
} finally {
Counter += 1;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
Counter += 1;
}
} else {
Counter += 1;
}
if (Counter != 7) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A set jump followed by a try/except, followed by a try/finally which
// calls a subroutine which contains a try finally that raises an
// exception that is handled to the try/except.
//
DbgPrint(" test26...");
Counter = 0;
if (setjmp(JumpBuffer) == 0) {
try {
try {
try {
try {
Counter += 1;
dojump(JumpBuffer, &Counter);
} finally {
Counter += 1;
}
} finally {
Counter += 1;
longjmp(JumpBuffer, 1);
}
} finally {
Counter += 1;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
Counter += 1;
}
} else {
Counter += 1;
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Test nested exceptions.
//
DbgPrint(" test27...");
Counter = 0;
try {
try {
Counter += 1;
except1(&Counter);
} except(except2(GetExceptionInformation(), &Counter)) {
Counter += 2;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
Counter += 3;
}
if (Counter != 55) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that causes an integer overflow exception.
//
DbgPrint(" test28...");
Counter = 0;
try {
Counter += 1;
addtwo(0x7fff0000, 0x10000, &Counter);
} except ((GetExceptionCode() == STATUS_INTEGER_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Simple try that raises an misaligned data exception.
//
#if 0
DbgPrint(" test29...");
Counter = 0;
try {
Counter += 1;
foo2(BlackHole, (PLONG)BadByte);
} except ((GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
#endif
//
// Continue from a try body with an exception clause in a loop.
//
DbgPrint(" test30...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 0) {
continue;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 40;
}
Counter += 2;
}
if (Counter != 15) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from a try body with an finally clause in a loop.
//
DbgPrint(" test31...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 0) {
continue;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
}
if (Counter != 40) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from doubly nested try body with an exception clause in a
// loop.
//
DbgPrint(" test32...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 0) {
continue;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 10;
}
Counter += 2;
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 20;
}
Counter += 3;
}
if (Counter != 30) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from doubly nested try body with an finally clause in a loop.
//
DbgPrint(" test33...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 0) {
continue;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
} finally {
Counter += 4;
}
Counter += 5;
}
if (Counter != 105) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from a finally clause in a loop.
//
DbgPrint(" test34...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 0) {
Counter += 1;
}
} finally {
Counter += 2;
continue;
}
Counter += 4;
}
if (Counter != 25) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from a doubly nested finally clause in a loop.
//
DbgPrint(" test35...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 0) {
Counter += 1;
}
} finally {
Counter += 2;
continue;
}
Counter += 4;
} finally {
Counter += 5;
}
Counter += 6;
}
if (Counter != 75) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Continue from a doubly nested finally clause in a loop.
//
DbgPrint(" test36...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 0) {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 4;
} finally {
Counter += 5;
continue;
}
Counter += 6;
}
if (Counter != 115) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a try body with an exception clause in a loop.
//
DbgPrint(" test37...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 40;
}
Counter += 2;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a try body with an finally clause in a loop.
//
DbgPrint(" test38...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from doubly nested try body with an exception clause in a
// loop.
//
DbgPrint(" test39...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 10;
}
Counter += 2;
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 20;
}
Counter += 3;
}
if (Counter != 6) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from doubly nested try body with an finally clause in a loop.
//
DbgPrint(" test40...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
} finally {
Counter += 4;
}
Counter += 5;
}
if (Counter != 21) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a finally clause in a loop.
//
DbgPrint(" test41...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
break;
}
Counter += 4;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a doubly nested finally clause in a loop.
//
DbgPrint(" test42...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
break;
}
Counter += 4;
} finally {
Counter += 5;
}
Counter += 6;
}
if (Counter != 7) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a doubly nested finally clause in a loop.
//
DbgPrint(" test43...");
Counter = 0;
for (Index1 = 0; Index1 < 10; Index1 += 1) {
try {
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 4;
} finally {
Counter += 5;
break;
}
Counter += 6;
}
if (Counter != 11) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a try body with an exception clause in a switch.
//
DbgPrint(" test44...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 40;
}
Counter += 2;
break;
}
if (Counter != 0) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a try body with an finally clause in a switch.
//
DbgPrint(" test45...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
}
if (Counter != 2) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from doubly nested try body with an exception clause in a
// switch.
//
DbgPrint(" test46...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 10;
}
Counter += 2;
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 20;
}
Counter += 3;
}
if (Counter != 0) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from doubly nested try body with an finally clause in a switch.
//
DbgPrint(" test47...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
try {
if ((Index1 & 0x1) == 1) {
break;
} else {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 3;
} finally {
Counter += 4;
}
Counter += 5;
}
if (Counter != 6) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a finally clause in a switch.
//
DbgPrint(" test48...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
break;
}
Counter += 4;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a doubly nested finally clause in a switch.
//
DbgPrint(" test49...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
break;
}
Counter += 4;
} finally {
Counter += 5;
}
Counter += 6;
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Break from a doubly nested finally clause in a switch.
//
DbgPrint(" test50...");
Counter = 0;
Index1 = 1;
switch (Index2) {
case BLUE:
Counter += 100;
break;
case RED:
try {
try {
if ((Index1 & 0x1) == 1) {
Counter += 1;
}
} finally {
Counter += 2;
}
Counter += 4;
} finally {
Counter += 5;
break;
}
Counter += 6;
}
if (Counter != 12) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Leave from an if in a simple try/finally.
//
DbgPrint(" test51...");
Counter = 0;
try {
if (Echo(Counter) == Counter) {
Counter += 3;
leave;
} else {
Counter += 100;
}
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Leave from a loop in a simple try/finally.
//
DbgPrint(" test52...");
Counter = 0;
try {
for (Index1 = 0; Index1 < 10; Index1 += 1) {
if (Echo(Index1) == Index1) {
Counter += 3;
leave;
}
Counter += 100;
}
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Leave from a switch in a simple try/finally.
//
DbgPrint(" test53...");
Counter = 0;
try {
switch (Index2) {
case BLUE:
break;
case RED:
Counter += 3;
leave;
}
Counter += 100;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Counter != 8) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Leave from an if in doubly nested try/finally followed by a leave
// from an if in the outer try/finally.
//
DbgPrint(" test54...");
Counter = 0;
try {
try {
if (Echo(Counter) == Counter) {
Counter += 3;
leave;
} else {
Counter += 100;
}
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Echo(Counter) == Counter) {
Counter += 3;
leave;
} else {
Counter += 100;
}
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Counter != 16) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Leave from an if in doubly nested try/finally followed by a leave
// from the finally of the outer try/finally.
//
DbgPrint(" test55...");
Counter = 0;
try {
try {
if (Echo(Counter) == Counter) {
Counter += 3;
leave;
} else {
Counter += 100;
}
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
leave;
}
}
Counter += 100;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
if (Counter != 13) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/finally within the except clause of a try/except that is always
// executed.
//
DbgPrint(" test56...");
Counter = 0;
try {
Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except (Counter) {
try {
Counter += 3;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
}
if (Counter != 9) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/finally within the finally clause of a try/finally.
//
DbgPrint(" test57...");
Counter = 0;
try {
Counter += 1;
} finally {
if (abnormal_termination() == FALSE) {
try {
Counter += 3;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
}
}
if (Counter != 9) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/except within the finally clause of a try/finally.
//
DbgPrint(" test58...");
Counter = 0;
try {
Counter -= 1;
} finally {
try {
Counter += 2;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except (Counter) {
try {
Counter += 3;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 5;
}
}
}
}
if (Counter != 9) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/except within the except clause of a try/except that is always
// executed.
//
DbgPrint(" test59...");
Counter = 0;
try {
Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except (Counter) {
try {
Counter += 3;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except(Counter - 3) {
Counter += 5;
}
}
if (Counter != 9) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try with a Try which exits the scope with a goto
//
DbgPrint(" test60...");
Counter = 0;
try {
try {
goto outside;
} except(1) {
Counter += 1;
}
outside:
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except(1) {
Counter += 3;
}
if (Counter != 3) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/except which gets an exception from a subfunction within
// a try/finally which has a try/except in the finally clause
//
DbgPrint(" test61...");
Counter = 0;
try {
Test61Part2 (&Counter);
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 11;
}
if (Counter != 24) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/except within a try/except where the outer try/except gets
// a floating overflow exception.
//
DbgPrint(" test62...");
_controlfp(_controlfp(0,0) & ~EM_OVERFLOW, _MCW_EM);
Counter = 0;
try {
doubleresult = SquareDouble(1.7e300);
try {
doubleresult = SquareDouble (1.0);
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 3;
}
} except ((GetExceptionCode() == STATUS_FLOAT_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
_clearfp ();
//
// Try/except within a try/except where the outer try/except gets
// a floating overflow exception in a subfunction.
//
DbgPrint(" test63...");
Counter = 0;
try {
SquareDouble17E300((PVOID)&doubleresult);
try {
SquareDouble17E300((PVOID)&doubleresult);
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 3;
}
} except ((GetExceptionCode() == STATUS_FLOAT_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
Counter += 1;
}
if (Counter != 1) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
_clearfp ();
//
// Try/finally within a try/except where the finally body causes an
// exception that leads to a collided unwind during the exception
// dispatch.
//
DbgPrint(" test64...");
Counter = 0;
try {
Counter += 1;
try {
Counter += 1;
FAULT;
Counter += 20;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 20;
} else {
Counter += 1;
FAULT;
}
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 10;
}
if (Counter != 13) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Try/finally within a try/finally within a try/except that leads to a
// collided unwind during the exception dispatch.
//
DbgPrint(" test65...");
Counter = 0;
try {
Counter += 1;
try {
Counter += 1;
FAULT;
Counter += 20;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 20;
} else {
try {
Counter += 1;
FAULT;
Counter += 20;
} finally {
if (abnormal_termination() == FALSE) {
Counter += 20;
} else {
Counter += 1;
}
}
}
FAULT;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Counter += 10;
}
if (Counter != 14) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A call to a function with a try/finally that returns out of the try
// body.
//
DbgPrint(" test66...");
Counter = 0;
if ((test66sub(&Counter) + 1) != Counter) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// A call to a function with a try finally that returnss out of the
// termination hander.
//
DbgPrint(" test67...");
Counter = 0;
if (test67sub(&Counter) != Counter) {
DbgPrint("failed, count = %d\n", Counter);
} else {
DbgPrint("succeeded\n");
}
//
// Announce end of exception test.
//
DbgBreakPoint();
DbgPrint("End of exception test\n");
return;
}
VOID
addtwo (
long First,
long Second,
long *Place
)
{
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
*Place = First + Second;
return;
}
VOID
bar1 (
IN NTSTATUS Status,
IN PLONG Counter
)
{
try {
foo1(Status);
} finally {
if (abnormal_termination() != FALSE) {
*Counter = 99;
} else {
*Counter = 100;
}
}
return;
}
VOID
bar2 (
IN PLONG BlackHole,
IN PLONG BadAddress,
IN PLONG Counter
)
{
try {
foo2(BlackHole, BadAddress);
} finally {
if (abnormal_termination() != FALSE) {
*Counter = 99;
} else {
*Counter = 100;
}
}
return;
}
VOID
dojump (
IN jmp_buf JumpBuffer,
IN PLONG Counter
)
{
try {
try {
*Counter += 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} finally {
*Counter += 1;
}
} finally {
*Counter += 1;
longjmp(JumpBuffer, 1);
}
}
VOID
eret(
IN NTSTATUS Status,
IN PLONG Counter
)
{
try {
try {
foo1(Status);
} except ((GetExceptionCode() == Status) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
*Counter += 1;
return;
}
} finally {
*Counter += 1;
}
return;
}
VOID
except1 (
IN PLONG Counter
)
{
try {
*Counter += 5;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} except (except3(GetExceptionInformation(), Counter)) {
*Counter += 7;
}
*Counter += 9;
return;
}
ULONG
except2 (
IN PEXCEPTION_POINTERS ExceptionPointers,
IN PLONG Counter
)
{
PEXCEPTION_RECORD ExceptionRecord;
ExceptionRecord = ExceptionPointers->ExceptionRecord;
if ((ExceptionRecord->ExceptionCode == STATUS_UNSUCCESSFUL) &&
((ExceptionRecord->ExceptionFlags & EXCEPTION_NESTED_CALL) == 0)) {
*Counter += 11;
return EXCEPTION_EXECUTE_HANDLER;
} else {
*Counter += 13;
return EXCEPTION_CONTINUE_SEARCH;
}
}
ULONG
except3 (
IN PEXCEPTION_POINTERS ExceptionPointers,
IN PLONG Counter
)
{
PEXCEPTION_RECORD ExceptionRecord;
ExceptionRecord = ExceptionPointers->ExceptionRecord;
if ((ExceptionRecord->ExceptionCode == STATUS_INTEGER_OVERFLOW) &&
((ExceptionRecord->ExceptionFlags & EXCEPTION_NESTED_CALL) == 0)) {
*Counter += 17;
RtlRaiseStatus(STATUS_UNSUCCESSFUL);
} else if ((ExceptionRecord->ExceptionCode == STATUS_UNSUCCESSFUL) &&
((ExceptionRecord->ExceptionFlags & EXCEPTION_NESTED_CALL) != 0)) {
*Counter += 19;
return EXCEPTION_CONTINUE_SEARCH;
}
*Counter += 23;
return EXCEPTION_EXECUTE_HANDLER;
}
VOID
foo1 (
IN NTSTATUS Status
)
{
//
// Raise exception.
//
RtlRaiseStatus(Status);
return;
}
VOID
foo2 (
IN PLONG BlackHole,
IN PLONG BadAddress
)
{
//
// Raise exception.
//
*BlackHole += *BadAddress;
return;
}
VOID
fret (
IN PLONG Counter
)
{
try {
try {
*Counter += 1;
} finally {
*Counter += 1;
return;
}
} finally {
*Counter += 1;
}
return;
}
LONG
Echo (
IN LONG Value
)
{
return Value;
}
VOID
Test61Part2 (
IN OUT PULONG Counter
)
{
try {
*Counter -= 1;
RtlRaiseStatus(STATUS_INTEGER_OVERFLOW);
} finally {
*Counter += 2;
*Counter += 5;
*Counter += 7;
}
}
double
SquareDouble (
IN double op
)
{
return op * op;
}
VOID
SquareDouble17E300 (
OUT PVOID output
)
{
double ans;
ans = SquareDouble (1.7e300);
*(double *) output = ans;
}
LONG
test66sub (
IN PLONG Counter
)
{
*Counter += 1;
try {
*Counter += 1;
return(*Counter);
} finally {
*Counter += 1;
}
}
LONG
test67sub (
IN PLONG Counter
)
{
*Counter += 1;
try {
*Counter += 1;
} finally {
*Counter += 1;
return(*Counter);
}
}