2549 lines
46 KiB
C
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);
|
|
}
|
|
}
|