sync with trunk (r46275)
[reactos.git] / ntoskrnl / include / internal / cm_x.h
1 /*
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)
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 exclusively locked
96 //
97 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
98 ASSERT((CmpSpecialBootCondition == TRUE) || \
99 (CmpTestRegistryLockExclusive() == TRUE))
100
101 //
102 // Makes sure this is a valid KCB
103 //
104 #define ASSERT_KCB_VALID(k) \
105 ASSERT((k)->Signature == CM_KCB_SIGNATURE)
106
107 //
108 // Checks if a KCB is exclusively locked
109 //
110 #define CmpIsKcbLockedExclusive(k) \
111 (GET_HASH_ENTRY(CmpCacheTable, \
112 (k)->ConvKey).Owner == KeGetCurrentThread())
113
114 //
115 // Exclusively acquires a KCB
116 //
117 #define CmpAcquireKcbLockExclusive(k) \
118 { \
119 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
120 (k)->ConvKey).Lock); \
121 GET_HASH_ENTRY(CmpCacheTable, \
122 (k)->ConvKey).Owner = KeGetCurrentThread(); \
123 }
124
125 //
126 // Exclusively acquires a KCB by index
127 //
128 #define CmpAcquireKcbLockExclusiveByIndex(i) \
129 { \
130 ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
131 CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
132 }
133
134 //
135 // Exclusively acquires a KCB by key
136 //
137 #define CmpAcquireKcbLockExclusiveByKey(k) \
138 { \
139 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
140 (k)).Lock); \
141 GET_HASH_ENTRY(CmpCacheTable, \
142 (k)).Owner = KeGetCurrentThread(); \
143 }
144
145
146 //
147 // Shared acquires a KCB
148 //
149 #define CmpAcquireKcbLockShared(k) \
150 { \
151 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
152 (k)->ConvKey).Lock); \
153 }
154
155 //
156 // Shared acquires a KCB by index
157 //
158 #define CmpAcquireKcbLockSharedByIndex(i) \
159 { \
160 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
161 }
162
163 //
164 // Tries to convert a KCB lock
165 //
166 FORCEINLINE
167 BOOLEAN
168 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
169 {
170 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
171 if (ExConvertPushLockSharedToExclusive(
172 &GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
173 {
174 GET_HASH_ENTRY(CmpCacheTable,
175 k->ConvKey).Owner = KeGetCurrentThread();
176 return TRUE;
177 }
178 return FALSE;
179 }
180
181 //
182 // Releases an exlusively or shared acquired KCB
183 //
184 #define CmpReleaseKcbLock(k) \
185 { \
186 GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
187 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
188 (k)->ConvKey).Lock); \
189 }
190
191 //
192 // Releases an exlusively or shared acquired KCB by index
193 //
194 #define CmpReleaseKcbLockByIndex(i) \
195 { \
196 CmpCacheTable[(i)].Owner = NULL; \
197 ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
198 }
199
200 //
201 // Releases an exlusively or shared acquired KCB by key
202 //
203 #define CmpReleaseKcbLockByKey(k) \
204 { \
205 GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
206 ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
207 (k)).Lock); \
208 }
209
210 //
211 // Converts a KCB lock
212 //
213 FORCEINLINE
214 VOID
215 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
216 {
217 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
218 CmpReleaseKcbLock(k);
219 CmpAcquireKcbLockExclusive(k);
220 }
221
222 //
223 // Exclusively acquires an NCB
224 //
225 #define CmpAcquireNcbLockExclusive(n) \
226 { \
227 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
228 (n)->ConvKey).Lock); \
229 }
230
231 //
232 // Exclusively acquires an NCB by key
233 //
234 #define CmpAcquireNcbLockExclusiveByKey(k) \
235 { \
236 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
237 (k)).Lock); \
238 }
239
240 //
241 // Releases an exlusively or shared acquired NCB
242 //
243 #define CmpReleaseNcbLock(k) \
244 { \
245 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
246 (k)->ConvKey).Lock); \
247 }
248
249 //
250 // Releases an exlusively or shared acquired NCB by key
251 //
252 #define CmpReleaseNcbLockByKey(k) \
253 { \
254 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
255 (k)).Lock); \
256 }