VOID NTAPI CmpLazyFlushWorker(IN PVOID Parameter) { BOOLEAN ForceFlush, Result, MoreWork = FALSE; ULONG DirtyCount = 0; PAGED_CODE(); /* Don't do anything if lazy flushing isn't enabled yet */ if (CmpHoldLazyFlush) { DPRINT1("Lazy flush held. Bye bye.\n"); CmpLazyFlushPending = FALSE; return; } /* Check if we are forcing a flush */ ForceFlush = CmpForceForceFlush; if (ForceFlush) { DPRINT("Forcing flush.\n"); /* Lock the registry exclusively */ CmpLockRegistryExclusive(); } else { DPRINT("Not forcing flush.\n"); /* Starve writers before locking */ InterlockedIncrement(&CmpFlushStarveWriters); CmpLockRegistry(); } /* Flush the next hive */ MoreWork = CmpDoFlushNextHive(ForceFlush, &Result, &DirtyCount); if (!MoreWork) { /* We're done */ InterlockedIncrement((PLONG)&CmpLazyFlushCount); } /* Check if we have starved writers */ if (!ForceFlush) InterlockedDecrement(&CmpFlushStarveWriters); /* Not pending anymore, release the registry lock */ CmpLazyFlushPending = FALSE; CmpUnlockRegistry(); DPRINT("Lazy flush done. More work to be done: %s. Entries still dirty: %u.\n", MoreWork ? "Yes" : "No", DirtyCount); if (MoreWork) { /* Relaunch the flush timer, so the remaining hives get flushed */ CmpLazyFlush(); } }
VOID NTAPI CmpLazyFlushWorker(IN PVOID Parameter) { BOOLEAN ForceFlush, Result, MoreWork = FALSE; ULONG DirtyCount = 0; PAGED_CODE(); /* Don't do anything if lazy flushing isn't enabled yet */ if (CmpHoldLazyFlush) return; /* Check if we are forcing a flush */ ForceFlush = CmpForceForceFlush; if (ForceFlush) { /* Lock the registry exclusively */ CmpLockRegistryExclusive(); } else { /* Do a normal lock */ CmpLockRegistry(); InterlockedIncrement(&CmpFlushStarveWriters); } /* Flush the next hive */ MoreWork = CmpDoFlushNextHive(ForceFlush, &Result, &DirtyCount); if (!MoreWork) { /* We're done */ InterlockedIncrement((PLONG)&CmpLazyFlushCount); } /* Check if we have starved writers */ if (!ForceFlush) InterlockedDecrement(&CmpFlushStarveWriters); /* Not pending anymore, release the registry lock */ CmpLazyFlushPending = FALSE; CmpUnlockRegistry(); /* Check if we need to flush another hive */ if ((MoreWork) || (DirtyCount)) CmpLazyFlush(); }
VOID CmpLateUnloadHiveWorker( IN PVOID Hive ) /*++ Routine Description: "Late" unloads the hive; If nothing goes badly wrong (i.e. insufficient resources), this function should succeed Arguments: CmHive - the frozen hive to be unloaded Return Value: NONE. --*/ { NTSTATUS Status; HCELL_INDEX Cell; PCM_KEY_CONTROL_BLOCK RootKcb; PCMHIVE CmHive; CM_PAGED_CODE(); // // first, load the registry exclusive // CmpLockRegistryExclusive(); // // hive is the parameter to this worker; make sure we free the work item // allocated by CmpDeleteKeyObject // CmHive = (PCMHIVE)Hive; ASSERT( CmHive->UnloadWorkItem != NULL ); ExFreePool( CmHive->UnloadWorkItem ); // // if this attempt doesn't succeed, mark that we can try another // CmHive->UnloadWorkItem = NULL; ASSERT( !(CmHive->Hive.HiveFlags & HIVE_IS_UNLOADING) ); if( CmHive->Frozen == FALSE ) { // // another thread mounted the exact same hive in the exact same place, hence unfreezing the hive // we've done the cleanup part (free the workitem) nothing more to do. // or hive is already in process of being unloaded // ASSERT( CmHive->RootKcb == NULL ); CmpUnlockRegistry(); return; } // // this is just about the only possible way the hive can get corrupted in between // if( HvShutdownComplete == TRUE ) { // too late to do anything CmpUnlockRegistry(); return; } // // hive should be frozen, otherwise we wouldn't get here // ASSERT( CmHive->Frozen == TRUE ); RootKcb = CmHive->RootKcb; // // root kcb must be valid and has only our "artificial" refcount on it // ASSERT( RootKcb != NULL ); if( RootKcb->RefCount > 1 ) { // // somebody else must've gotten in between dropping/reacquiring the reglock // and opened a handle inside this hive; bad luck, we can't unload // CmpUnlockRegistry(); return; } ASSERT_KCB(RootKcb); Cell = RootKcb->KeyCell; Status = CmUnloadKey(RootKcb,0,CM_UNLOAD_REG_LOCKED_EX); ASSERT( (Status != STATUS_CANNOT_DELETE) && (Status != STATUS_INVALID_PARAMETER) ); if(NT_SUCCESS(Status)) { // CmUnloadKey already released the lock CmpLockRegistry(); CmpDereferenceKeyControlBlock(RootKcb); } CmpUnlockRegistry(); }