[KMTEST]
[reactos.git] / rostests / kmtests / ntos_ke / KeApc.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Asynchronous Procedure Call test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 static
11 _IRQL_requires_min_(PASSIVE_LEVEL)
12 _IRQL_requires_max_(DISPATCH_LEVEL)
13 BOOLEAN
14 (NTAPI
15 *pKeAreAllApcsDisabled)(VOID);
16
17 static
18 _Acquires_lock_(_Global_critical_region_)
19 _IRQL_requires_max_(APC_LEVEL)
20 VOID
21 (NTAPI
22 *pKeEnterGuardedRegion)(VOID);
23
24 static
25 _Releases_lock_(_Global_critical_region_)
26 _IRQL_requires_max_(APC_LEVEL)
27 VOID
28 (NTAPI
29 *pKeLeaveGuardedRegion)(VOID);
30
31 #define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql) do \
32 { \
33 ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \
34 ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \
35 if (pKeAreAllApcsDisabled) \
36 ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \
37 ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \
38 ok_irql(Irql); \
39 } while (0)
40
41 START_TEST(KeApc)
42 {
43 KIRQL Irql;
44 PKTHREAD Thread;
45
46 pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled");
47 pKeEnterGuardedRegion = KmtGetSystemRoutineAddress(L"KeEnterGuardedRegion");
48 pKeLeaveGuardedRegion = KmtGetSystemRoutineAddress(L"KeLeaveGuardedRegion");
49
50 if (skip(pKeAreAllApcsDisabled != NULL, "KeAreAllApcsDisabled unavailable\n"))
51 {
52 /* We can live without this function here */
53 }
54
55 Thread = KeGetCurrentThread();
56
57 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
58
59 /* critical region */
60 KeEnterCriticalRegion();
61 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
62 KeEnterCriticalRegion();
63 CheckApcs(-2, 0, FALSE, PASSIVE_LEVEL);
64 KeEnterCriticalRegion();
65 CheckApcs(-3, 0, FALSE, PASSIVE_LEVEL);
66 KeLeaveCriticalRegion();
67 CheckApcs(-2, 0, FALSE, PASSIVE_LEVEL);
68 KeLeaveCriticalRegion();
69 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
70 KeLeaveCriticalRegion();
71 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
72
73 /* guarded region */
74 if (!skip(pKeEnterGuardedRegion &&
75 pKeLeaveGuardedRegion, "Guarded regions not available\n"))
76 {
77 pKeEnterGuardedRegion();
78 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
79 pKeEnterGuardedRegion();
80 CheckApcs(0, -2, TRUE, PASSIVE_LEVEL);
81 pKeEnterGuardedRegion();
82 CheckApcs(0, -3, TRUE, PASSIVE_LEVEL);
83 pKeLeaveGuardedRegion();
84 CheckApcs(0, -2, TRUE, PASSIVE_LEVEL);
85 pKeLeaveGuardedRegion();
86 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
87 pKeLeaveGuardedRegion();
88 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
89
90 /* mix them */
91 pKeEnterGuardedRegion();
92 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
93 KeEnterCriticalRegion();
94 CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL);
95 KeLeaveCriticalRegion();
96 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
97 pKeLeaveGuardedRegion();
98 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
99
100 KeEnterCriticalRegion();
101 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
102 pKeEnterGuardedRegion();
103 CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL);
104 pKeLeaveGuardedRegion();
105 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
106 KeLeaveCriticalRegion();
107 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
108 }
109
110 /* leave without entering */
111 if (!KmtIsCheckedBuild)
112 {
113 KeLeaveCriticalRegion();
114 CheckApcs(1, 0, FALSE, PASSIVE_LEVEL);
115 KeEnterCriticalRegion();
116 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
117
118 if (!skip(pKeEnterGuardedRegion &&
119 pKeLeaveGuardedRegion, "Guarded regions not available\n"))
120 {
121 pKeLeaveGuardedRegion();
122 CheckApcs(0, 1, TRUE, PASSIVE_LEVEL);
123 pKeEnterGuardedRegion();
124 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
125
126 KeLeaveCriticalRegion();
127 CheckApcs(1, 0, FALSE, PASSIVE_LEVEL);
128 pKeLeaveGuardedRegion();
129 CheckApcs(1, 1, TRUE, PASSIVE_LEVEL);
130 KeEnterCriticalRegion();
131 CheckApcs(0, 1, TRUE, PASSIVE_LEVEL);
132 pKeEnterGuardedRegion();
133 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
134 }
135 }
136
137 /* manually disable APCs */
138 Thread->KernelApcDisable = -1;
139 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
140 Thread->SpecialApcDisable = -1;
141 CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL);
142 Thread->KernelApcDisable = 0;
143 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
144 Thread->SpecialApcDisable = 0;
145 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
146
147 /* raised irql - APC_LEVEL should disable APCs */
148 KeRaiseIrql(APC_LEVEL, &Irql);
149 CheckApcs(0, 0, TRUE, APC_LEVEL);
150 KeLowerIrql(Irql);
151 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
152
153 /* KeAre*ApcsDisabled are documented to work up to DISPATCH_LEVEL... */
154 KeRaiseIrql(DISPATCH_LEVEL, &Irql);
155 CheckApcs(0, 0, TRUE, DISPATCH_LEVEL);
156 KeLowerIrql(Irql);
157 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
158
159 /* ... but also work on higher levels! */
160 KeRaiseIrql(HIGH_LEVEL, &Irql);
161 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
162 KeLowerIrql(Irql);
163 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
164
165 /* now comes the crazy stuff */
166 KeRaiseIrql(HIGH_LEVEL, &Irql);
167 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
168 KeEnterCriticalRegion();
169 CheckApcs(-1, 0, TRUE, HIGH_LEVEL);
170 KeLeaveCriticalRegion();
171 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
172
173 /* Ke*GuardedRegion assert at > APC_LEVEL */
174 if (!KmtIsCheckedBuild &&
175 !skip(pKeEnterGuardedRegion &&
176 pKeLeaveGuardedRegion, "Guarded regions not available\n"))
177 {
178 pKeEnterGuardedRegion();
179 CheckApcs(0, -1, TRUE, HIGH_LEVEL);
180 pKeLeaveGuardedRegion();
181 }
182 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
183 KeLowerIrql(Irql);
184 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
185
186 if (!KmtIsCheckedBuild &&
187 !skip(pKeEnterGuardedRegion &&
188 pKeLeaveGuardedRegion, "Guarded regions not available\n"))
189 {
190 KeRaiseIrql(HIGH_LEVEL, &Irql);
191 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
192 KeEnterCriticalRegion();
193 CheckApcs(-1, 0, TRUE, HIGH_LEVEL);
194 pKeEnterGuardedRegion();
195 CheckApcs(-1, -1, TRUE, HIGH_LEVEL);
196 KeLowerIrql(Irql);
197 CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL);
198 KeLeaveCriticalRegion();
199 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
200 pKeLeaveGuardedRegion();
201 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
202
203 pKeEnterGuardedRegion();
204 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
205 KeRaiseIrql(HIGH_LEVEL, &Irql);
206 CheckApcs(0, -1, TRUE, HIGH_LEVEL);
207 KeEnterCriticalRegion();
208 CheckApcs(-1, -1, TRUE, HIGH_LEVEL);
209 pKeLeaveGuardedRegion();
210 CheckApcs(-1, 0, TRUE, HIGH_LEVEL);
211 KeLowerIrql(Irql);
212 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
213 KeLeaveCriticalRegion();
214 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
215
216 KeEnterCriticalRegion();
217 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
218 KeRaiseIrql(HIGH_LEVEL, &Irql);
219 CheckApcs(-1, 0, TRUE, HIGH_LEVEL);
220 pKeEnterGuardedRegion();
221 CheckApcs(-1, -1, TRUE, HIGH_LEVEL);
222 KeLeaveCriticalRegion();
223 CheckApcs(0, -1, TRUE, HIGH_LEVEL);
224 KeLowerIrql(Irql);
225 CheckApcs(0, -1, TRUE, PASSIVE_LEVEL);
226 pKeLeaveGuardedRegion();
227 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
228 }
229
230 KeEnterCriticalRegion();
231 CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL);
232 KeRaiseIrql(HIGH_LEVEL, &Irql);
233 CheckApcs(-1, 0, TRUE, HIGH_LEVEL);
234 KeLeaveCriticalRegion();
235 CheckApcs(0, 0, TRUE, HIGH_LEVEL);
236 KeLowerIrql(Irql);
237 CheckApcs(0, 0, FALSE, PASSIVE_LEVEL);
238 }