📄 fatstruc.h
字号:
// file objects. This count gets decremented in FatCommonCleanup,
// while the OpenCount below gets decremented in FatCommonClose.
//
CLONG UncleanCount;
//
// A count of the number of file objects that have opened
// this file/directory. For files & directories the FsContext of the
// file object points to this record.
//
CLONG OpenCount;
//
// A count of how many of "UncleanCount" handles were opened for
// non-cached I/O.
//
CLONG NonCachedUncleanCount;
//
// The following field is used to locate the dirent for this fcb/dcb.
// All directory are opened as mapped files so the only additional
// information we need to locate this dirent (beside its parent directory)
// is the byte offset for the dirent. Note that for the root dcb
// this field is not used.
//
VBO DirentOffsetWithinDirectory;
//
// The following field is filled in when there is an Lfn associated
// with this file. It is the STARTING offset of the Lfn.
//
VBO LfnOffsetWithinDirectory;
//
// Thess entries is kept in ssync with the dirent. It allows a more
// accurate verify capability and speeds up FatFastQueryBasicInfo().
//
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
//
// Valid data to disk
//
ULONG ValidDataToDisk;
//
// The following field contains the retrieval mapping structure
// for the file/directory. Note that for the Root Dcb this
// structure is set at mount time. Also note that in this
// implementation of Fat the Mcb really maps VBOs to LBOs and not
// VBNs to LBNs.
//
LARGE_MCB Mcb;
//
// The following union is cased off of the node type code for the fcb.
// There is a seperate case for the directory versus file fcbs.
//
union {
//
// A Directory Control Block (Dcb)
//
struct {
//
// A queue of all the fcbs/dcbs that are opened under this
// Dcb.
//
LIST_ENTRY ParentDcbQueue;
//
// The following field points to the file object used to do I/O to
// the directory file for this dcb. The directory file maps the
// sectors for the directory. This field is initialized by
// CreateRootDcb but is left null by CreateDcb. It isn't
// until we try to read/write the directory file that we
// create the stream file object for non root dcbs.
//
ULONG DirectoryFileOpenCount;
PFILE_OBJECT DirectoryFile;
//
// If the UnusedDirentVbo is != 0xffffffff, then the dirent at this
// offset is guarenteed to unused. A value of 0xffffffff means
// it has yet to be initialized. Note that a value beyond the
// end of allocation means that there an unused dirent, but we
// will have to allocate another cluster to use it.
//
// DeletedDirentHint contains lowest possible VBO of a deleted
// dirent (assuming as above that it is not 0xffffffff).
//
VBO UnusedDirentVbo;
VBO DeletedDirentHint;
//
// The following two entries links together all the Fcbs
// opened under this Dcb sorted in a splay tree by name.
//
// I'd like to go into why we have (and must have) two separate
// splay trees within the current fastfat architecture. I will
// provide some insight into what would have to change if we
// wanted to have a single UNICODE tree.
//
// What makes FAT unique is that both Oem and Unicode names sit
// side by side on disk. Several unique UNICODE names coming
// into fastfat can match a single OEM on-disk name, and there
// is really no way to enumerate all the possible UNICODE
// source strings that can map to a given OEM name. This argues
// for converting the incomming UNICODE name into OEM, and then
// running through an OEM splay tree of the open files. This
// works well when there are only OEM names on disk.
//
// The UNICODE name on disk can be VERY different from the short
// name in the DIRENT and not even representable in the OEM code
// page. Even if it were representable in OEM, it is possible
// that a case varient of the original UNICODE name would match
// a different OEM name, causing us to miss the Fcb in the
// prefix lookup phase. In these cases, we must put UNICODE
// name in the splay to guarentee that we find any case varient
// of the input UNICODE name. See the routine description of
// FatConstructNamesInFcb() for a detailed analysis of how we
// detect this case.
//
// The fundamental limitation we are imposing here is that if
// an Fcb exists for an open file, we MUST find it during the
// prefix stage. This is a basic premise of the create path
// in fastfat. In fact if we later find it gravelling through
// the disk (but not the splay tree), we will bug check if we
// try to add a duplicate entry to the splay tree (not to
// mention having two Fcbs). If we had some mechanism to deal
// with cases (and they would be rare) that we don't find the
// entry in the splay tree, but the Fcb is actually in there,
// then we could go to a single UNICODE splay tree. While
// this uses more pool for the splay tree, and makes string
// compares maybe take a bit as longer, it would eliminate the
// need for any NLS conversion during the prefix phase, so it
// might really be a net win.
//
// The current scheme was optimized for non-extended names
// (i.e. US names). As soon as you start using extended
// characters, then it is clearly a win as many code paths
// become active that would otherwise not be needed if we
// only had a single UNICODE splay tree.
//
// We may think about changing this someday.
//
PRTL_SPLAY_LINKS RootOemNode;
PRTL_SPLAY_LINKS RootUnicodeNode;
//
// The following field keeps track of free dirents, i.e.,
// dirents that are either unallocated for deleted.
//
RTL_BITMAP FreeDirentBitmap;
//
// Since the FCB specific part of this union is larger, use
// the slack here for an initial bitmap buffer. Currently
// there is enough space here for an 8K cluster.
//
ULONG FreeDirentBitmapBuffer[1];
} Dcb;
//
// A File Control Block (Fcb)
//
struct {
//
// The following field is used by the filelock module
// to maintain current byte range locking information.
//
FILE_LOCK FileLock;
//
// The following field is used by the oplock module
// to maintain current oplock information.
//
OPLOCK Oplock;
//
// This pointer is used to detect writes that eminated in the
// cache manager's lazywriter. It prevents lazy writer threads,
// who already have the Fcb shared, from trying to acquire it
// exclusive, and thus causing a deadlock.
//
PVOID LazyWriteThread;
} Fcb;
} Specific;
//
// The following field is used to verify that the Ea's for a file
// have not changed between calls to query for Ea's. It is compared
// with a similar field in a Ccb.
//
// IMPORTANT!! **** DO NOT MOVE THIS FIELD ****
//
// The slack space in the union above is computed from
// the field offset of the EaModificationCount.
//
ULONG EaModificationCount;
//
// The following field is the fully qualified file name for this FCB/DCB
// starting from the root of the volume, and last file name in the
// fully qualified name.
//
FILE_NAME_NODE ShortName;
//
// The following field is only filled in if it is needed with the user's
// opened path
//
UNICODE_STRING FullFileName;
USHORT FinalNameLength;
//
// To make life simpler we also keep in the Fcb/Dcb a current copy of
// the fat attribute byte for the file/directory. This field must
// also be updated when we create the Fcb, modify the File, or verify
// the Fcb
//
UCHAR DirentFatFlags;
//
// The case preserved long filename
//
UNICODE_STRING ExactCaseLongName;
//
// If the UNICODE Lfn is fully expressible in the system Oem code
// page, then we will store it in a prefix table, otherwise we will
// store the last UNICODE name in the Fcb. In both cases the name
// has been upcased.
//
// Note that we may need neither of these fields if an LFN was strict
// 8.3 or differed only in case. Indeed if there wasn't an LFN, we
// don't need them at all.
//
union {
//
// This first field is present if FCB_STATE_HAS_OEM_LONG_NAME
// is set in the FcbState.
//
FILE_NAME_NODE Oem;
//
// This first field is present if FCB_STATE_HAS_UNICODE_LONG_NAME
// is set in the FcbState.
//
FILE_NAME_NODE Unicode;
} LongName;
//
// Defragmentation / ReallocateOnWrite synchronization object. This
// is filled in by FatMoveFile() and affects the read and write paths.
//
PKEVENT MoveFileEvent;
} FCB, *PFCB;
#ifndef BUILDING_FSKDEXT
//
// DCB clashes with a type defined outside the filesystems, in headers
// pulled in by FSKD. We don't need this typedef for fskd anyway....
//
typedef FCB DCB;
typedef DCB *PDCB;
#endif
//
// Here are the Fcb state fields.
//
#define FCB_STATE_DELETE_ON_CLOSE (0x00000001)
#define FCB_STATE_TRUNCATE_ON_CLOSE (0x00000002)
#define FCB_STATE_PAGING_FILE (0x00000004)
#define FCB_STATE_FORCE_MISS_IN_PROGRESS (0x00000008)
#define FCB_STATE_FLUSH_FAT (0x00000010)
#define FCB_STATE_TEMPORARY (0x00000020)
#define FCB_STATE_SYSTEM_FILE (0x00000080)
#define FCB_STATE_NAMES_IN_SPLAY_TREE (0x00000100)
#define FCB_STATE_HAS_OEM_LONG_NAME (0x00000200)
#define FCB_STATE_HAS_UNICODE_LONG_NAME (0x00000400)
#define FCB_STATE_DELAY_CLOSE (0x00000800)
//
// Copies of the dirent's FAT_DIRENT_NT_BYTE_* flags for
// preserving case of the short name of a file
//
#define FCB_STATE_8_LOWER_CASE (0x00001000)
#define FCB_STATE_3_LOWER_CASE (0x00002000)
//
// This is the slack allocation in the Dcb part of the UNION above
//
#define DCB_UNION_SLACK_SPACE ((ULONG) \
(FIELD_OFFSET(DCB, EaModificationCount) - \
FIELD_OFFSET(DCB, Specific.Dcb.FreeDirentBitmapBuffer)) \
)
//
// This is the special (64bit) allocation size that indicates the
// real size must be retrieved from disk. Define it here so we
// avoid excessive magic numbering around the driver.
//
#define FCB_LOOKUP_ALLOCATIONSIZE_HINT ((LONGLONG) -1)
//
// The Ccb record is allocated for every file object. Note that this
// record is exactly 0x34 long on x86 so that it will fit into a 0x40
// piece of pool. Please carefully consider modifications.
//
// Define the Flags field.
//
#define CCB_FLAG_MATCH_ALL (0x0001)
#define CCB_FLAG_SKIP_SHORT_NAME_COMPARE (0x0002)
//
// This tells us whether we allocated buffers to hold search templates.
//
#define CCB_FLAG_FREE_OEM_BEST_FIT (0x0004)
#define CCB_FLAG_FREE_UNICODE (0x0008)
//
// These flags prevents cleanup from updating the modify time, etc.
//
#define CCB_FLAG_USER_SET_LAST_WRITE (0x0010)
#define CCB_FLAG_USER_SET_LAST_ACCESS (0x0020)
#define CCB_FLAG_USER_SET_CREATION (0x0040)
//
// This bit says the file object associated with this Ccb was opened for
// read only access.
//
#define CCB_FLAG_READ_ONLY (0x0080)
//
// These flags, are used is DASD handles in read and write.
//
#define CCB_FLAG_DASD_FLUSH_DONE (0x0100)
#define CCB_FLAG_DASD_PURGE_DONE (0x0200)
//
// This flag keeps track of a handle that was opened for
// DELETE_ON_CLOSE.
//
#define CCB_FLAG_DELETE_ON_CLOSE (0x0400)
//
// This flag keeps track of which side of the name pair on the file
// associated with the handle was opened
//
#define CCB_FLAG_OPENED_BY_SHORTNAME (0x0800)
//
// This flag indicates that the query template has not been upcased
// (i.e., query should be case-insensitive)
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -