reactos/rostests/kmtests/ntos_ke/KeApc.c
Thomas Faber e6c56afe8c [KMTESTS]
- Add KmtGetSystemRoutineAddress and use it to avoid importing functions that are not available in some versions of Windows. This allows running kmtests on Windows XP SP3 (and probably Server 2003 SP0/SP2). Note that failures on XP are still not valid bugs, this is purely for convenience!  Dedicated to Jérôme.
ROSTESTS-150

svn path=/trunk/; revision=66281
2015-02-15 10:23:21 +00:00

239 lines
8 KiB
C

/*
* 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);
}