diff options
Diffstat (limited to 'private/ntos/cntfs/filobsup.c')
-rw-r--r-- | private/ntos/cntfs/filobsup.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/private/ntos/cntfs/filobsup.c b/private/ntos/cntfs/filobsup.c new file mode 100644 index 000000000..3b505d5ba --- /dev/null +++ b/private/ntos/cntfs/filobsup.c @@ -0,0 +1,332 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + FilObSup.c + +Abstract: + + This module implements the Ntfs File object support routines. + +Author: + + Gary Kimura [GaryKi] 21-May-1991 + +Revision History: + +--*/ + +#include "NtfsProc.h" + +// +// The debug trace level +// + +#define Dbg (DEBUG_TRACE_FILOBSUP) + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, NtfsSetFileObject) +#pragma alloc_text(PAGE, NtfsUpdateScbFromFileObject) +#endif + + +VOID +NtfsSetFileObject ( + IN PFILE_OBJECT FileObject, + IN TYPE_OF_OPEN TypeOfOpen, + IN PSCB Scb, + IN PCCB Ccb OPTIONAL + ) + +/*++ + +Routine Description: + + This routine sets the file system pointers within the file object + +Arguments: + + FileObject - Supplies a pointer to the file object being modified. + + TypeOfOpen - Supplies the type of open denoted by the file object. + This is only used by this procedure for sanity checking. + + Scb - Supplies a pointer to Scb for the file object. + + Ccb - Optionally supplies a pointer to a ccb + +Return Value: + + None. + +--*/ + +{ + ASSERT_FILE_OBJECT( FileObject ); + ASSERT_SCB( Scb ); + ASSERT_OPTIONAL_CCB( Ccb ); + + PAGED_CODE(); + + DebugTrace( +1, Dbg, ("NtfsSetFileObject, FileObject = %08lx\n", FileObject) ); + + // + // Load up the FileObject fields. + // + + FileObject->FsContext = Scb; + FileObject->FsContext2 = Ccb; + FileObject->Vpb = Scb->Vcb->Vpb; + + // + // Now store TypeOfOpen if there is a Ccb + // + + ASSERT((Ccb != NULL) || (TypeOfOpen == StreamFileOpen) || (TypeOfOpen == UnopenedFileObject)); + if (Ccb != NULL) { + Ccb->TypeOfOpen = (UCHAR)TypeOfOpen; + } + + // + // If this file has the temporary attribute bit set, don't lazy + // write it unless absolutely necessary. + // + + if (FlagOn( Scb->ScbState, SCB_STATE_TEMPORARY )) { + SetFlag( FileObject->Flags, FO_TEMPORARY_FILE ); + } + + // + // And return to our caller + // + + DebugTrace( -1, Dbg, ("NtfsSetFileObject -> VOID\n") ); + + return; +} + + +// +// Local support routine +// + +VOID +NtfsUpdateScbFromFileObject ( + IN PIRP_CONTEXT IrpContext, + IN PFILE_OBJECT FileObject, + IN PSCB Scb, + IN BOOLEAN CheckTimeStamps + ) + +/*++ + +Routine Description: + + This routine is called to update the Scb/Fcb to reflect the changes to + a file through the fast io path. It only called with a file object which + represents a user's handle. + +Arguments: + + FileObject - This is the file object used in the fast io path. + + Scb - This is the Scb for this stream. + + CheckTimeStamps - Indicates whether we want to update the time stamps from the + fast io flags as well. This will be TRUE if our caller will update the standard information, + attribute header and duplicate info. FALSE if only the attribute header and duplicate info. + The latter case is the valid data length callback from the cache manager. + +Return Value: + + None. + +--*/ + +{ + + PFCB Fcb = Scb->Fcb; + ULONG CcbFlags; + ULONG ScbFlags = 0; + LONGLONG CurrentTime; + + PAGED_CODE(); + + // + // If the size of the main data stream is not part of the Fcb then update it + // now and set the correct Fcb flag. + // + + if (FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA )) { + + if (Fcb->Info.FileSize != Scb->Header.FileSize.QuadPart) { + + Fcb->Info.FileSize = Scb->Header.FileSize.QuadPart; + SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_SIZE ); + } + + if (Fcb->Info.AllocatedLength != Scb->TotalAllocated) { + + Fcb->Info.AllocatedLength = Scb->TotalAllocated; + SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_ALLOC_SIZE ); + } + + if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) { + + SetFlag( ScbFlags, SCB_STATE_CHECK_ATTRIBUTE_SIZE ); + } + + // + // Remember to update the size in the attribute header for named streams as well. + // + + } else if (FlagOn( FileObject->Flags, FO_FILE_SIZE_CHANGED )) { + + SetFlag( ScbFlags, SCB_STATE_NOTIFY_RESIZE_STREAM | SCB_STATE_CHECK_ATTRIBUTE_SIZE ); + } + + ClearFlag( FileObject->Flags, FO_FILE_SIZE_CHANGED ); + + // + // Check whether to update the time stamps if our caller requested it. + // + + if (CheckTimeStamps && !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) { + + BOOLEAN UpdateLastAccess = FALSE; + BOOLEAN UpdateLastChange = FALSE; + BOOLEAN UpdateLastModify = FALSE; + BOOLEAN SetArchive = TRUE; + + // + // Copy the Ccb flags to a local variable. Then we won't have to test + // for the existence of the Ccb each time. + // + + CcbFlags = 0; + + // + // Capture the real flags if present and clear them since we will update the Scb/Fcb. + // + + if (FileObject->FsContext2 != NULL) { + + CcbFlags = ((PCCB) FileObject->FsContext2)->Flags; + ClearFlag( ((PCCB) FileObject->FsContext2)->Flags, + (CCB_FLAG_UPDATE_LAST_MODIFY | + CCB_FLAG_UPDATE_LAST_CHANGE | + CCB_FLAG_SET_ARCHIVE) ); + } + + NtfsGetCurrentTime( IrpContext, CurrentTime ); + + // + // If there was a write to the file then update the last change, last access + // and last write and the archive bit. + // + + if (FlagOn( FileObject->Flags, FO_FILE_MODIFIED )) { + + UpdateLastModify = + UpdateLastAccess = + UpdateLastChange = TRUE; + + // + // Otherwise test each of the individual bits in the file object and + // Ccb. + // + + } else { + + if (FlagOn( FileObject->Flags, FO_FILE_FAST_IO_READ )) { + + UpdateLastAccess = TRUE; + } + + if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_CHANGE )) { + + UpdateLastChange = TRUE; + + if (FlagOn( CcbFlags, CCB_FLAG_UPDATE_LAST_MODIFY )) { + + UpdateLastModify = TRUE; + } + + if (!FlagOn( CcbFlags, CCB_FLAG_SET_ARCHIVE )) { + + SetArchive = FALSE; + } + } + } + + // + // Now set the correct Fcb bits. + // + + if (UpdateLastChange) { + + if (SetArchive) { + + SetFlag( Fcb->Info.FileAttributes, FILE_ATTRIBUTE_ARCHIVE ); + SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_FILE_ATTR ); + SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO ); + } + + if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_CHANGE_TIME )) { + + Fcb->Info.LastChangeTime = CurrentTime; + SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_CHANGE ); + SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO ); + } + + if (UpdateLastModify) { + + // + // Remember a change to a named data stream. + // + + if (!FlagOn( Scb->ScbState, SCB_STATE_UNNAMED_DATA ) && + (Scb->AttributeTypeCode == $DATA)) { + + SetFlag( ScbFlags, SCB_STATE_NOTIFY_MODIFY_STREAM ); + } + + if (!FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_MOD_TIME )) { + + Fcb->Info.LastModificationTime = CurrentTime; + SetFlag( Fcb->InfoFlags, FCB_INFO_CHANGED_LAST_MOD ); + SetFlag( Fcb->FcbState, FCB_STATE_UPDATE_STD_INFO ); + } + } + } + + if (UpdateLastAccess && + !FlagOn( CcbFlags, CCB_FLAG_USER_SET_LAST_ACCESS_TIME ) && + !FlagOn( NtfsData.Flags, NTFS_FLAGS_DISABLE_LAST_ACCESS )) { + + Fcb->CurrentLastAccess = CurrentTime; + } + + // + // Clear all of the fast io flags in the file object. + // + + ClearFlag( FileObject->Flags, FO_FILE_MODIFIED | FO_FILE_FAST_IO_READ ); + } + + // + // Now store the Scb flags into the Scb. + // + + if (ScbFlags) { + + NtfsAcquireFsrtlHeader( Scb ); + SetFlag( Scb->ScbState, ScbFlags ); + NtfsReleaseFsrtlHeader( Scb ); + } + + return; +} + |