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 #include <xmmintrin.h>
13 * Keep these returning different values, to prevent compiler folding
14 * them into a single function, thereby voiding the test
16 LONG WINAPI
Filter1(LPEXCEPTION_POINTERS p
) { return 0; }
17 LONG WINAPI
Filter2(LPEXCEPTION_POINTERS p
) { return 1; }
21 * Verify that SetUnhandledExceptionFilter actually returns the
26 TestSetUnhandledExceptionFilter(VOID
)
28 LPTOP_LEVEL_EXCEPTION_FILTER p1
, p2
;
29 p1
= SetUnhandledExceptionFilter(Filter1
);
30 p2
= SetUnhandledExceptionFilter(Filter2
);
31 ok(p1
!= Filter1
, "SetUnhandledExceptionFilter returned what was set, not prev\n");
32 ok(p2
!= Filter2
, "SetUnhandledExceptionFilter returned what was set, not prev\n");
33 ok(p2
== Filter1
, "SetUnhandledExceptionFilter didn't return previous filter\n");
34 ok(p1
!= p2
, "SetUnhandledExceptionFilter seems to return random stuff\n");
36 p1
= SetUnhandledExceptionFilter(NULL
);
37 ok(p1
== Filter2
, "SetUnhandledExceptionFilter didn't return previous filter\n");
40 static LONG WINAPI
ExceptionFilterSSESupport(LPEXCEPTION_POINTERS exp
)
42 PEXCEPTION_RECORD rec
= exp
->ExceptionRecord
;
43 PCONTEXT ctx
= exp
->ContextRecord
;
45 trace("Exception raised while using SSE instructions.\n");
47 ok(rec
->ExceptionCode
== EXCEPTION_ILLEGAL_INSTRUCTION
, "Exception code is 0x%08x.\n", (unsigned int)rec
->ExceptionCode
);
49 if(rec
->ExceptionCode
!= EXCEPTION_ILLEGAL_INSTRUCTION
)
51 trace("Unexpected exception code, terminating!\n");
52 return EXCEPTION_EXECUTE_HANDLER
;
55 ok((ctx
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
, "Context does not contain control register.\n");
59 return EXCEPTION_CONTINUE_EXECUTION
;
62 static BOOL ExceptionCaught
= FALSE
;
64 static LONG WINAPI
ExceptionFilterSSEException(LPEXCEPTION_POINTERS exp
)
66 PEXCEPTION_RECORD rec
= exp
->ExceptionRecord
;
67 PCONTEXT ctx
= exp
->ContextRecord
;
69 trace("Exception raised while dividing by 0.\n");
71 ok(rec
->ExceptionCode
== STATUS_FLOAT_MULTIPLE_TRAPS
, "Exception code is 0x%08x.\n", (unsigned int)rec
->ExceptionCode
);
73 if(rec
->ExceptionCode
!= STATUS_FLOAT_MULTIPLE_TRAPS
)
75 trace("Unexpected exception code, terminating!\n");
76 return EXCEPTION_EXECUTE_HANDLER
;
79 ok((ctx
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
, "Context does not contain control register.\n");
81 ExceptionCaught
= TRUE
;
85 return EXCEPTION_CONTINUE_EXECUTION
;
89 VOID
TestSSEExceptions(VOID
)
91 LPTOP_LEVEL_EXCEPTION_FILTER p
;
92 BOOL supportsSSE
= FALSE
;
95 /* Test SSE support for the CPU */
96 p
= SetUnhandledExceptionFilter(ExceptionFilterSSESupport
);
97 ok(p
== NULL
, "Previous filter should be NULL\n");
106 "xorps %%xmm0, %%xmm0\n"
110 #endif /* _MSC_VER */
113 skip("CPU doesn't support SSE instructions.\n");
114 SetUnhandledExceptionFilter(NULL
);
117 /* Deliberately throw a divide by 0 exception */
118 p
= SetUnhandledExceptionFilter(ExceptionFilterSSEException
);
119 ok(p
== ExceptionFilterSSESupport
, "Unexpected old filter : 0x%p", p
);
121 /* Unmask divide by 0 exception */
123 _mm_setcsr(csr
& 0xFFFFFDFF);
125 /* We can't use _mm_div_ps, as it masks the exception before performing anything*/
126 #if defined(_MSC_VER)
145 "xorps %%xmm0, %%xmm0\n"
146 "pushl $0x3f800000\n"
147 "pushl $0x3f800000\n"
148 "pushl $0x3f800000\n"
149 "pushl $0x3f800000\n"
150 "movups (%%esp), %%xmm1\n"
153 "divps %%xmm0, %%xmm1\n"
159 #endif /* _MSC_VER */
164 ok(ExceptionCaught
, "The exception was not caught.\n");
166 p
= SetUnhandledExceptionFilter(NULL
);
167 ok(p
== ExceptionFilterSSEException
, "Unexpected old filter : 0x%p", p
);
170 START_TEST(SetUnhandledExceptionFilter
)
172 TestSetUnhandledExceptionFilter();