PCM_KEY_HASH_TABLE_ENTRY CmpCacheTable;
PCM_NAME_HASH_TABLE_ENTRY CmpNameCacheTable;
-BOOLEAN CmpHoldLazyFlush;
-
/* FUNCTIONS *****************************************************************/
VOID
Length = CmpHashTableSize * sizeof(CM_KEY_HASH_TABLE_ENTRY);
/* Allocate it */
- CmpCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
+ CmpCacheTable = CmpAllocate(Length, TRUE, TAG_CM);
if (!CmpCacheTable)
{
/* Take the system down */
Length = CmpHashTableSize * sizeof(CM_NAME_HASH_TABLE_ENTRY);
/* Now allocate the name cache table */
- CmpNameCacheTable = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
+ CmpNameCacheTable = CmpAllocate(Length, TRUE, TAG_CM);
if (!CmpNameCacheTable)
{
/* Take the system down */
Length = NodeName->Length / sizeof(WCHAR);
for (i = 0; i < (NodeName->Length / sizeof(WCHAR)); i++)
{
- /* Check if this is a valid character */
- if (*NodeName->Buffer > (UCHAR)-1)
+ /* Check if this is a 16-bit character */
+ if (NodeName->Buffer[i] > (UCHAR)-1)
{
/* This is the actual size, and we know we're not compressed */
Length = NodeName->Length;
IsCompressed = FALSE;
+ break;
}
}
-
+
/* Lock the NCB entry */
CmpAcquireNcbLockExclusiveByKey(ConvKey);
Ncb = CONTAINING_RECORD(HashEntry, CM_NAME_CONTROL_BLOCK, NameHash);
/* Check if the hash matches */
- if ((ConvKey = HashEntry->ConvKey) && (Length = Ncb->NameLength))
+ if ((ConvKey == HashEntry->ConvKey) && (Length == Ncb->NameLength))
{
/* Assume success */
Found = TRUE;
if (Found)
{
/* Reference it */
+ ASSERT(Ncb->RefCount != 0xFFFF);
Ncb->RefCount++;
+ break;
}
}
/* Go to the next hash */
HashEntry = HashEntry->NextHash;
}
-
+
/* Check if we didn't find it */
if (!Found)
{
/* Allocate one */
NcbSize = FIELD_OFFSET(CM_NAME_CONTROL_BLOCK, Name) + Length;
- Ncb = ExAllocatePoolWithTag(PagedPool, NcbSize, TAG_CM);
+ Ncb = CmpAllocate(NcbSize, TRUE, TAG_CM);
if (!Ncb)
{
/* Release the lock and fail */
CmpReleaseNcbLockByKey(ConvKey);
return NULL;
}
-
+
/* Clear it out */
RtlZeroMemory(Ncb, NcbSize);
-
+
/* Check if the name was compressed */
if (IsCompressed)
{
/* Copy the compressed name */
- Ncb->Compressed = TRUE;
- for (i = 0; i < Length; i++)
+ for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
{
/* Copy Unicode to ANSI */
((PCHAR)Ncb->Name)[i] = (CHAR)RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
else
{
/* Copy the name directly */
- Ncb->Compressed = FALSE;
- for (i = 0; i < Length; i++)
+ for (i = 0; i < NodeName->Length / sizeof(WCHAR); i++)
{
/* Copy each unicode character */
Ncb->Name[i] = RtlUpcaseUnicodeChar(NodeName->Buffer[i]);
}
}
-
+
/* Setup the rest of the NCB */
+ Ncb->Compressed = IsCompressed;
Ncb->ConvKey = ConvKey;
Ncb->RefCount++;
Ncb->NameLength = Length;
-
+
/* Insert the name in the hash table */
HashEntry = &Ncb->NameHash;
HashEntry->NextHash = GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry;
GET_HASH_ENTRY(CmpNameCacheTable, ConvKey).Entry = HashEntry;
}
-
+
/* Release NCB lock */
CmpReleaseNcbLockByKey(ConvKey);
CmpAcquireNcbLockExclusiveByKey(ConvKey);
/* Decrease the reference count */
+ ASSERT(Ncb->RefCount >= 1);
if (!(--Ncb->RefCount))
{
/* Find the NCB in the table */
}
/* Found it, now free it */
- ExFreePool(Ncb);
+ CmpFree(Ncb, 0);
}
/* Release the lock */
if (CMP_IS_CELL_CACHED(CachedList[i]))
{
/* Free it */
- ExFreePool((PVOID)CMP_GET_CACHED_CELL(CachedList[i]));
+ CmpFree((PVOID)CMP_GET_CACHED_CELL(CachedList[i]), 0);
}
}
/* Now free the list */
- ExFreePool((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList));
+ CmpFree((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList), 0);
Kcb->ValueCache.ValueList = HCELL_NIL;
}
else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);
/* Check if we have an index hint block and free it */
- if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) ExFreePool(Kcb->IndexHint);
+ if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) CmpFree(Kcb->IndexHint, 0);
/* Check if we were already deleted */
Parent = Kcb->ParentKcb;
if (Kcb->ExtFlags & (CM_KCB_SUBKEY_HINT))
{
/* Kill it */
- ExFreePool(Kcb->IndexHint);
+ CmpFree(Kcb->IndexHint, 0);
}
/* Remove subkey flags */
}
/* Check if there's no linked cell */
- if (Kcb->KeyCell == HCELL_NIL)
+ if (Kcb->KeyCell == HCELL_NIL)
{
/* Make sure it's a delete */
- ASSERT(Kcb->Delete);
- KeyNode = NULL;
- }
+ ASSERT(Kcb->Delete);
+ KeyNode = NULL;
+ }
else
{
/* Get the key node */
- KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
- }
-
+ KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
+ }
+
/* Check if we got the node */
if (!KeyNode)
{
Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
Kcb->SubKeyCount = KeyNode->SubKeyCounts[Stable] +
KeyNode->SubKeyCounts[Volatile];
-
+
/* Release the cell */
HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
}
NewRefCount = OldRefCount - 1;
/* Check if we still have references */
- if( (NewRefCount & 0xFFFF) > 0)
+ if ((NewRefCount & 0xFFFF) > 0)
{
/* Do the dereference */
if (InterlockedCompareExchange((PLONG)&Kcb->RefCount,
}
/* Check if this is a KCB inside a frozen hive */
- if ((Kcb) && (((PCMHIVE)Hive)->Frozen) && (!(Kcb->Flags & KEY_SYM_LINK)))
+ if ((Kcb) && (((PCMHIVE)Hive)->Frozen) && (!(Kcb->Flags & KEY_SYM_LINK)))
{
/* Don't add these to the delay close */
- Kcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
+ Kcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
}
-
+
/* Sanity check */
ASSERT((!Kcb) || (Kcb->Delete == FALSE));
}
/* Allocate the unicode string now */
- KeyName = ExAllocatePoolWithTag(PagedPool,
- NameLength + sizeof(UNICODE_STRING),
- TAG_CM);
+ KeyName = CmpAllocate(NameLength + sizeof(UNICODE_STRING),
+ TRUE,
+ TAG_CM);
if (!KeyName) return NULL;
MyKcb->ExtFlags & CM_KCB_KEY_NON_EXIST)
{
/* Failure */
- ExFreePool(KeyName);
+ CmpFree(KeyName, 0);
return NULL;
}
if (!KeyNode)
{
/* Failure */
- ExFreePool(KeyName);
+ CmpFree(KeyName, 0);
return NULL;
}
}
for (i = 0; i < 4; i++)
{
/* Add it into the list */
- if (!InterlockedCompareExchangePointer(&KeyBody->KeyControlBlock->
+ if (!InterlockedCompareExchangePointer((PVOID*)&KeyBody->KeyControlBlock->
KeyBodyArray[i],
KeyBody,
NULL))
for (i = 0; i < 4; i++)
{
/* Add it into the list */
- if (InterlockedCompareExchangePointer(&KeyBody->KeyControlBlock->
+ if (InterlockedCompareExchangePointer((VOID*)&KeyBody->KeyControlBlock->
KeyBodyArray[i],
NULL,
KeyBody) == KeyBody)
/* Unlock it it if we did a manual lock */
if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock);
}
+
+VOID
+NTAPI
+CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb,
+ IN BOOLEAN LockHeld)
+{
+ PLIST_ENTRY NextEntry, ListHead;
+ PCM_KEY_BODY KeyBody;
+
+ /* Sanity check */
+ LockHeld ? CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() : CmpIsKcbLockedExclusive(Kcb);
+ while (TRUE)
+ {
+ /* Is the list empty? */
+ ListHead = &Kcb->KeyBodyListHead;
+ if (!IsListEmpty(ListHead))
+ {
+ /* Loop the list */
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the key body */
+ KeyBody = CONTAINING_RECORD(NextEntry, CM_KEY_BODY, KeyBodyList);
+ ASSERT(KeyBody->Type == '20yk');
+
+ /* Check for notifications */
+ if (KeyBody->NotifyBlock)
+ {
+ /* Is the lock held? */
+ if (LockHeld)
+ {
+ /* Flush it */
+ CmpFlushNotify(KeyBody, LockHeld);
+ ASSERT(KeyBody->NotifyBlock == NULL);
+ continue;
+ }
+
+ /* Lock isn't held, so we need to take a reference */
+ if (ObReferenceObjectSafe(KeyBody))
+ {
+ /* Now we can flush */
+ CmpFlushNotify(KeyBody, LockHeld);
+ ASSERT(KeyBody->NotifyBlock == NULL);
+
+ /* Release the reference we took */
+ ObDereferenceObjectDeferDelete(KeyBody);
+ continue;
+ }
+ }
+
+ /* Try the next entry */
+ NextEntry = NextEntry->Flink;
+ }
+ }
+
+ /* List has been parsed, exit */
+ break;
+ }
+}