From e6c56afe8c9e506818613d0df3d97be0806097d6 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sun, 15 Feb 2015 10:23:21 +0000 Subject: [PATCH] =?utf8?q?[KMTESTS]=20-=20Add=20KmtGetSystemRoutineAddress?= =?utf8?q?=20and=20use=20it=20to=20avoid=20importing=20functions=20that=20?= =?utf8?q?are=20not=20available=20in=20some=20versions=20of=20Windows.=20T?= =?utf8?q?his=20allows=20running=20kmtests=20on=20Windows=20XP=20SP3=20(an?= =?utf8?q?d=20probably=20Server=202003=20SP0/SP2).=20Note=20that=20failure?= =?utf8?q?s=20on=20XP=20are=20still=20not=20valid=20bugs,=20this=20is=20pu?= =?utf8?q?rely=20for=20convenience!=20=20Dedicated=20to=20J=C3=A9r=C3=B4me?= =?utf8?q?.=20ROSTESTS-150?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit svn path=/trunk/; revision=66281 --- rostests/kmtests/include/kmt_test.h | 1 + rostests/kmtests/include/kmt_test_kernel.h | 7 + rostests/kmtests/kmtest_drv/testlist.c | 2 +- rostests/kmtests/ntos_ex/ExFastMutex.c | 57 ++++++-- rostests/kmtests/ntos_ex/ExResource.c | 112 ++++++++++++--- rostests/kmtests/ntos_ke/KeApc.c | 153 +++++++++++++-------- rostests/kmtests/ntos_ke/KeGuardedMutex.c | 151 ++++++++++++++++---- rostests/kmtests/ntos_ke/KeMutex.c | 16 ++- rostests/kmtests/ntos_ke/KeSpinLock.c | 81 +++++++---- 9 files changed, 441 insertions(+), 139 deletions(-) diff --git a/rostests/kmtests/include/kmt_test.h b/rostests/kmtests/include/kmt_test.h index 0c6adaa6260..ca3038d8db3 100644 --- a/rostests/kmtests/include/kmt_test.h +++ b/rostests/kmtests/include/kmt_test.h @@ -132,6 +132,7 @@ VOID KmtSetIrql(IN KIRQL NewIrql); BOOLEAN KmtAreInterruptsEnabled(VOID); ULONG KmtGetPoolTag(PVOID Memory); USHORT KmtGetPoolType(PVOID Memory); +PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName); PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL); VOID KmtFinishThread(IN PKTHREAD Thread OPTIONAL, IN PKEVENT Event OPTIONAL); #elif defined KMT_USER_MODE diff --git a/rostests/kmtests/include/kmt_test_kernel.h b/rostests/kmtests/include/kmt_test_kernel.h index aa0a84bd21a..7d7c346991d 100644 --- a/rostests/kmtests/include/kmt_test_kernel.h +++ b/rostests/kmtests/include/kmt_test_kernel.h @@ -126,6 +126,13 @@ USHORT KmtGetPoolType(PVOID Memory) return Header->PoolType; } +PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName) +{ + UNICODE_STRING RoutineNameString; + RtlInitUnicodeString(&RoutineNameString, (PWSTR)RoutineName); + return MmGetSystemRoutineAddress(&RoutineNameString); +} + PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL) { NTSTATUS Status; diff --git a/rostests/kmtests/kmtest_drv/testlist.c b/rostests/kmtests/kmtest_drv/testlist.c index 8801e30e0cc..e8b0dc725ea 100644 --- a/rostests/kmtests/kmtest_drv/testlist.c +++ b/rostests/kmtests/kmtest_drv/testlist.c @@ -94,7 +94,7 @@ const KMT_TEST TestList[] = { "KeIrql", Test_KeIrql }, { "KeMutex", Test_KeMutex }, { "-KeProcessor", Test_KeProcessor }, - { "KeSpinLock", Test_KeSpinLock }, + { "KeSpinLock", Test_KeSpinLock }, { "KeTimer", Test_KeTimer }, { "-KernelType", Test_KernelType }, { "MmSection", Test_MmSection }, diff --git a/rostests/kmtests/ntos_ex/ExFastMutex.c b/rostests/kmtests/ntos_ex/ExFastMutex.c index db5cf14d0e8..ffd3034ba8b 100644 --- a/rostests/kmtests/ntos_ex/ExFastMutex.c +++ b/rostests/kmtests/ntos_ex/ExFastMutex.c @@ -10,9 +10,23 @@ //#define NDEBUG #include -NTKERNELAPI VOID FASTCALL ExiAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex); -NTKERNELAPI VOID FASTCALL ExiReleaseFastMutex(IN OUT PFAST_MUTEX FastMutex); -NTKERNELAPI BOOLEAN FASTCALL ExiTryToAcquireFastMutex(IN OUT PFAST_MUTEX FastMutex); +static +VOID +(FASTCALL +*pExEnterCriticalRegionAndAcquireFastMutexUnsafe)( + _Inout_ PFAST_MUTEX FastMutex +); + +static +VOID +(FASTCALL +*pExReleaseFastMutexUnsafeAndLeaveCriticalRegion)( + _Inout_ PFAST_MUTEX FastMutex +); + +static VOID (FASTCALL *pExiAcquireFastMutex)(IN OUT PFAST_MUTEX FastMutex); +static VOID (FASTCALL *pExiReleaseFastMutex)(IN OUT PFAST_MUTEX FastMutex); +static BOOLEAN (FASTCALL *pExiTryToAcquireFastMutex)(IN OUT PFAST_MUTEX FastMutex); #define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, \ ExpectedContention, ExpectedOldIrql, \ @@ -44,15 +58,18 @@ TestFastMutex( ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); -#ifdef _M_IX86 /* ntoskrnl's fastcall version */ - ExiAcquireFastMutex(Mutex); - CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); - ok_bool_false(ExiTryToAcquireFastMutex(Mutex), "ExiTryToAcquireFastMutex returned"); - CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); - ExiReleaseFastMutex(Mutex); - CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); -#endif + if (!skip(pExiAcquireFastMutex && + pExiReleaseFastMutex && + pExiTryToAcquireFastMutex, "No fastcall fast mutex functions\n")) + { + pExiAcquireFastMutex(Mutex); + CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); + ok_bool_false(pExiTryToAcquireFastMutex(Mutex), "ExiTryToAcquireFastMutex returned"); + CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); + pExiReleaseFastMutex(Mutex); + CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); + } /* try to acquire */ ok_bool_true(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned"); @@ -61,9 +78,14 @@ TestFastMutex( CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); /* shortcut functions with critical region */ - ExEnterCriticalRegionAndAcquireFastMutexUnsafe(Mutex); - ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(Mutex); + if (!skip(pExEnterCriticalRegionAndAcquireFastMutexUnsafe && + pExReleaseFastMutexUnsafeAndLeaveCriticalRegion, + "Shortcut functions not available")) + { + pExEnterCriticalRegionAndAcquireFastMutexUnsafe(Mutex); + ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); + pExReleaseFastMutexUnsafeAndLeaveCriticalRegion(Mutex); + } /* acquire/release unsafe */ if (!KmtIsCheckedBuild || OriginalIrql == APC_LEVEL) @@ -291,6 +313,13 @@ START_TEST(ExFastMutex) FAST_MUTEX Mutex; KIRQL Irql; + pExEnterCriticalRegionAndAcquireFastMutexUnsafe = KmtGetSystemRoutineAddress(L"ExEnterCriticalRegionAndAcquireFastMutexUnsafe"); + pExReleaseFastMutexUnsafeAndLeaveCriticalRegion = KmtGetSystemRoutineAddress(L"ExReleaseFastMutexUnsafeAndLeaveCriticalRegion"); + + pExiAcquireFastMutex = KmtGetSystemRoutineAddress(L"ExiAcquireFastMutex"); + pExiReleaseFastMutex = KmtGetSystemRoutineAddress(L"ExiReleaseFastMutex"); + pExiTryToAcquireFastMutex = KmtGetSystemRoutineAddress(L"ExiTryToAcquireFastMutex"); + memset(&Mutex, 0x55, sizeof Mutex); ExInitializeFastMutex(&Mutex); CheckMutex(&Mutex, 1L, NULL, 0LU, 0x55555555LU, PASSIVE_LEVEL); diff --git a/rostests/kmtests/ntos_ex/ExResource.c b/rostests/kmtests/ntos_ex/ExResource.c index 5ace01a0b0d..49ccf84e426 100644 --- a/rostests/kmtests/ntos_ex/ExResource.c +++ b/rostests/kmtests/ntos_ex/ExResource.c @@ -10,6 +10,49 @@ //#define NDEBUG #include +static +_IRQL_requires_max_(APC_LEVEL) +_Acquires_lock_(_Global_critical_region_) +PVOID +(NTAPI +*pExEnterCriticalRegionAndAcquireResourceShared)( + _Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_shared_lock_(*_Curr_) + PERESOURCE Resource); + +static +_IRQL_requires_max_(APC_LEVEL) +_Acquires_lock_(_Global_critical_region_) +PVOID +(NTAPI +*pExEnterCriticalRegionAndAcquireResourceExclusive)( + _Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_exclusive_lock_(*_Curr_) + PERESOURCE Resource); + +static +_IRQL_requires_max_(APC_LEVEL) +_Acquires_lock_(_Global_critical_region_) +PVOID +(NTAPI +*pExEnterCriticalRegionAndAcquireSharedWaitForExclusive)( + _Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) + PERESOURCE Resource); + +static +_IRQL_requires_max_(DISPATCH_LEVEL) +_Releases_lock_(_Global_critical_region_) +VOID +(FASTCALL +*pExReleaseResourceAndLeaveCriticalRegion)( + _Inout_ _Requires_lock_held_(*_Curr_) _Releases_lock_(*_Curr_) + PERESOURCE Resource); + +static +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +BOOLEAN +(NTAPI +*pKeAreAllApcsDisabled)(VOID); + /* TODO: This is getting pretty long, make it somehow easier to read if possible */ /* TODO: this is the Windows Server 2003 version! ROS should use this! @@ -137,65 +180,83 @@ TestResourceUndocumentedShortcuts( LONG Count = 0; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_uint(pKeAreAllApcsDisabled(), AreApcsDisabled); + if (skip(pExEnterCriticalRegionAndAcquireResourceShared && + pExEnterCriticalRegionAndAcquireSharedWaitForExclusive && + pExEnterCriticalRegionAndAcquireResourceExclusive && + pExReleaseResourceAndLeaveCriticalRegion, "No shortcuts\n")) + { + return; + } /* ExEnterCriticalRegionAndAcquireResourceShared, ExEnterCriticalRegionAndAcquireSharedWaitForExclusive */ Count = 0; - Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; + Ret = pExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); - Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; + Ret = pExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); - ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res); ++Count; + pExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); while (Count-- > 1) { - ExReleaseResourceAndLeaveCriticalRegion(Res); + pExReleaseResourceAndLeaveCriticalRegion(Res); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); } - ExReleaseResourceAndLeaveCriticalRegion(Res); + pExReleaseResourceAndLeaveCriticalRegion(Res); ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); /* ExEnterCriticalRegionAndAcquireResourceExclusive */ Count = 0; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); - Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); + Ret = pExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); - Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; + Ret = pExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); - ExReleaseResourceAndLeaveCriticalRegion(Res); --Count; + pExReleaseResourceAndLeaveCriticalRegion(Res); --Count; ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); - ExReleaseResourceAndLeaveCriticalRegion(Res); --Count; + pExReleaseResourceAndLeaveCriticalRegion(Res); --Count; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); - ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled); + if (pKeAreAllApcsDisabled) + ok_eq_uint(pKeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); } @@ -400,6 +461,17 @@ START_TEST(ExResource) ERESOURCE Res; KIRQL Irql; + pExEnterCriticalRegionAndAcquireResourceShared = KmtGetSystemRoutineAddress(L"ExEnterCriticalRegionAndAcquireResourceShared"); + pExEnterCriticalRegionAndAcquireSharedWaitForExclusive = KmtGetSystemRoutineAddress(L"ExEnterCriticalRegionAndAcquireSharedWaitForExclusive"); + pExEnterCriticalRegionAndAcquireResourceExclusive = KmtGetSystemRoutineAddress(L"ExEnterCriticalRegionAndAcquireResourceExclusive"); + pExReleaseResourceAndLeaveCriticalRegion = KmtGetSystemRoutineAddress(L"ExReleaseResourceAndLeaveCriticalRegion"); + pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled"); + + if (skip(pKeAreAllApcsDisabled != NULL, "KeAreAllApcsDisabled unavailable\n")) + { + /* We can live without this function here */ + } + /* this must be true even with the different structure versions */ ASSERT(sizeof(ERESOURCE) == sizeof(ERESOURCE_2K3)); diff --git a/rostests/kmtests/ntos_ke/KeApc.c b/rostests/kmtests/ntos_ke/KeApc.c index 5c4f63f84bd..ec240e4220a 100644 --- a/rostests/kmtests/ntos_ke/KeApc.c +++ b/rostests/kmtests/ntos_ke/KeApc.c @@ -7,11 +7,33 @@ #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); \ - ok_eq_bool(KeAreAllApcsDisabled(), AllApcsDisabled); \ + if (pKeAreAllApcsDisabled) \ + ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \ ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \ ok_irql(Irql); \ } while (0) @@ -19,7 +41,18 @@ START_TEST(KeApc) { KIRQL Irql; - PKTHREAD Thread = KeGetCurrentThread(); + 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); @@ -38,37 +71,41 @@ START_TEST(KeApc) CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); /* guarded region */ - KeEnterGuardedRegion(); - CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeEnterGuardedRegion(); - CheckApcs(0, -2, TRUE, PASSIVE_LEVEL); - KeEnterGuardedRegion(); - CheckApcs(0, -3, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(0, -2, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); + 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 */ - KeEnterGuardedRegion(); - CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeEnterCriticalRegion(); - CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); - KeLeaveCriticalRegion(); - CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - 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); - KeEnterGuardedRegion(); - CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); - KeLeaveCriticalRegion(); - 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) @@ -78,19 +115,23 @@ START_TEST(KeApc) KeEnterCriticalRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(0, 1, TRUE, PASSIVE_LEVEL); - KeEnterGuardedRegion(); - CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); - - KeLeaveCriticalRegion(); - CheckApcs(1, 0, FALSE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); - CheckApcs(1, 1, TRUE, PASSIVE_LEVEL); - KeEnterCriticalRegion(); - CheckApcs(0, 1, TRUE, PASSIVE_LEVEL); - KeEnterGuardedRegion(); - 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 */ @@ -130,38 +171,42 @@ START_TEST(KeApc) CheckApcs(0, 0, TRUE, HIGH_LEVEL); /* Ke*GuardedRegion assert at > APC_LEVEL */ - if (!KmtIsCheckedBuild) + if (!KmtIsCheckedBuild && + !skip(pKeEnterGuardedRegion && + pKeLeaveGuardedRegion, "Guarded regions not available\n")) { - KeEnterGuardedRegion(); + pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, HIGH_LEVEL); - KeLeaveGuardedRegion(); + pKeLeaveGuardedRegion(); } CheckApcs(0, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); - if (!KmtIsCheckedBuild) + 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); - KeEnterGuardedRegion(); + pKeEnterGuardedRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(-1, -1, TRUE, PASSIVE_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); + pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); - KeEnterGuardedRegion(); + pKeEnterGuardedRegion(); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(0, -1, TRUE, HIGH_LEVEL); KeEnterCriticalRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); - KeLeaveGuardedRegion(); + pKeLeaveGuardedRegion(); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); @@ -172,13 +217,13 @@ START_TEST(KeApc) CheckApcs(-1, 0, FALSE, PASSIVE_LEVEL); KeRaiseIrql(HIGH_LEVEL, &Irql); CheckApcs(-1, 0, TRUE, HIGH_LEVEL); - KeEnterGuardedRegion(); + pKeEnterGuardedRegion(); CheckApcs(-1, -1, TRUE, HIGH_LEVEL); KeLeaveCriticalRegion(); CheckApcs(0, -1, TRUE, HIGH_LEVEL); KeLowerIrql(Irql); CheckApcs(0, -1, TRUE, PASSIVE_LEVEL); - KeLeaveGuardedRegion(); + pKeLeaveGuardedRegion(); CheckApcs(0, 0, FALSE, PASSIVE_LEVEL); } diff --git a/rostests/kmtests/ntos_ke/KeGuardedMutex.c b/rostests/kmtests/ntos_ke/KeGuardedMutex.c index e0d4e101e30..9b2a79e1327 100644 --- a/rostests/kmtests/ntos_ke/KeGuardedMutex.c +++ b/rostests/kmtests/ntos_ke/KeGuardedMutex.c @@ -10,6 +10,86 @@ #define NDEBUG #include +static +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +BOOLEAN +(NTAPI +*pKeAreAllApcsDisabled)(VOID); + +static +_Acquires_lock_(_Global_critical_region_) +_Requires_lock_not_held_(*Mutex) +_Acquires_lock_(*Mutex) +_IRQL_requires_max_(APC_LEVEL) +_IRQL_requires_min_(PASSIVE_LEVEL) +VOID +(FASTCALL +*pKeAcquireGuardedMutex)( + _Inout_ PKGUARDED_MUTEX GuardedMutex); + +static +_Requires_lock_not_held_(*FastMutex) +_Acquires_lock_(*FastMutex) +_IRQL_requires_max_(APC_LEVEL) +_IRQL_requires_min_(PASSIVE_LEVEL) +VOID +(FASTCALL +*pKeAcquireGuardedMutexUnsafe)( + _Inout_ PKGUARDED_MUTEX GuardedMutex); + +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); + +static +_IRQL_requires_max_(APC_LEVEL) +_IRQL_requires_min_(PASSIVE_LEVEL) +VOID +(FASTCALL +*pKeInitializeGuardedMutex)( + _Out_ PKGUARDED_MUTEX GuardedMutex); + +static +_Requires_lock_held_(*FastMutex) +_Releases_lock_(*FastMutex) +_IRQL_requires_max_(APC_LEVEL) +VOID +(FASTCALL +*pKeReleaseGuardedMutexUnsafe)( + _Inout_ PKGUARDED_MUTEX GuardedMutex); + +static +_Releases_lock_(_Global_critical_region_) +_Requires_lock_held_(*Mutex) +_Releases_lock_(*Mutex) +_IRQL_requires_max_(APC_LEVEL) +VOID +(FASTCALL +*pKeReleaseGuardedMutex)( + _Inout_ PKGUARDED_MUTEX GuardedMutex); + +static +_Must_inspect_result_ +_Success_(return != FALSE) +_IRQL_requires_max_(APC_LEVEL) +_Post_satisfies_(return == 1 || return == 0) +BOOLEAN +(FASTCALL +*pKeTryToAcquireGuardedMutex)( + _When_ (return, _Requires_lock_not_held_(*_Curr_) _Acquires_exclusive_lock_(*_Curr_)) _Acquires_lock_(_Global_critical_region_) + _Inout_ PKGUARDED_MUTEX GuardedMutex); + #define CheckMutex(Mutex, ExpectedCount, ExpectedOwner, ExpectedContention, \ ExpectedKernelApcDisable, ExpectedSpecialApcDisable, \ KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, \ @@ -25,7 +105,7 @@ ok_eq_int((Mutex)->SpecialApcDisable, 0x5555); \ ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \ ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \ - ok_eq_bool(KeAreAllApcsDisabled(), AllApcsDisabled); \ + ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \ ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \ ok_irql(ExpectedIrql); \ } while (0) @@ -48,17 +128,17 @@ TestGuardedMutex( if (!KmtIsCheckedBuild || OriginalIrql <= APC_LEVEL) { /* acquire/release normally */ - KeAcquireGuardedMutex(Mutex); + pKeAcquireGuardedMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql); - ok_bool_false(KeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned"); + ok_bool_false(pKeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); /* try to acquire */ - ok_bool_true(KeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned"); + ok_bool_true(pKeTryToAcquireGuardedMutex(Mutex), "KeTryToAcquireGuardedMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); } else @@ -69,9 +149,9 @@ TestGuardedMutex( if (!KmtIsCheckedBuild || OriginalIrql == APC_LEVEL || SpecialApcsDisabled < 0) { /* acquire/release unsafe */ - KeAcquireGuardedMutexUnsafe(Mutex); + pKeAcquireGuardedMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); - KeReleaseGuardedMutexUnsafe(Mutex); + pKeReleaseGuardedMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); } @@ -79,29 +159,29 @@ TestGuardedMutex( if (!KmtIsCheckedBuild) { /* mismatched acquire/release */ - KeAcquireGuardedMutex(Mutex); + pKeAcquireGuardedMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql); - KeReleaseGuardedMutexUnsafe(Mutex); + pKeReleaseGuardedMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled - 1, TRUE, OriginalIrql); - KeLeaveGuardedRegion(); + pKeLeaveGuardedRegion(); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); - KeAcquireGuardedMutexUnsafe(Mutex); + pKeAcquireGuardedMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled + 1, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -1, OriginalIrql); - KeEnterGuardedRegion(); + pKeEnterGuardedRegion(); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); /* release without acquire */ - KeReleaseGuardedMutexUnsafe(Mutex); + pKeReleaseGuardedMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, NULL, 0LU, 0x5555, SpecialApcsDisabled - 1, KernelApcsDisabled, SpecialApcsDisabled, AllApcsDisabled, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 1, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -1, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); /* TODO: here we see that Mutex->Count isn't actually just a count. Test the bits correctly! */ CheckMutex(Mutex, 0L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 2, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -2, OriginalIrql); - KeReleaseGuardedMutex(Mutex); + pKeReleaseGuardedMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, 0x5555, SpecialApcsDisabled, KernelApcsDisabled, SpecialApcsDisabled + 3, OriginalIrql >= APC_LEVEL || SpecialApcsDisabled != -3, OriginalIrql); Thread->SpecialApcDisable -= 3; } @@ -242,10 +322,10 @@ TestGuardedMutexConcurrent( LARGE_INTEGER Timeout; Timeout.QuadPart = -50 * 1000 * 10; /* 50 ms */ - InitThreadData(&ThreadData, Mutex, KeAcquireGuardedMutex, NULL, KeReleaseGuardedMutex); - InitThreadData(&ThreadData2, Mutex, KeAcquireGuardedMutex, NULL, KeReleaseGuardedMutex); - InitThreadData(&ThreadDataUnsafe, Mutex, KeAcquireGuardedMutexUnsafe, NULL, KeReleaseGuardedMutexUnsafe); - InitThreadData(&ThreadDataTry, Mutex, NULL, KeTryToAcquireGuardedMutex, KeReleaseGuardedMutex); + InitThreadData(&ThreadData, Mutex, pKeAcquireGuardedMutex, NULL, pKeReleaseGuardedMutex); + InitThreadData(&ThreadData2, Mutex, pKeAcquireGuardedMutex, NULL, pKeReleaseGuardedMutex); + InitThreadData(&ThreadDataUnsafe, Mutex, pKeAcquireGuardedMutexUnsafe, NULL, pKeReleaseGuardedMutexUnsafe); + InitThreadData(&ThreadDataTry, Mutex, NULL, pKeTryToAcquireGuardedMutex, pKeReleaseGuardedMutex); /* have a thread acquire the mutex */ Status = StartThread(&ThreadData, NULL, PASSIVE_LEVEL, FALSE, FALSE); @@ -337,6 +417,29 @@ START_TEST(KeGuardedMutex) }; int i; + pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled"); + pKeInitializeGuardedMutex = KmtGetSystemRoutineAddress(L"KeInitializeGuardedMutex"); + pKeAcquireGuardedMutex = KmtGetSystemRoutineAddress(L"KeAcquireGuardedMutex"); + pKeAcquireGuardedMutexUnsafe = KmtGetSystemRoutineAddress(L"KeAcquireGuardedMutexUnsafe"); + pKeEnterGuardedRegion = KmtGetSystemRoutineAddress(L"KeEnterGuardedRegion"); + pKeLeaveGuardedRegion = KmtGetSystemRoutineAddress(L"KeLeaveGuardedRegion"); + pKeReleaseGuardedMutex = KmtGetSystemRoutineAddress(L"KeReleaseGuardedMutex"); + pKeReleaseGuardedMutexUnsafe = KmtGetSystemRoutineAddress(L"KeReleaseGuardedMutexUnsafe"); + pKeTryToAcquireGuardedMutex = KmtGetSystemRoutineAddress(L"KeTryToAcquireGuardedMutex"); + + if (skip(pKeAreAllApcsDisabled && + pKeInitializeGuardedMutex && + pKeAcquireGuardedMutex && + pKeAcquireGuardedMutexUnsafe && + pKeEnterGuardedRegion && + pKeLeaveGuardedRegion && + pKeReleaseGuardedMutex && + pKeReleaseGuardedMutexUnsafe && + pKeTryToAcquireGuardedMutex, "No guarded mutexes\n")) + { + return; + } + for (i = 0; i < sizeof TestIterations / sizeof TestIterations[0]; ++i) { trace("Run %d\n", i); @@ -345,7 +448,7 @@ START_TEST(KeGuardedMutex) Thread->SpecialApcDisable = TestIterations[i].SpecialApcsDisabled; RtlFillMemory(&Mutex, sizeof Mutex, 0x55); - KeInitializeGuardedMutex(&Mutex); + pKeInitializeGuardedMutex(&Mutex); CheckMutex(&Mutex, 1L, NULL, 0LU, 0x5555, 0x5555, TestIterations[i].KernelApcsDisabled, TestIterations[i].SpecialApcsDisabled, TestIterations[i].AllApcsDisabled, TestIterations[i].Irql); TestGuardedMutex(&Mutex, TestIterations[i].KernelApcsDisabled, TestIterations[i].SpecialApcsDisabled, TestIterations[i].AllApcsDisabled, TestIterations[i].Irql); @@ -356,6 +459,6 @@ START_TEST(KeGuardedMutex) trace("Concurrent test\n"); RtlFillMemory(&Mutex, sizeof Mutex, 0x55); - KeInitializeGuardedMutex(&Mutex); + pKeInitializeGuardedMutex(&Mutex); TestGuardedMutexConcurrent(&Mutex); } diff --git a/rostests/kmtests/ntos_ke/KeMutex.c b/rostests/kmtests/ntos_ke/KeMutex.c index 0670e8a15a7..257418c9fa4 100644 --- a/rostests/kmtests/ntos_ke/KeMutex.c +++ b/rostests/kmtests/ntos_ke/KeMutex.c @@ -7,6 +7,13 @@ #include +static +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +BOOLEAN +(NTAPI +*pKeAreAllApcsDisabled)(VOID); + #define ULONGS_PER_POINTER (sizeof(PVOID) / sizeof(ULONG)) #define MUTANT_SIZE (2 + 6 * ULONGS_PER_POINTER) @@ -55,7 +62,8 @@ C_ASSERT(sizeof(KMUTANT) == MUTANT_SIZE * sizeof(ULONG)); { \ ok_eq_bool(KeAreApcsDisabled(), KernelApcsDisabled || SpecialApcsDisabled); \ ok_eq_int(Thread->KernelApcDisable, KernelApcsDisabled); \ - ok_eq_bool(KeAreAllApcsDisabled(), AllApcsDisabled); \ + if (pKeAreAllApcsDisabled) \ + ok_eq_bool(pKeAreAllApcsDisabled(), AllApcsDisabled); \ ok_eq_int(Thread->SpecialApcDisable, SpecialApcsDisabled); \ ok_irql(Irql); \ } while (0) @@ -137,6 +145,12 @@ TestMutex(VOID) START_TEST(KeMutex) { + pKeAreAllApcsDisabled = KmtGetSystemRoutineAddress(L"KeAreAllApcsDisabled"); + if (skip(pKeAreAllApcsDisabled != NULL, "KeAreAllApcsDisabled unavailable\n")) + { + /* We can live without this function here */ + } + TestMutant(); TestMutex(); } diff --git a/rostests/kmtests/ntos_ke/KeSpinLock.c b/rostests/kmtests/ntos_ke/KeSpinLock.c index c88a038e6b7..dc2e944043e 100644 --- a/rostests/kmtests/ntos_ke/KeSpinLock.c +++ b/rostests/kmtests/ntos_ke/KeSpinLock.c @@ -20,20 +20,37 @@ __declspec(dllimport) void __stdcall KeReleaseSpinLockFromDpcLevel(unsigned long //#define NDEBUG #include -/* TODO: these are documented for Vista+ */ -NTKERNELAPI +static +_Must_inspect_result_ +_IRQL_requires_min_(DISPATCH_LEVEL) +_Post_satisfies_(return == 1 || return == 0) +BOOLEAN +(FASTCALL +*pKeTryToAcquireSpinLockAtDpcLevel)( + _Inout_ _Requires_lock_not_held_(*_Curr_) + _When_(return!=0, _Acquires_lock_(*_Curr_)) + PKSPIN_LOCK SpinLock); + +static VOID -FASTCALL -KeAcquireInStackQueuedSpinLockForDpc( +(FASTCALL +*pKeAcquireInStackQueuedSpinLockForDpc)( IN OUT PKSPIN_LOCK SpinLock, OUT PKLOCK_QUEUE_HANDLE LockHandle); -NTKERNELAPI +static VOID -FASTCALL -KeReleaseInStackQueuedSpinLockForDpc( +(FASTCALL +*pKeReleaseInStackQueuedSpinLockForDpc)( IN PKLOCK_QUEUE_HANDLE LockHandle); +static +_Must_inspect_result_ +BOOLEAN +(FASTCALL +*pKeTestSpinLock)( + _In_ PKSPIN_LOCK SpinLock); + /* TODO: multiprocessor testing */ struct _CHECK_DATA; @@ -119,8 +136,8 @@ DEFINE_ACQUIRE(AcquireForDpc, TRUE, CheckData->Irql = KeAcquireSpinLock DEFINE_RELEASE(ReleaseForDpc, TRUE, KeReleaseSpinLockForDpc(SpinLock, CheckData->Irql)) #endif -DEFINE_ACQUIRE(AcquireInStackForDpc, FALSE, KeAcquireInStackQueuedSpinLockForDpc(SpinLock, &CheckData->QueueHandle)) -DEFINE_RELEASE(ReleaseInStackForDpc, FALSE, KeReleaseInStackQueuedSpinLockForDpc(&CheckData->QueueHandle)) +DEFINE_ACQUIRE(AcquireInStackForDpc, FALSE, pKeAcquireInStackQueuedSpinLockForDpc(SpinLock, &CheckData->QueueHandle)) +DEFINE_RELEASE(ReleaseInStackForDpc, FALSE, pKeReleaseInStackQueuedSpinLockForDpc(&CheckData->QueueHandle)) #ifdef _X86_ DEFINE_ACQUIRE(AcquireInt, FALSE, KiAcquireSpinLock(SpinLock)) @@ -142,7 +159,7 @@ BOOLEAN TryQueuedSynch(PKSPIN_LOCK SpinLock, PCHECK_DATA CheckData) { return Ret; } BOOLEAN TryNoRaise(PKSPIN_LOCK SpinLock, PCHECK_DATA CheckData) { - BOOLEAN Ret = KeTryToAcquireSpinLockAtDpcLevel(SpinLock); + BOOLEAN Ret = pKeTryToAcquireSpinLockAtDpcLevel(SpinLock); return Ret; } @@ -197,7 +214,7 @@ BOOLEAN TryNoRaise(PKSPIN_LOCK SpinLock, PCHECK_DATA CheckData) { #define CheckSpinLock(SpinLock, CheckData, Value) do \ { \ - BOOLEAN Ret = SpinLock ? KeTestSpinLock(SpinLock) : TRUE; \ + BOOLEAN Ret = SpinLock && pKeTestSpinLock ? pKeTestSpinLock(SpinLock) : TRUE; \ KIRQL ExpectedIrql = (CheckData)->OriginalIrql; \ \ switch ((CheckData)->Check) \ @@ -257,7 +274,10 @@ TestSpinLock( } if (CheckData->AcquireNoRaise && - (CheckData->OriginalIrql >= DISPATCH_LEVEL || !KmtIsCheckedBuild)) + (CheckData->OriginalIrql >= DISPATCH_LEVEL || !KmtIsCheckedBuild) && + (CheckData->AcquireNoRaise != AcquireInStackForDpc || + !skip(pKeAcquireInStackQueuedSpinLockForDpc && + pKeReleaseInStackQueuedSpinLockForDpc, "No DPC spinlock functions\n"))) { /* acquire/release without irql change */ CheckData->AcquireNoRaise(SpinLock, CheckData); @@ -279,7 +299,8 @@ TestSpinLock( CheckData->IsAcquired = FALSE; KmtSetIrql(CheckData->OriginalIrql); - if (CheckData->TryAcquireNoRaise) + if (CheckData->TryAcquireNoRaise && + !skip(pKeTryToAcquireSpinLockAtDpcLevel != NULL, "KeTryToAcquireSpinLockAtDpcLevel unavailable\n")) { CheckSpinLock(SpinLock, CheckData, 0); ok_bool_true(CheckData->TryAcquireNoRaise(SpinLock, CheckData), "TryAcquireNoRaise returned"); @@ -320,7 +341,14 @@ START_TEST(KeSpinLock) { CheckQueue, SynchIrql, AcquireQueuedSynch, ReleaseQueued, TryQueuedSynch, NULL, NULL, NULL, LockQueuePfnLock }, }; int i, iIrql; - PKPRCB Prcb = KeGetCurrentPrcb(); + PKPRCB Prcb; + + pKeTryToAcquireSpinLockAtDpcLevel = KmtGetSystemRoutineAddress(L"KeTryToAcquireSpinLockAtDpcLevel"); + pKeAcquireInStackQueuedSpinLockForDpc = KmtGetSystemRoutineAddress(L"KeAcquireInStackQueuedSpinLockForDpc"); + pKeReleaseInStackQueuedSpinLockForDpc = KmtGetSystemRoutineAddress(L"KeReleaseInStackQueuedSpinLockForDpc"); + pKeTestSpinLock = KmtGetSystemRoutineAddress(L"KeTestSpinLock"); + + Prcb = KeGetCurrentPrcb(); /* KeInitializeSpinLock */ memset(&SpinLock, 0x55, sizeof SpinLock); @@ -328,17 +356,20 @@ START_TEST(KeSpinLock) ok_eq_ulongptr(SpinLock, 0); /* KeTestSpinLock */ - ok_bool_true(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); - SpinLock = 1; - ok_bool_false(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); - SpinLock = 2; - ok_bool_false(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); - SpinLock = (ULONG_PTR)-1; - ok_bool_false(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); - SpinLock = (ULONG_PTR)1 << (sizeof(ULONG_PTR) * CHAR_BIT - 1); - ok_bool_false(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); - SpinLock = 0; - ok_bool_true(KeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + if (!skip(pKeTestSpinLock != NULL, "KeTestSpinLock unavailable\n")) + { + ok_bool_true(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + SpinLock = 1; + ok_bool_false(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + SpinLock = 2; + ok_bool_false(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + SpinLock = (ULONG_PTR)-1; + ok_bool_false(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + SpinLock = (ULONG_PTR)1 << (sizeof(ULONG_PTR) * CHAR_BIT - 1); + ok_bool_false(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + SpinLock = 0; + ok_bool_true(pKeTestSpinLock(&SpinLock), "KeTestSpinLock returned"); + } /* on UP none of the following functions actually looks at the spinlock! */ if (!KmtIsMultiProcessorBuild && !KmtIsCheckedBuild) -- 2.17.1