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 } 239