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 the hashkey corresponding to a convkey 11 // 12 #define GET_HASH_KEY(ConvKey) \ 13 ((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME) 14 15 // 16 // Returns the index into the hash table, or the entry itself 17 // 18 #define GET_HASH_INDEX(ConvKey) \ 19 GET_HASH_KEY(ConvKey) % CmpHashTableSize 20 #define GET_HASH_ENTRY(Table, ConvKey) \ 21 (&Table[GET_HASH_INDEX(ConvKey)]) 22 #define ASSERT_VALID_HASH(h) \ 23 ASSERT_KCB_VALID(CONTAINING_RECORD((h), CM_KEY_CONTROL_BLOCK, KeyHash)) 24 25 // 26 // Returns whether or not the cell is cached 27 // 28 #define CMP_IS_CELL_CACHED(c) \ 29 (((c) & HCELL_CACHED) && ((c) != HCELL_NIL)) 30 31 // 32 // Return data from a cached cell 33 // 34 #define CMP_GET_CACHED_CELL(c) \ 35 (ULONG_PTR)((c) & ~HCELL_CACHED) 36 #define CMP_GET_CACHED_DATA(c) \ 37 (&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData)) 38 #define CMP_GET_CACHED_INDEX(c) \ 39 (&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex)) 40 #define CMP_GET_CACHED_VALUE(c) \ 41 (&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue)) 42 43 // 44 // Makes sure that the registry is locked 45 // 46 #define CMP_ASSERT_REGISTRY_LOCK() \ 47 ASSERT((CmpSpecialBootCondition == TRUE) || \ 48 (CmpTestRegistryLock() == TRUE)) 49 50 // 51 // Makes sure that the registry is locked or loading 52 // 53 #define CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(h) \ 54 ASSERT((CmpSpecialBootCondition == TRUE) || \ 55 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \ 56 (CmpTestRegistryLock() == TRUE)) 57 58 // 59 // Makes sure that the registry is exclusively locked 60 // 61 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \ 62 ASSERT((CmpSpecialBootCondition == TRUE) || \ 63 (CmpTestRegistryLockExclusive() == TRUE)) 64 65 // 66 // Makes sure that the registry is exclusively locked or loading 67 // 68 #define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(h) \ 69 ASSERT((CmpSpecialBootCondition == TRUE) || \ 70 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \ 71 (CmpTestRegistryLockExclusive() == TRUE)) 72 73 // 74 // Makes sure this is a valid KCB 75 // 76 #define ASSERT_KCB_VALID(k) \ 77 ASSERT((k)->Signature == CM_KCB_SIGNATURE) 78 79 // 80 // Checks if a KCB is exclusively locked 81 // 82 #define CmpIsKcbLockedExclusive(k) \ 83 (GET_HASH_ENTRY(CmpCacheTable, \ 84 (k)->ConvKey)->Owner == KeGetCurrentThread()) 85 86 // 87 // Exclusively acquires a KCB by index 88 // 89 FORCEINLINE 90 VOID 91 CmpAcquireKcbLockExclusiveByIndex(ULONG Index) 92 { 93 ExAcquirePushLockExclusive(&CmpCacheTable[Index].Lock); 94 CmpCacheTable[Index].Owner = KeGetCurrentThread(); 95 } 96 97 // 98 // Exclusively acquires a KCB 99 // 100 FORCEINLINE 101 VOID 102 CmpAcquireKcbLockExclusive(PCM_KEY_CONTROL_BLOCK Kcb) 103 { 104 CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(Kcb->ConvKey)); 105 } 106 107 // 108 // Exclusively acquires a KCB by key 109 // 110 FORCEINLINE 111 VOID 112 CmpAcquireKcbLockExclusiveByKey(IN ULONG ConvKey) 113 { 114 CmpAcquireKcbLockExclusiveByIndex(GET_HASH_INDEX(ConvKey)); 115 } 116 117 118 // 119 // Shared acquires a KCB 120 // 121 #define CmpAcquireKcbLockShared(k) \ 122 { \ 123 ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \ 124 (k)->ConvKey)->Lock); \ 125 } 126 127 // 128 // Shared acquires a KCB by index 129 // 130 #define CmpAcquireKcbLockSharedByIndex(i) \ 131 { \ 132 ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \ 133 } 134 135 // 136 // Tries to convert a KCB lock 137 // 138 FORCEINLINE 139 BOOLEAN 140 CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k) 141 { 142 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE); 143 if (ExConvertPushLockSharedToExclusive( 144 &GET_HASH_ENTRY(CmpCacheTable, k->ConvKey)->Lock)) 145 { 146 GET_HASH_ENTRY(CmpCacheTable, 147 k->ConvKey)->Owner = KeGetCurrentThread(); 148 return TRUE; 149 } 150 return FALSE; 151 } 152 153 // 154 // Releases an exlusively or shared acquired KCB by index 155 // 156 FORCEINLINE 157 VOID 158 CmpReleaseKcbLockByIndex(ULONG Index) 159 { 160 CmpCacheTable[Index].Owner = NULL; 161 ExReleasePushLock(&CmpCacheTable[Index].Lock); 162 } 163 164 // 165 // Releases an exlusively or shared acquired KCB 166 // 167 FORCEINLINE 168 VOID 169 CmpReleaseKcbLock(PCM_KEY_CONTROL_BLOCK Kcb) 170 { 171 CmpReleaseKcbLockByIndex(GET_HASH_INDEX(Kcb->ConvKey)); 172 } 173 174 // 175 // Releases an exlusively or shared acquired KCB by key 176 // 177 FORCEINLINE 178 VOID 179 CmpReleaseKcbLockByKey(ULONG ConvKey) 180 { 181 CmpReleaseKcbLockByIndex(GET_HASH_INDEX(ConvKey)); 182 } 183 184 // 185 // Converts a KCB lock 186 // 187 FORCEINLINE 188 VOID 189 CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k) 190 { 191 ASSERT(CmpIsKcbLockedExclusive(k) == FALSE); 192 CmpReleaseKcbLock(k); 193 CmpAcquireKcbLockExclusive(k); 194 } 195 196 // 197 // Exclusively acquires an NCB 198 // 199 #define CmpAcquireNcbLockExclusive(n) \ 200 { \ 201 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \ 202 (n)->ConvKey)->Lock); \ 203 } 204 205 // 206 // Exclusively acquires an NCB by key 207 // 208 #define CmpAcquireNcbLockExclusiveByKey(k) \ 209 { \ 210 ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \ 211 (k))->Lock); \ 212 } 213 214 // 215 // Releases an exlusively or shared acquired NCB 216 // 217 #define CmpReleaseNcbLock(k) \ 218 { \ 219 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \ 220 (k)->ConvKey)->Lock); \ 221 } 222 223 // 224 // Releases an exlusively or shared acquired NCB by key 225 // 226 #define CmpReleaseNcbLockByKey(k) \ 227 { \ 228 ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \ 229 (k))->Lock); \ 230 } 231 232 // 233 // Asserts that either the registry or the KCB is locked 234 // 235 #define CMP_ASSERT_HASH_ENTRY_LOCK(k) \ 236 { \ 237 ASSERT(((GET_HASH_ENTRY(CmpCacheTable, k)->Owner == \ 238 KeGetCurrentThread())) || \ 239 (CmpTestRegistryLockExclusive() == TRUE)); \ 240 } 241 242 // 243 // Asserts that either the registry or the KCB is locked 244 // 245 #define CMP_ASSERT_KCB_LOCK(k) \ 246 { \ 247 ASSERT((CmpIsKcbLockedExclusive(k) == TRUE) || \ 248 (CmpTestRegistryLockExclusive() == TRUE)); \ 249 } 250 251 // 252 // Gets the page attached to the KCB 253 // 254 #define CmpGetAllocPageFromKcb(k) \ 255 (PCM_ALLOC_PAGE)(((ULONG_PTR)(k)) & ~(PAGE_SIZE - 1)) 256 257 // 258 // Gets the page attached to the delayed allocation 259 // 260 #define CmpGetAllocPageFromDelayAlloc(a) \ 261 (PCM_ALLOC_PAGE)(((ULONG_PTR)(a)) & ~(PAGE_SIZE - 1)) 262 263 // 264 // Makes sure that the registry is locked for flushes 265 // 266 #define CMP_ASSERT_FLUSH_LOCK(h) \ 267 ASSERT((CmpSpecialBootCondition == TRUE) || \ 268 (((PCMHIVE)h)->HiveIsLoading == TRUE) || \ 269 (CmpTestHiveFlusherLockShared((PCMHIVE)h) == TRUE) || \ 270 (CmpTestHiveFlusherLockExclusive((PCMHIVE)h) == TRUE) || \ 271 (CmpTestRegistryLockExclusive() == TRUE)); 272