VOID
NtfsDecrementCleanupCounts (
IN PSCB Scb,
IN PLCB Lcb OPTIONAL,
IN BOOLEAN NonCachedHandle
)
/*++
Routine Description:
This procedure decrements the cleanup counts for the associated data structures
and if necessary it also start to cleanup associated internal attribute streams
Arguments:
Scb - Supplies the Scb used in this operation
Lcb - Optionally supplies the Lcb used in this operation
NonCachedHandle - Indicates this handle is for a user non-cached handle.
Return Value:
None.
翻译:
此过程减少关联数据结构的清理计数
如果有必要,它还会开始清理关联的内部属性流
论据:
Scb - 提供此操作中使用的 Scb
Lcb - 可选择提供此操作中使用的 Lcb
NonCachedHandle - 指示此句柄用于用户非缓存句柄。
--*/
{
PVCB Vcb = Scb->Vcb;
ASSERT_SCB( Scb );
ASSERT_FCB( Scb->Fcb );
ASSERT_VCB( Scb->Fcb->Vcb );
ASSERT_OPTIONAL_LCB( Lcb );
//
// First we decrement the appropriate cleanup counts
//
if (ARGUMENT_PRESENT(Lcb)) { Lcb->CleanupCount -= 1; }
InterlockedDecrement( &Scb->CleanupCount );
Scb->Fcb->CleanupCount -= 1;
if (NonCachedHandle) {
Scb->NonCachedCleanupCount -= 1;
}
InterlockedDecrement( &Vcb->CleanupCount );
//
// Now if the Fcb's cleanup count is zero that indicates that we are
// done with this Fcb from a user handle standpoint and we should
// now scan through all of the Scb's that are opened under this
// Fcb and shutdown any internal attributes streams we have open.
// For example, EAs and ACLs. We only need to do one. The domino effect
// will take of the rest.
//
if (Scb->Fcb->CleanupCount == 0) {
PSCB NextScb;
//
// Remember if we are dealing with a system file and return immediately.
//
if (NtfsSegmentNumber( &Scb->Fcb->FileReference ) < FIRST_USER_FILE_NUMBER &&
NtfsSegmentNumber( &Scb->Fcb->FileReference ) != ROOT_FILE_NAME_INDEX_NUMBER) {
return;
}
for (NextScb = CONTAINING_RECORD(Scb->Fcb->ScbQueue.Flink, SCB, FcbLinks);
&NextScb->FcbLinks != &Scb->Fcb->ScbQueue;
NextScb = CONTAINING_RECORD( NextScb->FcbLinks.Flink, SCB, FcbLinks )) {
//
// Skip the root index on the volume.
//
if (SafeNodeType( NextScb ) == NTFS_NTC_SCB_ROOT_INDEX) {
continue;
}
//
// If we have an index with children then break out.
//
if ((SafeNodeType( NextScb ) == NTFS_NTC_SCB_INDEX) &&
!IsListEmpty( &NextScb->ScbType.Index.LcbQueue )) {
break;
}
//
// If there is an internal stream then dereference it and get out.
//
if (NextScb->FileObject != NULL) {
NtfsDeleteInternalAttributeStream( NextScb,
(BOOLEAN) (Scb->Fcb->LinkCount == 0) );
break;
}
}
}
//
// And return to our caller
//
return;
}