mirror of
https://github.com/reactos/reactos.git
synced 2024-09-11 21:34:09 +00:00
336 lines
11 KiB
C
336 lines
11 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/cm/cm_x.h
|
|
* PURPOSE: Inlined Functions for the Configuration Manager
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
//
|
|
// Returns whether or not this is a small valued key
|
|
//
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
CmpIsKeyValueSmall(OUT PULONG RealLength,
|
|
IN ULONG Length)
|
|
{
|
|
/* Check if the length has the special size value */
|
|
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
|
|
{
|
|
/* It does, so this is a small key: return the real length */
|
|
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
|
|
return TRUE;
|
|
}
|
|
|
|
/* This is not a small key, return the length we read */
|
|
*RealLength = Length;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Returns whether or not this is a big valued key
|
|
//
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
CmpIsKeyValueBig(IN PHHIVE Hive,
|
|
IN ULONG Length)
|
|
{
|
|
/* Check if the hive is XP Beta 1 or newer */
|
|
if (Hive->Version >= HSYS_WHISTLER_BETA1)
|
|
{
|
|
/* Check if the key length is valid for a big value key */
|
|
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
|
|
{
|
|
/* Yes, this value is big */
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/* Not a big value key */
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Returns the hashkey corresponding to a convkey
|
|
//
|
|
#define GET_HASH_KEY(ConvKey) \
|
|
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
|
|
|
|
//
|
|
// Returns the index into the hash table, or the entry itself
|
|
//
|
|
#define GET_HASH_INDEX(ConvKey) \
|
|
GET_HASH_KEY(ConvKey) % CmpHashTableSize
|
|
#define GET_HASH_ENTRY(Table, ConvKey) \
|
|
(Table[GET_HASH_INDEX(ConvKey)])
|
|
#define ASSERT_VALID_HASH(h) \
|
|
ASSERT_KCB_VALID(CONTAINING_RECORD((h), CM_KEY_CONTROL_BLOCK, KeyHash))
|
|
|
|
//
|
|
// Returns whether or not the cell is cached
|
|
//
|
|
#define CMP_IS_CELL_CACHED(c) \
|
|
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
|
|
|
|
//
|
|
// Return data from a cached cell
|
|
//
|
|
#define CMP_GET_CACHED_CELL(c) \
|
|
(ULONG_PTR)((c) & ~HCELL_CACHED)
|
|
#define CMP_GET_CACHED_DATA(c) \
|
|
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
|
|
#define CMP_GET_CACHED_INDEX(c) \
|
|
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
|
|
#define CMP_GET_CACHED_VALUE(c) \
|
|
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
|
|
|
|
//
|
|
// Makes sure that the registry is locked
|
|
//
|
|
#define CMP_ASSERT_REGISTRY_LOCK() \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
|
(CmpTestRegistryLock() == TRUE))
|
|
|
|
//
|
|
// Makes sure that the registry is locked or loading
|
|
//
|
|
#define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h) \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
|
(((PCMHIVE)h)->HiveIsLoading == TRUE) || \
|
|
(CmpTestRegistryLock() == TRUE))
|
|
|
|
//
|
|
// Makes sure that the registry is exclusively locked
|
|
//
|
|
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE))
|
|
|
|
//
|
|
// Makes sure that the registry is exclusively locked or loading
|
|
//
|
|
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h) \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
|
(((PCMHIVE)h)->HiveIsLoading == TRUE) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE))
|
|
|
|
//
|
|
// Makes sure this is a valid KCB
|
|
//
|
|
#define ASSERT_KCB_VALID(k) \
|
|
ASSERT((k)->Signature == CM_KCB_SIGNATURE)
|
|
|
|
//
|
|
// Checks if a KCB is exclusively locked
|
|
//
|
|
#define CmpIsKcbLockedExclusive(k) \
|
|
(GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)->ConvKey).Owner == KeGetCurrentThread())
|
|
|
|
//
|
|
// Exclusively acquires a KCB
|
|
//
|
|
#define CmpAcquireKcbLockExclusive(k) \
|
|
{ \
|
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)->ConvKey).Lock); \
|
|
GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)->ConvKey).Owner = KeGetCurrentThread(); \
|
|
}
|
|
|
|
//
|
|
// Exclusively acquires a KCB by index
|
|
//
|
|
#define CmpAcquireKcbLockExclusiveByIndex(i) \
|
|
{ \
|
|
ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
|
|
CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
|
|
}
|
|
|
|
//
|
|
// Exclusively acquires a KCB by key
|
|
//
|
|
#define CmpAcquireKcbLockExclusiveByKey(k) \
|
|
{ \
|
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)).Lock); \
|
|
GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)).Owner = KeGetCurrentThread(); \
|
|
}
|
|
|
|
|
|
//
|
|
// Shared acquires a KCB
|
|
//
|
|
#define CmpAcquireKcbLockShared(k) \
|
|
{ \
|
|
ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)->ConvKey).Lock); \
|
|
}
|
|
|
|
//
|
|
// Shared acquires a KCB by index
|
|
//
|
|
#define CmpAcquireKcbLockSharedByIndex(i) \
|
|
{ \
|
|
ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
|
|
}
|
|
|
|
//
|
|
// Tries to convert a KCB lock
|
|
//
|
|
FORCEINLINE
|
|
BOOLEAN
|
|
CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
|
{
|
|
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
|
if (ExConvertPushLockSharedToExclusive(
|
|
&GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
|
|
{
|
|
GET_HASH_ENTRY(CmpCacheTable,
|
|
k->ConvKey).Owner = KeGetCurrentThread();
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Releases an exlusively or shared acquired KCB
|
|
//
|
|
#define CmpReleaseKcbLock(k) \
|
|
{ \
|
|
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
|
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)->ConvKey).Lock); \
|
|
}
|
|
|
|
//
|
|
// Releases an exlusively or shared acquired KCB by index
|
|
//
|
|
#define CmpReleaseKcbLockByIndex(i) \
|
|
{ \
|
|
CmpCacheTable[(i)].Owner = NULL; \
|
|
ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
|
|
}
|
|
|
|
//
|
|
// Releases an exlusively or shared acquired KCB by key
|
|
//
|
|
#define CmpReleaseKcbLockByKey(k) \
|
|
{ \
|
|
GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
|
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
|
(k)).Lock); \
|
|
}
|
|
|
|
//
|
|
// Converts a KCB lock
|
|
//
|
|
FORCEINLINE
|
|
VOID
|
|
CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
|
{
|
|
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
|
CmpReleaseKcbLock(k);
|
|
CmpAcquireKcbLockExclusive(k);
|
|
}
|
|
|
|
//
|
|
// Exclusively acquires an NCB
|
|
//
|
|
#define CmpAcquireNcbLockExclusive(n) \
|
|
{ \
|
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
|
(n)->ConvKey).Lock); \
|
|
}
|
|
|
|
//
|
|
// Exclusively acquires an NCB by key
|
|
//
|
|
#define CmpAcquireNcbLockExclusiveByKey(k) \
|
|
{ \
|
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
|
(k)).Lock); \
|
|
}
|
|
|
|
//
|
|
// Releases an exlusively or shared acquired NCB
|
|
//
|
|
#define CmpReleaseNcbLock(k) \
|
|
{ \
|
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
|
(k)->ConvKey).Lock); \
|
|
}
|
|
|
|
//
|
|
// Releases an exlusively or shared acquired NCB by key
|
|
//
|
|
#define CmpReleaseNcbLockByKey(k) \
|
|
{ \
|
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
|
(k)).Lock); \
|
|
}
|
|
|
|
//
|
|
// Asserts that either the registry or the hash entry is locked
|
|
//
|
|
#define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
|
|
{ \
|
|
ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
|
|
KeGetCurrentThread())) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE)); \
|
|
}
|
|
|
|
//
|
|
// Asserts that either the registry or the KCB is locked
|
|
//
|
|
#define CMP_ASSERT_KCB_LOCK(k) \
|
|
{ \
|
|
ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE)); \
|
|
}
|
|
|
|
//
|
|
// Gets the page attached to the KCB
|
|
//
|
|
#define CmpGetAllocPageFromKcb(k) \
|
|
(PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
|
|
|
|
//
|
|
// Gets the page attached to the delayed allocation
|
|
//
|
|
#define CmpGetAllocPageFromDelayAlloc(a) \
|
|
(PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
|
|
|
|
//
|
|
// Makes sure that the registry is locked for flushes
|
|
//
|
|
#define CMP_ASSERT_FLUSH_LOCK(h) \
|
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
|
(((PCMHIVE)h)->HiveIsLoading == TRUE) || \
|
|
(CmpTestHiveFlusherLockShared((PCMHIVE)h) == TRUE) || \
|
|
(CmpTestHiveFlusherLockExclusive((PCMHIVE)h) == TRUE) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE));
|
|
|
|
//
|
|
// Asserts that either the registry or the KCB is locked
|
|
//
|
|
#define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
|
|
{ \
|
|
ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
|
|
KeGetCurrentThread())) || \
|
|
(CmpTestRegistryLockExclusive() == TRUE)); \
|
|
}
|
|
|
|
//
|
|
// Gets the page attached to the KCB
|
|
//
|
|
#define CmpGetAllocPageFromKcb(k) \
|
|
(PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
|
|
|
|
//
|
|
// Gets the page attached to the delayed allocation
|
|
//
|
|
#define CmpGetAllocPageFromDelayAlloc(a) \
|
|
(PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
|