/* * PROJECT: ReactOS kernel-mode tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Kernel-Mode Test Suite Asynchronous Procedure Call test * PROGRAMMER: Thomas Faber */ #include static _IRQL_requires_min_(PASSIVE_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL) BOOLEAN (NTAPI *pKeAreAllApcsDisabled)(VOID); static _Acquires_lock_(_Global_critical_region_) _IRQL_requires_max_(APC_LEVEL) VOID (NTAPI *pKeEnterGuardedRegion)(VOID); static _Releases_lock_(_Global_critical_region_) _IRQL_requires_max_(APC_LEVEL) VOID (NTAPI *pKeLeaveGuardedRegion)(VOID); #define CheckApcs(KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, Irql) do \ { \ ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \ ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \ if (pKeAreAllApcsDisabled) \ ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \ ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \ ok_irql(Irql); \ } while (0) START_TEST(KeApc) { KIRQL Irql; PKTHREAD Thread; pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled"); pKeEnterGuardedRegion = KmtGetSystemRoutineAddress(L"KeEnterGuardedRegion"); pKeLeaveGuardedRegion = KmtGetSystemRoutineAddress(L"KeLeaveGuardedRegion"); if (skip(pKeAreAllApcsDisabled != NULL, "KeAreAllApcsDisabled unavailable\n")) { /* We can live without this function here */ } Thread = KeGetCurrentThread(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* critical region */ KeEnterCriticalRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(-2, 0, FALSE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(-3, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(-2, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* guarded region */ if (!skip(pKeEnterGuardedRegion && pKeLeaveGuardedRegion, "Guarded regions not available\n")) { pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(0, -2, TRUE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(0, -3, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, -2, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* mix them */ pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); } /* leave without entering */ if (!KmtIsCheckedBuild) { KeLeaveCriticalRegion(); CheckApcs(1, 0, FALSE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); if (!skip(pKeEnterGuardedRegion && pKeLeaveGuardedRegion, "Guarded regions not available\n")) { pKeLeaveGuardedRegion(); CheckApcs(0, 1, TRUE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(1, 0, FALSE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(1, 1, TRUE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(0, 1, TRUE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); } } /* manually disable APCs */ Thread->KernelApcDisable = -1; CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); Thread->SpecialApcDisable = -1; CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); Thread->KernelApcDisable = 0; CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); Thread->SpecialApcDisable = 0; CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* raised irql - APC_LEVEL should disable APCs */ KeRaiseIrql(APC_LEVEL, &Irql); CheckApcs(0, 0, TRUE, APC_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* KeAre*ApcsDisabled are documented to work up to DISPATCH_LEVEL... */ KeRaiseIrql(DISPATCH_LEVEL, &Irql); CheckApcs(0, 0, TRUE, DISPATCH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* ... but also work on higher levels! */ KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* now comes the crazy stuff */ KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, 0, TRUE, HIGH_LEVEL); /* Ke*GuardedRegion assert at > APC_LEVEL */ if (!KmtIsCheckedBuild && !skip(pKeEnterGuardedRegion && pKeLeaveGuardedRegion, "Guarded regions not available\n")) { pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, HIGH_LEVEL); pKeLeaveGuardedRegion(); } CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); if (!KmtIsCheckedBuild && !skip(pKeEnterGuardedRegion && pKeLeaveGuardedRegion, "Guarded regions not available\n")) { KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); pKeEnterGuardedRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(0, -1, TRUE, HIGH_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); pKeEnterGuardedRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, -1, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); } KeEnterCriticalRegion(); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); }