/*++ 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 "stdio.h" #include "nt.h" #include "ntrtl.h" #include "setjmpex.h" #include "float.h" #pragma warning(disable:4532) // // Define switch constants. // #define BLUE 0 #define RED 1 // // 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 ); VOID __cdecl main( int argc, char *argv[] ) { 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. // printf("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. // printf(" test1..."); Counter = 0; try { Counter += 1; } finally { if (abnormal_termination() == FALSE) { Counter += 1; } } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try statement with an exception clause that is never executed // because there is no exception raised in the try clause. // printf(" test2..."); Counter = 0; try { Counter += 1; } except (Counter) { Counter += 1; } if (Counter != 1) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try statement with an exception handler that is never executed // because the exception expression continues execution. // printf(" test3..."); Counter = 0; try { Counter -= 1; RtlRaiseException(&ExceptionRecord); } except (Counter) { Counter -= 1; } if (Counter != - 1) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try statement with an exception clause that is always executed. // printf(" test4..."); Counter = 0; try { Counter += 1; RtlRaiseStatus(STATUS_INTEGER_OVERFLOW); } except (Counter) { Counter += 1; } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try statement with an exception clause that is always executed. // printf(" test5..."); Counter = 0; try { Counter += 1; *BlackHole += *BadAddress; } except (Counter) { Counter += 1; } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simply try statement with a finally clause that is entered as the // result of an exception. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simply try statement with a finally clause that is entered as the // result of an exception. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try that calls a function which raises an exception. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try that calls a function which raises an exception. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" test11..."); Counter = 0; try { bar2(BlackHole, BadAddress, &Counter); } except ((GetExceptionCode() == STATUS_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { Counter -= 1; } if (Counter != 98) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A try within an except // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded..."); } Counter += 1; } } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A try within an except // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded..."); } Counter += 1; } } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A goto from an exception clause that needs to pass // through a finally // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A goto from an finally clause that needs to pass // through a finally // printf(" test15..."); Counter = 0; try { try { Counter += 1; } finally { Counter += 1; goto t10; } } finally { Counter += 1; } t10:; if (Counter != 3) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A goto from an exception clause that needs to pass // through a finally into the outer finally clause. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A goto from an finally clause that needs to pass // through a finally into the outer finally clause. // printf(" test17..."); Counter = 0; try { try { Counter += 1; } finally { Counter += 1; goto t12; } t12:; } finally { Counter += 1; } if (Counter != 3) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A return from an except clause // printf(" test18..."); Counter = 0; try { Counter += 1; eret(STATUS_ACCESS_VIOLATION, &Counter); } finally { Counter += 1; } if (Counter != 4) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A return from a finally clause // printf(" test19..."); Counter = 0; try { Counter += 1; fret(&Counter); } finally { Counter += 1; } if (Counter != 5) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A simple set jump followed by a long jump. // printf(" test20..."); Counter = 0; if (setjmp(JumpBuffer) == 0) { Counter += 1; longjmp(JumpBuffer, 1); } else { Counter += 1; } if (Counter != 2) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A set jump followed by a long jump out of a finally clause that is // sequentially executed. // printf(" test21..."); Counter = 0; if (setjmp(JumpBuffer) == 0) { try { Counter += 1; } finally { Counter += 1; longjmp(JumpBuffer, 1); } } else { Counter += 1; } if (Counter != 3) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // A set jump within a try clause followed by a long jump out of a // finally clause that is sequentially executed. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("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. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Test nested exceptions. // printf(" test27..."); Counter = 0; try { try { Counter += 1; except1(&Counter); } except(except2(GetExceptionInformation(), &Counter)) { Counter += 2; } } except(EXCEPTION_EXECUTE_HANDLER) { Counter += 3; } if (Counter != 55) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try that causes an integer overflow exception. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Simple try that raises an misaligned data exception. // #ifndef i386 printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } #endif // // Continue from a try body with an exception clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from a try body with an finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from doubly nested try body with an exception clause in a // loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from doubly nested try body with an finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from a finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from a doubly nested finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Continue from a doubly nested finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a try body with an exception clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a try body with an finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from doubly nested try body with an exception clause in a // loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from doubly nested try body with an finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a doubly nested finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a doubly nested finally clause in a loop. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a try body with an exception clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a try body with an finally clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from doubly nested try body with an exception clause in a // switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from doubly nested try body with an finally clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a finally clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a doubly nested finally clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Break from a doubly nested finally clause in a switch. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Leave from an if in a simple try/finally. // printf(" test51..."); Counter = 0; try { if (Echo(Counter) == Counter) { Counter += 3; leave; } else { Counter += 100; } } finally { if (abnormal_termination() == FALSE) { Counter += 5; } } if (Counter != 8) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Leave from a loop in a simple try/finally. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Leave from a switch in a simple try/finally. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Leave from an if in doubly nested try/finally followed by a leave // from an if in the outer try/finally. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Leave from an if in doubly nested try/finally followed by a leave // from the finally of the outer try/finally. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Try/finally within the except clause of a try/except that is always // executed. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Try/finally within the finally clause of a try/finally. // printf(" test57..."); Counter = 0; try { Counter += 1; } finally { if (abnormal_termination() == FALSE) { try { Counter += 3; } finally { if (abnormal_termination() == FALSE) { Counter += 5; } } } } if (Counter != 9) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Try/except within the finally clause of a try/finally. // /* printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } */ // // Try/except within the except clause of a try/except that is always // executed. // printf(" 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) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Try with a Try which exits the scope with a goto // printf(" test60..."); Counter = 0; try { try { goto outside; } except(1) { Counter += 1; } outside: RtlRaiseStatus(STATUS_INTEGER_OVERFLOW); } except(1) { Counter += 3; } if (Counter != 3) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Try/except which gets an exception from a subfunction within // a try/finally which has a try/except in the finally clause // printf(" test61..."); Counter = 0; try { Test61Part2 (&Counter); } except (EXCEPTION_EXECUTE_HANDLER) { Counter += 11; } if (Counter != 24) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } // // Check for precision of floating point exception // printf(" test62..."); /* enable floating point overflow */ _controlfp(_controlfp(0,0) & ~EM_OVERFLOW, _MCW_EM); Counter = 0; try { doubleresult = SquareDouble (1.7e300); try { doubleresult = SquareDouble (1.0); } except (1) { Counter += 3; } } except (1) { Counter += 1; } if (Counter != 1) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } _clearfp (); // // Callout for test #63 due to bogus compiler behaviour caused by test #62. // PerformFpTest (); // // Announce end of exception test. // printf("End of exception test\n"); return; } VOID PerformFpTest() { LONG Counter; double doubleresult; // // Check for precision of floating point exception in subfunction // printf(" test63..."); Counter = 0; try { SquareDouble17E300 ((PVOID) &doubleresult); try { SquareDouble17E300 ((PVOID) &doubleresult); } except (1) { Counter += 3; } } except (1) { Counter += 1; } if (Counter != 1) { printf("failed, count = %d\n", Counter); } else { printf("succeeded\n"); } _clearfp (); } 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; }