/*++ 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) #pragma warning(disable:4702) // unreachable code #pragma optimize("",off) // // 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 ); ULONG64 Catch ( IN PEXCEPTION_RECORD ExceptionRecord ); 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 PLONG 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; LONG 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"); } // // Emulate C++ exception handing and frame consolidation. // DbgPrint(" test68..."); Counter = 0; try { Counter += 1; ExceptionRecord.ExceptionCode = 0xbaadf00d; ExceptionRecord.ExceptionInformation[4] = (ULONG_PTR)&Catch; RtlRaiseException(&ExceptionRecord); } except (Counter) { Counter += 1; } if (Counter != 2) { 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; } ULONG64 Catch ( IN PEXCEPTION_RECORD ExceptionRecord ) { UNREFERENCED_PARAMETER(ExceptionRecord); return 0; } 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 (((NTSTATUS)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 PLONG 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); } }