2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/cm/cm_x.h
5 * PURPOSE: Inlined Functions for the Configuration Manager
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
10 // Returns whether or not this is a small valued key
14 CmpIsKeyValueSmall(OUT PULONG RealLength
,
17 /* Check if the length has the special size value */
18 if (Length
>= CM_KEY_VALUE_SPECIAL_SIZE
)
20 /* It does, so this is a small key: return the real length */
21 *RealLength
= Length
- CM_KEY_VALUE_SPECIAL_SIZE
;
25 /* This is not a small key, return the length we read */
31 // Returns whether or not this is a big valued key
35 CmpIsKeyValueBig(IN PHHIVE Hive
,
38 /* Check if the hive is XP Beta 1 or newer */
39 if (Hive
->Version
>= HSYS_WHISTLER_BETA1
)
41 /* Check if the key length is valid for a big value key */
42 if ((Length
< CM_KEY_VALUE_SPECIAL_SIZE
) && (Length
> CM_KEY_VALUE_BIG
))
44 /* Yes, this value is big */
49 /* Not a big value key */
54 // Returns the hashkey corresponding to a convkey
56 #define GET_HASH_KEY(ConvKey) \
57 ((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
60 // Returns the index into the hash table, or the entry itself
62 #define GET_HASH_INDEX(ConvKey) \
63 GET_HASH_KEY(ConvKey) % CmpHashTableSize
64 #define GET_HASH_ENTRY(Table, ConvKey) \
65 (Table[GET_HASH_INDEX(ConvKey)])
66 #define ASSERT_VALID_HASH(h) \
67 ASSERT_KCB_VALID(CONTAINING_RECORD((h), CM_KEY_CONTROL_BLOCK, KeyHash))
70 // Returns whether or not the cell is cached
72 #define CMP_IS_CELL_CACHED(c) \
73 (((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
76 // Return data from a cached cell
78 #define CMP_GET_CACHED_CELL(c) \
79 (ULONG_PTR)((c) & ~HCELL_CACHED)
80 #define CMP_GET_CACHED_DATA(c) \
81 (&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
82 #define CMP_GET_CACHED_INDEX(c) \
83 (&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
84 #define CMP_GET_CACHED_VALUE(c) \
85 (&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
88 // Makes sure that the registry is locked
90 #define CMP_ASSERT_REGISTRY_LOCK() \
91 ASSERT((CmpSpecialBootCondition == TRUE) || \
92 (CmpTestRegistryLock() == TRUE))
95 // Makes sure that the registry is exclusively locked
97 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
98 ASSERT((CmpSpecialBootCondition == TRUE) || \
99 (CmpTestRegistryLockExclusive() == TRUE))
102 // Makes sure this is a valid KCB
104 #define ASSERT_KCB_VALID(k) \
105 ASSERT((k)->Signature == CM_KCB_SIGNATURE)
108 // Checks if a KCB is exclusively locked
110 #define CmpIsKcbLockedExclusive(k) \
111 (GET_HASH_ENTRY(CmpCacheTable, \
112 (k)->ConvKey).Owner == KeGetCurrentThread())
115 // Exclusively acquires a KCB
117 #define CmpAcquireKcbLockExclusive(k) \
119 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
120 (k)->ConvKey).Lock); \
121 GET_HASH_ENTRY(CmpCacheTable, \
122 (k)->ConvKey).Owner = KeGetCurrentThread(); \
126 // Exclusively acquires a KCB by index
128 #define CmpAcquireKcbLockExclusiveByIndex(i) \
130 ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
131 CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
135 // Exclusively acquires a KCB by key
137 #define CmpAcquireKcbLockExclusiveByKey(k) \
139 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
141 GET_HASH_ENTRY(CmpCacheTable, \
142 (k)).Owner = KeGetCurrentThread(); \
147 // Shared acquires a KCB
149 #define CmpAcquireKcbLockShared(k) \
151 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
152 (k)->ConvKey).Lock); \
156 // Shared acquires a KCB by index
158 #define CmpAcquireKcbLockSharedByIndex(i) \
160 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
164 // Tries to convert a KCB lock
168 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
170 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
171 if (ExConvertPushLockSharedToExclusive(
172 &GET_HASH_ENTRY(CmpCacheTable
, k
->ConvKey
).Lock
))
174 GET_HASH_ENTRY(CmpCacheTable
,
175 k
->ConvKey
).Owner
= KeGetCurrentThread();
182 // Releases an exlusively or shared acquired KCB
184 #define CmpReleaseKcbLock(k) \
186 GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
187 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
188 (k)->ConvKey).Lock); \
192 // Releases an exlusively or shared acquired KCB by index
194 #define CmpReleaseKcbLockByIndex(i) \
196 CmpCacheTable[(i)].Owner = NULL; \
197 ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
201 // Releases an exlusively or shared acquired KCB by key
203 #define CmpReleaseKcbLockByKey(k) \
205 GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
206 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
211 // Converts a KCB lock
215 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
217 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
218 CmpReleaseKcbLock(k
);
219 CmpAcquireKcbLockExclusive(k
);
223 // Exclusively acquires an NCB
225 #define CmpAcquireNcbLockExclusive(n) \
227 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
228 (n)->ConvKey).Lock); \
232 // Exclusively acquires an NCB by key
234 #define CmpAcquireNcbLockExclusiveByKey(k) \
236 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
241 // Releases an exlusively or shared acquired NCB
243 #define CmpReleaseNcbLock(k) \
245 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
246 (k)->ConvKey).Lock); \
250 // Releases an exlusively or shared acquired NCB by key
252 #define CmpReleaseNcbLockByKey(k) \
254 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
259 // Asserts that either the registry or the KCB is locked
261 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
263 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
264 KeGetCurrentThread())) || \
265 (CmpTestRegistryLockExclusive() == TRUE)); \
269 // Gets the page attached to the KCB
271 #define CmpGetAllocPageFromKcb(k) \
272 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
275 // Gets the page attached to the delayed allocation
277 #define CmpGetAllocPageFromDelayAlloc(a) \
278 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))