1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     FatStruc.h
8 
9 Abstract:
10 
11     This module defines the data structures that make up the major internal
12     part of the Fat file system.
13 
14 
15 --*/
16 
17 #ifndef _FATSTRUC_
18 #define _FATSTRUC_
19 
20 typedef PVOID PBCB;     //**** Bcb's are now part of the cache module
21 
22 #ifdef __REACTOS__
23 #undef __volatile
24 #define __volatile volatile
25 #endif
26 
27 //
28 //  The FAT_DATA record is the top record in the Fat file system in-memory
29 //  data structure.  This structure must be allocated from non-paged pool.
30 //
31 
32 typedef struct _FAT_DATA {
33 
34     //
35     //  The type and size of this record (must be FAT_NTC_DATA_HEADER)
36     //
37 
38     NODE_TYPE_CODE NodeTypeCode;
39     NODE_BYTE_SIZE NodeByteSize;
40 
41 
42     PVOID LazyWriteThread;
43 
44 
45     //
46     //  A queue of all the devices that are mounted by the file system.
47     //
48 
49     LIST_ENTRY VcbQueue;
50 
51     //
52     //  A pointer to the Driver object we were initialized with
53     //
54 
55     PDRIVER_OBJECT DriverObject;
56 
57     //
58     //  A pointer to the filesystem device objects we created.
59     //
60 
61     PVOID DiskFileSystemDeviceObject;
62     PVOID CdromFileSystemDeviceObject;
63 
64     //
65     //  A resource variable to control access to the global Fat data record
66     //
67 
68     ERESOURCE Resource;
69 
70     //
71     //  A pointer to our EPROCESS struct, which is a required input to the
72     //  Cache Management subsystem.
73     //
74 
75     PEPROCESS OurProcess;
76 
77     //
78     //  Number of processors when the driver loaded.
79     //
80 
81     ULONG NumberProcessors;
82 
83     //
84     //  The following tells us if we should use Chicago extensions.
85     //
86 
87     BOOLEAN ChicagoMode:1;
88 
89     //
90     //  The following field tells us if we are running on a Fujitsu
91     //  FMR Series. These machines supports extra formats on the
92     //  FAT file system.
93     //
94 
95     BOOLEAN FujitsuFMR:1;
96 
97     //
98     //  Inidicates that FspClose is currently processing closes.
99     //
100 
101     BOOLEAN AsyncCloseActive:1;
102 
103     //
104     //  The following BOOLEAN says shutdown has started on FAT.  It
105     //  instructs FspClose to not keep the Vcb resources anymore.
106     //
107 
108     BOOLEAN ShutdownStarted:1;
109 
110     //
111     //  The following flag tells us if we are going to generate LFNs
112     //  for valid 8.3 names with extended characters.
113     //
114 
115     BOOLEAN CodePageInvariant:1;
116 
117     //
118     //  The following flags tell us if we are in an aggresive push to lower
119     //  the size of the deferred close queues.
120     //
121 
122     BOOLEAN HighAsync:1;
123     BOOLEAN HighDelayed:1;
124 
125 
126     //
127     //  The following list entry is used for performing closes that can't
128     //  be done in the context of the original caller.
129     //
130 
131     ULONG AsyncCloseCount;
132     LIST_ENTRY AsyncCloseList;
133 
134     //
135     //  The following two fields record if we are delaying a close.
136     //
137 
138     ULONG DelayedCloseCount;
139     LIST_ENTRY DelayedCloseList;
140 
141     //
142     //  This is the ExWorkerItem that does both kinds of deferred closes.
143     //
144 
145     PIO_WORKITEM FatCloseItem;
146 
147     //
148     //  This spinlock protects several rapid-fire operations. NOTE: this is
149     //  pretty horrible style.
150     //
151 
152     KSPIN_LOCK GeneralSpinLock;
153 
154     //
155     //  Cache manager call back structures, which must be passed on each call
156     //  to CcInitializeCacheMap.
157     //
158 
159     CACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
160     CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks;
161 
162 
163     PVOID ZeroPage;
164 
165 } FAT_DATA;
166 typedef FAT_DATA *PFAT_DATA;
167 
168 //
169 // An array of these structures will keep
170 
171 typedef struct _FAT_WINDOW {
172 
173     ULONG FirstCluster;       // The first cluster in this window.
174     ULONG LastCluster;        // The last cluster in this window.
175     ULONG ClustersFree;       // The number of clusters free in this window.
176 
177 } FAT_WINDOW;
178 typedef FAT_WINDOW *PFAT_WINDOW;
179 
180 //
181 //  Forward reference some circular referenced structures.
182 //
183 
184 typedef struct _VCB VCB;
185 typedef VCB *PVCB;
186 
187 typedef struct _FCB FCB;
188 typedef FCB *PFCB;
189 
190 //
191 //  This structure is used to keep track of information needed to do a
192 //  deferred close.  It is now embedded in a CCB so we don't have to
193 //  allocate one in the close path (with mustsucceed).
194 //
195 
196 typedef struct {
197 
198     //
199     //  Two sets of links, one for the global list and one for closes
200     //  on a particular volume.
201     //
202 
203     LIST_ENTRY GlobalLinks;
204     LIST_ENTRY VcbLinks;
205 
206     PVCB Vcb;
207     PFCB Fcb;
208     enum _TYPE_OF_OPEN TypeOfOpen;
209     BOOLEAN Free;
210 
211 } CLOSE_CONTEXT;
212 
213 typedef CLOSE_CONTEXT *PCLOSE_CONTEXT;
214 
215 
216 //
217 //  The Vcb (Volume control Block) record corresponds to every volume mounted
218 //  by the file system.  They are ordered in a queue off of FatData.VcbQueue.
219 //  This structure must be allocated from non-paged pool
220 //
221 
222 typedef enum _VCB_CONDITION {
223     VcbGood = 1,
224     VcbNotMounted,
225     VcbBad
226 } VCB_CONDITION;
227 
228 typedef struct _VCB {
229 
230     //
231     //  This is a common head for the FAT volume file
232     //
233 
234     FSRTL_ADVANCED_FCB_HEADER VolumeFileHeader;
235 
236     //
237     //  The links for the device queue off of FatData.VcbQueue
238     //
239 
240     LIST_ENTRY VcbLinks;
241 
242     //
243     //  A pointer the device object passed in by the I/O system on a mount
244     //  This is the target device object that the file system talks to when it
245     //  needs to do any I/O (e.g., the disk stripper device object).
246     //
247     //
248 
249     PDEVICE_OBJECT TargetDeviceObject;
250 
251 #if (NTDDI_VERSION > NTDDI_WIN8)
252     //
253     //  The volume GUID of the target device object.
254     //
255 
256     GUID VolumeGuid;
257 #endif
258 
259     //
260     //  The volume GUID path of the target device object.
261     //
262 
263     UNICODE_STRING VolumeGuidPath;
264 
265 
266     //
267     //  A pointer to the VPB for the volume passed in by the I/O system on
268     //  a mount.
269     //
270 
271     PVPB Vpb;
272 
273     //
274     //  The internal state of the device.  This is a collection of fsd device
275     //  state flags.
276     //
277 
278     ULONG VcbState;
279     VCB_CONDITION VcbCondition;
280 
281     //
282     //  A pointer to the root DCB for this volume
283     //
284 
285     struct _FCB *RootDcb;
286 
287     //
288     //  If the FAT has so many entries that the free cluster bitmap would
289     //  be too large, we split the FAT into buckets, and only one bucket's
290     //  worth of bits are kept in the bitmap.
291     //
292 
293     ULONG NumberOfWindows;
294     PFAT_WINDOW Windows;
295     PFAT_WINDOW CurrentWindow;
296 
297     //
298     //  A count of the number of file objects that have opened the volume
299     //  for direct access, and their share access state.
300     //
301 
302     CLONG DirectAccessOpenCount;
303     SHARE_ACCESS ShareAccess;
304 
305     //
306     //  A count of the number of file objects that have any file/directory
307     //  opened on this volume, not including direct access.  And also the
308     //  count of the number of file objects that have a file opened for
309     //  only read access (i.e., they cannot be modifying the disk).
310     //
311 
312     CLONG OpenFileCount;
313     CLONG ReadOnlyCount;
314 
315     //
316     //  A count of the number of internal opens on this VCB.
317     //
318 
319     __volatile ULONG InternalOpenCount;
320 
321     //
322     //  A count of the number of residual opens on this volume.
323     //  This is usually two or three.  One is for the virutal volume
324     //  file.  One is for the root directory.  And one is for the
325     //  EA file, if there is one.
326     //
327 
328     __volatile ULONG ResidualOpenCount;
329 
330     //
331     //  The bios parameter block field contains
332     //  an unpacked copy of the bpb for the volume, it is initialized
333     //  during mount time and can be read by everyone else after that.
334     //
335 
336     BIOS_PARAMETER_BLOCK Bpb;
337 
338     PUCHAR First0x24BytesOfBootSector;
339 
340     //
341     //  The following structure contains information useful to the
342     //  allocation support routines.  Many of them are computed from
343     //  elements of the Bpb, but are too involved to recompute every time
344     //  they are needed.
345     //
346 
347     struct {
348 
349         LBO RootDirectoryLbo;       // Lbo of beginning of root directory
350         LBO FileAreaLbo;            // Lbo of beginning of file area
351         ULONG RootDirectorySize;    // size of root directory in bytes
352 
353         ULONG NumberOfClusters;     // total number of clusters on the volume
354         ULONG NumberOfFreeClusters; // number of free clusters on the volume
355 
356 
357         UCHAR FatIndexBitSize;      // indicates if 12, 16, or 32 bit fat table
358 
359         UCHAR LogOfBytesPerSector;  // Log(Bios->BytesPerSector)
360         UCHAR LogOfBytesPerCluster; // Log(Bios->SectorsPerCluster)
361 
362     } AllocationSupport;
363 
364     //
365     //  The following Mcb is used to keep track of dirty sectors in the Fat.
366     //  Runs of holes denote clean sectors while runs of LBO == VBO denote
367     //  dirty sectors.  The VBOs are that of the volume file, starting at
368     //  0.  The granuality of dirt is one sectors, and additions are only
369     //  made in sector chunks to prevent problems with several simultaneous
370     //  updaters.
371     //
372 
373     LARGE_MCB DirtyFatMcb;
374 
375     //
376     //  The following MCB contains a list of all the bad clusters on the volume.
377     //  It is empty until the first time the bad sectors on the volume are queried
378     //  by calling FSCTL_GET_RETRIEVAL_POINTERS with a volume handle.
379     //
380 
381     LARGE_MCB   BadBlockMcb;
382 
383     //
384     //  The FreeClusterBitMap keeps track of all the clusters in the fat.
385     //  A 1 means occupied while a 0 means free.  It allows quick location
386     //  of contiguous runs of free clusters.  It is initialized on mount
387     //  or verify.
388     //
389 
390     RTL_BITMAP FreeClusterBitMap;
391 
392     //
393     //  The following fast mutex controls access to the free cluster bit map
394     //  and the buckets.
395     //
396 
397     FAST_MUTEX FreeClusterBitMapMutex;
398 
399     //
400     //  A resource variable to control access to the volume specific data
401     //  structures
402     //
403 
404     ERESOURCE Resource;
405 
406     //
407     //  A resource to make sure no one changes the volume bitmap while
408     //  you're using it.  Only for volumes with NumberOfWindows > 1.
409     //
410 
411     ERESOURCE ChangeBitMapResource;
412 
413 
414     //
415     //  The following field points to the file object used to do I/O to
416     //  the virtual volume file.  The virtual volume file maps sectors
417     //  0 through the end of fat and is of a fixed size (determined during
418     //  mount)
419     //
420 
421     PFILE_OBJECT VirtualVolumeFile;
422 
423     //
424     //  The following field contains a record of special pointers used by
425     //  MM and Cache to manipluate section objects.  Note that the values
426     //  are set outside of the file system.  However the file system on an
427     //  open/create will set the file object's SectionObject field to point
428     //  to this field
429     //
430 
431     SECTION_OBJECT_POINTERS SectionObjectPointers;
432 
433     //
434     //  The following fields is a hint cluster index used by the file system
435     //  when allocating a new cluster.
436     //
437 
438     ULONG ClusterHint;
439 
440     //
441     //  This field contains the "DeviceObject" that this volume is
442     //  currently mounted on.  Note Vcb->Vpb->RealDevice is constant.
443     //
444 
445     PDEVICE_OBJECT CurrentDevice;
446 
447     //
448     //  This is a pointer to the file object and the Fcb which represent the ea data.
449     //
450 
451     PFILE_OBJECT VirtualEaFile;
452     struct _FCB *EaFcb;
453 
454     //
455     //  The following field is a pointer to the file object that has the
456     //  volume locked. if the VcbState has the locked flag set.
457     //
458 
459     PFILE_OBJECT FileObjectWithVcbLocked;
460 
461     //
462     //  The following is the head of a list of notify Irps.
463     //
464 
465     LIST_ENTRY DirNotifyList;
466 
467     //
468     //  The following is used to synchronize the dir notify list.
469     //
470 
471     PNOTIFY_SYNC NotifySync;
472 
473     //
474     //  The following fast mutex is used to synchronize directory stream
475     //  file object creation.
476     //
477 
478     FAST_MUTEX DirectoryFileCreationMutex;
479 
480     //
481     //  This field holds the thread address of the current (or most recent
482     //  depending on VcbState) thread doing a verify operation on this volume.
483     //
484 
485     PKTHREAD VerifyThread;
486 
487     //
488     //  The following two structures are used for CleanVolume callbacks.
489     //
490 
491     KDPC CleanVolumeDpc;
492     KTIMER CleanVolumeTimer;
493 
494     //
495     //  This field records the last time FatMarkVolumeDirty was called, and
496     //  avoids excessive calls to push the CleanVolume forward in time.
497     //
498 
499     LARGE_INTEGER LastFatMarkVolumeDirtyCall;
500 
501     //
502     //  The following fields holds a pointer to a struct which is used to
503     //  hold performance counters.
504     //
505 
506     struct _FILE_SYSTEM_STATISTICS *Statistics;
507 
508     //
509     //  The property tunneling cache for this volume
510     //
511 
512     TUNNEL Tunnel;
513 
514     //
515     //  The media change count is returned by IOCTL_CHECK_VERIFY and
516     //  is used to verify that no user-mode app has swallowed a media change
517     //  notification.  This is only meaningful for removable media.
518     //
519 
520     ULONG ChangeCount;
521 
522     //
523     //  The device number of the underlying storage device.
524     //
525 
526     ULONG DeviceNumber;
527 
528     //
529     //  Preallocated VPB for swapout, so we are not forced to consider
530     //  must succeed pool.
531     //
532 
533     PVPB SwapVpb;
534 
535     //
536     //  Per volume threading of the close queues.
537     //
538 
539     LIST_ENTRY AsyncCloseList;
540     LIST_ENTRY DelayedCloseList;
541 
542     //
543     //  Fast mutex used by the ADVANCED FCB HEADER in this structure
544     //
545 
546     FAST_MUTEX AdvancedFcbHeaderMutex;
547 
548 
549     //
550     //  How many close contexts were preallocated on this Vcb
551     //
552 #if DBG
553     ULONG CloseContextCount;
554 #endif
555 
556 } VCB;
557 typedef VCB *PVCB;
558 
559 #define VCB_STATE_FLAG_LOCKED               (0x00000001)
560 #define VCB_STATE_FLAG_REMOVABLE_MEDIA      (0x00000002)
561 #define VCB_STATE_FLAG_VOLUME_DIRTY         (0x00000004)
562 #define VCB_STATE_FLAG_MOUNTED_DIRTY        (0x00000010)
563 #define VCB_STATE_FLAG_SHUTDOWN             (0x00000040)
564 #define VCB_STATE_FLAG_CLOSE_IN_PROGRESS    (0x00000080)
565 #define VCB_STATE_FLAG_DELETED_FCB          (0x00000100)
566 #define VCB_STATE_FLAG_CREATE_IN_PROGRESS   (0x00000200)
567 #define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE  (0x00000800)
568 #define VCB_STATE_FLAG_DEFERRED_FLUSH       (0x00001000)
569 #define VCB_STATE_FLAG_ASYNC_CLOSE_ACTIVE   (0x00002000)
570 #define VCB_STATE_FLAG_WRITE_PROTECTED      (0x00004000)
571 #define VCB_STATE_FLAG_REMOVAL_PREVENTED    (0x00008000)
572 #define VCB_STATE_FLAG_VOLUME_DISMOUNTED    (0x00010000)
573 #define VCB_STATE_VPB_NOT_ON_DEVICE         (0x00020000)
574 #define VCB_STATE_FLAG_VPB_MUST_BE_FREED    (0x00040000)
575 #define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS (0x00080000)
576 #define VCB_STATE_FLAG_BAD_BLOCKS_POPULATED (0x00100000)
577 #define VCB_STATE_FLAG_HOTPLUGGABLE         (0x00200000)
578 #define VCB_STATE_FLAG_MOUNT_IN_PROGRESS    (0x00800000)
579 
580 
581 //
582 //  N.B - VOLUME_DISMOUNTED is an indication that FSCTL_DISMOUNT volume was
583 //  executed on a volume. It does not replace VcbCondition as an indication
584 //  that the volume is invalid/unrecoverable.
585 //
586 
587 //
588 //  Define the file system statistics struct.  Vcb->Statistics points to an
589 //  array of these (one per processor) and they must be 64 byte aligned to
590 //  prevent cache line tearing.
591 //
592 
593 #define FILE_SYSTEM_STATISTICS_WITHOUT_PAD (sizeof( FILESYSTEM_STATISTICS ) + sizeof( FAT_STATISTICS ))
594 
595 typedef struct _FILE_SYSTEM_STATISTICS {
596 
597         //
598         //  This contains the actual data.
599         //
600 
601         FILESYSTEM_STATISTICS Common;
602         FAT_STATISTICS Fat;
603 
604         //
605         //  Pad this structure to a multiple of 64 bytes.
606         //
607 
608         UCHAR Pad[((FILE_SYSTEM_STATISTICS_WITHOUT_PAD + 0x3f) & ~0x3f) - FILE_SYSTEM_STATISTICS_WITHOUT_PAD];
609 
610 } FILE_SYSTEM_STATISTICS;
611 
612 typedef FILE_SYSTEM_STATISTICS *PFILE_SYSTEM_STATISTICS;
613 
614 
615 //
616 //  The Volume Device Object is an I/O system device object with a workqueue
617 //  and an VCB record appended to the end.  There are multiple of these
618 //  records, one for every mounted volume, and are created during
619 //  a volume mount operation.  The work queue is for handling an overload of
620 //  work requests to the volume.
621 //
622 
623 typedef struct _VOLUME_DEVICE_OBJECT {
624 
625     DEVICE_OBJECT DeviceObject;
626 
627     //
628     //  The following field tells how many requests for this volume have
629     //  either been enqueued to ExWorker threads or are currently being
630     //  serviced by ExWorker threads.  If the number goes above
631     //  a certain threshold, put the request on the overflow queue to be
632     //  executed later.
633     //
634 
635     ULONG PostedRequestCount;
636 
637     //
638     //  The following field indicates the number of IRP's waiting
639     //  to be serviced in the overflow queue.
640     //
641 
642     ULONG OverflowQueueCount;
643 
644     //
645     //  The following field contains the queue header of the overflow queue.
646     //  The Overflow queue is a list of IRP's linked via the IRP's ListEntry
647     //  field.
648     //
649 
650     LIST_ENTRY OverflowQueue;
651 
652     //
653     //  The following spinlock protects access to all the above fields.
654     //
655 
656     KSPIN_LOCK OverflowQueueSpinLock;
657 
658     //
659     //  This is a common head for the FAT volume file
660     //
661 
662     FSRTL_COMMON_FCB_HEADER VolumeFileHeader;
663 
664     //
665     //  This is the file system specific volume control block.
666     //
667 
668     VCB Vcb;
669 
670 } VOLUME_DEVICE_OBJECT;
671 
672 typedef VOLUME_DEVICE_OBJECT *PVOLUME_DEVICE_OBJECT;
673 
674 
675 //
676 //  This is the structure used to contains the short name for a file
677 //
678 
679 typedef struct _FILE_NAME_NODE {
680 
681     //
682     //  This points back to the Fcb for this file.
683     //
684 
685     struct _FCB *Fcb;
686 
687     //
688     //  This is the name of this node.
689     //
690 
691     union {
692 
693         OEM_STRING Oem;
694 
695         UNICODE_STRING Unicode;
696 
697     } Name;
698 
699     //
700     //  Marker so we can figure out what kind of name we opened up in
701     //  Fcb searches
702     //
703 
704     BOOLEAN FileNameDos;
705 
706     //
707     //  And the links.  Our parent Dcb has a pointer to the root entry.
708     //
709 
710     RTL_SPLAY_LINKS Links;
711 
712 } FILE_NAME_NODE;
713 typedef FILE_NAME_NODE *PFILE_NAME_NODE;
714 
715 //
716 //  This structure contains fields which must be in non-paged pool.
717 //
718 
719 typedef struct _NON_PAGED_FCB {
720 
721     //
722     //  The following field contains a record of special pointers used by
723     //  MM and Cache to manipluate section objects.  Note that the values
724     //  are set outside of the file system.  However the file system on an
725     //  open/create will set the file object's SectionObject field to point
726     //  to this field
727     //
728 
729     SECTION_OBJECT_POINTERS SectionObjectPointers;
730 
731     //
732     //  This context is non-zero only if the file currently has asynchronous
733     //  non-cached valid data length extending writes.  It allows
734     //  synchronization between pending writes and other operations.
735     //
736 
737     ULONG OutstandingAsyncWrites;
738 
739     //
740     //  This event is set when OutstandingAsyncWrites transitions to zero.
741     //
742 
743     PKEVENT OutstandingAsyncEvent;
744 
745     //
746     //  This is the mutex that is inserted into the FCB_ADVANCED_HEADER
747     //  FastMutex field
748     //
749 
750     FAST_MUTEX AdvancedFcbHeaderMutex;
751 
752 
753 } NON_PAGED_FCB;
754 
755 typedef NON_PAGED_FCB *PNON_PAGED_FCB;
756 
757 //
758 //  The Fcb/Dcb record corresponds to every open file and directory, and to
759 //  every directory on an opened path.  They are ordered in two queues, one
760 //  queue contains every Fcb/Dcb record off of FatData.FcbQueue, the other
761 //  queue contains only device specific records off of Vcb.VcbSpecificFcbQueue
762 //
763 
764 typedef enum _FCB_CONDITION {
765     FcbGood = 1,
766     FcbBad,
767     FcbNeedsToBeVerified
768 } FCB_CONDITION;
769 
770 typedef struct _FCB {
771 
772     //
773     //  The following field is used for fast I/O
774     //
775     //  The following comments refer to the use of the AllocationSize field
776     //  of the FsRtl-defined header to the nonpaged Fcb.
777     //
778     //  For a directory when we create a Dcb we will not immediately
779     //  initialize the cache map, instead we will postpone it until our first
780     //  call to FatReadDirectoryFile or FatPrepareWriteDirectoryFile.
781     //  At that time we will search the Fat to find out the current allocation
782     //  size (by calling FatLookupFileAllocationSize) and then initialize the
783     //  cache map to this allocation size.
784     //
785     //  For a file when we create an Fcb we will not immediately initialize
786     //  the cache map, instead we will postpone it until we need it and
787     //  then we determine the allocation size from either searching the
788     //  fat to determine the real file allocation, or from the allocation
789     //  that we've just allocated if we're creating a file.
790     //
791     //  A value of -1 indicates that we do not know what the current allocation
792     //  size really is, and need to examine the fat to find it.  A value
793     //  of than -1 is the real file/directory allocation size.
794     //
795     //  Whenever we need to extend the allocation size we call
796     //  FatAddFileAllocation which (if we're really extending the allocation)
797     //  will modify the Fat, Mcb, and update this field.  The caller
798     //  of FatAddFileAllocation is then responsible for altering the Cache
799     //  map size.
800     //
801     //  We are now using the ADVANCED fcb header to support filter contexts
802     //  at the stream level
803     //
804 
805     FSRTL_ADVANCED_FCB_HEADER Header;
806 
807     //
808     //  This structure contains fields which must be in non-paged pool.
809     //
810 
811     PNON_PAGED_FCB NonPaged;
812 
813     //
814     //  The head of the fat alloaction chain.  FirstClusterOfFile == 0
815     //  means that the file has no current allocation.
816     //
817 
818     ULONG FirstClusterOfFile;
819 
820 
821     //
822     //  The links for the queue of all fcbs for a specific dcb off of
823     //  Dcb.ParentDcbQueue.  For the root directory this queue is empty
824     //  For a non-existent fcb this queue is off of the non existent
825     //  fcb queue entry in the vcb.
826     //
827 
828     LIST_ENTRY ParentDcbLinks;
829 
830     //
831     //  A pointer to the Dcb that is the parent directory containing
832     //  this fcb.  If this record itself is the root dcb then this field
833     //  is null.
834     //
835 
836     struct _FCB *ParentDcb;
837 
838     //
839     //  A pointer to the Vcb containing this Fcb
840     //
841 
842     PVCB Vcb;
843 
844     //
845     //  The internal state of the Fcb.  This is a collection Fcb state flags.
846     //  Also the shared access for each time this file/directory is opened.
847     //
848 
849     ULONG FcbState;
850     FCB_CONDITION FcbCondition;
851     SHARE_ACCESS ShareAccess;
852 
853 #ifdef SYSCACHE_COMPILE
854 
855     //
856     //  For syscache we keep a bitmask that tells us if we have dispatched IO for
857     //  the page aligned chunks of the stream.
858     //
859 
860     PULONG WriteMask;
861     ULONG WriteMaskData;
862 
863 #endif
864 
865     //
866     //  A count of the number of file objects that have been opened for
867     //  this file/directory, but not yet been cleaned up yet.  This count
868     //  is only used for data file objects, not for the Acl or Ea stream
869     //  file objects.  This count gets decremented in FatCommonCleanup,
870     //  while the OpenCount below gets decremented in FatCommonClose.
871     //
872 
873     CLONG UncleanCount;
874 
875     //
876     //  A count of the number of file objects that have opened
877     //  this file/directory.  For files & directories the FsContext of the
878     //  file object points to this record.
879     //
880 
881     CLONG OpenCount;
882 
883     //
884     //  A count of how many of "UncleanCount" handles were opened for
885     //  non-cached I/O.
886     //
887 
888     CLONG NonCachedUncleanCount;
889 
890     //
891     //  A count of purge failure mode references. A non zero count means
892     //  purge failure mode is enabled. The count is synchronized by the
893     //  Fcb.
894     //
895 
896     CLONG PurgeFailureModeEnableCount;
897 
898     //
899     //  The following field is used to locate the dirent for this fcb/dcb.
900     //  All directory are opened as mapped files so the only additional
901     //  information we need to locate this dirent (beside its parent directory)
902     //  is the byte offset for the dirent.  Note that for the root dcb
903     //  this field is not used.
904     //
905 
906     VBO DirentOffsetWithinDirectory;
907 
908     //
909     //  The following field is filled in when there is an Lfn associated
910     //  with this file.  It is the STARTING offset of the Lfn.
911     //
912 
913     VBO LfnOffsetWithinDirectory;
914 
915     //
916     //  Thess entries is kept in ssync with the dirent.  It allows a more
917     //  accurate verify capability and speeds up FatFastQueryBasicInfo().
918     //
919 
920     LARGE_INTEGER CreationTime;
921     LARGE_INTEGER LastAccessTime;
922     LARGE_INTEGER LastWriteTime;
923 
924     //
925     //  Valid data to disk
926     //
927 
928     ULONG ValidDataToDisk;
929 
930     //
931     //  The following field contains the retrieval mapping structure
932     //  for the file/directory.  Note that for the Root Dcb this
933     //  structure is set at mount time.  Also note that in this
934     //  implementation of Fat the Mcb really maps VBOs to LBOs and not
935     //  VBNs to LBNs.
936     //
937 
938     LARGE_MCB Mcb;
939 
940     //
941     //  The following union is cased off of the node type code for the fcb.
942     //  There is a seperate case for the directory versus file fcbs.
943     //
944 
945     union {
946 
947         //
948         //  A Directory Control Block (Dcb)
949         //
950 
951         struct {
952 
953             //
954             //  A queue of all the fcbs/dcbs that are opened under this
955             //  Dcb.
956             //
957 
958             LIST_ENTRY ParentDcbQueue;
959 
960             //
961             //  The following field points to the file object used to do I/O to
962             //  the directory file for this dcb.  The directory file maps the
963             //  sectors for the directory.  This field is initialized by
964             //  CreateRootDcb but is left null by CreateDcb.  It isn't
965             //  until we try to read/write the directory file that we
966             //  create the stream file object for non root dcbs.
967             //
968 
969             __volatile ULONG DirectoryFileOpenCount;
970             PFILE_OBJECT DirectoryFile;
971 
972 
973             //
974             //  If the UnusedDirentVbo is != 0xffffffff, then the dirent at this
975             //  offset is guarenteed to unused.  A value of 0xffffffff means
976             //  it has yet to be initialized.  Note that a value beyond the
977             //  end of allocation means that there an unused dirent, but we
978             //  will have to allocate another cluster to use it.
979             //
980             //  DeletedDirentHint contains lowest possible VBO of a deleted
981             //  dirent (assuming as above that it is not 0xffffffff).
982             //
983 
984             VBO UnusedDirentVbo;
985             VBO DeletedDirentHint;
986 
987             //
988             //  The following two entries links together all the Fcbs
989             //  opened under this Dcb sorted in a splay tree by name.
990             //
991             //  I'd like to go into why we have (and must have) two separate
992             //  splay trees within the current fastfat architecture.  I will
993             //  provide some insight into what would have to change if we
994             //  wanted to have a single UNICODE tree.
995             //
996             //  What makes FAT unique is that both Oem and Unicode names sit
997             //  side by side on disk.  Several unique UNICODE names coming
998             //  into fastfat can match a single OEM on-disk name, and there
999             //  is really no way to enumerate all the possible UNICODE
1000             //  source strings that can map to a given OEM name.  This argues
1001             //  for converting the incomming UNICODE name into OEM, and then
1002             //  running through an OEM splay tree of the open files.  This
1003             //  works well when there are only OEM names on disk.
1004             //
1005             //  The UNICODE name on disk can be VERY different from the short
1006             //  name in the DIRENT and not even representable in the OEM code
1007             //  page.  Even if it were representable in OEM, it is possible
1008             //  that a case varient of the original UNICODE name would match
1009             //  a different OEM name, causing us to miss the Fcb in the
1010             //  prefix lookup phase.  In these cases, we must put UNICODE
1011             //  name in the splay to guarentee that we find any case varient
1012             //  of the input UNICODE name.  See the routine description of
1013             //  FatConstructNamesInFcb() for a detailed analysis of how we
1014             //  detect this case.
1015             //
1016             //  The fundamental limitation we are imposing here is that if
1017             //  an Fcb exists for an open file, we MUST find it during the
1018             //  prefix stage.  This is a basic premise of the create path
1019             //  in fastfat.  In fact if we later find it gravelling through
1020             //  the disk (but not the splay tree), we will bug check if we
1021             //  try to add a duplicate entry to the splay tree (not to
1022             //  mention having two Fcbs).  If we had some mechanism to deal
1023             //  with cases (and they would be rare) that we don't find the
1024             //  entry in the splay tree, but the Fcb is actually in there,
1025             //  then we could go to a single UNICODE splay tree.  While
1026             //  this uses more pool for the splay tree, and makes string
1027             //  compares maybe take a bit as longer, it would eliminate the
1028             //  need for any NLS conversion during the prefix phase, so it
1029             //  might really be a net win.
1030             //
1031             //  The current scheme was optimized for non-extended names
1032             //  (i.e. US names).  As soon as you start using extended
1033             //  characters, then it is clearly a win as many code paths
1034             //  become active that would otherwise not be needed if we
1035             //  only had a single UNICODE splay tree.
1036             //
1037             //  We may think about changing this someday.
1038             //
1039 
1040             PRTL_SPLAY_LINKS RootOemNode;
1041             PRTL_SPLAY_LINKS RootUnicodeNode;
1042 
1043             //
1044             //  The following field keeps track of free dirents, i.e.,
1045             //  dirents that are either unallocated for deleted.
1046             //
1047 
1048             RTL_BITMAP FreeDirentBitmap;
1049 
1050             //
1051             //  Since the FCB specific part of this union is larger, use
1052             //  the slack here for an initial bitmap buffer.  Currently
1053             //  there is enough space here for an 8K cluster.
1054             //
1055 
1056             ULONG FreeDirentBitmapBuffer[1];
1057 
1058         } Dcb;
1059 
1060         //
1061         //  A File Control Block (Fcb)
1062         //
1063 
1064         struct {
1065 
1066             //
1067             //  The following field is used by the filelock module
1068             //  to maintain current byte range locking information.
1069             //
1070 
1071             FILE_LOCK FileLock;
1072 
1073 #if (NTDDI_VERSION < NTDDI_WIN8)
1074             //
1075             //  The following field is used by the oplock module
1076             //  to maintain current oplock information.
1077             //
1078 
1079             OPLOCK Oplock;
1080 #endif
1081 
1082             //
1083             //  This pointer is used to detect writes that eminated in the
1084             //  cache manager's lazywriter.  It prevents lazy writer threads,
1085             //  who already have the Fcb shared, from trying to acquire it
1086             //  exclusive, and thus causing a deadlock.
1087             //
1088 
1089             PVOID LazyWriteThread;
1090 
1091 
1092         } Fcb;
1093 
1094     } Specific;
1095 
1096     //
1097     //  The following field is used to verify that the Ea's for a file
1098     //  have not changed between calls to query for Ea's.  It is compared
1099     //  with a similar field in a Ccb.
1100     //
1101     //  IMPORTANT!! **** DO NOT MOVE THIS FIELD ****
1102     //
1103     //              The slack space in the union above is computed from
1104     //              the field offset of the EaModificationCount.
1105     //
1106 
1107     ULONG EaModificationCount;
1108 
1109     //
1110     //  The following field is the fully qualified file name for this FCB/DCB
1111     //  starting from the root of the volume, and last file name in the
1112     //  fully qualified name.
1113     //
1114 
1115     FILE_NAME_NODE ShortName;
1116 
1117     //
1118     //  The following field is only filled in if it is needed with the user's
1119     //  opened path
1120     //
1121 
1122     UNICODE_STRING FullFileName;
1123 
1124     USHORT FinalNameLength;
1125 
1126     //
1127     //  To make life simpler we also keep in the Fcb/Dcb a current copy of
1128     //  the fat attribute byte for the file/directory.  This field must
1129     //  also be updated when we create the Fcb, modify the File, or verify
1130     //  the Fcb
1131     //
1132 
1133     UCHAR DirentFatFlags;
1134 
1135     //
1136     //  The case preserved long filename
1137     //
1138 
1139     UNICODE_STRING ExactCaseLongName;
1140 
1141     //
1142     //  If the UNICODE Lfn is fully expressible in the system Oem code
1143     //  page, then we will store it in a prefix table, otherwise we will
1144     //  store the last UNICODE name in the Fcb.  In both cases the name
1145     //  has been upcased.
1146     //
1147     //  Note that we may need neither of these fields if an LFN was strict
1148     //  8.3 or differed only in case.  Indeed if there wasn't an LFN, we
1149     //  don't need them at all.
1150     //
1151 
1152     union {
1153 
1154         //
1155         //  This first field is present if FCB_STATE_HAS_OEM_LONG_NAME
1156         //  is set in the FcbState.
1157         //
1158 
1159         FILE_NAME_NODE Oem;
1160 
1161         //
1162         //  This first field is present if FCB_STATE_HAS_UNICODE_LONG_NAME
1163         //  is set in the FcbState.
1164         //
1165 
1166         FILE_NAME_NODE Unicode;
1167 
1168     } LongName;
1169 
1170     //
1171     //  Defragmentation / ReallocateOnWrite synchronization object.  This
1172     //  is filled in by FatMoveFile() and affects the read and write paths.
1173     //
1174 
1175     PKEVENT MoveFileEvent;
1176 
1177 } FCB, *PFCB;
1178 
1179 #ifndef BUILDING_FSKDEXT
1180 //
1181 //  DCB clashes with a type defined outside the filesystems,  in headers
1182 //  pulled in by FSKD.  We don't need this typedef for fskd anyway....
1183 //
1184 typedef FCB DCB;
1185 typedef DCB *PDCB;
1186 #endif
1187 
1188 
1189 //
1190 //  Here are the Fcb state fields.
1191 //
1192 
1193 #define FCB_STATE_DELETE_ON_CLOSE        (0x00000001)
1194 #define FCB_STATE_TRUNCATE_ON_CLOSE      (0x00000002)
1195 #define FCB_STATE_PAGING_FILE            (0x00000004)
1196 #define FCB_STATE_FORCE_MISS_IN_PROGRESS (0x00000008)
1197 #define FCB_STATE_FLUSH_FAT              (0x00000010)
1198 #define FCB_STATE_TEMPORARY              (0x00000020)
1199 #define FCB_STATE_SYSTEM_FILE            (0x00000080)
1200 #define FCB_STATE_NAMES_IN_SPLAY_TREE    (0x00000100)
1201 #define FCB_STATE_HAS_OEM_LONG_NAME      (0x00000200)
1202 #define FCB_STATE_HAS_UNICODE_LONG_NAME  (0x00000400)
1203 #define FCB_STATE_DELAY_CLOSE            (0x00000800)
1204 
1205 //
1206 //  Copies of the dirent's FAT_DIRENT_NT_BYTE_* flags for
1207 //  preserving case of the short name of a file
1208 //
1209 
1210 #define FCB_STATE_8_LOWER_CASE           (0x00001000)
1211 #define FCB_STATE_3_LOWER_CASE           (0x00002000)
1212 
1213 //
1214 // indicates FSCTL_MOVE_FILE is denied on this FCB
1215 //
1216 
1217 #define FCB_STATE_DENY_DEFRAG            (0x00004000)
1218 
1219 
1220 //
1221 // Flag to indicate we should zero any deallocations from this file.
1222 //
1223 
1224 #define FCB_STATE_ZERO_ON_DEALLOCATION   (0x00080000)
1225 
1226 //
1227 //  This is the slack allocation in the Dcb part of the UNION above
1228 //
1229 
1230 #define DCB_UNION_SLACK_SPACE ((ULONG)                       \
1231     (FIELD_OFFSET(DCB, EaModificationCount) -                \
1232      FIELD_OFFSET(DCB, Specific.Dcb.FreeDirentBitmapBuffer)) \
1233 )
1234 
1235 //
1236 //  This is the special (64bit) allocation size that indicates the
1237 //  real size must be retrieved from disk.  Define it here so we
1238 //  avoid excessive magic numbering around the driver.
1239 //
1240 
1241 #define FCB_LOOKUP_ALLOCATIONSIZE_HINT   ((LONGLONG) -1)
1242 
1243 
1244 //
1245 //  The Ccb record is allocated for every file object.  Note that this
1246 //  record is exactly 0x34 long on x86 so that it will fit into a 0x40
1247 //  piece of pool.  Please carefully consider modifications.
1248 //
1249 //  Define the Flags field.
1250 //
1251 
1252 #define CCB_FLAG_MATCH_ALL               (0x0001)
1253 #define CCB_FLAG_SKIP_SHORT_NAME_COMPARE (0x0002)
1254 
1255 //
1256 //  This tells us whether we allocated buffers to hold search templates.
1257 //
1258 
1259 #define CCB_FLAG_FREE_OEM_BEST_FIT       (0x0004)
1260 #define CCB_FLAG_FREE_UNICODE            (0x0008)
1261 
1262 //
1263 //  These flags prevents cleanup from updating the modify time, etc.
1264 //
1265 
1266 #define CCB_FLAG_USER_SET_LAST_WRITE     (0x0010)
1267 #define CCB_FLAG_USER_SET_LAST_ACCESS    (0x0020)
1268 #define CCB_FLAG_USER_SET_CREATION       (0x0040)
1269 
1270 //
1271 //  This bit says the file object associated with this Ccb was opened for
1272 //  read only access.
1273 //
1274 
1275 #define CCB_FLAG_READ_ONLY               (0x0080)
1276 
1277 //
1278 //  These flags, are used is DASD handles in read and write.
1279 //
1280 
1281 #define CCB_FLAG_DASD_FLUSH_DONE         (0x0100)
1282 #define CCB_FLAG_DASD_PURGE_DONE         (0x0200)
1283 
1284 //
1285 //  This flag keeps track of a handle that was opened for
1286 //  DELETE_ON_CLOSE.
1287 //
1288 
1289 #define CCB_FLAG_DELETE_ON_CLOSE         (0x0400)
1290 
1291 //
1292 //  This flag keeps track of which side of the name pair on the file
1293 //  associated with the handle was opened
1294 //
1295 
1296 #define CCB_FLAG_OPENED_BY_SHORTNAME     (0x0800)
1297 
1298 //
1299 //  This flag indicates that the query template has not been upcased
1300 // (i.e., query should be case-insensitive)
1301 //
1302 
1303 #define CCB_FLAG_QUERY_TEMPLATE_MIXED    (0x1000)
1304 
1305 //
1306 //  This flag indicates that reads and writes via this DASD handle
1307 //  are allowed to start or extend past the end of file.
1308 //
1309 
1310 #define CCB_FLAG_ALLOW_EXTENDED_DASD_IO  (0x2000)
1311 
1312 //
1313 //  This flag indicates we want to match volume labels in directory
1314 //  searches (important for the root dir defrag).
1315 //
1316 
1317 #define CCB_FLAG_MATCH_VOLUME_ID         (0x4000)
1318 
1319 //
1320 //  This flag indicates the ccb has been converted over into a
1321 //  close context for asynchronous/delayed closing of the handle.
1322 //
1323 
1324 #define CCB_FLAG_CLOSE_CONTEXT           (0x8000)
1325 
1326 //
1327 //  This flag indicates that when the handle is closed, we want
1328 //  a physical dismount to occur.
1329 //
1330 
1331 #define CCB_FLAG_COMPLETE_DISMOUNT       (0x10000)
1332 
1333 //
1334 //  This flag indicates the handle may not call priveleged
1335 //  FSCTL which modify the volume.
1336 //
1337 
1338 #define CCB_FLAG_MANAGE_VOLUME_ACCESS    (0x20000)
1339 
1340 //
1341 //  This flag indicates that a format unit commmand was issued
1342 //  on this handle and all subsequent writes need to ignore verify.
1343 //
1344 
1345 #define CCB_FLAG_SENT_FORMAT_UNIT        (0x40000)
1346 
1347 //
1348 //  This flag indicates that this CCB was the one that marked the
1349 //  handle as non-movable.
1350 //
1351 
1352 #define CCB_FLAG_DENY_DEFRAG             (0x80000)
1353 
1354 //
1355 //  This flag indicates that this CCB wrote to the file.
1356 //
1357 
1358 #define CCB_FLAG_FIRST_WRITE_SEEN       (0x100000)
1359 
1360 typedef struct _CCB {
1361 
1362     //
1363     //  Type and size of this record (must be FAT_NTC_CCB)
1364     //
1365 
1366     NODE_TYPE_CODE NodeTypeCode;
1367     NODE_BYTE_SIZE NodeByteSize;
1368 
1369     //
1370     //  Define a 24bit wide field for Flags, but a UCHAR for Wild Cards Present
1371     //  since it is used so often.  Line these up on byte boundaries for grins.
1372     //
1373 #ifdef __REACTOS__
1374     ULONG Flags; // Due to https://developercommunity.visualstudio.com/t/Broken-runtime-checks-with-CL-19293013/1503629
1375     // Note: the following BOOLEAN will not be packed anyway!
1376 #else
1377     ULONG Flags:24;
1378 #endif
1379     BOOLEAN ContainsWildCards;
1380 
1381     //
1382     //  Pointer to EDP context.
1383     //
1384 
1385     PVOID EncryptionOnCloseContext;
1386 
1387     //
1388     //  Overlay a close context on the data of the CCB.  The remaining
1389     //  fields are not useful during close, and we would like to avoid
1390     //  paying extra pool for it.
1391     //
1392 
1393     union {
1394 
1395         struct {
1396 
1397             //
1398             //  Save the offset to start search from.
1399             //
1400 
1401             VBO OffsetToStartSearchFrom;
1402 
1403             //
1404             //  The query template is used to filter directory query requests.
1405             //  It originally is set to null and on the first call the NtQueryDirectory
1406             //  it is set to the input filename or "*" if the name is not supplied.
1407             //  All subsquent queries then use this template.
1408             //
1409             //  The Oem structure are unions because if the name is wild we store
1410             //  the arbitrary length string, while if the name is constant we store
1411             //  8.3 representation for fast comparison.
1412             //
1413 
1414             union {
1415 
1416                 //
1417                 //  If the template contains a wild card use this.
1418                 //
1419 
1420                 OEM_STRING Wild;
1421 
1422                 //
1423                 //  If the name is constant, use this part.
1424                 //
1425 
1426                 FAT8DOT3 Constant;
1427 
1428             } OemQueryTemplate;
1429 
1430             UNICODE_STRING UnicodeQueryTemplate;
1431 
1432             //
1433             //  The field is compared with the similar field in the Fcb to determine
1434             //  if the Ea's for a file have been modified.
1435             //
1436 
1437             ULONG EaModificationCount;
1438 
1439             //
1440             //  The following field is used as an offset into the Eas for a
1441             //  particular file.  This will be the offset for the next
1442             //  Ea to return.  A value of 0xffffffff indicates that the
1443             //  Ea's are exhausted.
1444             //
1445 
1446             ULONG OffsetOfNextEaToReturn;
1447 
1448         };
1449 
1450         CLOSE_CONTEXT CloseContext;
1451     };
1452 
1453 } CCB;
1454 typedef CCB *PCCB;
1455 
1456 //
1457 //  The Irp Context record is allocated for every orginating Irp.  It is
1458 //  created by the Fsd dispatch routines, and deallocated by the FatComplete
1459 //  request routine.  It contains a structure called of type REPINNED_BCBS
1460 //  which is used to retain pinned bcbs needed to handle abnormal termination
1461 //  unwinding.
1462 //
1463 
1464 #define REPINNED_BCBS_ARRAY_SIZE         (4)
1465 
1466 typedef struct _REPINNED_BCBS {
1467 
1468     //
1469     //  A pointer to the next structure contains additional repinned bcbs
1470     //
1471 
1472     struct _REPINNED_BCBS *Next;
1473 
1474     //
1475     //  A fixed size array of pinned bcbs.  Whenever a new bcb is added to
1476     //  the repinned bcb structure it is added to this array.  If the
1477     //  array is already full then another repinned bcb structure is allocated
1478     //  and pointed to with Next.
1479     //
1480 
1481     PBCB Bcb[ REPINNED_BCBS_ARRAY_SIZE ];
1482 
1483 } REPINNED_BCBS;
1484 typedef REPINNED_BCBS *PREPINNED_BCBS;
1485 
1486 typedef struct _IRP_CONTEXT {
1487 
1488     //
1489     //  Type and size of this record (must be FAT_NTC_IRP_CONTEXT)
1490     //
1491 
1492     NODE_TYPE_CODE NodeTypeCode;
1493     NODE_BYTE_SIZE NodeByteSize;
1494 
1495     //
1496     //  This structure is used for posting to the Ex worker threads.
1497     //
1498 
1499     WORK_QUEUE_ITEM WorkQueueItem;
1500 
1501     //
1502     //  A pointer to the originating Irp.
1503     //
1504 
1505     PIRP OriginatingIrp;
1506 
1507     //
1508     //  Originating Device (required for workque algorithms)
1509     //
1510 
1511     PDEVICE_OBJECT RealDevice;
1512 
1513     //
1514     //  Originating Vcb (required for exception handling)
1515     //  On mounts, this will be set before any exceptions
1516     //  indicating corruption can be thrown.
1517     //
1518 
1519     PVCB Vcb;
1520 
1521     //
1522     //  Major and minor function codes copied from the Irp
1523     //
1524 
1525     UCHAR MajorFunction;
1526     UCHAR MinorFunction;
1527 
1528     //
1529     //  The following fields indicate if we can wait/block for a resource
1530     //  or I/O, if we are to do everything write through, and if this
1531     //  entry into the Fsd is a recursive call.
1532     //
1533 
1534     UCHAR PinCount;
1535 
1536     ULONG Flags;
1537 
1538     //
1539     //  The following field contains the NTSTATUS value used when we are
1540     //  unwinding due to an exception
1541     //
1542 
1543     NTSTATUS ExceptionStatus;
1544 
1545     //
1546     //  The following context block is used for non-cached Io
1547     //
1548 
1549     struct _FAT_IO_CONTEXT *FatIoContext;
1550 
1551     //
1552     //  For a abnormal termination unwinding this field contains the Bcbs
1553     //  that are kept pinned until the Irp is completed.
1554     //
1555 
1556     REPINNED_BCBS Repinned;
1557 
1558 
1559 } IRP_CONTEXT;
1560 typedef IRP_CONTEXT *PIRP_CONTEXT;
1561 
1562 #define IRP_CONTEXT_FLAG_DISABLE_DIRTY              (0x00000001)
1563 #define IRP_CONTEXT_FLAG_WAIT                       (0x00000002)
1564 #define IRP_CONTEXT_FLAG_WRITE_THROUGH              (0x00000004)
1565 #define IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH      (0x00000008)
1566 #define IRP_CONTEXT_FLAG_RECURSIVE_CALL             (0x00000010)
1567 #define IRP_CONTEXT_FLAG_DISABLE_POPUPS             (0x00000020)
1568 #define IRP_CONTEXT_FLAG_DEFERRED_WRITE             (0x00000040)
1569 #define IRP_CONTEXT_FLAG_VERIFY_READ                (0x00000080)
1570 #define IRP_CONTEXT_STACK_IO_CONTEXT                (0x00000100)
1571 #define IRP_CONTEXT_FLAG_IN_FSP                     (0x00000200)
1572 #define IRP_CONTEXT_FLAG_USER_IO                    (0x00000400)       // for performance counters
1573 #define IRP_CONTEXT_FLAG_DISABLE_RAISE              (0x00000800)
1574 #define IRP_CONTEXT_FLAG_OVERRIDE_VERIFY            (0x00001000)
1575 #define IRP_CONTEXT_FLAG_CLEANUP_BREAKING_OPLOCK    (0x00002000)
1576 
1577 
1578 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1579 #define IRP_CONTEXT_FLAG_SWAPPED_STACK              (0x00100000)
1580 #endif
1581 
1582 #define IRP_CONTEXT_FLAG_PARENT_BY_CHILD            (0x80000000)
1583 
1584 
1585 //
1586 //  Context structure for non-cached I/O calls.  Most of these fields
1587 //  are actually only required for the Read/Write Multiple routines, but
1588 //  the caller must allocate one as a local variable anyway before knowing
1589 //  whether there are multiple requests are not.  Therefore, a single
1590 //  structure is used for simplicity.
1591 //
1592 
1593 typedef struct _FAT_IO_CONTEXT {
1594 
1595     //
1596     //  A copy of the IrpContext flags preserved for use in
1597     //  async I/O completion.
1598     //
1599 
1600     ULONG IrpContextFlags;
1601 
1602     //
1603     //  These two field are used for multiple run Io
1604     //
1605 
1606     __volatile LONG IrpCount;
1607     PIRP MasterIrp;
1608 
1609     //
1610     //  MDL to describe partial sector zeroing
1611     //
1612 
1613     PMDL ZeroMdl;
1614 
1615     union {
1616 
1617         //
1618         //  This element handles the asychronous non-cached Io
1619         //
1620 
1621         struct {
1622             PERESOURCE Resource;
1623             PERESOURCE Resource2;
1624             ERESOURCE_THREAD ResourceThreadId;
1625             ULONG RequestedByteCount;
1626             PFILE_OBJECT FileObject;
1627             PNON_PAGED_FCB NonPagedFcb;
1628         } Async;
1629 
1630         //
1631         //  and this element the sycnrhonous non-cached Io
1632         //
1633 
1634         KEVENT SyncEvent;
1635 
1636     } Wait;
1637 
1638 
1639 } FAT_IO_CONTEXT;
1640 
1641 typedef FAT_IO_CONTEXT *PFAT_IO_CONTEXT;
1642 
1643 //
1644 //  An array of these structures is passed to FatMultipleAsync describing
1645 //  a set of runs to execute in parallel.
1646 //
1647 
1648 typedef struct _IO_RUNS {
1649 
1650     LBO Lbo;
1651     VBO Vbo;
1652     ULONG Offset;
1653     ULONG ByteCount;
1654     PIRP SavedIrp;
1655 
1656 } IO_RUN;
1657 
1658 typedef IO_RUN *PIO_RUN;
1659 
1660 //
1661 //  This structure is used by FatDeleteDirent to preserve the first cluster
1662 //  and file size info for undelete utilities.
1663 //
1664 
1665 typedef struct _DELETE_CONTEXT {
1666 
1667     ULONG FileSize;
1668     ULONG FirstClusterOfFile;
1669 
1670 } DELETE_CONTEXT;
1671 
1672 typedef DELETE_CONTEXT *PDELETE_CONTEXT;
1673 
1674 //
1675 //  This record is used with to set a flush to go off one second after the
1676 //  first write on slow devices with a physical indication of activity, like
1677 //  a floppy.  This is an attempt to keep the red light on.
1678 //
1679 
1680 typedef struct _DEFERRED_FLUSH_CONTEXT {
1681 
1682     KDPC Dpc;
1683     KTIMER Timer;
1684     WORK_QUEUE_ITEM Item;
1685 
1686     PFILE_OBJECT File;
1687 
1688 } DEFERRED_FLUSH_CONTEXT;
1689 
1690 typedef DEFERRED_FLUSH_CONTEXT *PDEFERRED_FLUSH_CONTEXT;
1691 
1692 //
1693 //  This structure is used for the FatMarkVolumeClean callbacks.
1694 //
1695 
1696 typedef struct _CLEAN_AND_DIRTY_VOLUME_PACKET {
1697 
1698     WORK_QUEUE_ITEM Item;
1699     PIRP Irp;
1700     PVCB Vcb;
1701     PKEVENT Event;
1702 } CLEAN_AND_DIRTY_VOLUME_PACKET, *PCLEAN_AND_DIRTY_VOLUME_PACKET;
1703 
1704 //
1705 //  This structure is used when a page fault is running out of stack.
1706 //
1707 
1708 typedef struct _PAGING_FILE_OVERFLOW_PACKET {
1709     PIRP Irp;
1710     PFCB Fcb;
1711 } PAGING_FILE_OVERFLOW_PACKET, *PPAGING_FILE_OVERFLOW_PACKET;
1712 
1713 //
1714 //  This structure is used to access the EaFile.
1715 //
1716 
1717 #define EA_BCB_ARRAY_SIZE                   8
1718 
1719 typedef struct _EA_RANGE {
1720 
1721     PCHAR Data;
1722     ULONG StartingVbo;
1723     ULONG Length;
1724     USHORT BcbChainLength;
1725     BOOLEAN AuxilaryBuffer;
1726     PBCB *BcbChain;
1727     PBCB BcbArray[EA_BCB_ARRAY_SIZE];
1728 
1729 } EA_RANGE, *PEA_RANGE;
1730 
1731 #define EA_RANGE_HEADER_SIZE        (FIELD_OFFSET( EA_RANGE, BcbArray ))
1732 
1733 //
1734 //  These symbols are used by the upcase/downcase routines.
1735 //
1736 
1737 #define WIDE_LATIN_CAPITAL_A    (0xff21)
1738 #define WIDE_LATIN_CAPITAL_Z    (0xff3a)
1739 #define WIDE_LATIN_SMALL_A      (0xff41)
1740 #define WIDE_LATIN_SMALL_Z      (0xff5a)
1741 
1742 //
1743 //  These values are returned by FatInterpretClusterType.
1744 //
1745 
1746 typedef enum _CLUSTER_TYPE {
1747     FatClusterAvailable,
1748     FatClusterReserved,
1749     FatClusterBad,
1750     FatClusterLast,
1751     FatClusterNext
1752 } CLUSTER_TYPE;
1753 
1754 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
1755 // ============================================================================
1756 // ============================================================================
1757 //
1758 //                      Stack Swapping Support
1759 //
1760 // ============================================================================
1761 // ============================================================================
1762 
1763 //
1764 //  This structure is used when doing a callout on a new stack.
1765 //  It contains the parameters for various functions and a place
1766 //  to store the return code.
1767 //
1768 
1769 typedef struct _FAT_CALLOUT_PARAMETERS {
1770 
1771     union {
1772 
1773         //
1774         //  Parameters for a create request via FatCommonCreate().
1775         //
1776 
1777         struct {
1778 
1779             PIRP_CONTEXT IrpContext;
1780             PIRP Irp;
1781 
1782         } Create;
1783 
1784     };
1785 
1786     NTSTATUS IrpStatus;
1787     NTSTATUS ExceptionStatus;
1788 
1789 } FAT_CALLOUT_PARAMETERS, *PFAT_CALLOUT_PARAMETERS;
1790 #endif
1791 
1792 #endif // _FATSTRUC_
1793 
1794 
1795