KTIMER CmiWorkerTimer;
LIST_ENTRY CmiKeyObjectListHead;
LIST_ENTRY CmiConnectedHiveList;
-ULONG CmiTimer = 0;
+ULONG CmiTimer = 0; /* gets incremented every 5 seconds (CmiWorkerTimer) */
volatile BOOLEAN CmiHiveSyncEnabled = FALSE;
volatile BOOLEAN CmiHiveSyncPending = FALSE;
/* FUNCTIONS ****************************************************************/
+/* Debugging helper functions: */
+/* CmiVerifyHiveListIntegrity */
+/* CmiVerifyHiveListIntegrityWhileLocked */
+/* These functions are normally unused. However, should any of the asserts */
+/* checking for registry loops in CmiWorkerThread start to trigger, it is */
+/* recommended to add liberal amounts of calls to this function throughout */
+/* suspect code. This function is due to its iterative nature not intended */
+/* to be called during normal circumstances, but as a debugging aid. */
+static
+VOID
+NTAPI
+CmipVerifyHiveListIntegrity(BOOLEAN IsLocked)
+{
+ PLIST_ENTRY CurrentEntry;
+ if (!IsLocked)
+ {
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
+ }
+
+ if (IsListEmpty(&CmiKeyObjectListHead))
+ {
+ ASSERT(CmiKeyObjectListHead.Blink == CmiKeyObjectListHead.Flink);
+ }
+ /* walk the list both forwards and backwards */
+ CurrentEntry = CmiKeyObjectListHead.Flink;
+ while (CurrentEntry != &CmiKeyObjectListHead)
+ {
+ ASSERT(CurrentEntry->Blink != CurrentEntry);
+ ASSERT(CurrentEntry->Flink != CurrentEntry);
+ CurrentEntry = CurrentEntry->Flink;
+ }
+
+ CurrentEntry = CmiKeyObjectListHead.Blink;
+ while (CurrentEntry != &CmiKeyObjectListHead)
+ {
+ ASSERT(CurrentEntry->Blink != CurrentEntry);
+ ASSERT(CurrentEntry->Flink != CurrentEntry);
+ CurrentEntry = CurrentEntry->Blink;
+ }
+
+ if (!IsLocked)
+ {
+ ExReleaseResourceLite(&CmpRegistryLock);
+ KeLeaveCriticalRegion();
+ }
+}
+
+VOID NTAPI CmiVerifyHiveListIntegrity() { CmipVerifyHiveListIntegrity(FALSE); }
+VOID NTAPI CmiVerifyHiveListIntegrityWhileLocked() { CmipVerifyHiveListIntegrity(TRUE); }
+
+
+
VOID
NTAPI
CmiWorkerThread(PVOID Param)
NTSTATUS Status;
PLIST_ENTRY CurrentEntry;
PKEY_OBJECT CurrentKey;
- ULONG Count;
+ ULONG Count; /* how many objects have been dereferenced each pass */
+
+ /* Loop forever, getting woken up every 5 seconds by CmiWorkerTimer */
while (1)
{
if (1 == ObGetObjectPointerCount(CurrentKey) &&
!(CurrentKey->Flags & KO_MARKED_FOR_DELETE))
{
+ /* PointerCount is 1, and it's not marked for delete */
ObDereferenceObject(CurrentKey);
if (CurrentEntry == CmiKeyObjectListHead.Blink)
{
}
else
{
+ /* PointerCount was not 1, or it was marked for delete */
if (CurrentEntry == CurrentEntry->Blink)
{
DPRINT("Registry loop detected! Crashing\n");
return (PVOID)((MdBlock->BasePage << PAGE_SHIFT) | KSEG0_BASE);
}
+/* Precondition: Must not hold the hive lock CmpRegistryLock */
VOID
NTAPI
EnlistKeyBodyWithKCB(IN PKEY_OBJECT KeyObject,
IN ULONG Flags)
{
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
+
/* Insert it into the global list (we don't have KCBs here) */
InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry);
+
+ ExReleaseResourceLite(&CmpRegistryLock);
+ KeLeaveCriticalRegion();
}
NTSTATUS