- Fix pointer.
[reactos.git] / reactos / ntoskrnl / include / internal / cm_x.h
1 /*
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)
7 */
8
9 //
10 // Returns whether or not this is a small valued key
11 //
12 FORCEINLINE
13 BOOLEAN
14 CmpIsKeyValueSmall(OUT PULONG RealLength,
15 IN ULONG Length)
16 {
17 /* Check if the length has the special size value */
18 if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
19 {
20 /* It does, so this is a small key: return the real length */
21 *RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
22 return TRUE;
23 }
24
25 /* This is not a small key, return the length we read */
26 *RealLength = Length;
27 return FALSE;
28 }
29
30 //
31 // Returns whether or not this is a big valued key
32 //
33 FORCEINLINE
34 BOOLEAN
35 CmpIsKeyValueBig(IN PHHIVE Hive,
36 IN ULONG Length)
37 {
38 /* Check if the hive is XP Beta 1 or newer */
39 if (Hive->Version >= HSYS_WHISTLER_BETA1)
40 {
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))
43 {
44 /* Yes, this value is big */
45 return TRUE;
46 }
47 }
48
49 /* Not a big value key */
50 return FALSE;
51 }
52
53 //
54 // Returns the hashkey corresponding to a convkey
55 //
56 #define GET_HASH_KEY(ConvKey) \
57 ((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
58
59 //
60 // Returns the index into the hash table, or the entry itself
61 //
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))
68
69 //
70 // Returns whether or not the cell is cached
71 //
72 #define CMP_IS_CELL_CACHED(c) \
73 (((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
74
75 //
76 // Return data from a cached cell
77 //
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))
86
87 //
88 // Makes sure that the registry is locked
89 //
90 #define CMP_ASSERT_REGISTRY_LOCK() \
91 ASSERT((CmpSpecialBootCondition == TRUE) || \
92 (CmpTestRegistryLock() == TRUE))
93
94 //
95 // Makes sure that the registry is locked or loading
96 //
97 #define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h) \
98 ASSERT((CmpSpecialBootCondition == TRUE) || \
99 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
100 (CmpTestRegistryLock() == TRUE))
101
102 //
103 // Makes sure that the registry is exclusively locked
104 //
105 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
106 ASSERT((CmpSpecialBootCondition == TRUE) || \
107 (CmpTestRegistryLockExclusive() == TRUE))
108
109 //
110 // Makes sure that the registry is exclusively locked or loading
111 //
112 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h) \
113 ASSERT((CmpSpecialBootCondition == TRUE) || \
114 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \
115 (CmpTestRegistryLockExclusive() == TRUE))
116
117 //
118 // Makes sure this is a valid KCB
119 //
120 #define ASSERT_KCB_VALID(k) \
121 ASSERT((k)->Signature == CM_KCB_SIGNATURE)
122
123 //
124 // Checks if a KCB is exclusively locked
125 //
126 #define CmpIsKcbLockedExclusive(k) \
127 (GET_HASH_ENTRY(CmpCacheTable, \
128 (k)->ConvKey).Owner == KeGetCurrentThread())
129
130 //
131 // Exclusively acquires a KCB
132 //
133 #define CmpAcquireKcbLockExclusive(k) \
134 { \
135 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
136 (k)->ConvKey).Lock); \
137 GET_HASH_ENTRY(CmpCacheTable, \
138 (k)->ConvKey).Owner = KeGetCurrentThread(); \
139 }
140
141 //
142 // Exclusively acquires a KCB by index
143 //
144 #define CmpAcquireKcbLockExclusiveByIndex(i) \
145 { \
146 ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
147 CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
148 }
149
150 //
151 // Exclusively acquires a KCB by key
152 //
153 #define CmpAcquireKcbLockExclusiveByKey(k) \
154 { \
155 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
156 (k)).Lock); \
157 GET_HASH_ENTRY(CmpCacheTable, \
158 (k)).Owner = KeGetCurrentThread(); \
159 }
160
161
162 //
163 // Shared acquires a KCB
164 //
165 #define CmpAcquireKcbLockShared(k) \
166 { \
167 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
168 (k)->ConvKey).Lock); \
169 }
170
171 //
172 // Shared acquires a KCB by index
173 //
174 #define CmpAcquireKcbLockSharedByIndex(i) \
175 { \
176 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
177 }
178
179 //
180 // Tries to convert a KCB lock
181 //
182 FORCEINLINE
183 BOOLEAN
184 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
185 {
186 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
187 if (ExConvertPushLockSharedToExclusive(
188 &GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
189 {
190 GET_HASH_ENTRY(CmpCacheTable,
191 k->ConvKey).Owner = KeGetCurrentThread();
192 return TRUE;
193 }
194 return FALSE;
195 }
196
197 //
198 // Releases an exlusively or shared acquired KCB
199 //
200 #define CmpReleaseKcbLock(k) \
201 { \
202 GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
203 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
204 (k)->ConvKey).Lock); \
205 }
206
207 //
208 // Releases an exlusively or shared acquired KCB by index
209 //
210 #define CmpReleaseKcbLockByIndex(i) \
211 { \
212 CmpCacheTable[(i)].Owner = NULL; \
213 ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
214 }
215
216 //
217 // Releases an exlusively or shared acquired KCB by key
218 //
219 #define CmpReleaseKcbLockByKey(k) \
220 { \
221 GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
222 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
223 (k)).Lock); \
224 }
225
226 //
227 // Converts a KCB lock
228 //
229 FORCEINLINE
230 VOID
231 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
232 {
233 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
234 CmpReleaseKcbLock(k);
235 CmpAcquireKcbLockExclusive(k);
236 }
237
238 //
239 // Exclusively acquires an NCB
240 //
241 #define CmpAcquireNcbLockExclusive(n) \
242 { \
243 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
244 (n)->ConvKey).Lock); \
245 }
246
247 //
248 // Exclusively acquires an NCB by key
249 //
250 #define CmpAcquireNcbLockExclusiveByKey(k) \
251 { \
252 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
253 (k)).Lock); \
254 }
255
256 //
257 // Releases an exlusively or shared acquired NCB
258 //
259 #define CmpReleaseNcbLock(k) \
260 { \
261 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
262 (k)->ConvKey).Lock); \
263 }
264
265 //
266 // Releases an exlusively or shared acquired NCB by key
267 //
268 #define CmpReleaseNcbLockByKey(k) \
269 { \
270 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
271 (k)).Lock); \
272 }
273
274 //
275 // Asserts that either the registry or the hash entry is locked
276 //
277 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
278 { \
279 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
280 KeGetCurrentThread())) || \
281 (CmpTestRegistryLockExclusive() == TRUE)); \
282 }
283
284 //
285 // Asserts that either the registry or the KCB is locked
286 //
287 #define CMP_ASSERT_KCB_LOCK(k) \
288 { \
289 ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \
290 (CmpTestRegistryLockExclusive() == TRUE)); \
291 }
292
293 //
294 // Gets the page attached to the KCB
295 //
296 #define CmpGetAllocPageFromKcb(k) \
297 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
298
299 //
300 // Gets the page attached to the delayed allocation
301 //
302 #define CmpGetAllocPageFromDelayAlloc(a) \
303 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))
304
305 //
306 // Makes sure that the registry is locked for flushes
307 //
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));
314
315 //
316 // Asserts that either the registry or the KCB is locked
317 //
318 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \
319 { \
320 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k).Owner == \
321 KeGetCurrentThread())) || \
322 (CmpTestRegistryLockExclusive() == TRUE)); \
323 }
324
325 //
326 // Gets the page attached to the KCB
327 //
328 #define CmpGetAllocPageFromKcb(k) \
329 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1))
330
331 //
332 // Gets the page attached to the delayed allocation
333 //
334 #define CmpGetAllocPageFromDelayAlloc(a) \
335 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1))