reactos/rostests/kmtests/ntos_ke/KeApc.c

239 lines
8 KiB
C
Raw Normal View History

/*
* 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 <thomas.faber@reactos.org>
*/
#include <kmt_test.h>
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);
}