2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/internal/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 locked or loading
97 #define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h) \
98 ASSERT((CmpSpecialBootCondition == TRUE) || \
99 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
100 (CmpTestRegistryLock() == TRUE))
103 // Makes sure that the registry is exclusively locked
105 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
106 ASSERT((CmpSpecialBootCondition == TRUE) || \
107 (CmpTestRegistryLockExclusive() == TRUE))
110 // Makes sure that the registry is exclusively locked or loading
112 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h) \
113 ASSERT((CmpSpecialBootCondition == TRUE) || \
114 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
115 (CmpTestRegistryLockExclusive() == TRUE))
118 // Makes sure this is a valid KCB
120 #define ASSERT_KCB_VALID(k) \
121 ASSERT((k)->Signature == CM_KCB_SIGNATURE)
124 // Checks if a KCB is exclusively locked
126 #define CmpIsKcbLockedExclusive(k) \
127 (GET_HASH_ENTRY(CmpCacheTable, \
128 (k)->ConvKey).Owner == KeGetCurrentThread())
131 // Exclusively acquires a KCB
133 #define CmpAcquireKcbLockExclusive(k) \
135 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
136 (k)->ConvKey).Lock); \
137 GET_HASH_ENTRY(CmpCacheTable, \
138 (k)->ConvKey).Owner = KeGetCurrentThread(); \
142 // Exclusively acquires a KCB by index
144 #define CmpAcquireKcbLockExclusiveByIndex(i) \
146 ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
147 CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
151 // Exclusively acquires a KCB by key
153 #define CmpAcquireKcbLockExclusiveByKey(k) \
155 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
157 GET_HASH_ENTRY(CmpCacheTable, \
158 (k)).Owner = KeGetCurrentThread(); \
163 // Shared acquires a KCB
165 #define CmpAcquireKcbLockShared(k) \
167 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
168 (k)->ConvKey).Lock); \
172 // Shared acquires a KCB by index
174 #define CmpAcquireKcbLockSharedByIndex(i) \
176 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
180 // Tries to convert a KCB lock
184 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
186 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
187 if (ExConvertPushLockSharedToExclusive(
188 &GET_HASH_ENTRY(CmpCacheTable
, k
->ConvKey
).Lock
))
190 GET_HASH_ENTRY(CmpCacheTable
,
191 k
->ConvKey
).Owner
= KeGetCurrentThread();
198 // Releases an exlusively or shared acquired KCB
200 #define CmpReleaseKcbLock(k) \
202 GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
203 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
204 (k)->ConvKey).Lock); \
208 // Releases an exlusively or shared acquired KCB by index
210 #define CmpReleaseKcbLockByIndex(i) \
212 CmpCacheTable[(i)].Owner = NULL; \
213 ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
217 // Releases an exlusively or shared acquired KCB by key
219 #define CmpReleaseKcbLockByKey(k) \
221 GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
222 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
227 // Converts a KCB lock
231 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k
)
233 ASSERT(CmpIsKcbLockedExclusive(k
) == FALSE
);
234 CmpReleaseKcbLock(k
);
235 CmpAcquireKcbLockExclusive(k
);
239 // Exclusively acquires an NCB
241 #define CmpAcquireNcbLockExclusive(n) \
243 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
244 (n)->ConvKey).Lock); \
248 // Exclusively acquires an NCB by key
250 #define CmpAcquireNcbLockExclusiveByKey(k) \
252 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
257 // Releases an exlusively or shared acquired NCB
259 #define CmpReleaseNcbLock(k) \
261 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
262 (k)->ConvKey).Lock); \
266 // Releases an exlusively or shared acquired NCB by key
268 #define CmpReleaseNcbLockByKey(k) \
270 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
275 // Asserts that either the registry or the hash entry is locked
277 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
279 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
280 KeGetCurrentThread())) || \
281 (CmpTestRegistryLockExclusive() == TRUE)); \
285 // Asserts that either the registry or the KCB is locked
287 #define CMP_ASSERT_KCB_LOCK(k) \
289 ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \
290 (CmpTestRegistryLockExclusive() == TRUE)); \
294 // Gets the page attached to the KCB
296 #define CmpGetAllocPageFromKcb(k) \
297 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
300 // Gets the page attached to the delayed allocation
302 #define CmpGetAllocPageFromDelayAlloc(a) \
303 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
306 // Makes sure that the registry is locked for flushes
308 #define CMP_ASSERT_FLUSH_LOCK(h) \
309 ASSERT((CmpSpecialBootCondition == TRUE) || \
310 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
311 (CmpTestHiveFlusherLockShared((PCMHIVE)h) == TRUE) || \
312 (CmpTestHiveFlusherLockExclusive((PCMHIVE)h) == TRUE) || \
313 (CmpTestRegistryLockExclusive() == TRUE));