1 /*
2  * PROJECT:         ReactOS kernel-mode tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Kernel-Mode Test Suite Exception test
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #define KMT_EMULATE_KERNEL
9 #include <kmt_test.h>
10 
11 static
12 VOID
13 PossiblyRaise(
14     _In_ BOOLEAN Raise)
15 {
16     if (Raise)
17     {
18         ExRaiseStatus(STATUS_ASSERTION_FAILURE);
19     }
20 }
21 
22 static
23 VOID
24 InnerFunction(
25     _Inout_ PULONG State,
26     _In_ BOOLEAN Raise)
27 {
28     _SEH2_VOLATILE INT Var = 123;
29     static _SEH2_VOLATILE INT *AddressOfVar;
30 
31     AddressOfVar = &Var;
32     ok_eq_ulong(*State, 1);
33     _SEH2_TRY
34     {
35         *State = 2;
36         PossiblyRaise(Raise);
37         ok_eq_ulong(*State, 2);
38         *State = 3;
39     }
40     _SEH2_FINALLY
41     {
42         ok_eq_int(Var, 123);
43         ok_eq_pointer(&Var, AddressOfVar);
44         if (Raise)
45             ok_eq_ulong(*State, 2);
46         else
47             ok_eq_ulong(*State, 3);
48         *State = 4;
49     }
50     _SEH2_END;
51 
52     ok_eq_int(Var, 123);
53     ok_eq_pointer(&Var, AddressOfVar);
54     ok_eq_ulong(*State, 4);
55     *State = 5;
56 }
57 
58 static
59 VOID
60 OuterFunction(
61     _Inout_ PULONG State,
62     _In_ BOOLEAN Raise)
63 {
64     _SEH2_VOLATILE INT Var = 456;
65     static _SEH2_VOLATILE INT *AddressOfVar;
66 
67     AddressOfVar = &Var;
68     ok_eq_ulong(*State, 0);
69     _SEH2_TRY
70     {
71         *State = 1;
72         InnerFunction(State, Raise);
73         ok_eq_ulong(*State, 5);
74         *State = 6;
75     }
76     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
77     {
78         ok_eq_int(Var, 456);
79         ok_eq_pointer(&Var, AddressOfVar);
80         ok_eq_ulong(*State, 4);
81         *State = 7;
82     }
83     _SEH2_END;
84 
85     ok_eq_int(Var, 456);
86     ok_eq_pointer(&Var, AddressOfVar);
87     if (Raise)
88         ok_eq_ulong(*State, 7);
89     else
90         ok_eq_ulong(*State, 6);
91     *State = 8;
92 }
93 
94 static
95 VOID
96 TestNestedExceptionHandler(VOID)
97 {
98     ULONG State;
99 
100     State = 0;
101     OuterFunction(&State, FALSE);
102     ok_eq_ulong(State, 8);
103 
104     State = 0;
105     OuterFunction(&State, TRUE);
106     ok_eq_ulong(State, 8);
107 }
108 
109 START_TEST(RtlException)
110 {
111     PCHAR Buffer[128];
112 
113     /* Access a valid pointer - must not trigger SEH */
114     KmtStartSeh()
115         RtlFillMemory(Buffer, sizeof(Buffer), 0x12);
116     KmtEndSeh(STATUS_SUCCESS);
117 
118     /* Read from a NULL pointer - must cause an access violation */
119     KmtStartSeh()
120         (void)*(volatile CHAR *)NULL;
121     KmtEndSeh(STATUS_ACCESS_VIOLATION);
122 
123     /* Write to a NULL pointer - must cause an access violation */
124     KmtStartSeh()
125         *(volatile CHAR *)NULL = 5;
126     KmtEndSeh(STATUS_ACCESS_VIOLATION);
127 
128     /* TODO: Find where MmBadPointer is defined - gives an unresolved external */
129 #if 0 //def KMT_KERNEL_MODE
130     /* Read from MmBadPointer - must cause an access violation */
131     KmtStartSeh()
132         (void)*(volatile CHAR *)MmBadPointer;
133     KmtEndSeh(STATUS_ACCESS_VIOLATION);
134 
135     /* Write to MmBadPointer - must cause an access violation */
136     KmtStartSeh()
137         *(volatile CHAR *)MmBadPointer = 5;
138     KmtEndSeh(STATUS_ACCESS_VIOLATION);
139 #endif
140 
141     KmtStartSeh()
142         ExRaiseStatus(STATUS_ACCESS_VIOLATION);
143     KmtEndSeh(STATUS_ACCESS_VIOLATION);
144 
145     KmtStartSeh()
146         ExRaiseStatus(STATUS_TIMEOUT);
147     KmtEndSeh(STATUS_TIMEOUT);
148 
149     KmtStartSeh()
150         ExRaiseStatus(STATUS_STACK_OVERFLOW);
151     KmtEndSeh(STATUS_STACK_OVERFLOW);
152 
153     KmtStartSeh()
154         ExRaiseStatus(STATUS_GUARD_PAGE_VIOLATION);
155     KmtEndSeh(STATUS_GUARD_PAGE_VIOLATION);
156 
157     TestNestedExceptionHandler();
158 
159     /* We cannot test this in kernel mode easily - the stack is just "somewhere"
160      * in system space, and there's no guard page below it */
161 #ifdef KMT_USER_MODE
162     /* Overflow the stack - must cause a special exception */
163     KmtStartSeh()
164         volatile CHAR *Pointer;
165 
166         while (1)
167         {
168             Pointer = _alloca(1024);
169             *Pointer = 5;
170         }
171     KmtEndSeh(STATUS_STACK_OVERFLOW);
172 #endif
173 }
174