3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module defines the data structures that make up the major internal
12 part of the Cdfs file system.
16 The global data structures with the CdDataRecord. It contains a pointer
17 to a File System Device object and a queue of Vcb's. There is a Vcb for
18 every currently or previously mounted volumes. We may be in the process
19 of tearing down the Vcb's which have been dismounted. The Vcb's are
20 allocated as an extension to a volume device object.
29 | +--------+ +--------+
32 | +--------+ +--------+
33 +> |Vcb | <-> |Vcb | <-> ...
38 Each Vcb contains a table of all the Fcbs for the volume indexed by
39 their FileId. Each Vcb contains a pointer to the root directory of
40 the volume. Each directory Fcb contains a queue of child Fcb's for
41 its children. There can also be detached subtrees due to open operations
42 by Id where the Fcb's are not connected to the root.
44 The following diagram shows the root structure.
47 | Vcb |---->| Fcb |-----------------------------------------------+
48 | | | Table |--------------------------------------------+ | |
49 | |--+ | |-----------------------------------------+ | | |
50 +--------+ | +--------+ | | |
52 | | | +--------------------+ | | |
53 | V +---------+ | | | |
54 | +--------+ | | | | |
55 | |RootFcb | V V | | |
56 +->| | +--------+ +--------+ | | |
57 | |-->|Child | |Child | | | |
58 +--------+ | Fcb |<-->| Fcb |<--> ... | | |
60 +--------+ +--------+ | | |
62 (Freestanding sub-tree) | | |
64 |OpenById|<-----------------------------------------+ | |
65 | Dir | +--------+ | |
66 | |--->|OpenById|<------------------------------+ |
67 +--------+ | Child | +--------+ |
68 | Dir |--->|OpenById|<-------------------+
73 Attached to each Directory Fcb is a prefix table containing the names
74 of children of this directory for which there is an Fcb. Not all Fcb's
75 will necessarily have an entry in this table.
79 | Fcb |----->| Table |--------------------+
81 +--------+ +--------+ | |
85 | +--------+ +--------+ +--------+ +--------+
86 | | Fcb | | Fcb | | Fcb | | Fcb |
87 +---------->| |<-->| |<-->| |<-->| |
89 +--------+ +--------+ +--------+ +--------+
92 Each file object open on a CDROM volume contains two context pointers. The
93 first will point back to the Fcb for the file object. The second, if present,
94 points to a Ccb (ContextControlBlock) which contains the per-handle information.
95 This includes the state of any directory enumeration.
97 +--------+ +--------+ +--------+
98 | Fcb |<------| File | | Ccb |
101 +--------+ +--------+ +--------+
103 | | +--------+ +--------+
105 | +---------| Object|--->| |
107 | +--------+ +--------+
111 +--------------| File |
118 1. A resource in the CdData synchronizes access to the Vcb queue. This
119 is used during mount/verify/dismount operations.
121 2. A resource in the Vcb is used to synchronize access to Vcb for
122 open/close operations. Typically acquired shared, it
123 is acquired exclusively to lock out these operations.
125 3. A second resource in the Vcb is used to synchronize all file operations.
126 Typically acquired shared, it is acquired exclusively to lock
127 out all file operations. Acquiring both Vcb resources will lock
130 4. A resource in the nonpaged Fcb will synchronize open/close operations
133 5. A fast mutex in the Vcb will protect access to the Fcb table and
134 the open counts in the Vcb. It is also used to modify the reference
135 counts in all Fcbs. This mutex cannot be acquired
136 exclusely and is an end resource.
138 6. A fast mutex in the Fcb will synchronize access to all Fcb fields
139 which aren't synchronized in some other way. A thread may acquire
140 mutexes for multiple Fcb's as long as it works it way toward the
141 root of the tree. This mutex can also be acquired recursively.
143 7. Normal locking order is CdData/Vcb/Fcb starting at any point in this
144 chain. The Vcb is required prior to acquiring resources for multiple
145 files. Shared ownership of the Vcb is sufficient in this case.
147 8. Normal locking order when acquiring multiple Fcb's is from some
148 starting Fcb and walking towards the root of tree. Create typically
149 walks down the tree. In this case we will attempt to acquire the
150 next node optimistically and if that fails we will reference
151 the current node in the tree, release it and acquire the next node.
152 At that point it will be safe to reacquire the parent node.
154 9. Locking order for the Fcb (via the fast mutex) will be from leaf of
155 tree back towards the root. No other resource may be acquired
156 after locking the Vcb (other than in-page reads).
158 10. Cleanup operations only lock the Vcb and Fcb long enough to change the
159 critical counts and share access fields. No reason to synchronize
160 otherwise. None of the structures can go away from beneath us
169 typedef PVOID PBCB
; //**** Bcb's are now part of the cache module
171 #define BYTE_COUNT_EMBEDDED_NAME (32)
175 // The CD_MCB is used to store the mapping of logical file offset to
176 // logical disk offset. NOTE - This package only deals with the
177 // logical 2048 sectors. Translating to 'raw' sectors happens in
178 // software. We will embed a single MCB_ENTRY in the Fcb since this
179 // will be the typical case.
182 typedef struct _CD_MCB
{
185 // Size and current count of the Mcb entries.
188 ULONG MaximumEntryCount
;
189 ULONG CurrentEntryCount
;
192 // Pointer to the start of the Mcb entries.
195 struct _CD_MCB_ENTRY
*McbArray
;
198 typedef CD_MCB
*PCD_MCB
;
200 typedef struct _CD_MCB_ENTRY
{
203 // Starting offset and number of bytes described by this entry.
204 // The Byte count is rounded to a logical block boundary if this is
212 // Starting offset in the file of mapping described by this dirent.
218 // Data length and block length. Data length is the length of each
219 // data block. Total length is the length of each data block and
223 LONGLONG DataBlockByteCount
;
224 LONGLONG TotalBlockByteCount
;
227 typedef CD_MCB_ENTRY
*PCD_MCB_ENTRY
;
231 // Cd name structure. The following structure is used to represent the
232 // full Cdrom name. This name can be stored in either Unicode or ANSI
236 typedef struct _CD_NAME
{
239 // String containing name without the version number.
240 // The maximum length field for filename indicates the
241 // size of the buffer allocated for the two parts of the name.
244 UNICODE_STRING FileName
;
247 // String containging the version number.
250 UNICODE_STRING VersionString
;
253 typedef CD_NAME
*PCD_NAME
;
256 // Following is the splay link structure for the prefix lookup.
257 // The names can be in either Unicode string or Ansi string format.
260 typedef struct _NAME_LINK
{
262 RTL_SPLAY_LINKS Links
;
263 UNICODE_STRING FileName
;
266 typedef NAME_LINK
*PNAME_LINK
;
270 // Prefix entry. There is one of these for each name in the prefix table.
271 // An Fcb will have one of these embedded for the long name and an optional
272 // pointer to the short name entry.
275 typedef struct _PREFIX_ENTRY
{
278 // Pointer to the Fcb for this entry.
284 // Flags field. Used to indicate if the name is in the prefix table.
290 // Exact case name match.
293 NAME_LINK ExactCaseName
;
296 // Case-insensitive name link.
299 NAME_LINK IgnoreCaseName
;
301 WCHAR FileNameBuffer
[ BYTE_COUNT_EMBEDDED_NAME
];
304 typedef PREFIX_ENTRY
*PPREFIX_ENTRY
;
306 #define PREFIX_FLAG_EXACT_CASE_IN_TREE (0x00000001)
307 #define PREFIX_FLAG_IGNORE_CASE_IN_TREE (0x00000002)
311 // The CD_DATA record is the top record in the CDROM file system in-memory
312 // data structure. This structure must be allocated from non-paged pool.
315 typedef struct _CD_DATA
{
318 // The type and size of this record (must be CDFS_NTC_DATA_HEADER)
321 _Field_range_(==, CDFS_NTC_DATA_HEADER
) NODE_TYPE_CODE NodeTypeCode
;
322 NODE_BYTE_SIZE NodeByteSize
;
325 // A pointer to the Driver object we were initialized with
328 PDRIVER_OBJECT DriverObject
;
337 // The following fields are used to allocate IRP context structures
338 // using a lookaside list, and other fixed sized structures from a
339 // small cache. We use the CdData mutex to protext these structures.
342 ULONG IrpContextDepth
;
343 ULONG IrpContextMaxDepth
;
344 SINGLE_LIST_ENTRY IrpContextList
;
347 // Filesystem device object for CDFS.
350 PDEVICE_OBJECT FileSystemDeviceObject
;
353 // Following are used to manage the async and delayed close queue.
355 // FspCloseActive - Indicates whether there is a thread processing the
357 // ReduceDelayedClose - Indicates that we have hit the upper threshold
358 // for the delayed close queue and need to reduce it to lower threshold.
360 // AsyncCloseQueue - Queue of IrpContext waiting for async close operation.
361 // AsyncCloseCount - Number of entries on the async close queue.
363 // DelayedCloseQueue - Queue of IrpContextLite waiting for delayed close
365 // MaxDelayedCloseCount - Trigger delay close work at this threshold.
366 // MinDelayedCloseCount - Turn off delay close work at this threshold.
367 // DelayedCloseCount - Number of entries on the delayted close queue.
369 // CloseItem - Workqueue item used to start FspClose thread.
372 LIST_ENTRY AsyncCloseQueue
;
373 ULONG AsyncCloseCount
;
374 BOOLEAN FspCloseActive
;
375 BOOLEAN ReduceDelayedClose
;
379 // The following fields describe the deferred close file objects.
382 LIST_ENTRY DelayedCloseQueue
;
383 ULONG DelayedCloseCount
;
384 ULONG MaxDelayedCloseCount
;
385 ULONG MinDelayedCloseCount
;
388 // Fast mutex used to lock the fields of this structure.
391 PVOID CdDataLockThread
;
392 FAST_MUTEX CdDataMutex
;
395 // A resource variable to control access to the global CDFS data record
398 ERESOURCE DataResource
;
401 // Cache manager call back structure, which must be passed on each call
402 // to CcInitializeCacheMap.
405 CACHE_MANAGER_CALLBACKS CacheManagerCallbacks
;
406 CACHE_MANAGER_CALLBACKS CacheManagerVolumeCallbacks
;
409 // This is the ExWorkerItem that does both kinds of deferred closes.
412 PIO_WORKITEM CloseItem
;
415 typedef CD_DATA
*PCD_DATA
;
418 #define CD_FLAGS_SHUTDOWN (0x0001)
422 // Since DVD drives allow > 100 "sessions", we need to use a larger TOC
423 // than the legacy CD definition. The maximum is theoretically 0xaa-16 (max
424 // number of open tracks in a session), but it's quite possible that some
425 // drive does not enforce this, so we'll go with 169 (track 0xaa is always the
429 #define MAXIMUM_NUMBER_TRACKS_LARGE 0xAA
431 typedef struct _CDROM_TOC_LARGE
{
437 UCHAR Length
[2]; // add two bytes for this field
445 TRACK_DATA TrackData
[ MAXIMUM_NUMBER_TRACKS_LARGE
];
447 } CDROM_TOC_LARGE
, *PCDROM_TOC_LARGE
;
449 typedef struct _CD_SECTOR_CACHE_CHUNK
{
454 } CD_SECTOR_CACHE_CHUNK
, *PCD_SECTOR_CACHE_CHUNK
;
456 #define CD_SEC_CACHE_CHUNKS 4
457 #define CD_SEC_CHUNK_BLOCKS 0x18
460 // The Vcb (Volume control block) record corresponds to every
461 // volume mounted by the file system. They are ordered in a queue off
462 // of CdData.VcbQueue.
464 // The Vcb will be in several conditions during its lifespan.
466 // NotMounted - Disk is not currently mounted (i.e. removed
467 // from system) but cleanup and close operations are
470 // MountInProgress - State of the Vcb from the time it is
471 // created until it is successfully mounted or the mount
474 // Mounted - Volume is currently in the mounted state.
476 // Invalid - User has invalidated the volume. Only legal operations
477 // are cleanup and close.
479 // DismountInProgress - We have begun the process of tearing down the
480 // Vcb. It can be deleted when all the references to it
484 typedef enum _VCB_CONDITION
{
490 VcbDismountInProgress
494 typedef struct _VCB
{
497 // The type and size of this record (must be CDFS_NTC_VCB)
500 _Field_range_(==, CDFS_NTC_VCB
) NODE_TYPE_CODE NodeTypeCode
;
501 NODE_BYTE_SIZE NodeByteSize
;
504 // Vpb for this volume.
510 // Device object for the driver below us.
513 PDEVICE_OBJECT TargetDeviceObject
;
516 // File object used to lock the volume.
519 PFILE_OBJECT VolumeLockFileObject
;
522 // Link into queue of Vcb's in the CdData structure. We will create a union with
523 // a LONGLONG to force the Vcb to be quad-aligned.
533 // State flags and condition for the Vcb.
537 VCB_CONDITION VcbCondition
;
540 // Various counts for this Vcb.
542 // VcbCleanup - Open handles left on this system.
543 // VcbReference - Number of reasons this Vcb is still present.
544 // VcbUserReference - Number of user file objects still present.
548 __volatile ULONG VcbReference
;
549 __volatile ULONG VcbUserReference
;
552 // Fcb for the Volume Dasd file, root directory and the Path Table.
555 struct _FCB
*VolumeDasdFcb
;
556 struct _FCB
*RootIndexFcb
;
557 struct _FCB
*PathTableFcb
;
560 // Location of current session and offset of volume descriptors.
564 ULONG VdSectorOffset
;
565 ULONG PrimaryVdSectorOffset
;
568 // Following is a sector from the last non-cached read of an XA file.
569 // Also the cooked offset on the disk.
573 LONGLONG XADiskOffset
;
576 // Vcb resource. This is used to synchronize open/cleanup/close operations.
579 ERESOURCE VcbResource
;
582 // File resource. This is used to synchronize all file operations except
583 // open/cleanup/close.
586 ERESOURCE FileResource
;
589 // Vcb fast mutex. This is used to synchronize the fields in the Vcb
590 // when modified when the Vcb is not held exclusively. Included here
591 // are the count fields and Fcb table.
593 // We also use this to synchronize changes to the Fcb reference field.
600 // The following is used to synchronize the dir notify package.
603 PNOTIFY_SYNC NotifySync
;
606 // The following is the head of a list of notify Irps.
609 LIST_ENTRY DirNotifyList
;
612 // Logical block size for this volume as well constant values
613 // associated with the block size.
617 ULONG BlockToSectorShift
;
618 ULONG BlockToByteShift
;
619 ULONG BlocksPerSector
;
621 ULONG BlockInverseMask
;
624 // Fcb table. Synchronized with the Vcb fast mutex.
627 RTL_GENERIC_TABLE FcbTable
;
630 // Volume TOC. Cache this information for quick lookup.
633 PCDROM_TOC_LARGE CdromToc
;
639 // Block factor to determine last session information.
645 // Media change count from device driver for bulletproof detection
649 ULONG MediaChangeCount
;
652 // For raw reads, CDFS must obey the port maximum transfer restrictions.
655 ULONG MaximumTransferRawSectors
;
656 ULONG MaximumPhysicalPages
;
659 // Preallocated VPB for swapout, so we are not forced to consider
660 // must succeed pool.
666 // Directory block cache. Read large numbers of blocks on directory
667 // reads, hoping to benefit from the fact that most mastered/pressed
668 // discs clump metadata in one place thus allowing us to crudely
669 // pre-cache and reduce seeks back to directory data during app install,
672 // Note that the purpose of this is to PRE cache unread data,
673 // not cache already read data (since Cc already provides that), thus
674 // speeding initial access to the volume.
677 PUCHAR SectorCacheBuffer
;
678 CD_SECTOR_CACHE_CHUNK SecCacheChunks
[ CD_SEC_CACHE_CHUNKS
];
679 ULONG SecCacheLRUChunkIndex
;
682 KEVENT SectorCacheEvent
;
683 ERESOURCE SectorCacheResource
;
685 #ifdef CDFS_TELEMETRY_DATA
688 // An ID that is common across the volume stack used to correlate volume events and for telemetry purposes.
689 // It may have a different value than the VolumeGuid.
692 GUID VolumeCorrelationId
;
694 #endif // CDFS_TELEMETRY_DATA
698 ULONG SecCacheMisses
;
702 #define VCB_STATE_HSG (0x00000001)
703 #define VCB_STATE_ISO (0x00000002)
704 #define VCB_STATE_JOLIET (0x00000004)
705 #define VCB_STATE_LOCKED (0x00000010)
706 #define VCB_STATE_REMOVABLE_MEDIA (0x00000020)
707 #define VCB_STATE_CDXA (0x00000040)
708 #define VCB_STATE_AUDIO_DISK (0x00000080)
709 #define VCB_STATE_NOTIFY_REMOUNT (0x00000100)
710 #define VCB_STATE_VPB_NOT_ON_DEVICE (0x00000200)
711 #define VCB_STATE_SHUTDOWN (0x00000400)
712 #define VCB_STATE_DISMOUNTED (0x00000800)
716 // The Volume Device Object is an I/O system device object with a
717 // workqueue and an VCB record appended to the end. There are multiple
718 // of these records, one for every mounted volume, and are created during
719 // a volume mount operation. The work queue is for handling an overload
720 // of work requests to the volume.
723 typedef struct _VOLUME_DEVICE_OBJECT
{
725 DEVICE_OBJECT DeviceObject
;
728 // The following field tells how many requests for this volume have
729 // either been enqueued to ExWorker threads or are currently being
730 // serviced by ExWorker threads. If the number goes above
731 // a certain threshold, put the request on the overflow queue to be
735 __volatile ULONG PostedRequestCount
;
738 // The following field indicates the number of IRP's waiting
739 // to be serviced in the overflow queue.
742 ULONG OverflowQueueCount
;
745 // The following field contains the queue header of the overflow queue.
746 // The Overflow queue is a list of IRP's linked via the IRP's ListEntry
750 LIST_ENTRY OverflowQueue
;
753 // The following spinlock protects access to all the above fields.
756 KSPIN_LOCK OverflowQueueSpinLock
;
759 // This is the file system specific volume control block.
764 } VOLUME_DEVICE_OBJECT
;
765 typedef VOLUME_DEVICE_OBJECT
*PVOLUME_DEVICE_OBJECT
;
769 // The following two structures are the separate union structures for
770 // data and index Fcb's. The path table is actually the same structure
771 // as the index Fcb since it uses the first few fields.
774 typedef enum _FCB_CONDITION
{
780 typedef struct _FCB_DATA
{
782 #if (NTDDI_VERSION < NTDDI_WIN8)
784 // The following field is used by the oplock module
785 // to maintain current oplock information.
792 // The following field is used by the filelock module
793 // to maintain current byte range locking information.
794 // A file lock is allocated as needed.
800 typedef FCB_DATA
*PFCB_DATA
;
802 typedef struct _FCB_INDEX
{
805 // Internal stream file.
808 PFILE_OBJECT FileObject
;
811 // Offset of first entry in stream. This is for case where directory
812 // or path table does not begin on a sector boundary. This value is
813 // added to all offset values to determine the real offset.
819 // List of child fcbs.
825 // Ordinal number for this directory. Combine this with the path table offset
826 // in the FileId and you have a starting point in the path table.
832 // Children path table start. This is the offset in the path table
833 // for the first child of the directory. A value of zero indicates
834 // that we haven't found the first child yet. If there are no child
835 // directories we will position at a point in the path table so that
836 // subsequent searches will fail quickly.
839 ULONG ChildPathTableOffset
;
843 // Root of splay trees for exact and ignore case prefix trees.
846 PRTL_SPLAY_LINKS ExactCaseRoot
;
847 PRTL_SPLAY_LINKS IgnoreCaseRoot
;
850 typedef FCB_INDEX
*PFCB_INDEX
;
852 typedef struct _FCB_NONPAGED
{
855 // Type and size of this record must be CDFS_NTC_FCB_NONPAGED
858 _Field_range_(==, CDFS_NTC_FCB_NONPAGED
) NODE_TYPE_CODE NodeTypeCode
;
859 NODE_BYTE_SIZE NodeByteSize
;
862 // The following field contains a record of special pointers used by
863 // MM and Cache to manipluate section objects. Note that the values
864 // are set outside of the file system. However the file system on an
865 // open/create will set the file object's SectionObject field to
866 // point to this field
869 SECTION_OBJECT_POINTERS SegmentObject
;
872 // This is the resource structure for this Fcb.
875 ERESOURCE FcbResource
;
878 // This is the FastMutex for this Fcb.
884 // This is the mutex that is inserted into the FCB_ADVANCED_HEADER
888 FAST_MUTEX AdvancedFcbHeaderMutex
;
891 typedef FCB_NONPAGED
*PFCB_NONPAGED
;
894 // The Fcb/Dcb record corresponds to every open file and directory, and to
895 // every directory on an opened path.
898 typedef struct _FCB
{
901 // The following field is used for fast I/O. It contains the node
902 // type code and size, indicates if fast I/O is possible, contains
903 // allocation, file, and valid data size, a resource, and call back
904 // pointers for FastIoRead and FastMdlRead.
907 // Node type codes for the Fcb must be one of the following.
909 // CDFS_NTC_FCB_PATH_TABLE
910 // CDFS_NTC_FCB_INDEX
915 // Common Fsrtl Header. The named header is for the fieldoff.c output. We
916 // use the unnamed header internally.
921 FSRTL_ADVANCED_FCB_HEADER Header
;
922 FSRTL_ADVANCED_FCB_HEADER
;
932 // Parent Fcb for this Fcb. This may be NULL if this file was opened
933 // by ID, also for the root Fcb.
936 struct _FCB
*ParentFcb
;
939 // Links to the queue of Fcb's in the parent.
945 // FileId for this file.
951 // Counts on this Fcb. Cleanup count represents the number of open handles
952 // on this Fcb. Reference count represents the number of reasons this Fcb
953 // is still present. It includes file objects, children Fcb and anyone
954 // who wants to prevent this Fcb from going away. Cleanup count is synchronized
955 // with the FcbResource. The reference count is synchronized with the
960 __volatile ULONG FcbReference
;
961 ULONG FcbUserReference
;
964 // State flags for this Fcb.
970 // NT style attributes for the Fcb.
973 ULONG FileAttributes
;
976 // CDXA attributes for this file.
982 // File number from the system use area.
988 // This is the thread and count for the thread which has locked this
996 // Pointer to the Fcb non-paged structures.
999 PFCB_NONPAGED FcbNonpaged
;
1002 // Share access structure.
1005 SHARE_ACCESS ShareAccess
;
1008 // Mcb for the on disk mapping and a single map entry.
1011 CD_MCB_ENTRY McbEntry
;
1015 // Embed the prefix entry for the longname. Store an optional pointer
1016 // to a prefix structure for the short name.
1019 PPREFIX_ENTRY ShortNamePrefix
;
1020 PREFIX_ENTRY FileNamePrefix
;
1023 // Time stamp for this file.
1026 LONGLONG CreationTime
;
1038 #define FCB_STATE_INITIALIZED (0x00000001)
1039 #define FCB_STATE_IN_FCB_TABLE (0x00000002)
1040 #define FCB_STATE_MODE2FORM2_FILE (0x00000004)
1041 #define FCB_STATE_MODE2_FILE (0x00000008)
1042 #define FCB_STATE_DA_FILE (0x00000010)
1045 // These file types are read as raw 2352 byte sectors
1048 #define FCB_STATE_RAWSECTOR_MASK ( FCB_STATE_MODE2FORM2_FILE | \
1049 FCB_STATE_MODE2_FILE | \
1052 #define SIZEOF_FCB_DATA \
1053 (FIELD_OFFSET( FCB, FcbType ) + sizeof( FCB_DATA ))
1055 #define SIZEOF_FCB_INDEX \
1056 (FIELD_OFFSET( FCB, FcbType ) + sizeof( FCB_INDEX ))
1060 // The Ccb record is allocated for every file object
1063 typedef struct _CCB
{
1066 // Type and size of this record (must be CDFS_NTC_CCB)
1069 _Field_range_(==, CDFS_NTC_CCB
) NODE_TYPE_CODE NodeTypeCode
;
1070 NODE_BYTE_SIZE NodeByteSize
;
1073 // Flags. Indicates flags to apply for the current open.
1079 // Fcb for the file being opened.
1085 // We store state information in the Ccb for a directory
1086 // enumeration on this handle.
1090 // Offset in the directory stream to base the next enumeration.
1093 ULONG CurrentDirentOffset
;
1094 CD_NAME SearchExpression
;
1099 #define CCB_FLAG_OPEN_BY_ID (0x00000001)
1100 #define CCB_FLAG_OPEN_RELATIVE_BY_ID (0x00000002)
1101 #define CCB_FLAG_IGNORE_CASE (0x00000004)
1102 #define CCB_FLAG_OPEN_WITH_VERSION (0x00000008)
1103 #define CCB_FLAG_DISMOUNT_ON_CLOSE (0x00000010)
1104 #define CCB_FLAG_ALLOW_EXTENDED_DASD_IO (0x00000020)
1107 // Following flags refer to index enumeration.
1110 #define CCB_FLAG_ENUM_NAME_EXP_HAS_WILD (0x00010000)
1111 #define CCB_FLAG_ENUM_VERSION_EXP_HAS_WILD (0x00020000)
1112 #define CCB_FLAG_ENUM_MATCH_ALL (0x00040000)
1113 #define CCB_FLAG_ENUM_VERSION_MATCH_ALL (0x00080000)
1114 #define CCB_FLAG_ENUM_RETURN_NEXT (0x00100000)
1115 #define CCB_FLAG_ENUM_INITIALIZED (0x00200000)
1116 #define CCB_FLAG_ENUM_NOMATCH_CONSTANT_ENTRY (0x00400000)
1120 // The Irp Context record is allocated for every orginating Irp. It is
1121 // created by the Fsd dispatch routines, and deallocated by the CdComplete
1125 typedef struct _IRP_CONTEXT
{
1128 // Type and size of this record (must be CDFS_NTC_IRP_CONTEXT)
1131 _Field_range_(==, CDFS_NTC_IRP_CONTEXT
) NODE_TYPE_CODE NodeTypeCode
;
1132 NODE_BYTE_SIZE NodeByteSize
;
1135 // Originating Irp for the request.
1141 // Vcb for this operation. When this is NULL it means we were called
1142 // with our filesystem device object instead of a volume device object.
1143 // (Mount will fill this in once the Vcb is created)
1149 // Exception encountered during the request. Any error raised explicitly by
1150 // the file system will be stored here. Any other error raised by the system
1151 // is stored here after normalizing it.
1154 NTSTATUS ExceptionStatus
;
1155 ULONG RaisedAtLineFile
;
1158 // Flags for this request.
1164 // Real device object. This represents the physical device closest to the media.
1167 PDEVICE_OBJECT RealDevice
;
1170 // Io context for a read request.
1171 // Address of Fcb for teardown oplock in create case.
1176 struct _CD_IO_CONTEXT
*IoContext
;
1181 // Top level irp context for this thread.
1184 struct _IRP_CONTEXT
*TopLevel
;
1187 // Major and minor function codes.
1190 UCHAR MajorFunction
;
1191 UCHAR MinorFunction
;
1194 // Pointer to the top-level context if this IrpContext is responsible
1195 // for cleaning it up.
1198 struct _THREAD_CONTEXT
*ThreadContext
;
1201 // This structure is used for posting to the Ex worker threads.
1204 WORK_QUEUE_ITEM WorkQueueItem
;
1207 typedef IRP_CONTEXT
*PIRP_CONTEXT
;
1209 #define IRP_CONTEXT_FLAG_ON_STACK (0x00000001)
1210 #define IRP_CONTEXT_FLAG_MORE_PROCESSING (0x00000002)
1211 #define IRP_CONTEXT_FLAG_WAIT (0x00000004)
1212 #define IRP_CONTEXT_FLAG_FORCE_POST (0x00000008)
1213 #define IRP_CONTEXT_FLAG_TOP_LEVEL (0x00000010)
1214 #define IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS (0x00000020)
1215 #define IRP_CONTEXT_FLAG_IN_FSP (0x00000040)
1216 #define IRP_CONTEXT_FLAG_IN_TEARDOWN (0x00000080)
1217 #define IRP_CONTEXT_FLAG_ALLOC_IO (0x00000100)
1218 #define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000200)
1219 #define IRP_CONTEXT_FLAG_FORCE_VERIFY (0x00000400)
1222 // Flags used for create.
1225 #define IRP_CONTEXT_FLAG_FULL_NAME (0x10000000)
1226 #define IRP_CONTEXT_FLAG_TRAIL_BACKSLASH (0x20000000)
1229 // The following flags need to be cleared when a request is posted.
1232 #define IRP_CONTEXT_FLAGS_CLEAR_ON_POST ( \
1233 IRP_CONTEXT_FLAG_MORE_PROCESSING | \
1234 IRP_CONTEXT_FLAG_WAIT | \
1235 IRP_CONTEXT_FLAG_FORCE_POST | \
1236 IRP_CONTEXT_FLAG_TOP_LEVEL | \
1237 IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS | \
1238 IRP_CONTEXT_FLAG_IN_FSP | \
1239 IRP_CONTEXT_FLAG_IN_TEARDOWN | \
1240 IRP_CONTEXT_FLAG_DISABLE_POPUPS \
1244 // The following flags need to be cleared when a request is retried.
1247 #define IRP_CONTEXT_FLAGS_CLEAR_ON_RETRY ( \
1248 IRP_CONTEXT_FLAG_MORE_PROCESSING | \
1249 IRP_CONTEXT_FLAG_IN_TEARDOWN | \
1250 IRP_CONTEXT_FLAG_DISABLE_POPUPS \
1254 // The following flags are set each time through the Fsp loop.
1257 #define IRP_CONTEXT_FSP_FLAGS ( \
1258 IRP_CONTEXT_FLAG_WAIT | \
1259 IRP_CONTEXT_FLAG_TOP_LEVEL | \
1260 IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS | \
1261 IRP_CONTEXT_FLAG_IN_FSP \
1266 // Following structure is used to queue a request to the delayed close queue.
1267 // This structure should be the minimum block allocation size.
1270 typedef struct _IRP_CONTEXT_LITE
{
1273 // Type and size of this record (must be CDFS_NTC_IRP_CONTEXT_LITE)
1276 _Field_range_(==, CDFS_NTC_IRP_CONTEXT_LITE
) NODE_TYPE_CODE NodeTypeCode
;
1277 NODE_BYTE_SIZE NodeByteSize
;
1280 // Fcb for the file object being closed.
1286 // List entry to attach to delayed close queue.
1289 LIST_ENTRY DelayedCloseLinks
;
1292 // User reference count for the file object being closed.
1295 ULONG UserReference
;
1298 // Real device object. This represents the physical device closest to the media.
1301 PDEVICE_OBJECT RealDevice
;
1304 typedef IRP_CONTEXT_LITE
*PIRP_CONTEXT_LITE
;
1308 // Context structure for asynchronous I/O calls. Most of these fields
1309 // are actually only required for the ReadMultiple routines, but
1310 // the caller must allocate one as a local variable anyway before knowing
1311 // whether there are multiple requests are not. Therefore, a single
1312 // structure is used for simplicity.
1315 typedef struct _CD_IO_CONTEXT
{
1318 // These two fields are used for multiple run Io
1321 __volatile LONG IrpCount
;
1323 __volatile NTSTATUS Status
;
1324 BOOLEAN AllocatedContext
;
1329 // This element handles the asynchronous non-cached Io
1334 PERESOURCE Resource
;
1335 ERESOURCE_THREAD ResourceThreadId
;
1336 ULONG RequestedByteCount
;
1340 // and this element handles the synchronous non-cached Io.
1347 typedef CD_IO_CONTEXT
*PCD_IO_CONTEXT
;
1351 // Following structure is used to track the top level request. Each Cdfs
1352 // Fsd and Fsp entry point will examine the top level irp location in the
1353 // thread local storage to determine if this request is top level and/or
1354 // top level Cdfs. The top level Cdfs request will remember the previous
1355 // value and update that location with a stack location. This location
1356 // can be accessed by recursive Cdfs entry points.
1359 typedef struct _THREAD_CONTEXT
{
1362 // CDFS signature. Used to confirm structure on stack is valid.
1368 // Previous value in top-level thread location. We restore this
1372 PIRP SavedTopLevelIrp
;
1375 // Top level Cdfs IrpContext. Initial Cdfs entry point on stack
1376 // will store the IrpContext for the request in this stack location.
1379 PIRP_CONTEXT TopLevelIrpContext
;
1382 typedef THREAD_CONTEXT
*PTHREAD_CONTEXT
;
1386 // The following structure is used for enumerating the entries in the
1387 // path table. We will always map this two sectors at a time so we don't
1388 // have to worry about entries which span sectors. We move through
1389 // one sector at a time though. We will unpin and remap after
1390 // crossing a sector boundary.
1392 // The only special case is where we span a cache view. In that case
1393 // we will allocate a buffer and read both pieces into it.
1395 // This strategy takes advantage of the CC enhancement which allows
1396 // overlapping ranges.
1399 typedef struct _PATH_ENUM_CONTEXT
{
1402 // Pointer to the current sector and the offset of this sector to
1403 // the beginning of the path table. The Data pointer may be
1404 // a pool block in the case where we cross a cache view
1405 // boundary. Also the length of the data for this block.
1413 // Bcb for the sector. (We may actually have pinned two sectors)
1414 // This will be NULL for the case where we needed to allocate a
1415 // buffer in the case where we span a cache view.
1421 // Offset to current entry within the current data block.
1427 // Did we allocate the buffer for the entry.
1430 BOOLEAN AllocatedData
;
1433 // End of Path Table. This tells us whether the current data
1434 // block includes the end of the path table. This is the
1435 // only block where we need to do a careful check about whether
1436 // the path table entry fits into the buffer.
1438 // Also once we have reached the end of the path table we don't
1439 // need to remap the data as we move into the final sector.
1440 // We always look at the last two sectors together.
1443 BOOLEAN LastDataBlock
;
1445 } PATH_ENUM_CONTEXT
;
1446 typedef PATH_ENUM_CONTEXT
*PPATH_ENUM_CONTEXT
;
1448 #define VACB_MAPPING_MASK (VACB_MAPPING_GRANULARITY - 1)
1449 #define LAST_VACB_SECTOR_OFFSET (VACB_MAPPING_GRANULARITY - SECTOR_SIZE)
1453 // Path Entry. This is our representation of the on disk data.
1456 typedef struct _PATH_ENTRY
{
1459 // Directory number and offset. This is the ordinal and the offset from
1460 // the beginning of the path table stream for this entry.
1465 ULONG PathTableOffset
;
1468 // Logical block Offset on the disk for this entry. We already bias
1469 // this by any Xar blocks.
1475 // Length of on-disk path table entry.
1478 ULONG PathEntryLength
;
1484 ULONG ParentOrdinal
;
1487 // DirName length and Id. Typically the pointer here points to the raw on-disk
1488 // bytes. We will point to a fixed self entry if this is the root directory.
1495 // Following are the flags used to cleanup this structure.
1501 // The following is the filename string and version number strings. We embed a buffer
1502 // large enough to hold two 8.3 names. One for exact case and one for case insensitive.
1506 CD_NAME CdCaseDirName
;
1508 WCHAR NameBuffer
[BYTE_COUNT_EMBEDDED_NAME
/ sizeof( WCHAR
) * 2];
1511 typedef PATH_ENTRY
*PPATH_ENTRY
;
1513 #define PATH_ENTRY_FLAG_ALLOC_BUFFER (0x00000001)
1517 // Compound path entry. This structure combines the on-disk entries
1518 // with the in-memory structures.
1521 typedef struct _COMPOUND_PATH_ENTRY
{
1523 PATH_ENUM_CONTEXT PathContext
;
1524 PATH_ENTRY PathEntry
;
1526 } COMPOUND_PATH_ENTRY
;
1527 typedef COMPOUND_PATH_ENTRY
*PCOMPOUND_PATH_ENTRY
;
1531 // The following is used for enumerating through a directory via the
1535 typedef struct _DIRENT_ENUM_CONTEXT
{
1538 // Pointer the current sector and the offset of this sector within
1539 // the directory file. Also the data length of this pinned block.
1547 // Bcb for the sector.
1553 // Offset to the current dirent within this sector.
1559 // Length to next dirent. A zero indicates to move to the next sector.
1562 ULONG NextDirentOffset
;
1564 } DIRENT_ENUM_CONTEXT
;
1565 typedef DIRENT_ENUM_CONTEXT
*PDIRENT_ENUM_CONTEXT
;
1569 // Following structure is used to smooth out the differences in the HSG, ISO
1570 // and Joliett directory entries.
1573 typedef struct _DIRENT
{
1576 // Offset in the Directory of this entry. Note this includes
1577 // any bytes added to the beginning of the directory to pad
1578 // down to a sector boundary.
1586 // Starting offset on the disk including any Xar blocks.
1589 ULONG StartingOffset
;
1592 // DataLength of the data. If not the last block then this should
1593 // be an integral number of logical blocks.
1599 // The following field is the time stamp out of the directory entry.
1600 // Use a pointer into the dirent for this.
1606 // The following field is the dirent file flags field.
1612 // Following field is a Cdfs flag field used to clean up this structure.
1618 // The following fields indicate the file unit size and interleave gap
1619 // for interleaved files. Each of these are in logical blocks.
1623 ULONG InterleaveGapSize
;
1626 // System use offset. Zero value indicates no system use area.
1629 ULONG SystemUseOffset
;
1632 // CDXA attributes and file number for this file.
1635 USHORT XAAttributes
;
1639 // Filename length and ID. We copy the length (in bytes) and keep
1640 // a pointer to the start of the name.
1647 // The following are the filenames stored by name and version numbers.
1648 // The fixed buffer here can hold two Unicode 8.3 names. This allows
1649 // us to upcase the name into a fixed buffer.
1653 CD_NAME CdCaseFileName
;
1656 // Data stream type. Indicates if this is audio, XA mode2 form2 or cooked sectors.
1659 XA_EXTENT_TYPE ExtentType
;
1661 WCHAR NameBuffer
[BYTE_COUNT_EMBEDDED_NAME
/ sizeof( WCHAR
) * 2];
1664 typedef DIRENT
*PDIRENT
;
1666 #define DIRENT_FLAG_ALLOC_BUFFER (0x01)
1667 #define DIRENT_FLAG_CONSTANT_ENTRY (0x02)
1669 #define DIRENT_FLAG_NOT_PERSISTENT (0)
1673 // Following structure combines the on-disk information with the normalized
1677 typedef struct _COMPOUND_DIRENT
{
1679 DIRENT_ENUM_CONTEXT DirContext
;
1683 typedef COMPOUND_DIRENT
*PCOMPOUND_DIRENT
;
1687 // The following structure is used to enumerate the files in a directory.
1688 // It contains three DirContext/Dirent pairs and then self pointers to
1689 // know which of these is begin used how.
1692 typedef struct _FILE_ENUM_CONTEXT
{
1695 // Pointers to the current compound dirents below.
1697 // PriorDirent - Initial dirent for the last file encountered.
1698 // InitialDirent - Initial dirent for the current file.
1699 // CurrentDirent - Second or later dirent for the current file.
1702 PCOMPOUND_DIRENT PriorDirent
;
1703 PCOMPOUND_DIRENT InitialDirent
;
1704 PCOMPOUND_DIRENT CurrentDirent
;
1707 // Flags indicating the state of the search.
1713 // This is an accumulation of the file sizes of the different extents
1714 // of a single file.
1720 // Short name for this file.
1724 WCHAR ShortNameBuffer
[ BYTE_COUNT_8_DOT_3
/ sizeof( WCHAR
) ];
1727 // Array of compound dirents.
1730 COMPOUND_DIRENT Dirents
[3];
1732 } FILE_ENUM_CONTEXT
;
1733 typedef FILE_ENUM_CONTEXT
*PFILE_ENUM_CONTEXT
;
1735 #define FILE_CONTEXT_MULTIPLE_DIRENTS (0x00000001)
1739 // RIFF header. Prepended to the data of a file containing XA sectors.
1740 // This is a hard-coded structure except that we bias the 'ChunkSize' and
1741 // 'RawSectors' fields with the file size. We also copy the attributes flag
1742 // from the system use area in the dirent. We always initialize this
1743 // structure by copying the XAFileHeader.
1746 typedef struct _RIFF_HEADER
{
1750 ULONG SignatureCDXA
;
1758 ULONG SignatureData
;
1762 typedef RIFF_HEADER
*PRIFF_HEADER
;
1765 // Audio play header for CDDA tracks.
1768 typedef struct _AUDIO_PLAY_HEADER
{
1772 ULONG SignatureCDDA
;
1778 ULONG StartingSector
;
1780 UCHAR TrackAddress
[4];
1781 UCHAR TrackLength
[4];
1783 } AUDIO_PLAY_HEADER
;
1784 typedef AUDIO_PLAY_HEADER
*PAUDIO_PLAY_HEADER
;
1788 // Some macros for supporting the use of a Generic Table
1789 // containing all the FCB/DCBs and indexed by their FileId.
1793 // The HighPart contains the path table offset of this directory in the
1796 // The LowPart contains zero except for the upper bit which is
1797 // set to indicate that this is a directory.
1801 // The HighPart contains the path table offset of the parent directory
1802 // in the path table.
1804 // The LowPart contains the byte offset of the dirent in the parent
1807 // A directory is always entered into the Fcb Table as if it's
1808 // dirent offset was zero. This enables any child to look in the FcbTable
1809 // for it's parent by searching with the same HighPart but with zero
1810 // as the value for LowPart.
1812 // The Id field is a LARGE_INTEGER where the High and Low parts can be
1813 // accessed separately.
1815 // The following macros are used to access the Fid fields.
1817 // CdQueryFidDirentOffset - Accesses the Dirent offset field
1818 // CdQueryFidPathTableNumber - Accesses the PathTable offset field
1819 // CdSetFidDirentOffset - Sets the Dirent offset field
1820 // CdSetFidPathTableNumber - Sets the PathTable ordinal field
1821 // CdFidIsDirectory - Queries if directory bit is set
1822 // CdFidSetDirectory - Sets directory bit
1825 #define FID_DIR_MASK 0x80000000 // high order bit means directory.
1827 #define CdQueryFidDirentOffset(I) ((I).LowPart & ~FID_DIR_MASK)
1828 #define CdQueryFidPathTableOffset(I) ((I).HighPart)
1829 #define CdSetFidDirentOffset(I,D) ((I).LowPart = D)
1830 #define CdSetFidPathTableOffset(I,P) ((I).HighPart = P)
1831 #define CdFidIsDirectory(I) FlagOn( (I).LowPart, FID_DIR_MASK )
1832 #define CdFidSetDirectory(I) SetFlag( (I).LowPart, FID_DIR_MASK )
1834 #define CdSetFidFromParentAndDirent(I,F,D) { \
1835 CdSetFidPathTableOffset( (I), CdQueryFidPathTableOffset( (F)->FileId )); \
1836 CdSetFidDirentOffset( (I), (D)->DirentOffset ); \
1837 if (FlagOn( (D)->DirentFlags, CD_ATTRIBUTE_DIRECTORY )) { \
1838 CdFidSetDirectory((I)); \
1842 #ifdef CDFS_TELEMETRY_DATA
1843 // ============================================================================
1844 // ============================================================================
1848 // ============================================================================
1849 // ============================================================================
1851 typedef struct _CDFS_TELEMETRY_DATA_CONTEXT
{
1854 // Number of times there was not enough stack space to generate telemetry
1857 volatile LONG MissedTelemetryPoints
;
1860 // System Time of the last periodic telemtry event. System Time
1861 // is according to KeQuerySystemTime()
1864 LARGE_INTEGER LastPeriodicTelemetrySystemTime
;
1867 // TickCount of the last periodic telemtry event. TickCount is
1868 // according to KeQueryTickCount()
1871 LARGE_INTEGER LastPeriodicTelemetryTickCount
;
1874 // Hint for Worker thread whether to generate
1875 // periodic telemetry or not
1878 BOOLEAN GeneratePeriodicTelemetry
;
1881 // Guid for ID parity with other file systems telemetry.
1890 // For DBG builds we want a machanism to change the frequency of
1894 LONGLONG PeriodicInterval
;
1899 // File system statistics at time of last period telemetry event
1902 FILESYSTEM_STATISTICS CommonStats
;
1904 } CDFS_TELEMETRY_DATA_CONTEXT
, *PCDFS_TELEMETRY_DATA_CONTEXT
;
1906 #endif // CDFS_TELEMETRY_DATA