3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module defines the data structures that make up the major internal
12 part of the Fat file system.
20 typedef PVOID PBCB
; //**** Bcb's are now part of the cache module
24 // The FAT_DATA record is the top record in the Fat file system in-memory
25 // data structure. This structure must be allocated from non-paged pool.
28 typedef struct _FAT_DATA
{
31 // The type and size of this record (must be FAT_NTC_DATA_HEADER)
34 NODE_TYPE_CODE NodeTypeCode
;
35 NODE_BYTE_SIZE NodeByteSize
;
38 PVOID LazyWriteThread
;
42 // A queue of all the devices that are mounted by the file system.
48 // A pointer to the Driver object we were initialized with
51 PDRIVER_OBJECT DriverObject
;
54 // A pointer to the filesystem device objects we created.
57 PVOID DiskFileSystemDeviceObject
;
58 PVOID CdromFileSystemDeviceObject
;
61 // A resource variable to control access to the global Fat data record
67 // A pointer to our EPROCESS struct, which is a required input to the
68 // Cache Management subsystem.
74 // Number of processors when the driver loaded.
77 ULONG NumberProcessors
;
80 // The following tells us if we should use Chicago extensions.
83 BOOLEAN ChicagoMode
:1;
86 // The following field tells us if we are running on a Fujitsu
87 // FMR Series. These machines supports extra formats on the
94 // Inidicates that FspClose is currently processing closes.
97 BOOLEAN AsyncCloseActive
:1;
100 // The following BOOLEAN says shutdown has started on FAT. It
101 // instructs FspClose to not keep the Vcb resources anymore.
104 BOOLEAN ShutdownStarted
:1;
107 // The following flag tells us if we are going to generate LFNs
108 // for valid 8.3 names with extended characters.
111 BOOLEAN CodePageInvariant
:1;
114 // The following flags tell us if we are in an aggresive push to lower
115 // the size of the deferred close queues.
119 BOOLEAN HighDelayed
:1;
123 // The following list entry is used for performing closes that can't
124 // be done in the context of the original caller.
127 ULONG AsyncCloseCount
;
128 LIST_ENTRY AsyncCloseList
;
131 // The following two fields record if we are delaying a close.
134 ULONG DelayedCloseCount
;
135 LIST_ENTRY DelayedCloseList
;
138 // This is the ExWorkerItem that does both kinds of deferred closes.
141 PIO_WORKITEM FatCloseItem
;
144 // This spinlock protects several rapid-fire operations. NOTE: this is
145 // pretty horrible style.
148 KSPIN_LOCK GeneralSpinLock
;
151 // Cache manager call back structures, which must be passed on each call
152 // to CcInitializeCacheMap.
155 CACHE_MANAGER_CALLBACKS CacheManagerCallbacks
;
156 CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks
;
162 typedef FAT_DATA
*PFAT_DATA
;
165 // An array of these structures will keep
167 typedef struct _FAT_WINDOW
{
169 ULONG FirstCluster
; // The first cluster in this window.
170 ULONG LastCluster
; // The last cluster in this window.
171 ULONG ClustersFree
; // The number of clusters free in this window.
174 typedef FAT_WINDOW
*PFAT_WINDOW
;
177 // Forward reference some circular referenced structures.
180 typedef struct _VCB VCB
;
183 typedef struct _FCB FCB
;
187 // This structure is used to keep track of information needed to do a
188 // deferred close. It is now embedded in a CCB so we don't have to
189 // allocate one in the close path (with mustsucceed).
195 // Two sets of links, one for the global list and one for closes
196 // on a particular volume.
199 LIST_ENTRY GlobalLinks
;
204 enum _TYPE_OF_OPEN TypeOfOpen
;
209 typedef CLOSE_CONTEXT
*PCLOSE_CONTEXT
;
213 // The Vcb (Volume control Block) record corresponds to every volume mounted
214 // by the file system. They are ordered in a queue off of FatData.VcbQueue.
215 // This structure must be allocated from non-paged pool
218 typedef enum _VCB_CONDITION
{
224 typedef struct _VCB
{
227 // This is a common head for the FAT volume file
230 FSRTL_ADVANCED_FCB_HEADER VolumeFileHeader
;
233 // The links for the device queue off of FatData.VcbQueue
239 // A pointer the device object passed in by the I/O system on a mount
240 // This is the target device object that the file system talks to when it
241 // needs to do any I/O (e.g., the disk stripper device object).
245 PDEVICE_OBJECT TargetDeviceObject
;
247 #if (NTDDI_VERSION > NTDDI_WIN8)
249 // The volume GUID of the target device object.
256 // The volume GUID path of the target device object.
259 UNICODE_STRING VolumeGuidPath
;
263 // A pointer to the VPB for the volume passed in by the I/O system on
270 // The internal state of the device. This is a collection of fsd device
275 VCB_CONDITION VcbCondition
;
278 // A pointer to the root DCB for this volume
281 struct _FCB
*RootDcb
;
284 // If the FAT has so many entries that the free cluster bitmap would
285 // be too large, we split the FAT into buckets, and only one bucket's
286 // worth of bits are kept in the bitmap.
289 ULONG NumberOfWindows
;
291 PFAT_WINDOW CurrentWindow
;
294 // A count of the number of file objects that have opened the volume
295 // for direct access, and their share access state.
298 CLONG DirectAccessOpenCount
;
299 SHARE_ACCESS ShareAccess
;
302 // A count of the number of file objects that have any file/directory
303 // opened on this volume, not including direct access. And also the
304 // count of the number of file objects that have a file opened for
305 // only read access (i.e., they cannot be modifying the disk).
312 // A count of the number of internal opens on this VCB.
315 __volatile ULONG InternalOpenCount
;
318 // A count of the number of residual opens on this volume.
319 // This is usually two or three. One is for the virutal volume
320 // file. One is for the root directory. And one is for the
321 // EA file, if there is one.
324 __volatile ULONG ResidualOpenCount
;
327 // The bios parameter block field contains
328 // an unpacked copy of the bpb for the volume, it is initialized
329 // during mount time and can be read by everyone else after that.
332 BIOS_PARAMETER_BLOCK Bpb
;
334 PUCHAR First0x24BytesOfBootSector
;
337 // The following structure contains information useful to the
338 // allocation support routines. Many of them are computed from
339 // elements of the Bpb, but are too involved to recompute every time
345 LBO RootDirectoryLbo
; // Lbo of beginning of root directory
346 LBO FileAreaLbo
; // Lbo of beginning of file area
347 ULONG RootDirectorySize
; // size of root directory in bytes
349 ULONG NumberOfClusters
; // total number of clusters on the volume
350 ULONG NumberOfFreeClusters
; // number of free clusters on the volume
353 UCHAR FatIndexBitSize
; // indicates if 12, 16, or 32 bit fat table
355 UCHAR LogOfBytesPerSector
; // Log(Bios->BytesPerSector)
356 UCHAR LogOfBytesPerCluster
; // Log(Bios->SectorsPerCluster)
361 // The following Mcb is used to keep track of dirty sectors in the Fat.
362 // Runs of holes denote clean sectors while runs of LBO == VBO denote
363 // dirty sectors. The VBOs are that of the volume file, starting at
364 // 0. The granuality of dirt is one sectors, and additions are only
365 // made in sector chunks to prevent problems with several simultaneous
369 LARGE_MCB DirtyFatMcb
;
372 // The following MCB contains a list of all the bad clusters on the volume.
373 // It is empty until the first time the bad sectors on the volume are queried
374 // by calling FSCTL_GET_RETRIEVAL_POINTERS with a volume handle.
377 LARGE_MCB BadBlockMcb
;
380 // The FreeClusterBitMap keeps track of all the clusters in the fat.
381 // A 1 means occupied while a 0 means free. It allows quick location
382 // of contiguous runs of free clusters. It is initialized on mount
386 RTL_BITMAP FreeClusterBitMap
;
389 // The following fast mutex controls access to the free cluster bit map
393 FAST_MUTEX FreeClusterBitMapMutex
;
396 // A resource variable to control access to the volume specific data
403 // A resource to make sure no one changes the volume bitmap while
404 // you're using it. Only for volumes with NumberOfWindows > 1.
407 ERESOURCE ChangeBitMapResource
;
411 // The following field points to the file object used to do I/O to
412 // the virtual volume file. The virtual volume file maps sectors
413 // 0 through the end of fat and is of a fixed size (determined during
417 PFILE_OBJECT VirtualVolumeFile
;
420 // The following field contains a record of special pointers used by
421 // MM and Cache to manipluate section objects. Note that the values
422 // are set outside of the file system. However the file system on an
423 // open/create will set the file object's SectionObject field to point
427 SECTION_OBJECT_POINTERS SectionObjectPointers
;
430 // The following fields is a hint cluster index used by the file system
431 // when allocating a new cluster.
437 // This field contains the "DeviceObject" that this volume is
438 // currently mounted on. Note Vcb->Vpb->RealDevice is constant.
441 PDEVICE_OBJECT CurrentDevice
;
444 // This is a pointer to the file object and the Fcb which represent the ea data.
447 PFILE_OBJECT VirtualEaFile
;
451 // The following field is a pointer to the file object that has the
452 // volume locked. if the VcbState has the locked flag set.
455 PFILE_OBJECT FileObjectWithVcbLocked
;
458 // The following is the head of a list of notify Irps.
461 LIST_ENTRY DirNotifyList
;
464 // The following is used to synchronize the dir notify list.
467 PNOTIFY_SYNC NotifySync
;
470 // The following fast mutex is used to synchronize directory stream
471 // file object creation.
474 FAST_MUTEX DirectoryFileCreationMutex
;
477 // This field holds the thread address of the current (or most recent
478 // depending on VcbState) thread doing a verify operation on this volume.
481 PKTHREAD VerifyThread
;
484 // The following two structures are used for CleanVolume callbacks.
488 KTIMER CleanVolumeTimer
;
491 // This field records the last time FatMarkVolumeDirty was called, and
492 // avoids excessive calls to push the CleanVolume forward in time.
495 LARGE_INTEGER LastFatMarkVolumeDirtyCall
;
498 // The following fields holds a pointer to a struct which is used to
499 // hold performance counters.
502 struct _FILE_SYSTEM_STATISTICS
*Statistics
;
505 // The property tunneling cache for this volume
511 // The media change count is returned by IOCTL_CHECK_VERIFY and
512 // is used to verify that no user-mode app has swallowed a media change
513 // notification. This is only meaningful for removable media.
519 // The device number of the underlying storage device.
525 // Preallocated VPB for swapout, so we are not forced to consider
526 // must succeed pool.
532 // Per volume threading of the close queues.
535 LIST_ENTRY AsyncCloseList
;
536 LIST_ENTRY DelayedCloseList
;
539 // Fast mutex used by the ADVANCED FCB HEADER in this structure
542 FAST_MUTEX AdvancedFcbHeaderMutex
;
546 // How many close contexts were preallocated on this Vcb
549 ULONG CloseContextCount
;
555 #define VCB_STATE_FLAG_LOCKED (0x00000001)
556 #define VCB_STATE_FLAG_REMOVABLE_MEDIA (0x00000002)
557 #define VCB_STATE_FLAG_VOLUME_DIRTY (0x00000004)
558 #define VCB_STATE_FLAG_MOUNTED_DIRTY (0x00000010)
559 #define VCB_STATE_FLAG_SHUTDOWN (0x00000040)
560 #define VCB_STATE_FLAG_CLOSE_IN_PROGRESS (0x00000080)
561 #define VCB_STATE_FLAG_DELETED_FCB (0x00000100)
562 #define VCB_STATE_FLAG_CREATE_IN_PROGRESS (0x00000200)
563 #define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE (0x00000800)
564 #define VCB_STATE_FLAG_DEFERRED_FLUSH (0x00001000)
565 #define VCB_STATE_FLAG_ASYNC_CLOSE_ACTIVE (0x00002000)
566 #define VCB_STATE_FLAG_WRITE_PROTECTED (0x00004000)
567 #define VCB_STATE_FLAG_REMOVAL_PREVENTED (0x00008000)
568 #define VCB_STATE_FLAG_VOLUME_DISMOUNTED (0x00010000)
569 #define VCB_STATE_VPB_NOT_ON_DEVICE (0x00020000)
570 #define VCB_STATE_FLAG_VPB_MUST_BE_FREED (0x00040000)
571 #define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS (0x00080000)
572 #define VCB_STATE_FLAG_BAD_BLOCKS_POPULATED (0x00100000)
573 #define VCB_STATE_FLAG_HOTPLUGGABLE (0x00200000)
574 #define VCB_STATE_FLAG_MOUNT_IN_PROGRESS (0x00800000)
578 // N.B - VOLUME_DISMOUNTED is an indication that FSCTL_DISMOUNT volume was
579 // executed on a volume. It does not replace VcbCondition as an indication
580 // that the volume is invalid/unrecoverable.
584 // Define the file system statistics struct. Vcb->Statistics points to an
585 // array of these (one per processor) and they must be 64 byte aligned to
586 // prevent cache line tearing.
589 #define FILE_SYSTEM_STATISTICS_WITHOUT_PAD (sizeof( FILESYSTEM_STATISTICS ) + sizeof( FAT_STATISTICS ))
591 typedef struct _FILE_SYSTEM_STATISTICS
{
594 // This contains the actual data.
597 FILESYSTEM_STATISTICS Common
;
601 // Pad this structure to a multiple of 64 bytes.
604 UCHAR Pad
[((FILE_SYSTEM_STATISTICS_WITHOUT_PAD
+ 0x3f) & ~0x3f) - FILE_SYSTEM_STATISTICS_WITHOUT_PAD
];
606 } FILE_SYSTEM_STATISTICS
;
608 typedef FILE_SYSTEM_STATISTICS
*PFILE_SYSTEM_STATISTICS
;
612 // The Volume Device Object is an I/O system device object with a workqueue
613 // and an VCB record appended to the end. There are multiple of these
614 // records, one for every mounted volume, and are created during
615 // a volume mount operation. The work queue is for handling an overload of
616 // work requests to the volume.
619 typedef struct _VOLUME_DEVICE_OBJECT
{
621 DEVICE_OBJECT DeviceObject
;
624 // The following field tells how many requests for this volume have
625 // either been enqueued to ExWorker threads or are currently being
626 // serviced by ExWorker threads. If the number goes above
627 // a certain threshold, put the request on the overflow queue to be
631 ULONG PostedRequestCount
;
634 // The following field indicates the number of IRP's waiting
635 // to be serviced in the overflow queue.
638 ULONG OverflowQueueCount
;
641 // The following field contains the queue header of the overflow queue.
642 // The Overflow queue is a list of IRP's linked via the IRP's ListEntry
646 LIST_ENTRY OverflowQueue
;
649 // The following spinlock protects access to all the above fields.
652 KSPIN_LOCK OverflowQueueSpinLock
;
655 // This is a common head for the FAT volume file
658 FSRTL_COMMON_FCB_HEADER VolumeFileHeader
;
661 // This is the file system specific volume control block.
666 } VOLUME_DEVICE_OBJECT
;
668 typedef VOLUME_DEVICE_OBJECT
*PVOLUME_DEVICE_OBJECT
;
672 // This is the structure used to contains the short name for a file
675 typedef struct _FILE_NAME_NODE
{
678 // This points back to the Fcb for this file.
684 // This is the name of this node.
691 UNICODE_STRING Unicode
;
696 // Marker so we can figure out what kind of name we opened up in
703 // And the links. Our parent Dcb has a pointer to the root entry.
706 RTL_SPLAY_LINKS Links
;
709 typedef FILE_NAME_NODE
*PFILE_NAME_NODE
;
712 // This structure contains fields which must be in non-paged pool.
715 typedef struct _NON_PAGED_FCB
{
718 // The following field contains a record of special pointers used by
719 // MM and Cache to manipluate section objects. Note that the values
720 // are set outside of the file system. However the file system on an
721 // open/create will set the file object's SectionObject field to point
725 SECTION_OBJECT_POINTERS SectionObjectPointers
;
728 // This context is non-zero only if the file currently has asynchronous
729 // non-cached valid data length extending writes. It allows
730 // synchronization between pending writes and other operations.
733 ULONG OutstandingAsyncWrites
;
736 // This event is set when OutstandingAsyncWrites transitions to zero.
739 PKEVENT OutstandingAsyncEvent
;
742 // This is the mutex that is inserted into the FCB_ADVANCED_HEADER
746 FAST_MUTEX AdvancedFcbHeaderMutex
;
751 typedef NON_PAGED_FCB
*PNON_PAGED_FCB
;
754 // The Fcb/Dcb record corresponds to every open file and directory, and to
755 // every directory on an opened path. They are ordered in two queues, one
756 // queue contains every Fcb/Dcb record off of FatData.FcbQueue, the other
757 // queue contains only device specific records off of Vcb.VcbSpecificFcbQueue
760 typedef enum _FCB_CONDITION
{
766 typedef struct _FCB
{
769 // The following field is used for fast I/O
771 // The following comments refer to the use of the AllocationSize field
772 // of the FsRtl-defined header to the nonpaged Fcb.
774 // For a directory when we create a Dcb we will not immediately
775 // initialize the cache map, instead we will postpone it until our first
776 // call to FatReadDirectoryFile or FatPrepareWriteDirectoryFile.
777 // At that time we will search the Fat to find out the current allocation
778 // size (by calling FatLookupFileAllocationSize) and then initialize the
779 // cache map to this allocation size.
781 // For a file when we create an Fcb we will not immediately initialize
782 // the cache map, instead we will postpone it until we need it and
783 // then we determine the allocation size from either searching the
784 // fat to determine the real file allocation, or from the allocation
785 // that we've just allocated if we're creating a file.
787 // A value of -1 indicates that we do not know what the current allocation
788 // size really is, and need to examine the fat to find it. A value
789 // of than -1 is the real file/directory allocation size.
791 // Whenever we need to extend the allocation size we call
792 // FatAddFileAllocation which (if we're really extending the allocation)
793 // will modify the Fat, Mcb, and update this field. The caller
794 // of FatAddFileAllocation is then responsible for altering the Cache
797 // We are now using the ADVANCED fcb header to support filter contexts
798 // at the stream level
801 FSRTL_ADVANCED_FCB_HEADER Header
;
804 // This structure contains fields which must be in non-paged pool.
807 PNON_PAGED_FCB NonPaged
;
810 // The head of the fat alloaction chain. FirstClusterOfFile == 0
811 // means that the file has no current allocation.
814 ULONG FirstClusterOfFile
;
818 // The links for the queue of all fcbs for a specific dcb off of
819 // Dcb.ParentDcbQueue. For the root directory this queue is empty
820 // For a non-existent fcb this queue is off of the non existent
821 // fcb queue entry in the vcb.
824 LIST_ENTRY ParentDcbLinks
;
827 // A pointer to the Dcb that is the parent directory containing
828 // this fcb. If this record itself is the root dcb then this field
832 struct _FCB
*ParentDcb
;
835 // A pointer to the Vcb containing this Fcb
841 // The internal state of the Fcb. This is a collection Fcb state flags.
842 // Also the shared access for each time this file/directory is opened.
846 FCB_CONDITION FcbCondition
;
847 SHARE_ACCESS ShareAccess
;
849 #ifdef SYSCACHE_COMPILE
852 // For syscache we keep a bitmask that tells us if we have dispatched IO for
853 // the page aligned chunks of the stream.
862 // A count of the number of file objects that have been opened for
863 // this file/directory, but not yet been cleaned up yet. This count
864 // is only used for data file objects, not for the Acl or Ea stream
865 // file objects. This count gets decremented in FatCommonCleanup,
866 // while the OpenCount below gets decremented in FatCommonClose.
872 // A count of the number of file objects that have opened
873 // this file/directory. For files & directories the FsContext of the
874 // file object points to this record.
880 // A count of how many of "UncleanCount" handles were opened for
884 CLONG NonCachedUncleanCount
;
887 // A count of purge failure mode references. A non zero count means
888 // purge failure mode is enabled. The count is synchronized by the
892 CLONG PurgeFailureModeEnableCount
;
895 // The following field is used to locate the dirent for this fcb/dcb.
896 // All directory are opened as mapped files so the only additional
897 // information we need to locate this dirent (beside its parent directory)
898 // is the byte offset for the dirent. Note that for the root dcb
899 // this field is not used.
902 VBO DirentOffsetWithinDirectory
;
905 // The following field is filled in when there is an Lfn associated
906 // with this file. It is the STARTING offset of the Lfn.
909 VBO LfnOffsetWithinDirectory
;
912 // Thess entries is kept in ssync with the dirent. It allows a more
913 // accurate verify capability and speeds up FatFastQueryBasicInfo().
916 LARGE_INTEGER CreationTime
;
917 LARGE_INTEGER LastAccessTime
;
918 LARGE_INTEGER LastWriteTime
;
921 // Valid data to disk
924 ULONG ValidDataToDisk
;
927 // The following field contains the retrieval mapping structure
928 // for the file/directory. Note that for the Root Dcb this
929 // structure is set at mount time. Also note that in this
930 // implementation of Fat the Mcb really maps VBOs to LBOs and not
937 // The following union is cased off of the node type code for the fcb.
938 // There is a seperate case for the directory versus file fcbs.
944 // A Directory Control Block (Dcb)
950 // A queue of all the fcbs/dcbs that are opened under this
954 LIST_ENTRY ParentDcbQueue
;
957 // The following field points to the file object used to do I/O to
958 // the directory file for this dcb. The directory file maps the
959 // sectors for the directory. This field is initialized by
960 // CreateRootDcb but is left null by CreateDcb. It isn't
961 // until we try to read/write the directory file that we
962 // create the stream file object for non root dcbs.
965 __volatile ULONG DirectoryFileOpenCount
;
966 PFILE_OBJECT DirectoryFile
;
970 // If the UnusedDirentVbo is != 0xffffffff, then the dirent at this
971 // offset is guarenteed to unused. A value of 0xffffffff means
972 // it has yet to be initialized. Note that a value beyond the
973 // end of allocation means that there an unused dirent, but we
974 // will have to allocate another cluster to use it.
976 // DeletedDirentHint contains lowest possible VBO of a deleted
977 // dirent (assuming as above that it is not 0xffffffff).
981 VBO DeletedDirentHint
;
984 // The following two entries links together all the Fcbs
985 // opened under this Dcb sorted in a splay tree by name.
987 // I'd like to go into why we have (and must have) two separate
988 // splay trees within the current fastfat architecture. I will
989 // provide some insight into what would have to change if we
990 // wanted to have a single UNICODE tree.
992 // What makes FAT unique is that both Oem and Unicode names sit
993 // side by side on disk. Several unique UNICODE names coming
994 // into fastfat can match a single OEM on-disk name, and there
995 // is really no way to enumerate all the possible UNICODE
996 // source strings that can map to a given OEM name. This argues
997 // for converting the incomming UNICODE name into OEM, and then
998 // running through an OEM splay tree of the open files. This
999 // works well when there are only OEM names on disk.
1001 // The UNICODE name on disk can be VERY different from the short
1002 // name in the DIRENT and not even representable in the OEM code
1003 // page. Even if it were representable in OEM, it is possible
1004 // that a case varient of the original UNICODE name would match
1005 // a different OEM name, causing us to miss the Fcb in the
1006 // prefix lookup phase. In these cases, we must put UNICODE
1007 // name in the splay to guarentee that we find any case varient
1008 // of the input UNICODE name. See the routine description of
1009 // FatConstructNamesInFcb() for a detailed analysis of how we
1010 // detect this case.
1012 // The fundamental limitation we are imposing here is that if
1013 // an Fcb exists for an open file, we MUST find it during the
1014 // prefix stage. This is a basic premise of the create path
1015 // in fastfat. In fact if we later find it gravelling through
1016 // the disk (but not the splay tree), we will bug check if we
1017 // try to add a duplicate entry to the splay tree (not to
1018 // mention having two Fcbs). If we had some mechanism to deal
1019 // with cases (and they would be rare) that we don't find the
1020 // entry in the splay tree, but the Fcb is actually in there,
1021 // then we could go to a single UNICODE splay tree. While
1022 // this uses more pool for the splay tree, and makes string
1023 // compares maybe take a bit as longer, it would eliminate the
1024 // need for any NLS conversion during the prefix phase, so it
1025 // might really be a net win.
1027 // The current scheme was optimized for non-extended names
1028 // (i.e. US names). As soon as you start using extended
1029 // characters, then it is clearly a win as many code paths
1030 // become active that would otherwise not be needed if we
1031 // only had a single UNICODE splay tree.
1033 // We may think about changing this someday.
1036 PRTL_SPLAY_LINKS RootOemNode
;
1037 PRTL_SPLAY_LINKS RootUnicodeNode
;
1040 // The following field keeps track of free dirents, i.e.,
1041 // dirents that are either unallocated for deleted.
1044 RTL_BITMAP FreeDirentBitmap
;
1047 // Since the FCB specific part of this union is larger, use
1048 // the slack here for an initial bitmap buffer. Currently
1049 // there is enough space here for an 8K cluster.
1052 ULONG FreeDirentBitmapBuffer
[1];
1057 // A File Control Block (Fcb)
1063 // The following field is used by the filelock module
1064 // to maintain current byte range locking information.
1069 #if (NTDDI_VERSION < NTDDI_WIN8)
1071 // The following field is used by the oplock module
1072 // to maintain current oplock information.
1079 // This pointer is used to detect writes that eminated in the
1080 // cache manager's lazywriter. It prevents lazy writer threads,
1081 // who already have the Fcb shared, from trying to acquire it
1082 // exclusive, and thus causing a deadlock.
1085 PVOID LazyWriteThread
;
1093 // The following field is used to verify that the Ea's for a file
1094 // have not changed between calls to query for Ea's. It is compared
1095 // with a similar field in a Ccb.
1097 // IMPORTANT!! **** DO NOT MOVE THIS FIELD ****
1099 // The slack space in the union above is computed from
1100 // the field offset of the EaModificationCount.
1103 ULONG EaModificationCount
;
1106 // The following field is the fully qualified file name for this FCB/DCB
1107 // starting from the root of the volume, and last file name in the
1108 // fully qualified name.
1111 FILE_NAME_NODE ShortName
;
1114 // The following field is only filled in if it is needed with the user's
1118 UNICODE_STRING FullFileName
;
1120 USHORT FinalNameLength
;
1123 // To make life simpler we also keep in the Fcb/Dcb a current copy of
1124 // the fat attribute byte for the file/directory. This field must
1125 // also be updated when we create the Fcb, modify the File, or verify
1129 UCHAR DirentFatFlags
;
1132 // The case preserved long filename
1135 UNICODE_STRING ExactCaseLongName
;
1138 // If the UNICODE Lfn is fully expressible in the system Oem code
1139 // page, then we will store it in a prefix table, otherwise we will
1140 // store the last UNICODE name in the Fcb. In both cases the name
1141 // has been upcased.
1143 // Note that we may need neither of these fields if an LFN was strict
1144 // 8.3 or differed only in case. Indeed if there wasn't an LFN, we
1145 // don't need them at all.
1151 // This first field is present if FCB_STATE_HAS_OEM_LONG_NAME
1152 // is set in the FcbState.
1158 // This first field is present if FCB_STATE_HAS_UNICODE_LONG_NAME
1159 // is set in the FcbState.
1162 FILE_NAME_NODE Unicode
;
1167 // Defragmentation / ReallocateOnWrite synchronization object. This
1168 // is filled in by FatMoveFile() and affects the read and write paths.
1171 PKEVENT MoveFileEvent
;
1175 #ifndef BUILDING_FSKDEXT
1177 // DCB clashes with a type defined outside the filesystems, in headers
1178 // pulled in by FSKD. We don't need this typedef for fskd anyway....
1186 // Here are the Fcb state fields.
1189 #define FCB_STATE_DELETE_ON_CLOSE (0x00000001)
1190 #define FCB_STATE_TRUNCATE_ON_CLOSE (0x00000002)
1191 #define FCB_STATE_PAGING_FILE (0x00000004)
1192 #define FCB_STATE_FORCE_MISS_IN_PROGRESS (0x00000008)
1193 #define FCB_STATE_FLUSH_FAT (0x00000010)
1194 #define FCB_STATE_TEMPORARY (0x00000020)
1195 #define FCB_STATE_SYSTEM_FILE (0x00000080)
1196 #define FCB_STATE_NAMES_IN_SPLAY_TREE (0x00000100)
1197 #define FCB_STATE_HAS_OEM_LONG_NAME (0x00000200)
1198 #define FCB_STATE_HAS_UNICODE_LONG_NAME (0x00000400)
1199 #define FCB_STATE_DELAY_CLOSE (0x00000800)
1202 // Copies of the dirent's FAT_DIRENT_NT_BYTE_* flags for
1203 // preserving case of the short name of a file
1206 #define FCB_STATE_8_LOWER_CASE (0x00001000)
1207 #define FCB_STATE_3_LOWER_CASE (0x00002000)
1210 // indicates FSCTL_MOVE_FILE is denied on this FCB
1213 #define FCB_STATE_DENY_DEFRAG (0x00004000)
1217 // Flag to indicate we should zero any deallocations from this file.
1220 #define FCB_STATE_ZERO_ON_DEALLOCATION (0x00080000)
1223 // This is the slack allocation in the Dcb part of the UNION above
1226 #define DCB_UNION_SLACK_SPACE ((ULONG) \
1227 (FIELD_OFFSET(DCB, EaModificationCount) - \
1228 FIELD_OFFSET(DCB, Specific.Dcb.FreeDirentBitmapBuffer)) \
1232 // This is the special (64bit) allocation size that indicates the
1233 // real size must be retrieved from disk. Define it here so we
1234 // avoid excessive magic numbering around the driver.
1237 #define FCB_LOOKUP_ALLOCATIONSIZE_HINT ((LONGLONG) -1)
1241 // The Ccb record is allocated for every file object. Note that this
1242 // record is exactly 0x34 long on x86 so that it will fit into a 0x40
1243 // piece of pool. Please carefully consider modifications.
1245 // Define the Flags field.
1248 #define CCB_FLAG_MATCH_ALL (0x0001)
1249 #define CCB_FLAG_SKIP_SHORT_NAME_COMPARE (0x0002)
1252 // This tells us whether we allocated buffers to hold search templates.
1255 #define CCB_FLAG_FREE_OEM_BEST_FIT (0x0004)
1256 #define CCB_FLAG_FREE_UNICODE (0x0008)
1259 // These flags prevents cleanup from updating the modify time, etc.
1262 #define CCB_FLAG_USER_SET_LAST_WRITE (0x0010)
1263 #define CCB_FLAG_USER_SET_LAST_ACCESS (0x0020)
1264 #define CCB_FLAG_USER_SET_CREATION (0x0040)
1267 // This bit says the file object associated with this Ccb was opened for
1268 // read only access.
1271 #define CCB_FLAG_READ_ONLY (0x0080)
1274 // These flags, are used is DASD handles in read and write.
1277 #define CCB_FLAG_DASD_FLUSH_DONE (0x0100)
1278 #define CCB_FLAG_DASD_PURGE_DONE (0x0200)
1281 // This flag keeps track of a handle that was opened for
1285 #define CCB_FLAG_DELETE_ON_CLOSE (0x0400)
1288 // This flag keeps track of which side of the name pair on the file
1289 // associated with the handle was opened
1292 #define CCB_FLAG_OPENED_BY_SHORTNAME (0x0800)
1295 // This flag indicates that the query template has not been upcased
1296 // (i.e., query should be case-insensitive)
1299 #define CCB_FLAG_QUERY_TEMPLATE_MIXED (0x1000)
1302 // This flag indicates that reads and writes via this DASD handle
1303 // are allowed to start or extend past the end of file.
1306 #define CCB_FLAG_ALLOW_EXTENDED_DASD_IO (0x2000)
1309 // This flag indicates we want to match volume labels in directory
1310 // searches (important for the root dir defrag).
1313 #define CCB_FLAG_MATCH_VOLUME_ID (0x4000)
1316 // This flag indicates the ccb has been converted over into a
1317 // close context for asynchronous/delayed closing of the handle.
1320 #define CCB_FLAG_CLOSE_CONTEXT (0x8000)
1323 // This flag indicates that when the handle is closed, we want
1324 // a physical dismount to occur.
1327 #define CCB_FLAG_COMPLETE_DISMOUNT (0x10000)
1330 // This flag indicates the handle may not call priveleged
1331 // FSCTL which modify the volume.
1334 #define CCB_FLAG_MANAGE_VOLUME_ACCESS (0x20000)
1337 // This flag indicates that a format unit commmand was issued
1338 // on this handle and all subsequent writes need to ignore verify.
1341 #define CCB_FLAG_SENT_FORMAT_UNIT (0x40000)
1344 // This flag indicates that this CCB was the one that marked the
1345 // handle as non-movable.
1348 #define CCB_FLAG_DENY_DEFRAG (0x80000)
1351 // This flag indicates that this CCB wrote to the file.
1354 #define CCB_FLAG_FIRST_WRITE_SEEN (0x100000)
1356 typedef struct _CCB
{
1359 // Type and size of this record (must be FAT_NTC_CCB)
1362 NODE_TYPE_CODE NodeTypeCode
;
1363 NODE_BYTE_SIZE NodeByteSize
;
1366 // Define a 24bit wide field for Flags, but a UCHAR for Wild Cards Present
1367 // since it is used so often. Line these up on byte boundaries for grins.
1371 BOOLEAN ContainsWildCards
;
1374 // Pointer to EDP context.
1377 PVOID EncryptionOnCloseContext
;
1380 // Overlay a close context on the data of the CCB. The remaining
1381 // fields are not useful during close, and we would like to avoid
1382 // paying extra pool for it.
1390 // Save the offset to start search from.
1393 VBO OffsetToStartSearchFrom
;
1396 // The query template is used to filter directory query requests.
1397 // It originally is set to null and on the first call the NtQueryDirectory
1398 // it is set to the input filename or "*" if the name is not supplied.
1399 // All subsquent queries then use this template.
1401 // The Oem structure are unions because if the name is wild we store
1402 // the arbitrary length string, while if the name is constant we store
1403 // 8.3 representation for fast comparison.
1409 // If the template contains a wild card use this.
1415 // If the name is constant, use this part.
1422 UNICODE_STRING UnicodeQueryTemplate
;
1425 // The field is compared with the similar field in the Fcb to determine
1426 // if the Ea's for a file have been modified.
1429 ULONG EaModificationCount
;
1432 // The following field is used as an offset into the Eas for a
1433 // particular file. This will be the offset for the next
1434 // Ea to return. A value of 0xffffffff indicates that the
1435 // Ea's are exhausted.
1438 ULONG OffsetOfNextEaToReturn
;
1442 CLOSE_CONTEXT CloseContext
;
1449 // The Irp Context record is allocated for every orginating Irp. It is
1450 // created by the Fsd dispatch routines, and deallocated by the FatComplete
1451 // request routine. It contains a structure called of type REPINNED_BCBS
1452 // which is used to retain pinned bcbs needed to handle abnormal termination
1456 #define REPINNED_BCBS_ARRAY_SIZE (4)
1458 typedef struct _REPINNED_BCBS
{
1461 // A pointer to the next structure contains additional repinned bcbs
1464 struct _REPINNED_BCBS
*Next
;
1467 // A fixed size array of pinned bcbs. Whenever a new bcb is added to
1468 // the repinned bcb structure it is added to this array. If the
1469 // array is already full then another repinned bcb structure is allocated
1470 // and pointed to with Next.
1473 PBCB Bcb
[ REPINNED_BCBS_ARRAY_SIZE
];
1476 typedef REPINNED_BCBS
*PREPINNED_BCBS
;
1478 typedef struct _IRP_CONTEXT
{
1481 // Type and size of this record (must be FAT_NTC_IRP_CONTEXT)
1484 NODE_TYPE_CODE NodeTypeCode
;
1485 NODE_BYTE_SIZE NodeByteSize
;
1488 // This structure is used for posting to the Ex worker threads.
1491 WORK_QUEUE_ITEM WorkQueueItem
;
1494 // A pointer to the originating Irp.
1497 PIRP OriginatingIrp
;
1500 // Originating Device (required for workque algorithms)
1503 PDEVICE_OBJECT RealDevice
;
1506 // Originating Vcb (required for exception handling)
1507 // On mounts, this will be set before any exceptions
1508 // indicating corruption can be thrown.
1514 // Major and minor function codes copied from the Irp
1517 UCHAR MajorFunction
;
1518 UCHAR MinorFunction
;
1521 // The following fields indicate if we can wait/block for a resource
1522 // or I/O, if we are to do everything write through, and if this
1523 // entry into the Fsd is a recursive call.
1531 // The following field contains the NTSTATUS value used when we are
1532 // unwinding due to an exception
1535 NTSTATUS ExceptionStatus
;
1538 // The following context block is used for non-cached Io
1541 struct _FAT_IO_CONTEXT
*FatIoContext
;
1544 // For a abnormal termination unwinding this field contains the Bcbs
1545 // that are kept pinned until the Irp is completed.
1548 REPINNED_BCBS Repinned
;
1552 typedef IRP_CONTEXT
*PIRP_CONTEXT
;
1554 #define IRP_CONTEXT_FLAG_DISABLE_DIRTY (0x00000001)
1555 #define IRP_CONTEXT_FLAG_WAIT (0x00000002)
1556 #define IRP_CONTEXT_FLAG_WRITE_THROUGH (0x00000004)
1557 #define IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH (0x00000008)
1558 #define IRP_CONTEXT_FLAG_RECURSIVE_CALL (0x00000010)
1559 #define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000020)
1560 #define IRP_CONTEXT_FLAG_DEFERRED_WRITE (0x00000040)
1561 #define IRP_CONTEXT_FLAG_VERIFY_READ (0x00000080)
1562 #define IRP_CONTEXT_STACK_IO_CONTEXT (0x00000100)
1563 #define IRP_CONTEXT_FLAG_IN_FSP (0x00000200)
1564 #define IRP_CONTEXT_FLAG_USER_IO (0x00000400) // for performance counters
1565 #define IRP_CONTEXT_FLAG_DISABLE_RAISE (0x00000800)
1566 #define IRP_CONTEXT_FLAG_OVERRIDE_VERIFY (0x00001000)
1567 #define IRP_CONTEXT_FLAG_CLEANUP_BREAKING_OPLOCK (0x00002000)
1570 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1571 #define IRP_CONTEXT_FLAG_SWAPPED_STACK (0x00100000)
1574 #define IRP_CONTEXT_FLAG_PARENT_BY_CHILD (0x80000000)
1578 // Context structure for non-cached I/O calls. Most of these fields
1579 // are actually only required for the Read/Write Multiple routines, but
1580 // the caller must allocate one as a local variable anyway before knowing
1581 // whether there are multiple requests are not. Therefore, a single
1582 // structure is used for simplicity.
1585 typedef struct _FAT_IO_CONTEXT
{
1588 // A copy of the IrpContext flags preserved for use in
1589 // async I/O completion.
1592 ULONG IrpContextFlags
;
1595 // These two field are used for multiple run Io
1598 __volatile LONG IrpCount
;
1602 // MDL to describe partial sector zeroing
1610 // This element handles the asychronous non-cached Io
1614 PERESOURCE Resource
;
1615 PERESOURCE Resource2
;
1616 ERESOURCE_THREAD ResourceThreadId
;
1617 ULONG RequestedByteCount
;
1618 PFILE_OBJECT FileObject
;
1619 PNON_PAGED_FCB NonPagedFcb
;
1623 // and this element the sycnrhonous non-cached Io
1633 typedef FAT_IO_CONTEXT
*PFAT_IO_CONTEXT
;
1636 // An array of these structures is passed to FatMultipleAsync describing
1637 // a set of runs to execute in parallel.
1640 typedef struct _IO_RUNS
{
1650 typedef IO_RUN
*PIO_RUN
;
1653 // This structure is used by FatDeleteDirent to preserve the first cluster
1654 // and file size info for undelete utilities.
1657 typedef struct _DELETE_CONTEXT
{
1660 ULONG FirstClusterOfFile
;
1664 typedef DELETE_CONTEXT
*PDELETE_CONTEXT
;
1667 // This record is used with to set a flush to go off one second after the
1668 // first write on slow devices with a physical indication of activity, like
1669 // a floppy. This is an attempt to keep the red light on.
1672 typedef struct _DEFERRED_FLUSH_CONTEXT
{
1676 WORK_QUEUE_ITEM Item
;
1680 } DEFERRED_FLUSH_CONTEXT
;
1682 typedef DEFERRED_FLUSH_CONTEXT
*PDEFERRED_FLUSH_CONTEXT
;
1685 // This structure is used for the FatMarkVolumeClean callbacks.
1688 typedef struct _CLEAN_AND_DIRTY_VOLUME_PACKET
{
1690 WORK_QUEUE_ITEM Item
;
1694 } CLEAN_AND_DIRTY_VOLUME_PACKET
, *PCLEAN_AND_DIRTY_VOLUME_PACKET
;
1697 // This structure is used when a page fault is running out of stack.
1700 typedef struct _PAGING_FILE_OVERFLOW_PACKET
{
1703 } PAGING_FILE_OVERFLOW_PACKET
, *PPAGING_FILE_OVERFLOW_PACKET
;
1706 // This structure is used to access the EaFile.
1709 #define EA_BCB_ARRAY_SIZE 8
1711 typedef struct _EA_RANGE
{
1716 USHORT BcbChainLength
;
1717 BOOLEAN AuxilaryBuffer
;
1719 PBCB BcbArray
[EA_BCB_ARRAY_SIZE
];
1721 } EA_RANGE
, *PEA_RANGE
;
1723 #define EA_RANGE_HEADER_SIZE (FIELD_OFFSET( EA_RANGE, BcbArray ))
1726 // These symbols are used by the upcase/downcase routines.
1729 #define WIDE_LATIN_CAPITAL_A (0xff21)
1730 #define WIDE_LATIN_CAPITAL_Z (0xff3a)
1731 #define WIDE_LATIN_SMALL_A (0xff41)
1732 #define WIDE_LATIN_SMALL_Z (0xff5a)
1735 // These values are returned by FatInterpretClusterType.
1738 typedef enum _CLUSTER_TYPE
{
1739 FatClusterAvailable
,
1746 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1747 // ============================================================================
1748 // ============================================================================
1750 // Stack Swapping Support
1752 // ============================================================================
1753 // ============================================================================
1756 // This structure is used when doing a callout on a new stack.
1757 // It contains the parameters for various functions and a place
1758 // to store the return code.
1761 typedef struct _FAT_CALLOUT_PARAMETERS
{
1766 // Parameters for a create request via FatCommonCreate().
1771 PIRP_CONTEXT IrpContext
;
1779 NTSTATUS ExceptionStatus
;
1781 } FAT_CALLOUT_PARAMETERS
, *PFAT_CALLOUT_PARAMETERS
;
1784 #endif // _FATSTRUC_