2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for SetUnhandledExceptionFilter
5 * PROGRAMMER: Mike "tamlin" Nordell
10 #define WIN32_NO_STATUS
12 #include <ndk/rtltypes.h>
13 #include <xmmintrin.h>
16 * Keep these returning different values, to prevent compiler folding
17 * them into a single function, thereby voiding the test
19 LONG WINAPI
Filter1(LPEXCEPTION_POINTERS p
) { return 0; }
20 LONG WINAPI
Filter2(LPEXCEPTION_POINTERS p
) { return 1; }
24 * Verify that SetUnhandledExceptionFilter actually returns the
29 TestSetUnhandledExceptionFilter(VOID
)
31 LPTOP_LEVEL_EXCEPTION_FILTER p1
, p2
;
32 p1
= SetUnhandledExceptionFilter(Filter1
);
33 p2
= SetUnhandledExceptionFilter(Filter2
);
34 ok(p1
!= Filter1
, "SetUnhandledExceptionFilter returned what was set, not prev\n");
35 ok(p2
!= Filter2
, "SetUnhandledExceptionFilter returned what was set, not prev\n");
36 ok(p2
== Filter1
, "SetUnhandledExceptionFilter didn't return previous filter\n");
37 ok(p1
!= p2
, "SetUnhandledExceptionFilter seems to return random stuff\n");
39 p1
= SetUnhandledExceptionFilter(NULL
);
40 ok(p1
== Filter2
, "SetUnhandledExceptionFilter didn't return previous filter\n");
43 static LONG WINAPI
ExceptionFilterSSESupport(LPEXCEPTION_POINTERS exp
)
45 PEXCEPTION_RECORD rec
= exp
->ExceptionRecord
;
46 PCONTEXT ctx
= exp
->ContextRecord
;
48 trace("Exception raised while using SSE instructions.\n");
50 ok(rec
->ExceptionCode
== EXCEPTION_ILLEGAL_INSTRUCTION
, "Exception code is 0x%08x.\n", (unsigned int)rec
->ExceptionCode
);
52 if(rec
->ExceptionCode
!= EXCEPTION_ILLEGAL_INSTRUCTION
)
54 trace("Unexpected exception code, terminating!\n");
55 return EXCEPTION_EXECUTE_HANDLER
;
58 ok((ctx
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
, "Context does not contain control register.\n");
62 return EXCEPTION_CONTINUE_EXECUTION
;
65 static BOOL ExceptionCaught
= FALSE
;
67 static LONG WINAPI
ExceptionFilterSSEException(LPEXCEPTION_POINTERS exp
)
69 PEXCEPTION_RECORD rec
= exp
->ExceptionRecord
;
70 PCONTEXT ctx
= exp
->ContextRecord
;
72 trace("Exception raised while dividing by 0.\n");
74 ok(rec
->ExceptionCode
== STATUS_FLOAT_MULTIPLE_TRAPS
, "Exception code is 0x%08x.\n", (unsigned int)rec
->ExceptionCode
);
76 if(rec
->ExceptionCode
!= STATUS_FLOAT_MULTIPLE_TRAPS
)
78 trace("Unexpected exception code, terminating!\n");
79 return EXCEPTION_EXECUTE_HANDLER
;
82 ok((ctx
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
, "Context does not contain control register.\n");
84 ExceptionCaught
= TRUE
;
88 return EXCEPTION_CONTINUE_EXECUTION
;
92 VOID
TestSSEExceptions(VOID
)
94 LPTOP_LEVEL_EXCEPTION_FILTER p
;
95 BOOL supportsSSE
= FALSE
;
98 /* Test SSE support for the CPU */
99 p
= SetUnhandledExceptionFilter(ExceptionFilterSSESupport
);
100 ok(p
== NULL
, "Previous filter should be NULL\n");
109 "xorps %%xmm0, %%xmm0\n"
113 #endif /* _MSC_VER */
116 skip("CPU doesn't support SSE instructions.\n");
117 SetUnhandledExceptionFilter(NULL
);
120 /* Deliberately throw a divide by 0 exception */
121 p
= SetUnhandledExceptionFilter(ExceptionFilterSSEException
);
122 ok(p
== ExceptionFilterSSESupport
, "Unexpected old filter : 0x%p", p
);
124 /* Unmask divide by 0 exception */
126 _mm_setcsr(csr
& 0xFFFFFDFF);
128 /* We can't use _mm_div_ps, as it masks the exception before performing anything*/
129 #if defined(_MSC_VER)
148 "xorps %%xmm0, %%xmm0\n"
149 "pushl $0x3f800000\n"
150 "pushl $0x3f800000\n"
151 "pushl $0x3f800000\n"
152 "pushl $0x3f800000\n"
153 "movups (%%esp), %%xmm1\n"
156 "divps %%xmm0, %%xmm1\n"
162 #endif /* _MSC_VER */
167 ok(ExceptionCaught
, "The exception was not caught.\n");
169 p
= SetUnhandledExceptionFilter(NULL
);
170 ok(p
== ExceptionFilterSSEException
, "Unexpected old filter : 0x%p", p
);
173 START_TEST(SetUnhandledExceptionFilter
)
175 TestSetUnhandledExceptionFilter();