1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     FatProcs.h
8 
9 Abstract:
10 
11     This module defines all of the globally used procedures in the FAT
12     file system.
13 
14 
15 --*/
16 
17 #ifndef _FATPROCS_
18 #define _FATPROCS_
19 
20 #ifdef _MSC_VER
21 #pragma warning( disable: 4127 ) // conditional expression is constant
22 
23 #pragma warning( push )
24 #pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union
25 #pragma warning( disable: 4214 ) // nonstandard extension used : bit field types
26 #endif
27 
28 #include <ntifs.h>
29 
30 
31 #include <ntddscsi.h>
32 #include <scsi.h>
33 #include <ntddcdrm.h>
34 #include <ntdddisk.h>
35 #include <ntddstor.h>
36 #include <ntintsafe.h>
37 #ifdef __REACTOS__
38 #include <pseh/pseh2.h>
39 #include <dbgbitmap.h>
40 #endif
41 
42 
43 #ifdef __REACTOS__
44 // Downgrade unsupported NT6.2+ features.
45 #undef MdlMappingNoExecute
46 #define MdlMappingNoExecute 0
47 #define NonPagedPoolNx NonPagedPool
48 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
49 #undef POOL_NX_ALLOCATION
50 #define POOL_NX_ALLOCATION 0
51 
52 // Moved up: needed in 'fatstruc.h'.
53 typedef enum _TYPE_OF_OPEN {
54 
55     UnopenedFileObject = 1,
56     UserFileOpen,
57     UserDirectoryOpen,
58     UserVolumeOpen,
59     VirtualVolumeFile,
60     DirectoryFile,
61     EaFile,
62 } TYPE_OF_OPEN;
63 #endif
64 
65 #include "nodetype.h"
66 #include "fat.h"
67 #include "lfn.h"
68 #include "fatstruc.h"
69 #include "fatdata.h"
70 
71 
72 
73 #ifdef _MSC_VER
74 #pragma warning( pop )
75 #endif
76 
77 #ifndef INLINE
78 #define INLINE __inline
79 #endif
80 
81 #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
82 
83 #ifndef MAX_ULONG
84 #define MAX_ULONG ((ULONG)-1)
85 #endif
86 
87 #ifndef MAX_USHORT
88 #define MAX_USHORT ((USHORT)-1)
89 #endif
90 
91 //
92 //  We must explicitly tag our allocations.
93 //
94 
95 #undef FsRtlAllocatePool
96 #undef FsRtlAllocatePoolWithQuota
97 
98 //
99 //  A function that returns finished denotes if it was able to complete the
100 //  operation (TRUE) or could not complete the operation (FALSE) because the
101 //  wait value stored in the irp context was false and we would have had
102 //  to block for a resource or I/O
103 //
104 
105 typedef BOOLEAN FINISHED;
106 
107 //
108 //  Size (characters) of stack allocated name component buffers in
109 //  the create/rename paths.
110 //
111 
112 #define FAT_CREATE_INITIAL_NAME_BUF_SIZE    32
113 
114 
115 //
116 //  Some string buffer handling functions,  implemented in strucsup.c
117 //
118 
119 VOID
120 FatFreeStringBuffer (
121     _Inout_ PVOID String
122     );
123 
124 VOID
125 FatExtendString(
126     _Inout_ PVOID String,
127     _In_ USHORT DesiredBufferSize,
128     _In_ BOOLEAN FreeOldBuffer,
129     __out_opt PBOOLEAN NeedsFree
130     );
131 
132 VOID
133 FatEnsureStringBufferEnough (
134     _Inout_ PVOID String,
135     _In_ USHORT DesiredBufferSize
136     );
137 
138 BOOLEAN
139 FatAddMcbEntry (
140     IN PVCB Vcb,
141     IN PLARGE_MCB Mcb,
142     IN VBO Vbo,
143     IN LBO Lbo,
144     IN ULONG SectorCount
145     );
146 
147 BOOLEAN
148 FatLookupMcbEntry (
149     IN PVCB Vcb,
150     IN PLARGE_MCB Mcb,
151     IN VBO Vbo,
152     OUT PLBO Lbo,
153     OUT PULONG ByteCount OPTIONAL,
154     OUT PULONG Index OPTIONAL
155     );
156 
157 BOOLEAN
158 FatLookupLastMcbEntry (
159     IN PVCB Vcb,
160     IN PLARGE_MCB Mcb,
161     OUT PVBO Vbo,
162     OUT PLBO Lbo,
163     OUT PULONG Index OPTIONAL
164     );
165 
166 BOOLEAN
167 FatGetNextMcbEntry (
168     IN PVCB Vcb,
169     IN PLARGE_MCB Mcb,
170     IN ULONG RunIndex,
171     OUT PVBO Vbo,
172     OUT PLBO Lbo,
173     OUT PULONG ByteCount
174     );
175 
176 VOID
177 FatRemoveMcbEntry (
178     IN PVCB Vcb,
179     IN PLARGE_MCB Mcb,
180     IN VBO Vbo,
181     IN ULONG SectorCount
182     );
183 
184 
185 //
186 //  File access check routine, implemented in AcChkSup.c
187 //
188 
189 BOOLEAN
190 FatCheckFileAccess (
191     PIRP_CONTEXT IrpContext,
192     IN UCHAR DirentAttributes,
193     IN PACCESS_MASK DesiredAccess
194     );
195 
196 BOOLEAN
197 FatCheckManageVolumeAccess (
198     _In_ PIRP_CONTEXT IrpContext,
199     _In_ PACCESS_STATE AccessState,
200     _In_ KPROCESSOR_MODE ProcessorMode
201     );
202 
203 NTSTATUS
204 FatExplicitDeviceAccessGranted (
205     IN PIRP_CONTEXT IrpContext,
206     IN PDEVICE_OBJECT DeviceObject,
207     IN PACCESS_STATE AccessState,
208     IN KPROCESSOR_MODE ProcessorMode
209     );
210 
211 
212 //
213 //  Allocation support routines, implemented in AllocSup.c
214 //
215 
216 static
217 INLINE
218 BOOLEAN
FatIsIoRangeValid(IN PVCB Vcb,IN LARGE_INTEGER Start,IN ULONG Length)219 FatIsIoRangeValid (
220     IN PVCB Vcb,
221     IN LARGE_INTEGER Start,
222     IN ULONG Length
223     )
224 
225 /*++
226 
227 Routine Description:
228 
229     This routine enforces the restriction that object space must be
230     representable in 32 bits.
231 
232 Arguments:
233 
234     Vcb - the volume the range is on
235 
236     Start - starting byte (zero based) of the range
237 
238     Length - size of the range
239 
240     HeaderSize - if the file has a header
241 
242 Return Value:
243 
244     BOOLEAN - if, considering the cluster size, the neccesary size of
245         the object to contain the range can be represented in 32 bits.
246 
247 --*/
248 
249 {
250 
251     UNREFERENCED_PARAMETER( Vcb );
252 
253     //
254     //  The only restriction on a FAT object is that the filesize must
255     //  fit in 32bits, i.e. <= 0xffffffff. This then implies that the
256     //  range of valid byte offsets is [0, fffffffe].
257     //
258     //  Two phases which check for illegality
259     //
260     //      - if the high 32bits are nonzero
261     //      - if the length would cause a 32bit overflow
262     //
263 
264     return !(Start.HighPart ||
265              Start.LowPart + Length < Start.LowPart);
266 }
267 
268 
269 //
270 //  This strucure is used by FatLookupFatEntry to remember a pinned page
271 //  of fat.
272 //
273 
274 typedef struct _FAT_ENUMERATION_CONTEXT {
275 
276     VBO VboOfPinnedPage;
277     PBCB Bcb;
278     PVOID PinnedPage;
279 
280 } FAT_ENUMERATION_CONTEXT, *PFAT_ENUMERATION_CONTEXT;
281 
282 VOID
283 FatLookupFatEntry (
284     IN PIRP_CONTEXT IrpContext,
285     IN PVCB Vcb,
286     IN ULONG FatIndex,
287     IN OUT PULONG FatEntry,
288     IN OUT PFAT_ENUMERATION_CONTEXT Context
289     );
290 
291 VOID
292 FatSetupAllocationSupport (
293     IN PIRP_CONTEXT IrpContext,
294     IN PVCB Vcb
295     );
296 
297 VOID
298 FatTearDownAllocationSupport (
299     IN PIRP_CONTEXT IrpContext,
300     IN PVCB Vcb
301     );
302 
303 _Requires_lock_held_(_Global_critical_region_)
304 VOID
305 FatLookupFileAllocation (
306     IN PIRP_CONTEXT IrpContext,
307     IN PFCB FcbOrDcb,
308     IN VBO Vbo,
309     OUT PLBO Lbo,
310     OUT PULONG ByteCount,
311     OUT PBOOLEAN Allocated,
312     OUT PBOOLEAN EndOnMax,
313     OUT PULONG Index OPTIONAL
314     );
315 
316 _Requires_lock_held_(_Global_critical_region_)
317 VOID
318 FatAddFileAllocation (
319     IN PIRP_CONTEXT IrpContext,
320     IN PFCB FcbOrDcb,
321     IN PFILE_OBJECT FileObject OPTIONAL,
322     IN ULONG AllocationSize
323     );
324 
325 _Requires_lock_held_(_Global_critical_region_)
326 VOID
327 FatTruncateFileAllocation (
328     IN PIRP_CONTEXT IrpContext,
329     IN PFCB FcbOrDcb,
330     IN ULONG AllocationSize
331     );
332 
333 _Requires_lock_held_(_Global_critical_region_)
334 VOID
335 FatLookupFileAllocationSize (
336     IN PIRP_CONTEXT IrpContext,
337     IN PFCB FcbOrDcb
338     );
339 
340 _Requires_lock_held_(_Global_critical_region_)
341 VOID
342 FatAllocateDiskSpace (
343     IN PIRP_CONTEXT IrpContext,
344     IN PVCB Vcb,
345     IN ULONG AbsoluteClusterHint,
346     IN OUT PULONG ByteCount,
347     IN BOOLEAN ExactMatchRequired,
348     OUT PLARGE_MCB Mcb
349     );
350 
351 _Requires_lock_held_(_Global_critical_region_)
352 VOID
353 FatDeallocateDiskSpace (
354     IN PIRP_CONTEXT IrpContext,
355     IN PVCB Vcb,
356     IN PLARGE_MCB Mcb,
357     IN BOOLEAN ZeroOnDeallocate
358     );
359 
360 _Requires_lock_held_(_Global_critical_region_)
361 VOID
362 FatSplitAllocation (
363     IN PIRP_CONTEXT IrpContext,
364     IN PVCB Vcb,
365     IN OUT PLARGE_MCB Mcb,
366     IN VBO SplitAtVbo,
367     OUT PLARGE_MCB RemainingMcb
368     );
369 
370 _Requires_lock_held_(_Global_critical_region_)
371 VOID
372 FatMergeAllocation (
373     IN PIRP_CONTEXT IrpContext,
374     IN PVCB Vcb,
375     IN OUT PLARGE_MCB Mcb,
376     IN PLARGE_MCB SecondMcb
377     );
378 
379 _Requires_lock_held_(_Global_critical_region_)
380 VOID
381 FatSetFatEntry (
382     IN PIRP_CONTEXT IrpContext,
383     IN PVCB Vcb,
384     IN ULONG FatIndex,
385     IN FAT_ENTRY FatEntry
386     );
387 
388 UCHAR
389 FatLogOf(
390     IN ULONG Value
391     );
392 
393 
394 //
395 //   Buffer control routines for data caching, implemented in CacheSup.c
396 //
397 
398 VOID
399 FatReadVolumeFile (
400     IN PIRP_CONTEXT IrpContext,
401     IN PVCB Vcb,
402     IN VBO StartingVbo,
403     IN ULONG ByteCount,
404     OUT PBCB *Bcb,
405     OUT PVOID *Buffer
406     );
407 
408 _Requires_lock_held_(_Global_critical_region_)
409 VOID
410 FatPrepareWriteVolumeFile (
411     IN PIRP_CONTEXT IrpContext,
412     IN PVCB Vcb,
413     IN VBO StartingVbo,
414     IN ULONG ByteCount,
415     OUT PBCB *Bcb,
416     OUT PVOID *Buffer,
417     IN BOOLEAN Reversible,
418     IN BOOLEAN Zero
419     );
420 
421 _Requires_lock_held_(_Global_critical_region_)
422 VOID
423 FatReadDirectoryFile (
424     IN PIRP_CONTEXT IrpContext,
425     IN PDCB Dcb,
426     IN VBO StartingVbo,
427     IN ULONG ByteCount,
428     IN BOOLEAN Pin,
429     OUT PBCB *Bcb,
430     OUT PVOID *Buffer,
431     OUT PNTSTATUS Status
432     );
433 
434 _Requires_lock_held_(_Global_critical_region_)
435 VOID
436 FatPrepareWriteDirectoryFile (
437     IN PIRP_CONTEXT IrpContext,
438     IN PDCB Dcb,
439     IN VBO StartingVbo,
440     IN ULONG ByteCount,
441     OUT PBCB *Bcb,
442     OUT PVOID *Buffer,
443     IN BOOLEAN Zero,
444     IN BOOLEAN Reversible,
445     OUT PNTSTATUS Status
446     );
447 
448 _Requires_lock_held_(_Global_critical_region_)
449 VOID
450 FatOpenDirectoryFile (
451     IN PIRP_CONTEXT IrpContext,
452     IN PDCB Dcb
453     );
454 
455 PFILE_OBJECT
456 FatOpenEaFile (
457     IN PIRP_CONTEXT IrpContext,
458     IN PFCB EaFcb
459     );
460 
461 VOID
462 FatCloseEaFile (
463     IN PIRP_CONTEXT IrpContext,
464     IN PVCB Vcb,
465     IN BOOLEAN FlushFirst
466     );
467 
468 
469 _Requires_lock_held_(_Global_critical_region_)
470 VOID
471 FatSetDirtyBcb (
472     IN PIRP_CONTEXT IrpContext,
473     IN PBCB Bcb,
474     IN PVCB Vcb OPTIONAL,
475     IN BOOLEAN Reversible
476     );
477 
478 VOID
479 FatRepinBcb (
480     IN PIRP_CONTEXT IrpContext,
481     IN PBCB Bcb
482     );
483 
484 VOID
485 FatUnpinRepinnedBcbs (
486     IN PIRP_CONTEXT IrpContext
487     );
488 
489 FINISHED
490 FatZeroData (
491     IN PIRP_CONTEXT IrpContext,
492     IN PVCB Vcb,
493     IN PFILE_OBJECT FileObject,
494     IN ULONG StartingZero,
495     IN ULONG ByteCount
496     );
497 
498 NTSTATUS
499 FatCompleteMdl (
500     IN PIRP_CONTEXT IrpContext,
501     IN PIRP Irp
502     );
503 
504 VOID
505 FatPinMappedData (
506     IN PIRP_CONTEXT IrpContext,
507     IN PDCB Dcb,
508     IN VBO StartingVbo,
509     IN ULONG ByteCount,
510     OUT PBCB *Bcb
511     );
512 
513 NTSTATUS
514 FatPrefetchPages (
515     IN PIRP_CONTEXT IrpContext,
516     IN PFILE_OBJECT FileObject,
517     IN ULONG StartingPage,
518     IN ULONG PageCount
519     );
520 
521 //
522 // VOID
523 // FatUnpinBcb (
524 //     IN PIRP_CONTEXT IrpContext,
525 //     IN OUT PBCB Bcb,
526 //     );
527 //
528 
529 //
530 //  This macro unpins a Bcb, in the checked build make sure all
531 //  requests unpin all Bcbs before leaving.
532 //
533 
534 #if DBG
535 
536 #define FatUnpinBcb(IRPCONTEXT,BCB) {       \
537     if ((BCB) != NULL) {                    \
538         CcUnpinData((BCB));                 \
539         NT_ASSERT( (IRPCONTEXT)->PinCount );\
540         (IRPCONTEXT)->PinCount -= 1;        \
541         (BCB) = NULL;                       \
542     }                                       \
543 }
544 
545 #else
546 
547 #define FatUnpinBcb(IRPCONTEXT,BCB) { \
548     if ((BCB) != NULL) {              \
549         CcUnpinData((BCB));           \
550         (BCB) = NULL;                 \
551     }                                 \
552 }
553 
554 #endif // DBG
555 
556 VOID
557 FatInitializeCacheMap (
558     _In_ PFILE_OBJECT FileObject,
559     _In_ PCC_FILE_SIZES FileSizes,
560     _In_ BOOLEAN PinAccess,
561     _In_ PCACHE_MANAGER_CALLBACKS Callbacks,
562     _In_ PVOID LazyWriteContext
563     );
564 
565 VOID
566 FatSyncUninitializeCacheMap (
567     IN PIRP_CONTEXT IrpContext,
568     IN PFILE_OBJECT FileObject
569     );
570 
571 
572 //
573 //  Device I/O routines, implemented in DevIoSup.c
574 //
575 //  These routines perform the actual device read and writes.  They only affect
576 //  the on disk structure and do not alter any other data structures.
577 //
578 
579 VOID
580 FatPagingFileIo (
581     IN PIRP Irp,
582     IN PFCB Fcb
583     );
584 
585 
586 _Requires_lock_held_(_Global_critical_region_)
587 NTSTATUS
588 FatNonCachedIo (
589     IN PIRP_CONTEXT IrpContext,
590     IN PIRP Irp,
591     IN PFCB FcbOrDcb,
592     IN ULONG StartingVbo,
593     IN ULONG ByteCount,
594     IN ULONG UserByteCount,
595     IN ULONG StreamFlags
596     );
597 
598 _Requires_lock_held_(_Global_critical_region_)
599 VOID
600 FatNonCachedNonAlignedRead (
601     IN PIRP_CONTEXT IrpContext,
602     IN PIRP Irp,
603     IN PFCB FcbOrDcb,
604     IN ULONG StartingVbo,
605     IN ULONG ByteCount
606     );
607 
608 VOID
609 FatMultipleAsync (
610     IN PIRP_CONTEXT IrpContext,
611     IN PVCB Vcb,
612     IN PIRP Irp,
613     IN ULONG MultipleIrpCount,
614     IN PIO_RUN IoRuns
615     );
616 
617 VOID
618 FatSingleAsync (
619     IN PIRP_CONTEXT IrpContext,
620     IN PVCB Vcb,
621     IN LBO Lbo,
622     IN ULONG ByteCount,
623     IN PIRP Irp
624     );
625 
626 VOID
627 FatWaitSync (
628     IN PIRP_CONTEXT IrpContext
629     );
630 
631 VOID
632 FatLockUserBuffer (
633     IN PIRP_CONTEXT IrpContext,
634     IN OUT PIRP Irp,
635     IN LOCK_OPERATION Operation,
636     IN ULONG BufferLength
637     );
638 
639 PVOID
640 FatBufferUserBuffer (
641     IN PIRP_CONTEXT IrpContext,
642     IN OUT PIRP Irp,
643     IN ULONG BufferLength
644     );
645 
646 PVOID
647 FatMapUserBuffer (
648     IN PIRP_CONTEXT IrpContext,
649     IN OUT PIRP Irp
650     );
651 
652 NTSTATUS
653 FatToggleMediaEjectDisable (
654     IN PIRP_CONTEXT IrpContext,
655     IN PVCB Vcb,
656     IN BOOLEAN PreventRemoval
657     );
658 
659 NTSTATUS
660 FatPerformDevIoCtrl (
661     IN PIRP_CONTEXT IrpContext,
662     IN ULONG IoControlCode,
663     IN PDEVICE_OBJECT Device,
664     IN PVOID InputBuffer OPTIONAL,
665     IN ULONG InputBufferLength,
666     OUT PVOID OutputBuffer OPTIONAL,
667     IN ULONG OutputBufferLength,
668     IN BOOLEAN InternalDeviceIoControl,
669     IN BOOLEAN OverrideVerify,
670     OUT PIO_STATUS_BLOCK Iosb OPTIONAL
671     );
672 
673 PMDL
674 FatBuildZeroMdl (
675     __in PIRP_CONTEXT IrpContext,
676     __in ULONG Length
677     );
678 
679 
680 //
681 //  Dirent support routines, implemented in DirSup.c
682 //
683 
684 //
685 //  Tunneling is a deletion precursor (all tunneling cases do
686 //  not involve deleting dirents, however)
687 //
688 
689 VOID
690 FatTunnelFcbOrDcb (
691     IN PFCB FcbOrDcb,
692     IN PCCB Ccb OPTIONAL
693     );
694 
695 _Requires_lock_held_(_Global_critical_region_)
696 ULONG
697 FatCreateNewDirent (
698     IN PIRP_CONTEXT IrpContext,
699     IN PDCB ParentDirectory,
700     IN ULONG DirentsNeeded,
701     IN BOOLEAN RescanDir
702     );
703 
704 _Requires_lock_held_(_Global_critical_region_)
705 VOID
706 FatInitializeDirectoryDirent (
707     IN PIRP_CONTEXT IrpContext,
708     IN PDCB Dcb,
709     IN PDIRENT ParentDirent
710     );
711 
712 _Requires_lock_held_(_Global_critical_region_)
713 VOID
714 FatDeleteDirent (
715     IN PIRP_CONTEXT IrpContext,
716     IN PFCB FcbOrDcb,
717     IN PDELETE_CONTEXT DeleteContext OPTIONAL,
718     IN BOOLEAN DeleteEa
719     );
720 
721 
722 _Requires_lock_held_(_Global_critical_region_)
723 VOID
724 FatLocateDirent (
725     IN PIRP_CONTEXT IrpContext,
726     IN PDCB ParentDirectory,
727     IN PCCB Ccb,
728     IN VBO OffsetToStartSearchFrom,
729     IN OUT PULONG Flags,
730     OUT PDIRENT *Dirent,
731     OUT PBCB *Bcb,
732     OUT PVBO ByteOffset,
733     OUT PBOOLEAN FileNameDos OPTIONAL,
734     IN OUT PUNICODE_STRING Lfn OPTIONAL,
735     IN OUT PUNICODE_STRING OrigLfn OPTIONAL
736     );
737 
738 _Requires_lock_held_(_Global_critical_region_)
739 VOID
740 FatLocateSimpleOemDirent (
741     IN PIRP_CONTEXT IrpContext,
742     IN PDCB ParentDirectory,
743     IN POEM_STRING FileName,
744     OUT PDIRENT *Dirent,
745     OUT PBCB *Bcb,
746     OUT PVBO ByteOffset
747     );
748 
749 _Requires_lock_held_(_Global_critical_region_)
750 BOOLEAN
751 FatLfnDirentExists (
752     IN PIRP_CONTEXT IrpContext,
753     IN PDCB Dcb,
754     IN PUNICODE_STRING Lfn,
755     IN PUNICODE_STRING LfnTmp
756     );
757 
758 _Requires_lock_held_(_Global_critical_region_)
759 VOID
760 FatLocateVolumeLabel (
761     IN PIRP_CONTEXT IrpContext,
762     IN PVCB Vcb,
763     OUT PDIRENT *Dirent,
764     OUT PBCB *Bcb,
765     OUT PVBO ByteOffset
766     );
767 
768 _Requires_lock_held_(_Global_critical_region_)
769 VOID
770 FatGetDirentFromFcbOrDcb (
771     IN PIRP_CONTEXT IrpContext,
772     IN PFCB FcbOrDcb,
773     IN BOOLEAN ReturnOnFailure,
774     OUT PDIRENT *Dirent,
775     OUT PBCB *Bcb
776     );
777 
778 _Requires_lock_held_(_Global_critical_region_)
779 BOOLEAN
780 FatIsDirectoryEmpty (
781     IN PIRP_CONTEXT IrpContext,
782     IN PDCB Dcb
783     );
784 
785 _Requires_lock_held_(_Global_critical_region_)
786 VOID
787 FatDeleteFile (
788     IN PIRP_CONTEXT IrpContext,
789     IN PDCB TargetDcb,
790     IN ULONG LfnOffset,
791     IN ULONG DirentOffset,
792     IN PDIRENT Dirent,
793     IN PUNICODE_STRING Lfn
794     );
795 
796 
797 VOID
798 FatConstructDirent (
799     IN PIRP_CONTEXT IrpContext,
800     IN OUT PDIRENT Dirent,
801     IN POEM_STRING FileName,
802     IN BOOLEAN ComponentReallyLowercase,
803     IN BOOLEAN ExtensionReallyLowercase,
804     IN PUNICODE_STRING Lfn OPTIONAL,
805     IN USHORT Attributes,
806     IN BOOLEAN ZeroAndSetTimeFields,
807     IN PLARGE_INTEGER SetCreationTime OPTIONAL
808     );
809 
810 VOID
811 FatConstructLabelDirent (
812     IN PIRP_CONTEXT IrpContext,
813     IN OUT PDIRENT Dirent,
814     IN POEM_STRING Label
815     );
816 
817 _Requires_lock_held_(_Global_critical_region_)
818 VOID
819 FatSetFileSizeInDirent (
820     IN PIRP_CONTEXT IrpContext,
821     IN PFCB Fcb,
822     IN PULONG AlternativeFileSize OPTIONAL
823     );
824 
825 _Requires_lock_held_(_Global_critical_region_)
826 VOID
827 FatSetFileSizeInDirentNoRaise (
828     IN PIRP_CONTEXT IrpContext,
829     IN PFCB Fcb,
830     IN PULONG AlternativeFileSize OPTIONAL
831     );
832 
833 
834 _Requires_lock_held_(_Global_critical_region_)
835 VOID
836 FatUpdateDirentFromFcb (
837    IN PIRP_CONTEXT IrpContext,
838    IN PFILE_OBJECT FileObject,
839    IN PFCB FcbOrDcb,
840    IN PCCB Ccb
841    );
842 
843 
844 //
845 //  Generate a relatively unique static 64bit ID from a FAT Fcb/Dcb
846 //
847 //  ULONGLONG
848 //  FatDirectoryKey (FcbOrDcb);
849 //
850 
851 #define FatDirectoryKey(FcbOrDcb)  ((ULONGLONG)((FcbOrDcb)->CreationTime.QuadPart ^ (FcbOrDcb)->FirstClusterOfFile))
852 
853 
854 //
855 //  The following routines are used to access and manipulate the
856 //  clusters containing EA data in the ea data file.  They are
857 //  implemented in EaSup.c
858 //
859 
860 //
861 //  VOID
862 //  FatUpcaseEaName (
863 //      IN PIRP_CONTEXT IrpContext,
864 //      IN POEM_STRING EaName,
865 //      OUT POEM_STRING UpcasedEaName
866 //      );
867 //
868 
869 #define FatUpcaseEaName( IRPCONTEXT, NAME, UPCASEDNAME ) \
870     RtlUpperString( UPCASEDNAME, NAME )
871 
872 _Requires_lock_held_(_Global_critical_region_)
873 VOID
874 FatGetEaLength (
875     IN PIRP_CONTEXT IrpContext,
876     IN PVCB Vcb,
877     IN PDIRENT Dirent,
878     OUT PULONG EaLength
879     );
880 
881 _Requires_lock_held_(_Global_critical_region_)
882 VOID
883 FatGetNeedEaCount (
884     IN PIRP_CONTEXT IrpContext,
885     IN PVCB Vcb,
886     IN PDIRENT Dirent,
887     OUT PULONG NeedEaCount
888     );
889 
890 _Requires_lock_held_(_Global_critical_region_)
891 VOID
892 FatCreateEa (
893     IN PIRP_CONTEXT IrpContext,
894     IN PVCB Vcb,
895     IN PUCHAR Buffer,
896     IN ULONG Length,
897     IN POEM_STRING FileName,
898     OUT PUSHORT EaHandle
899     );
900 
901 _Requires_lock_held_(_Global_critical_region_)
902 VOID
903 FatDeleteEa (
904     IN PIRP_CONTEXT IrpContext,
905     IN PVCB Vcb,
906     IN USHORT EaHandle,
907     IN POEM_STRING FileName
908     );
909 
910 _Requires_lock_held_(_Global_critical_region_)
911 VOID
912 FatGetEaFile (
913     IN PIRP_CONTEXT IrpContext,
914     IN OUT PVCB Vcb,
915     OUT PDIRENT *EaDirent,
916     OUT PBCB *EaBcb,
917     IN BOOLEAN CreateFile,
918     IN BOOLEAN ExclusiveFcb
919     );
920 
921 VOID
922 FatReadEaSet (
923     IN PIRP_CONTEXT IrpContext,
924     IN PVCB Vcb,
925     IN USHORT EaHandle,
926     IN POEM_STRING FileName,
927     IN BOOLEAN ReturnEntireSet,
928     OUT PEA_RANGE EaSetRange
929     );
930 
931 _Requires_lock_held_(_Global_critical_region_)
932 VOID
933 FatDeleteEaSet (
934     IN PIRP_CONTEXT IrpContext,
935     IN PVCB Vcb,
936     IN PBCB EaBcb,
937     OUT PDIRENT EaDirent,
938     IN USHORT EaHandle,
939     IN POEM_STRING Filename
940     );
941 
942 _Requires_lock_held_(_Global_critical_region_)
943 VOID
944 FatAddEaSet (
945     IN PIRP_CONTEXT IrpContext,
946     IN PVCB Vcb,
947     IN ULONG EaSetLength,
948     IN PBCB EaBcb,
949     OUT PDIRENT EaDirent,
950     OUT PUSHORT EaHandle,
951     OUT PEA_RANGE EaSetRange
952     );
953 
954 VOID
955 FatDeletePackedEa (
956     IN PIRP_CONTEXT IrpContext,
957     IN OUT PEA_SET_HEADER EaSetHeader,
958     IN OUT PULONG PackedEasLength,
959     IN ULONG Offset
960     );
961 
962 VOID
963 FatAppendPackedEa (
964     IN PIRP_CONTEXT IrpContext,
965     IN OUT PEA_SET_HEADER *EaSetHeader,
966     IN OUT PULONG PackedEasLength,
967     IN OUT PULONG AllocationLength,
968     IN PFILE_FULL_EA_INFORMATION FullEa,
969     IN ULONG BytesPerCluster
970     );
971 
972 ULONG
973 FatLocateNextEa (
974     IN PIRP_CONTEXT IrpContext,
975     IN PPACKED_EA FirstPackedEa,
976     IN ULONG PackedEasLength,
977     IN ULONG PreviousOffset
978     );
979 
980 BOOLEAN
981 FatLocateEaByName (
982     IN PIRP_CONTEXT IrpContext,
983     IN PPACKED_EA FirstPackedEa,
984     IN ULONG PackedEasLength,
985     IN POEM_STRING EaName,
986     OUT PULONG Offset
987     );
988 
989 BOOLEAN
990 FatIsEaNameValid (
991     IN PIRP_CONTEXT IrpContext,
992     IN OEM_STRING Name
993     );
994 
995 VOID
996 FatPinEaRange (
997     IN PIRP_CONTEXT IrpContext,
998     IN PFILE_OBJECT VirtualEaFile,
999     IN PFCB EaFcb,
1000     IN OUT PEA_RANGE EaRange,
1001     IN ULONG StartingVbo,
1002     IN ULONG Length,
1003     IN NTSTATUS ErrorStatus
1004     );
1005 
1006 VOID
1007 FatMarkEaRangeDirty (
1008     IN PIRP_CONTEXT IrpContext,
1009     IN PFILE_OBJECT EaFileObject,
1010     IN OUT PEA_RANGE EaRange
1011     );
1012 
1013 VOID
1014 FatUnpinEaRange (
1015     IN PIRP_CONTEXT IrpContext,
1016     IN OUT PEA_RANGE EaRange
1017     );
1018 
1019 //
1020 //  The following macro computes the size of a full ea (not including
1021 //  padding to bring it to a longword.  A full ea has a 4 byte offset,
1022 //  folowed by 1 byte flag, 1 byte name length, 2 bytes value length,
1023 //  the name, 1 null byte, and the value.
1024 //
1025 //      ULONG
1026 //      SizeOfFullEa (
1027 //          IN PFILE_FULL_EA_INFORMATION FullEa
1028 //          );
1029 //
1030 
1031 #define SizeOfFullEa(EA) (4+1+1+2+(EA)->EaNameLength+1+(EA)->EaValueLength)
1032 
1033 
1034 //
1035 //  The following routines are used to manipulate the fscontext fields
1036 //  of the file object, implemented in FilObSup.c
1037 //
1038 
1039 #ifndef __REACTOS__
1040 typedef enum _TYPE_OF_OPEN {
1041 
1042     UnopenedFileObject = 1,
1043     UserFileOpen,
1044     UserDirectoryOpen,
1045     UserVolumeOpen,
1046     VirtualVolumeFile,
1047     DirectoryFile,
1048     EaFile,
1049 } TYPE_OF_OPEN;
1050 #endif
1051 
1052 typedef enum _FAT_FLUSH_TYPE {
1053 
1054     NoFlush = 0,
1055     Flush,
1056     FlushAndInvalidate,
1057     FlushWithoutPurge
1058 
1059 } FAT_FLUSH_TYPE;
1060 
1061 VOID
1062 FatSetFileObject (
1063     IN PFILE_OBJECT FileObject OPTIONAL,
1064     IN TYPE_OF_OPEN TypeOfOpen,
1065     IN PVOID VcbOrFcbOrDcb,
1066     IN PCCB Ccb OPTIONAL
1067     );
1068 
1069 TYPE_OF_OPEN
1070 FatDecodeFileObject (
1071     _In_ PFILE_OBJECT FileObject,
1072     _Outptr_ PVCB *Vcb,
1073     _Outptr_ PFCB *FcbOrDcb,
1074     _Outptr_ PCCB *Ccb
1075     );
1076 
1077 _Requires_lock_held_(_Global_critical_region_)
1078 VOID
1079 FatPurgeReferencedFileObjects (
1080     IN PIRP_CONTEXT IrpContext,
1081     IN PFCB FcbOrDcb,
1082     IN FAT_FLUSH_TYPE FlushType
1083     );
1084 
1085 _Requires_lock_held_(_Global_critical_region_)
1086 VOID
1087 FatForceCacheMiss (
1088     IN PIRP_CONTEXT IrpContext,
1089     IN PFCB Fcb,
1090     IN FAT_FLUSH_TYPE FlushType
1091     );
1092 
1093 
1094 //
1095 //  File system control routines, implemented in FsCtrl.c
1096 //
1097 
1098 _Requires_lock_held_(_Global_critical_region_)
1099 VOID
1100 FatFlushAndCleanVolume(
1101     IN PIRP_CONTEXT IrpContext,
1102     IN PIRP Irp,
1103     IN PVCB Vcb,
1104     IN FAT_FLUSH_TYPE FlushType
1105     );
1106 
1107 BOOLEAN
1108 FatIsBootSectorFat (
1109     IN PPACKED_BOOT_SECTOR BootSector
1110     );
1111 
1112 _Requires_lock_held_(_Global_critical_region_)
1113 NTSTATUS
1114 FatLockVolumeInternal (
1115     IN PIRP_CONTEXT IrpContext,
1116     IN PVCB Vcb,
1117     IN PFILE_OBJECT FileObject OPTIONAL
1118     );
1119 
1120 NTSTATUS
1121 FatUnlockVolumeInternal (
1122     IN PIRP_CONTEXT IrpContext,
1123     IN PVCB Vcb,
1124     IN PFILE_OBJECT FileObject OPTIONAL
1125     );
1126 
1127 
1128 //
1129 //  Name support routines, implemented in NameSup.c
1130 //
1131 
1132 //
1133 //  BOOLEAN
1134 //  FatAreNamesEqual (
1135 //      IN PIRP_CONTEXT IrpContext,
1136 //      IN OEM_STRING ConstantNameA,
1137 //      IN OEM_STRING ConstantNameB
1138 //      )
1139 //
1140 //  /*++
1141 //
1142 //  Routine Description:
1143 //
1144 //      This routine simple returns whether the two names are exactly equal.
1145 //      If the two names are known to be constant, this routine is much
1146 //      faster than FatIsDbcsInExpression.
1147 //
1148 //  Arguments:
1149 //
1150 //      ConstantNameA - Constant name.
1151 //
1152 //      ConstantNameB - Constant name.
1153 //
1154 //  Return Value:
1155 //
1156 //      BOOLEAN - TRUE if the two names are lexically equal.
1157 //
1158 
1159 #define FatAreNamesEqual(IRPCONTEXT,NAMEA,NAMEB) (      \
1160     ((ULONG)(NAMEA).Length == (ULONG)(NAMEB).Length) && \
1161     (RtlEqualMemory( &(NAMEA).Buffer[0],                \
1162                      &(NAMEB).Buffer[0],                \
1163                      (NAMEA).Length ))                  \
1164 )
1165 
1166 //
1167 //  BOOLEAN
1168 //  FatIsNameShortOemValid (
1169 //      IN PIRP_CONTEXT IrpContext,
1170 //      IN OEM_STRING Name,
1171 //      IN BOOLEAN CanContainWildCards,
1172 //      IN BOOLEAN PathNamePermissible,
1173 //      IN BOOLEAN LeadingBackslashPermissible
1174 //      )
1175 //
1176 //  /*++
1177 //
1178 //  Routine Description:
1179 //
1180 //      This routine scans the input name and verifies that if only
1181 //      contains valid characters
1182 //
1183 //  Arguments:
1184 //
1185 //      Name - Supplies the input name to check.
1186 //
1187 //      CanContainWildCards - Indicates if the name can contain wild cards
1188 //          (i.e., * and ?).
1189 //
1190 //  Return Value:
1191 //
1192 //          BOOLEAN - Returns TRUE if the name is valid and FALSE otherwise.
1193 //
1194 //  --*/
1195 //
1196 //  The FatIsNameLongOemValid and FatIsNameLongUnicodeValid are similar.
1197 //
1198 
1199 #define FatIsNameShortOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \
1200     FsRtlIsFatDbcsLegal((NAME),                   \
1201                         (CAN_CONTAIN_WILD_CARDS), \
1202                         (PATH_NAME_OK),           \
1203                         (LEADING_BACKSLASH_OK))   \
1204 )
1205 
1206 #define FatIsNameLongOemValid(IRPCONTEXT,NAME,CAN_CONTAIN_WILD_CARDS,PATH_NAME_OK,LEADING_BACKSLASH_OK) ( \
1207     FsRtlIsHpfsDbcsLegal((NAME),                  \
1208                         (CAN_CONTAIN_WILD_CARDS), \
1209                         (PATH_NAME_OK),           \
1210                         (LEADING_BACKSLASH_OK))   \
1211 )
1212 
1213 static
1214 INLINE
1215 BOOLEAN
FatIsNameLongUnicodeValid(PIRP_CONTEXT IrpContext,PUNICODE_STRING Name,BOOLEAN CanContainWildcards,BOOLEAN PathNameOk,BOOLEAN LeadingBackslashOk)1216 FatIsNameLongUnicodeValid (
1217     PIRP_CONTEXT IrpContext,
1218     PUNICODE_STRING Name,
1219     BOOLEAN CanContainWildcards,
1220     BOOLEAN PathNameOk,
1221     BOOLEAN LeadingBackslashOk
1222     )
1223 {
1224     ULONG i;
1225 
1226     UNREFERENCED_PARAMETER( IrpContext );
1227     UNREFERENCED_PARAMETER( LeadingBackslashOk );
1228     UNREFERENCED_PARAMETER( PathNameOk );
1229 
1230     //
1231     //  I'm not bothering to do the whole thing, just enough to make this call look
1232     //  the same as the others.
1233     //
1234 
1235     NT_ASSERT( !PathNameOk && !LeadingBackslashOk );
1236 
1237     for (i=0; i < Name->Length/sizeof(WCHAR); i++) {
1238 
1239         if ((Name->Buffer[i] < 0x80) &&
1240             !(FsRtlIsAnsiCharacterLegalHpfs(Name->Buffer[i], CanContainWildcards))) {
1241 
1242             return FALSE;
1243         }
1244     }
1245 
1246     return TRUE;
1247 }
1248 
1249 BOOLEAN
1250 FatIsNameInExpression (
1251     IN PIRP_CONTEXT IrpContext,
1252     IN OEM_STRING Expression,
1253     IN OEM_STRING Name
1254     );
1255 
1256 VOID
1257 FatStringTo8dot3 (
1258     _In_ PIRP_CONTEXT IrpContext,
1259     _In_ OEM_STRING InputString,
1260     _Out_writes_bytes_(11) PFAT8DOT3 Output8dot3
1261     );
1262 
1263 VOID
1264 Fat8dot3ToString (
1265     _In_ PIRP_CONTEXT IrpContext,
1266     _In_ PDIRENT Dirent,
1267     _In_ BOOLEAN RestoreCase,
1268     _Out_ POEM_STRING OutputString
1269     );
1270 
1271 _Requires_lock_held_(_Global_critical_region_)
1272 VOID
1273 FatGetUnicodeNameFromFcb (
1274     IN PIRP_CONTEXT IrpContext,
1275     IN PFCB Fcb,
1276     IN OUT PUNICODE_STRING Lfn
1277     );
1278 
1279 _Requires_lock_held_(_Global_critical_region_)
1280 VOID
1281 FatSetFullFileNameInFcb (
1282     IN PIRP_CONTEXT IrpContext,
1283     IN PFCB Fcb
1284     );
1285 
1286 VOID
1287 FatSetFullNameInFcb (
1288     _In_ PIRP_CONTEXT IrpContext,
1289     _Inout_ PFCB Fcb,
1290     _In_ PUNICODE_STRING FinalName
1291     );
1292 
1293 VOID
1294 FatUnicodeToUpcaseOem (
1295     IN PIRP_CONTEXT IrpContext,
1296     IN POEM_STRING OemString,
1297     IN PUNICODE_STRING UnicodeString
1298     );
1299 
1300 _Requires_lock_held_(_Global_critical_region_)
1301 VOID
1302 FatSelectNames (
1303     IN PIRP_CONTEXT IrpContext,
1304     IN PDCB Parent,
1305     IN POEM_STRING OemName,
1306     IN PUNICODE_STRING UnicodeName,
1307     IN OUT POEM_STRING ShortName,
1308     IN PUNICODE_STRING SuggestedShortName OPTIONAL,
1309     IN OUT BOOLEAN *AllLowerComponent,
1310     IN OUT BOOLEAN *AllLowerExtension,
1311     IN OUT BOOLEAN *CreateLfn
1312     );
1313 
1314 VOID
1315 FatEvaluateNameCase (
1316     IN PIRP_CONTEXT IrpContext,
1317     IN PUNICODE_STRING Name,
1318     IN OUT BOOLEAN *AllLowerComponent,
1319     IN OUT BOOLEAN *AllLowerExtension,
1320     IN OUT BOOLEAN *CreateLfn
1321     );
1322 
1323 BOOLEAN
1324 FatSpaceInName (
1325     IN PIRP_CONTEXT IrpContext,
1326     IN PUNICODE_STRING UnicodeName
1327     );
1328 
1329 VOID
1330 FatUnicodeRestoreShortNameCase(
1331     IN PUNICODE_STRING ShortNameWithCase,
1332     IN BOOLEAN LowerCase8,
1333     IN BOOLEAN LowerCase3
1334     );
1335 
1336 
1337 //
1338 //  Resources support routines/macros, implemented in ResrcSup.c
1339 //
1340 //  The following routines/macros are used for gaining shared and exclusive
1341 //  access to the global/vcb data structures.  The routines are implemented
1342 //  in ResrcSup.c.  There is a global resources that everyone tries to take
1343 //  out shared to do their work, with the exception of mount/dismount which
1344 //  take out the global resource exclusive.  All other resources only work
1345 //  on their individual item.  For example, an Fcb resource does not take out
1346 //  a Vcb resource.  But the way the file system is structured we know
1347 //  that when we are processing an Fcb other threads cannot be trying to remove
1348 //  or alter the Fcb, so we do not need to acquire the Vcb.
1349 //
1350 //  The procedures/macros are:
1351 //
1352 //          Macro          FatData    Vcb        Fcb         Subsequent macros
1353 //
1354 //  AcquireExclusiveGlobal Read/Write None       None        ReleaseGlobal
1355 //
1356 //  AcquireSharedGlobal    Read       None       None        ReleaseGlobal
1357 //
1358 //  AcquireExclusiveVcb    Read       Read/Write None        ReleaseVcb
1359 //
1360 //  AcquireSharedVcb       Read       Read       None        ReleaseVcb
1361 //
1362 //  AcquireExclusiveFcb    Read       None       Read/Write  ConvertToSharFcb
1363 //                                                           ReleaseFcb
1364 //
1365 //  AcquireSharedFcb       Read       None       Read        ReleaseFcb
1366 //
1367 //  ConvertToSharedFcb     Read       None       Read        ReleaseFcb
1368 //
1369 //  ReleaseGlobal
1370 //
1371 //  ReleaseVcb
1372 //
1373 //  ReleaseFcb
1374 //
1375 
1376 //
1377 //  FINISHED
1378 //  FatAcquireExclusiveGlobal (
1379 //      IN PIRP_CONTEXT IrpContext
1380 //      );
1381 //
1382 //  FINISHED
1383 //  FatAcquireSharedGlobal (
1384 //      IN PIRP_CONTEXT IrpContext
1385 //      );
1386 //
1387 
1388 #define FatAcquireExclusiveGlobal(IRPCONTEXT) (                                                                     \
1389     ExAcquireResourceExclusiveLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) )  \
1390 )
1391 
1392 #define FatAcquireSharedGlobal(IRPCONTEXT) (                                                                        \
1393     ExAcquireResourceSharedLite( &FatData.Resource, BooleanFlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT) )     \
1394 )
1395 
1396 //
1397 //  The following macro must only be called when Wait is TRUE!
1398 //
1399 //  FatAcquireExclusiveVolume (
1400 //      IN PIRP_CONTEXT IrpContext,
1401 //      IN PVCB Vcb
1402 //      );
1403 //
1404 //  FatReleaseVolume (
1405 //      IN PIRP_CONTEXT IrpContext,
1406 //      IN PVCB Vcb
1407 //      );
1408 //
1409 
1410 #define FatAcquireExclusiveVolume(IRPCONTEXT,VCB) {                                     \
1411     PFCB __FFFFFcb = NULL;                                                                    \
1412     NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT));                      \
1413     (VOID)FatAcquireExclusiveVcb( (IRPCONTEXT), (VCB) );                                \
1414     while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \
1415         (VOID)FatAcquireExclusiveFcb((IRPCONTEXT), __FFFFFcb );                               \
1416     }                                                                                   \
1417 }
1418 
1419 #define FatReleaseVolume(IRPCONTEXT,VCB) {                                              \
1420     PFCB __FFFFFcb = NULL;                                                                    \
1421     NT_ASSERT(FlagOn((IRPCONTEXT)->Flags, IRP_CONTEXT_FLAG_WAIT));                      \
1422     while ( (__FFFFFcb = FatGetNextFcbBottomUp((IRPCONTEXT), __FFFFFcb, (VCB)->RootDcb)) != NULL) { \
1423         (VOID)ExReleaseResourceLite( __FFFFFcb->Header.Resource );                            \
1424     }                                                                                   \
1425     FatReleaseVcb((IRPCONTEXT), (VCB));                                                 \
1426 }
1427 
1428 //
1429 //  Macro to enable easy tracking of Vcb state transitions.
1430 //
1431 
1432 #ifdef FASTFATDBG
1433 #define FatSetVcbCondition( V, X) {                                            \
1434             DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%d -> ",(V)->VcbCondition);     \
1435             DebugTrace(0,DEBUG_TRACE_VERFYSUP,"%x\n",(X));                     \
1436             (V)->VcbCondition = (X);                                           \
1437         }
1438 #else
1439 #define FatSetVcbCondition( V, X)       (V)->VcbCondition = (X)
1440 #endif
1441 
1442 //
1443 //  These macros can be used to determine what kind of FAT we have for an
1444 //  initialized Vcb.  It is somewhat more elegant to use these (visually).
1445 //
1446 
1447 #define FatIsFat32(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 32))
1448 #define FatIsFat16(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 16))
1449 #define FatIsFat12(VCB) ((BOOLEAN)((VCB)->AllocationSupport.FatIndexBitSize == 12))
1450 
1451 
1452 _Requires_lock_held_(_Global_critical_region_)
1453 _When_(return != FALSE && NoOpCheck != FALSE, _Acquires_exclusive_lock_(Vcb->Resource))
1454 FINISHED
1455 FatAcquireExclusiveVcb_Real (
1456     IN PIRP_CONTEXT IrpContext,
1457     IN PVCB Vcb,
1458     IN BOOLEAN NoOpCheck
1459     );
1460 
1461 #define FatAcquireExclusiveVcb( IC, V)          FatAcquireExclusiveVcb_Real( IC, V, FALSE)
1462 #define FatAcquireExclusiveVcbNoOpCheck( IC, V) FatAcquireExclusiveVcb_Real( IC, V, TRUE)
1463 
1464 _Requires_lock_held_(_Global_critical_region_)
1465 _When_(return != 0, _Acquires_shared_lock_(Vcb->Resource))
1466 FINISHED
1467 FatAcquireSharedVcb (
1468     IN PIRP_CONTEXT IrpContext,
1469     IN PVCB Vcb
1470     );
1471 
1472 _Requires_lock_held_(_Global_critical_region_)
1473 _Acquires_exclusive_lock_(*Fcb->Header.Resource)
1474 FINISHED
1475 FatAcquireExclusiveFcb (
1476     IN PIRP_CONTEXT IrpContext,
1477     IN PFCB Fcb
1478     );
1479 
1480 _Requires_lock_held_(_Global_critical_region_)
1481 _Acquires_shared_lock_(*Fcb->Header.Resource)
1482 FINISHED
1483 FatAcquireSharedFcb (
1484     IN PIRP_CONTEXT IrpContext,
1485     IN PFCB Fcb
1486     );
1487 
1488 _Requires_lock_held_(_Global_critical_region_)
1489 _When_(return != 0, _Acquires_shared_lock_(*Fcb->Header.Resource))
1490 FINISHED
1491 FatAcquireSharedFcbWaitForEx (
1492     IN PIRP_CONTEXT IrpContext,
1493     IN PFCB Fcb
1494     );
1495 
1496 #define FatVcbAcquiredExclusive(IRPCONTEXT,VCB) (                   \
1497     ExIsResourceAcquiredExclusiveLite(&(VCB)->Resource)  ||         \
1498     ExIsResourceAcquiredExclusiveLite(&FatData.Resource)            \
1499 )
1500 
1501 #define FatFcbAcquiredShared(IRPCONTEXT,FCB) (                      \
1502     ExIsResourceAcquiredSharedLite((FCB)->Header.Resource)          \
1503 )
1504 
1505 #define FatFcbAcquiredExclusive(IRPCONTEXT,FCB) (                   \
1506     ExIsResourceAcquiredExclusiveLite((FCB)->Header.Resource)       \
1507 )
1508 
1509 #define FatAcquireDirectoryFileMutex(VCB) {                         \
1510     NT_ASSERT(KeAreApcsDisabled());                                 \
1511     ExAcquireFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex);   \
1512 }
1513 
1514 #define FatReleaseDirectoryFileMutex(VCB) {                         \
1515     NT_ASSERT(KeAreApcsDisabled());                                 \
1516     ExReleaseFastMutexUnsafe(&(VCB)->DirectoryFileCreationMutex);   \
1517 }
1518 
1519 //
1520 //  The following are cache manager call backs
1521 
1522 BOOLEAN
1523 FatAcquireVolumeForClose (
1524     IN PVOID Vcb,
1525     IN BOOLEAN Wait
1526     );
1527 
1528 VOID
1529 FatReleaseVolumeFromClose (
1530     IN PVOID Vcb
1531     );
1532 
1533 _Requires_lock_held_(_Global_critical_region_)
1534 BOOLEAN
1535 NTAPI
1536 FatAcquireFcbForLazyWrite (
1537     IN PVOID Null,
1538     IN BOOLEAN Wait
1539     );
1540 
1541 _Requires_lock_held_(_Global_critical_region_)
1542 VOID
1543 NTAPI
1544 FatReleaseFcbFromLazyWrite (
1545     IN PVOID Null
1546     );
1547 
1548 _Requires_lock_held_(_Global_critical_region_)
1549 BOOLEAN
1550 NTAPI
1551 FatAcquireFcbForReadAhead (
1552     IN PVOID Null,
1553     IN BOOLEAN Wait
1554     );
1555 
1556 _Requires_lock_held_(_Global_critical_region_)
1557 VOID
1558 NTAPI
1559 FatReleaseFcbFromReadAhead (
1560     IN PVOID Null
1561     );
1562 
1563 _Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)
1564 _Requires_lock_held_(_Global_critical_region_)
1565 NTSTATUS
1566 NTAPI
1567 FatAcquireForCcFlush (
1568     IN PFILE_OBJECT FileObject,
1569     IN PDEVICE_OBJECT DeviceObject
1570     );
1571 
1572 _Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)
1573 _Requires_lock_held_(_Global_critical_region_)
1574 NTSTATUS
1575 NTAPI
1576 FatReleaseForCcFlush (
1577     IN PFILE_OBJECT FileObject,
1578     IN PDEVICE_OBJECT DeviceObject
1579     );
1580 
1581 BOOLEAN
1582 NTAPI
1583 FatNoOpAcquire (
1584     IN PVOID Fcb,
1585     IN BOOLEAN Wait
1586     );
1587 
1588 VOID
1589 NTAPI
1590 FatNoOpRelease (
1591     IN PVOID Fcb
1592     );
1593 
1594 _Requires_lock_held_(_Global_critical_region_)
1595 NTSTATUS
1596 NTAPI
1597 FatFilterCallbackAcquireForCreateSection (
1598     IN PFS_FILTER_CALLBACK_DATA CallbackData,
1599     OUT PVOID *CompletionContext
1600     );
1601 
1602 //
1603 //  VOID
1604 //  FatConvertToSharedFcb (
1605 //      IN PIRP_CONTEXT IrpContext,
1606 //      IN PFCB Fcb
1607 //      );
1608 //
1609 
1610 #define FatConvertToSharedFcb(IRPCONTEXT,Fcb) {                 \
1611     ExConvertExclusiveToSharedLite( (Fcb)->Header.Resource );   \
1612     }
1613 
1614 //
1615 //  VOID
1616 //  FatReleaseGlobal (
1617 //      IN PIRP_CONTEXT IrpContext
1618 //      );
1619 //
1620 //  VOID
1621 //  FatReleaseVcb (
1622 //      IN PIRP_CONTEXT IrpContext,
1623 //      IN PVCB Vcb
1624 //      );
1625 //
1626 //  VOID
1627 //  FatReleaseFcb (
1628 //      IN PIRP_CONTEXT IrpContext,
1629 //      IN PVCB Vcb
1630 //      );
1631 //
1632 
1633 #define FatDeleteResource(RESRC) {                      \
1634     ExDeleteResourceLite( (RESRC) );                    \
1635 }
1636 
1637 #define FatReleaseGlobal(IRPCONTEXT) {                  \
1638     ExReleaseResourceLite( &(FatData.Resource) );       \
1639     }
1640 
1641 #define FatReleaseVcb(IRPCONTEXT,Vcb) {                 \
1642     ExReleaseResourceLite( &((Vcb)->Resource) );        \
1643     }
1644 
1645 #define FatReleaseFcb(IRPCONTEXT,Fcb) {                 \
1646     ExReleaseResourceLite( (Fcb)->Header.Resource );    \
1647     }
1648 
1649 //
1650 //  The following macro is used to retrieve the oplock structure within
1651 //  the Fcb. This structure was moved to the advanced Fcb header
1652 //  in Win8.
1653 //
1654 
1655 #if (NTDDI_VERSION >= NTDDI_WIN8)
1656 
1657 #define FatGetFcbOplock(F)  &(F)->Header.Oplock
1658 
1659 #else
1660 
1661 #define FatGetFcbOplock(F)  &(F)->Specific.Fcb.Oplock
1662 
1663 #endif
1664 
1665 
1666 //
1667 //  In-memory structure support routine, implemented in StrucSup.c
1668 //
1669 
1670 _Requires_lock_held_(_Global_critical_region_)
1671 VOID
1672 FatInitializeVcb (
1673     IN PIRP_CONTEXT IrpContext,
1674     IN OUT PVCB Vcb,
1675     IN PDEVICE_OBJECT TargetDeviceObject,
1676     IN PVPB Vpb,
1677     IN PDEVICE_OBJECT FsDeviceObject
1678     );
1679 
1680 VOID
1681 FatTearDownVcb (
1682     IN PIRP_CONTEXT IrpContext,
1683     IN PVCB Vcb
1684     );
1685 
1686 VOID
1687 FatDeleteVcb (
1688     IN PIRP_CONTEXT IrpContext,
1689     IN PVCB Vcb
1690     );
1691 
1692 _Requires_lock_held_(_Global_critical_region_)
1693 VOID
1694 FatCreateRootDcb (
1695     IN PIRP_CONTEXT IrpContext,
1696     IN PVCB Vcb
1697     );
1698 
1699 PFCB
1700 FatCreateFcb (
1701     IN PIRP_CONTEXT IrpContext,
1702     IN PVCB Vcb,
1703     IN PDCB ParentDcb,
1704     IN ULONG LfnOffsetWithinDirectory,
1705     IN ULONG DirentOffsetWithinDirectory,
1706     IN PDIRENT Dirent,
1707     IN PUNICODE_STRING Lfn OPTIONAL,
1708     IN PUNICODE_STRING OrigLfn OPTIONAL,
1709     IN BOOLEAN IsPagingFile,
1710     IN BOOLEAN SingleResource
1711     );
1712 
1713 PDCB
1714 FatCreateDcb (
1715     IN PIRP_CONTEXT IrpContext,
1716     IN PVCB Vcb,
1717     IN PDCB ParentDcb,
1718     IN ULONG LfnOffsetWithinDirectory,
1719     IN ULONG DirentOffsetWithinDirectory,
1720     IN PDIRENT Dirent,
1721     IN PUNICODE_STRING Lfn OPTIONAL
1722     );
1723 
1724 VOID
1725 FatDeleteFcb (
1726     IN PIRP_CONTEXT IrpContext,
1727     IN PFCB *Fcb
1728     );
1729 
1730 PCCB
1731 FatCreateCcb (
1732     IN PIRP_CONTEXT IrpContext
1733     );
1734 
1735 VOID
1736 FatDeallocateCcbStrings(
1737         IN PCCB Ccb
1738         );
1739 
1740 VOID
1741 FatDeleteCcb (
1742     IN PIRP_CONTEXT IrpContext,
1743     IN PCCB *Ccb
1744     );
1745 
1746 PIRP_CONTEXT
1747 FatCreateIrpContext (
1748     IN PIRP Irp,
1749     IN BOOLEAN Wait
1750     );
1751 
1752 VOID
1753 FatDeleteIrpContext_Real (
1754     IN PIRP_CONTEXT IrpContext
1755     );
1756 
1757 #ifdef FASTFATDBG
1758 #define FatDeleteIrpContext(IRPCONTEXT) {   \
1759     FatDeleteIrpContext_Real((IRPCONTEXT)); \
1760     (IRPCONTEXT) = NULL;                    \
1761 }
1762 #else
1763 #define FatDeleteIrpContext(IRPCONTEXT) {   \
1764     FatDeleteIrpContext_Real((IRPCONTEXT)); \
1765 }
1766 #endif // FASTFAT_DBG
1767 
1768 PFCB
1769 FatGetNextFcbTopDown (
1770     IN PIRP_CONTEXT IrpContext,
1771     IN PFCB Fcb,
1772     IN PFCB TerminationFcb
1773     );
1774 
1775 PFCB
1776 FatGetNextFcbBottomUp (
1777     IN PIRP_CONTEXT IrpContext,
1778     IN PFCB Fcb,
1779     IN PFCB TerminationFcb
1780     );
1781 
1782 //
1783 //  These two macros just make the code a bit cleaner.
1784 //
1785 
1786 #define FatGetFirstChild(DIR) ((PFCB)(                          \
1787     IsListEmpty(&(DIR)->Specific.Dcb.ParentDcbQueue) ? NULL :   \
1788     CONTAINING_RECORD((DIR)->Specific.Dcb.ParentDcbQueue.Flink, \
1789                       DCB,                                      \
1790                       ParentDcbLinks.Flink)))
1791 
1792 #define FatGetNextSibling(FILE) ((PFCB)(                     \
1793     &(FILE)->ParentDcb->Specific.Dcb.ParentDcbQueue.Flink == \
1794     (PVOID)(FILE)->ParentDcbLinks.Flink ? NULL :             \
1795     CONTAINING_RECORD((FILE)->ParentDcbLinks.Flink,          \
1796                       FCB,                                   \
1797                       ParentDcbLinks.Flink)))
1798 
1799 _Requires_lock_held_(_Global_critical_region_)
1800 BOOLEAN
1801 FatCheckForDismount (
1802     IN PIRP_CONTEXT IrpContext,
1803     PVCB Vcb,
1804     IN BOOLEAN Force
1805     );
1806 
1807 VOID
1808 FatConstructNamesInFcb (
1809     IN PIRP_CONTEXT IrpContext,
1810     PFCB Fcb,
1811     PDIRENT Dirent,
1812     PUNICODE_STRING Lfn OPTIONAL
1813     );
1814 
1815 _Requires_lock_held_(_Global_critical_region_)
1816 VOID
1817 FatCheckFreeDirentBitmap (
1818     IN PIRP_CONTEXT IrpContext,
1819     IN PDCB Dcb
1820     );
1821 
1822 ULONG
1823 FatVolumeUncleanCount (
1824     IN PIRP_CONTEXT IrpContext,
1825     IN PVCB Vcb
1826     );
1827 
1828 VOID
1829 FatPreallocateCloseContext (
1830     IN PVCB Vcb
1831     );
1832 
1833 PCLOSE_CONTEXT
1834 FatAllocateCloseContext(
1835     IN PVCB Vcb
1836     );
1837 
1838 //
1839 //  BOOLEAN
1840 //  FatIsRawDevice (
1841 //      IN PIRP_CONTEXT IrpContext,
1842 //      IN NTSTATUS Status
1843 //      );
1844 //
1845 
1846 #define FatIsRawDevice(IC,S) (          \
1847     ((S) == STATUS_DEVICE_NOT_READY) || \
1848     ((S) == STATUS_NO_MEDIA_IN_DEVICE)  \
1849 )
1850 
1851 
1852 //
1853 //  Routines to support managing file names Fcbs and Dcbs.
1854 //  Implemented in SplaySup.c
1855 //
1856 
1857 VOID
1858 FatInsertName (
1859     IN PIRP_CONTEXT IrpContext,
1860     IN PRTL_SPLAY_LINKS *RootNode,
1861     IN PFILE_NAME_NODE Name
1862     );
1863 
1864 VOID
1865 FatRemoveNames (
1866     IN PIRP_CONTEXT IrpContext,
1867     IN PFCB Fcb
1868     );
1869 
1870 PFCB
1871 FatFindFcb (
1872     IN PIRP_CONTEXT IrpContext,
1873     IN OUT PRTL_SPLAY_LINKS *RootNode,
1874     IN PSTRING Name,
1875     OUT PBOOLEAN FileNameDos OPTIONAL
1876     );
1877 
1878 BOOLEAN
1879 FatIsHandleCountZero (
1880     IN PIRP_CONTEXT IrpContext,
1881     IN PVCB Vcb
1882     );
1883 
1884 typedef enum _COMPARISON {
1885     IsLessThan,
1886     IsGreaterThan,
1887     IsEqual
1888 } COMPARISON;
1889 
1890 COMPARISON
1891 FatCompareNames (
1892     IN PSTRING NameA,
1893     IN PSTRING NameB
1894     );
1895 
1896 //
1897 //  Do a macro here to check for a common case.
1898 //
1899 
1900 #define CompareNames(NAMEA,NAMEB) (                        \
1901     *(PUCHAR)(NAMEA)->Buffer != *(PUCHAR)(NAMEB)->Buffer ? \
1902     *(PUCHAR)(NAMEA)->Buffer < *(PUCHAR)(NAMEB)->Buffer ?  \
1903     IsLessThan : IsGreaterThan :                           \
1904     FatCompareNames((PSTRING)(NAMEA), (PSTRING)(NAMEB))    \
1905 )
1906 
1907 //
1908 //  Time conversion support routines, implemented in TimeSup.c
1909 //
1910 
1911 _Success_(return != FALSE)
1912 BOOLEAN
1913 FatNtTimeToFatTime (
1914     _In_ PIRP_CONTEXT IrpContext,
1915     _In_ PLARGE_INTEGER NtTime,
1916     _In_ BOOLEAN Rounding,
1917     _Out_ PFAT_TIME_STAMP FatTime,
1918     _Out_opt_ PUCHAR TenMsecs
1919     );
1920 
1921 LARGE_INTEGER
1922 FatFatTimeToNtTime (
1923     _In_ PIRP_CONTEXT IrpContext,
1924     _In_ FAT_TIME_STAMP FatTime,
1925     _In_ UCHAR TenMilliSeconds
1926     );
1927 
1928 LARGE_INTEGER
1929 FatFatDateToNtTime (
1930     _In_ PIRP_CONTEXT IrpContext,
1931     _In_ FAT_DATE FatDate
1932     );
1933 
1934 FAT_TIME_STAMP
1935 FatGetCurrentFatTime (
1936     _In_ PIRP_CONTEXT IrpContext
1937     );
1938 
1939 
1940 //
1941 //  Low level verification routines, implemented in VerfySup.c
1942 //
1943 //  The first routine is called to help process a verify IRP.  Its job is
1944 //  to walk every Fcb/Dcb and mark them as need to be verified.
1945 //
1946 //  The other routines are used by every dispatch routine to verify that
1947 //  an Vcb/Fcb/Dcb is still good.  The routine walks as much of the opened
1948 //  file/directory tree as necessary to make sure that the path is still valid.
1949 //  The function result indicates if the procedure needed to block for I/O.
1950 //  If the structure is bad the procedure raise the error condition
1951 //  STATUS_FILE_INVALID, otherwise they simply return to their caller
1952 //
1953 
1954 typedef enum _FAT_VOLUME_STATE {
1955     VolumeClean,
1956     VolumeDirty,
1957     VolumeDirtyWithSurfaceTest
1958 } FAT_VOLUME_STATE, *PFAT_VOLUME_STATE;
1959 
1960 VOID
1961 FatMarkFcbCondition (
1962     IN PIRP_CONTEXT IrpContext,
1963     IN PFCB Fcb,
1964     IN FCB_CONDITION FcbCondition,
1965     IN BOOLEAN Recursive
1966     );
1967 
1968 VOID
1969 FatVerifyVcb (
1970     IN PIRP_CONTEXT IrpContext,
1971     IN PVCB Vcb
1972     );
1973 
1974 _Requires_lock_held_(_Global_critical_region_)
1975 VOID
1976 FatVerifyFcb (
1977     IN PIRP_CONTEXT IrpContext,
1978     IN PFCB Fcb
1979     );
1980 
1981 
1982 KDEFERRED_ROUTINE FatCleanVolumeDpc;
1983 
1984 VOID
1985 NTAPI
1986 FatCleanVolumeDpc (
1987     _In_ PKDPC Dpc,
1988     _In_opt_ PVOID DeferredContext,
1989     _In_opt_ PVOID SystemArgument1,
1990     _In_opt_ PVOID SystemArgument2
1991     );
1992 
1993 _Requires_lock_held_(_Global_critical_region_)
1994 VOID
1995 FatMarkVolume (
1996     IN PIRP_CONTEXT IrpContext,
1997     IN PVCB Vcb,
1998     IN FAT_VOLUME_STATE VolumeState
1999     );
2000 
2001 WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover;
2002 
2003 VOID
2004 NTAPI
2005 FatFspMarkVolumeDirtyWithRecover (
2006     PVOID Parameter
2007     );
2008 
2009 VOID
2010 FatCheckDirtyBit (
2011     IN PIRP_CONTEXT IrpContext,
2012     IN PVCB Vcb
2013     );
2014 
2015 VOID
2016 FatQuickVerifyVcb (
2017     IN PIRP_CONTEXT IrpContext,
2018     IN PVCB Vcb
2019     );
2020 
2021 VOID
2022 FatVerifyOperationIsLegal (
2023     IN PIRP_CONTEXT IrpContext
2024     );
2025 
2026 _Requires_lock_held_(_Global_critical_region_)
2027 NTSTATUS
2028 FatPerformVerify (
2029     _In_ PIRP_CONTEXT IrpContext,
2030     _In_ PIRP Irp,
2031     _In_ PDEVICE_OBJECT Device
2032     );
2033 
2034 
2035 //
2036 //  Work queue routines for posting and retrieving an Irp, implemented in
2037 //  workque.c
2038 //
2039 
2040 VOID
2041 NTAPI
2042 FatOplockComplete (
2043     IN PVOID Context,
2044     IN PIRP Irp
2045     );
2046 
2047 VOID
2048 NTAPI
2049 FatPrePostIrp (
2050     IN PVOID Context,
2051     IN PIRP Irp
2052     );
2053 
2054 VOID
2055 #ifdef __REACTOS__
2056 NTAPI
2057 #endif
2058 FatAddToWorkque (
2059     IN PIRP_CONTEXT IrpContext,
2060     IN PIRP Irp
2061     );
2062 
2063 NTSTATUS
2064 FatFsdPostRequest (
2065     IN PIRP_CONTEXT IrpContext,
2066     IN PIRP Irp
2067     );
2068 
2069 //
2070 //  Miscellaneous support routines
2071 //
2072 
2073 //
2074 //      ULONG
2075 //      PtrOffset (
2076 //          IN PVOID BasePtr,
2077 //          IN PVOID OffsetPtr
2078 //          );
2079 //
2080 
2081 #define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
2082 
2083 //
2084 //  This macro takes a pointer (or ulong) and returns its rounded up word
2085 //  value
2086 //
2087 
2088 #define WordAlign(Ptr) (                \
2089     ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
2090     )
2091 
2092 //
2093 //  This macro takes a pointer (or ulong) and returns its rounded up longword
2094 //  value
2095 //
2096 
2097 #define LongAlign(Ptr) (                \
2098     ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
2099     )
2100 
2101 //
2102 //  This macro takes a pointer (or ulong) and returns its rounded up quadword
2103 //  value
2104 //
2105 
2106 #define QuadAlign(Ptr) (                \
2107     ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
2108     )
2109 
2110 //
2111 //  The following types and macros are used to help unpack the packed and
2112 //  misaligned fields found in the Bios parameter block
2113 //
2114 
2115 typedef union _UCHAR1 {
2116     UCHAR  Uchar[1];
2117     UCHAR  ForceAlignment;
2118 } UCHAR1, *PUCHAR1;
2119 
2120 typedef union _UCHAR2 {
2121     UCHAR  Uchar[2];
2122     USHORT ForceAlignment;
2123 } UCHAR2, *PUCHAR2;
2124 
2125 typedef union _UCHAR4 {
2126     UCHAR  Uchar[4];
2127     ULONG  ForceAlignment;
2128 } UCHAR4, *PUCHAR4;
2129 
2130 //
2131 //  This macro copies an unaligned src byte to an aligned dst byte
2132 //
2133 
2134 #define CopyUchar1(Dst,Src) {                               \
2135     *((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src));      \
2136     }
2137 
2138 //
2139 //  This macro copies an unaligned src word to an aligned dst word
2140 //
2141 
2142 #define CopyUchar2(Dst,Src) {                               \
2143     *((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src));      \
2144     }
2145 
2146 //
2147 //  This macro copies an unaligned src longword to an aligned dsr longword
2148 //
2149 
2150 #define CopyUchar4(Dst,Src) {                               \
2151     *((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src));      \
2152     }
2153 
2154 #define CopyU4char(Dst,Src) {                               \
2155     *((UNALIGNED UCHAR4 *)(Dst)) = *((UCHAR4 *)(Src));      \
2156     }
2157 
2158 //
2159 //  VOID
2160 //  FatNotifyReportChange (
2161 //      IN PIRP_CONTEXT IrpContext,
2162 //      IN PVCB Vcb,
2163 //      IN PFCB Fcb,
2164 //      IN ULONG Filter,
2165 //      IN ULONG Action
2166 //      );
2167 //
2168 
2169 #define FatNotifyReportChange(I,V,F,FL,A) {                                                         \
2170     if ((F)->FullFileName.Buffer == NULL) {                                                         \
2171         FatSetFullFileNameInFcb((I),(F));                                                           \
2172     }                                                                                               \
2173     NT_ASSERT( (F)->FullFileName.Length != 0 );                                                     \
2174     NT_ASSERT( (F)->FinalNameLength != 0 );                                                         \
2175     NT_ASSERT( (F)->FullFileName.Length > (F)->FinalNameLength );                                   \
2176     NT_ASSERT( (F)->FullFileName.Buffer[((F)->FullFileName.Length - (F)->FinalNameLength)/sizeof(WCHAR) - 1] == L'\\' ); \
2177     FsRtlNotifyFullReportChange( (V)->NotifySync,                                                   \
2178                                  &(V)->DirNotifyList,                                               \
2179                                  (PSTRING)&(F)->FullFileName,                                       \
2180                                  (USHORT) ((F)->FullFileName.Length -                               \
2181                                            (F)->FinalNameLength),                                   \
2182                                  (PSTRING)NULL,                                                     \
2183                                  (PSTRING)NULL,                                                     \
2184                                  (ULONG)FL,                                                         \
2185                                  (ULONG)A,                                                          \
2186                                  (PVOID)NULL );                                                     \
2187 }
2188 
2189 
2190 //
2191 //  The FSD Level dispatch routines.   These routines are called by the
2192 //  I/O system via the dispatch table in the Driver Object.
2193 //
2194 //  They each accept as input a pointer to a device object (actually most
2195 //  expect a volume device object, with the exception of the file system
2196 //  control function which can also take a file system device object), and
2197 //  a pointer to the IRP.  They either perform the function at the FSD level
2198 //  or post the request to the FSP work queue for FSP level processing.
2199 //
2200 
2201 _Function_class_(IRP_MJ_CLEANUP)
2202 _Function_class_(DRIVER_DISPATCH)
2203 NTSTATUS
2204 NTAPI
2205 FatFsdCleanup (                         //  implemented in Cleanup.c
2206     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2207     _Inout_ PIRP Irp
2208     );
2209 
2210 _Function_class_(IRP_MJ_CLOSE)
2211 _Function_class_(DRIVER_DISPATCH)
2212 NTSTATUS
2213 NTAPI
2214 FatFsdClose (                           //  implemented in Close.c
2215     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2216     _Inout_ PIRP Irp
2217     );
2218 
2219 _Function_class_(IRP_MJ_CREATE)
2220 _Function_class_(DRIVER_DISPATCH)
2221 NTSTATUS
2222 NTAPI
2223 FatFsdCreate (                          //  implemented in Create.c
2224     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2225     _Inout_ PIRP Irp
2226     );
2227 
2228 
2229 _Function_class_(IRP_MJ_DEVICE_CONTROL)
2230 _Function_class_(DRIVER_DISPATCH)
2231 NTSTATUS
2232 NTAPI
2233 FatFsdDeviceControl (                   //  implemented in DevCtrl.c
2234     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2235     _Inout_ PIRP Irp
2236     );
2237 
2238 _Function_class_(IRP_MJ_DIRECTORY_CONTROL)
2239 _Function_class_(DRIVER_DISPATCH)
2240 NTSTATUS
2241 NTAPI
2242 FatFsdDirectoryControl (                //  implemented in DirCtrl.c
2243     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2244     _Inout_ PIRP Irp
2245     );
2246 
2247 _Function_class_(IRP_MJ_QUERY_EA)
2248 _Function_class_(DRIVER_DISPATCH)
2249 NTSTATUS
2250 NTAPI
2251 FatFsdQueryEa (                         //  implemented in Ea.c
2252     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2253     _Inout_ PIRP Irp
2254     );
2255 
2256 _Function_class_(IRP_MJ_SET_EA)
2257 _Function_class_(DRIVER_DISPATCH)
2258 NTSTATUS
2259 NTAPI
2260 FatFsdSetEa (                           //  implemented in Ea.c
2261     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2262     _Inout_ PIRP Irp
2263     );
2264 
2265 _Function_class_(IRP_MJ_QUERY_INFORMATION)
2266 _Function_class_(DRIVER_DISPATCH)
2267 NTSTATUS
2268 NTAPI
2269 FatFsdQueryInformation (                //  implemented in FileInfo.c
2270     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2271     _Inout_ PIRP Irp
2272     );
2273 
2274 _Function_class_(IRP_MJ_SET_INFORMATION)
2275 _Function_class_(DRIVER_DISPATCH)
2276 NTSTATUS
2277 NTAPI
2278 FatFsdSetInformation (                  //  implemented in FileInfo.c
2279     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2280     _Inout_ PIRP Irp
2281     );
2282 
2283 _Function_class_(IRP_MJ_FLUSH_BUFFERS)
2284 _Function_class_(DRIVER_DISPATCH)
2285 NTSTATUS
2286 NTAPI
2287 FatFsdFlushBuffers (                    //  implemented in Flush.c
2288     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2289     _Inout_ PIRP Irp
2290     );
2291 
2292 _Function_class_(IRP_MJ_FILE_SYSTEM_CONTROL)
2293 _Function_class_(DRIVER_DISPATCH)
2294 NTSTATUS
2295 NTAPI
2296 FatFsdFileSystemControl (               //  implemented in FsCtrl.c
2297     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2298     _Inout_ PIRP Irp
2299     );
2300 
2301 _Function_class_(IRP_MJ_LOCK_CONTROL)
2302 _Function_class_(DRIVER_DISPATCH)
2303 NTSTATUS
2304 NTAPI
2305 FatFsdLockControl (                     //  implemented in LockCtrl.c
2306     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2307     _Inout_ PIRP Irp
2308     );
2309 
2310 _Function_class_(IRP_MJ_PNP)
2311 _Function_class_(DRIVER_DISPATCH)
2312 NTSTATUS
2313 NTAPI
2314 FatFsdPnp (                            //  implemented in Pnp.c
2315     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2316     _Inout_ PIRP Irp
2317     );
2318 
2319 _Function_class_(IRP_MJ_READ)
2320 _Function_class_(DRIVER_DISPATCH)
2321 NTSTATUS
2322 NTAPI
2323 FatFsdRead (                            //  implemented in Read.c
2324     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2325     _Inout_ PIRP Irp
2326     );
2327 
2328 _Function_class_(IRP_MJ_SHUTDOWN)
2329 _Function_class_(DRIVER_DISPATCH)
2330 NTSTATUS
2331 NTAPI
2332 FatFsdShutdown (                        //  implemented in Shutdown.c
2333     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2334     _Inout_ PIRP Irp
2335     );
2336 
2337 _Function_class_(IRP_MJ_QUERY_VOLUME_INFORMATION)
2338 _Function_class_(DRIVER_DISPATCH)
2339 NTSTATUS
2340 NTAPI
2341 FatFsdQueryVolumeInformation (          //  implemented in VolInfo.c
2342     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2343     _Inout_ PIRP Irp
2344     );
2345 
2346 _Function_class_(IRP_MJ_SET_VOLUME_INFORMATION)
2347 _Function_class_(DRIVER_DISPATCH)
2348 NTSTATUS
2349 NTAPI
2350 FatFsdSetVolumeInformation (            //  implemented in VolInfo.c
2351     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2352     _Inout_ PIRP Irp
2353     );
2354 
2355 _Function_class_(IRP_MJ_WRITE)
2356 _Function_class_(DRIVER_DISPATCH)
2357 NTSTATUS
2358 NTAPI
2359 FatFsdWrite (                           //  implemented in Write.c
2360     _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
2361     _Inout_ PIRP Irp
2362     );
2363 
2364 //
2365 //  The following macro is used to determine if an FSD thread can block
2366 //  for I/O or wait for a resource.  It returns TRUE if the thread can
2367 //  block and FALSE otherwise.  This attribute can then be used to call
2368 //  the FSD & FSP common work routine with the proper wait value.
2369 //
2370 
2371 #define CanFsdWait(IRP) IoIsOperationSynchronous(Irp)
2372 
2373 
2374 //
2375 //  The FSP level dispatch/main routine.  This is the routine that takes
2376 //  IRP's off of the work queue and calls the appropriate FSP level
2377 //  work routine.
2378 //
2379 
2380 
2381 WORKER_THREAD_ROUTINE FatFspDispatch;
2382 
2383 VOID
2384 NTAPI
2385 FatFspDispatch (                        //  implemented in FspDisp.c
2386     _In_ PVOID Context
2387     );
2388 
2389 //
2390 //  The following routines are the FSP work routines that are called
2391 //  by the preceding FatFspDispath routine.  Each takes as input a pointer
2392 //  to the IRP, perform the function, and return a pointer to the volume
2393 //  device object that they just finished servicing (if any).  The return
2394 //  pointer is then used by the main Fsp dispatch routine to check for
2395 //  additional IRPs in the volume's overflow queue.
2396 //
2397 //  Each of the following routines is also responsible for completing the IRP.
2398 //  We moved this responsibility from the main loop to the individual routines
2399 //  to allow them the ability to complete the IRP and continue post processing
2400 //  actions.
2401 //
2402 
2403 _Requires_lock_held_(_Global_critical_region_)
2404 NTSTATUS
2405 FatCommonCleanup (                      //  implemented in Cleanup.c
2406     IN PIRP_CONTEXT IrpContext,
2407     IN PIRP Irp
2408     );
2409 
2410 _Requires_lock_held_(_Global_critical_region_)
2411 NTSTATUS
2412 FatCommonClose (                        //  implemented in Close.c
2413     IN PVCB Vcb,
2414     IN PFCB Fcb,
2415     IN PCCB Ccb,
2416     IN TYPE_OF_OPEN TypeOfOpen,
2417     IN BOOLEAN Wait,
2418     IN BOOLEAN TopLevel,
2419     OUT PBOOLEAN VcbDeleted OPTIONAL
2420     );
2421 
2422 _Requires_lock_held_(_Global_critical_region_)
2423 VOID
2424 FatFspClose (                           //  implemented in Close.c
2425     IN PVCB Vcb OPTIONAL
2426     );
2427 
2428 _Requires_lock_held_(_Global_critical_region_)
2429 NTSTATUS
2430 FatCommonCreate (                       //  implemented in Create.c
2431     _Inout_ PIRP_CONTEXT IrpContext,
2432     _Inout_ PIRP Irp
2433     );
2434 
2435 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
2436 
2437 _Requires_lock_held_(_Global_critical_region_)
2438 NTSTATUS
2439 FatCommonCreateOnNewStack (        //  implemented in Create.c
2440     _Inout_ PIRP_CONTEXT IrpContext,
2441     _Inout_ PIRP Irp
2442     );
2443 
2444 _Requires_lock_held_(_Global_critical_region_)
2445 VOID
2446 FatCommonCreateCallout (              //  implemented in Create.c
2447     _In_ PFAT_CALLOUT_PARAMETERS CalloutParameters
2448     );
2449 
2450 #endif
2451 
2452 _Requires_lock_held_(_Global_critical_region_)
2453 NTSTATUS
2454 FatCommonDirectoryControl (             //  implemented in DirCtrl.c
2455     IN PIRP_CONTEXT IrpContext,
2456     IN PIRP Irp
2457     );
2458 
2459 _Requires_lock_held_(_Global_critical_region_)
2460 NTSTATUS
2461 FatCommonDeviceControl (                //  implemented in DevCtrl.c
2462     IN PIRP_CONTEXT IrpContext,
2463     IN PIRP Irp
2464     );
2465 
2466 NTSTATUS
2467 FatCommonQueryEa (                      //  implemented in Ea.c
2468     IN PIRP_CONTEXT IrpContext,
2469     IN PIRP Irp
2470     );
2471 
2472 NTSTATUS
2473 FatCommonSetEa (                        //  implemented in Ea.c
2474     IN PIRP_CONTEXT IrpContext,
2475     IN PIRP Irp
2476     );
2477 
2478 _Requires_lock_held_(_Global_critical_region_)
2479 NTSTATUS
2480 FatCommonQueryInformation (             //  implemented in FileInfo.c
2481     IN PIRP_CONTEXT IrpContext,
2482     IN PIRP Irp
2483     );
2484 
2485 _Requires_lock_held_(_Global_critical_region_)
2486 NTSTATUS
2487 FatCommonSetInformation (               //  implemented in FileInfo.c
2488     IN PIRP_CONTEXT IrpContext,
2489     IN PIRP Irp
2490     );
2491 
2492 _Requires_lock_held_(_Global_critical_region_)
2493 NTSTATUS
2494 FatCommonFlushBuffers (                 //  implemented in Flush.c
2495     IN PIRP_CONTEXT IrpContext,
2496     IN PIRP Irp
2497     );
2498 
2499 _Requires_lock_held_(_Global_critical_region_)
2500 NTSTATUS
2501 FatCommonFileSystemControl (            //  implemented in FsCtrl.c
2502     IN PIRP_CONTEXT IrpContext,
2503     IN PIRP Irp
2504     );
2505 
2506 _Requires_lock_held_(_Global_critical_region_)
2507 NTSTATUS
2508 FatCommonLockControl (                  //  implemented in LockCtrl.c
2509     IN PIRP_CONTEXT IrpContext,
2510     IN PIRP Irp
2511     );
2512 
2513 _Requires_lock_held_(_Global_critical_region_)
2514 NTSTATUS
2515 FatCommonPnp (                          //  implemented in Pnp.c
2516     IN PIRP_CONTEXT IrpContext,
2517     IN PIRP Irp
2518     );
2519 
2520 _Requires_lock_held_(_Global_critical_region_)
2521 NTSTATUS
2522 FatCommonRead (                         //  implemented in Read.c
2523     IN PIRP_CONTEXT IrpContext,
2524     IN PIRP Irp
2525     );
2526 
2527 _Requires_lock_held_(_Global_critical_region_)
2528 NTSTATUS
2529 FatCommonShutdown (                     //  implemented in Shutdown.c
2530     IN PIRP_CONTEXT IrpContext,
2531     IN PIRP Irp
2532     );
2533 
2534 _Requires_lock_held_(_Global_critical_region_)
2535 NTSTATUS
2536 FatCommonQueryVolumeInfo (              //  implemented in VolInfo.c
2537     IN PIRP_CONTEXT IrpContext,
2538     IN PIRP Irp
2539     );
2540 
2541 _Requires_lock_held_(_Global_critical_region_)
2542 NTSTATUS
2543 FatCommonSetVolumeInfo (                //  implemented in VolInfo.c
2544     IN PIRP_CONTEXT IrpContext,
2545     IN PIRP Irp
2546     );
2547 
2548 _Requires_lock_held_(_Global_critical_region_)
2549 NTSTATUS
2550 FatCommonWrite (                        //  implemented in Write.c
2551     IN PIRP_CONTEXT IrpContext,
2552     IN PIRP Irp
2553     );
2554 
2555 //
2556 //  The following is implemented in Flush.c, and does what is says.
2557 //
2558 
2559 _Requires_lock_held_(_Global_critical_region_)
2560 NTSTATUS
2561 FatFlushFile (
2562     IN PIRP_CONTEXT IrpContext,
2563     IN PFCB Fcb,
2564     IN FAT_FLUSH_TYPE FlushType
2565     );
2566 
2567 _Requires_lock_held_(_Global_critical_region_)
2568 NTSTATUS
2569 FatFlushDirectory (
2570     IN PIRP_CONTEXT IrpContext,
2571     IN PDCB Dcb,
2572     IN FAT_FLUSH_TYPE FlushType
2573     );
2574 
2575 NTSTATUS
2576 FatFlushFat (
2577     IN PIRP_CONTEXT IrpContext,
2578     IN PVCB Vcb
2579     );
2580 
2581 _Requires_lock_held_(_Global_critical_region_)
2582 NTSTATUS
2583 FatFlushVolume (
2584     IN PIRP_CONTEXT IrpContext,
2585     IN PVCB Vcb,
2586     IN FAT_FLUSH_TYPE FlushType
2587     );
2588 
2589 NTSTATUS
2590 FatHijackIrpAndFlushDevice (
2591     IN PIRP_CONTEXT IrpContext,
2592     IN PIRP Irp,
2593     IN PDEVICE_OBJECT TargetDeviceObject
2594     );
2595 
2596 VOID
2597 FatFlushFatEntries (
2598     IN PIRP_CONTEXT IrpContext,
2599     IN PVCB Vcb,
2600     IN ULONG Cluster,
2601     IN ULONG Count
2602 );
2603 
2604 VOID
2605 FatFlushDirentForFile (
2606     IN PIRP_CONTEXT IrpContext,
2607     IN PFCB Fcb
2608 );
2609 
2610 
2611 
2612 //
2613 //  The following procedure is used by the FSP and FSD routines to complete
2614 //  an IRP.
2615 //
2616 //  Note that this macro allows either the Irp or the IrpContext to be
2617 //  null, however the only legal order to do this in is:
2618 //
2619 //      FatCompleteRequest( NULL, Irp, Status );  // completes Irp & preserves context
2620 //      ...
2621 //      FatCompleteRequest( IrpContext, NULL, DontCare ); // deallocates context
2622 //
2623 //  This would typically be done in order to pass a "naked" IrpContext off to
2624 //  the Fsp for post processing, such as read ahead.
2625 //
2626 
2627 VOID
2628 FatCompleteRequest_Real (
2629     IN PIRP_CONTEXT IrpContext,
2630     IN PIRP Irp,
2631     IN NTSTATUS Status
2632     );
2633 
2634 #define FatCompleteRequest(IRPCONTEXT,IRP,STATUS) { \
2635     FatCompleteRequest_Real(IRPCONTEXT,IRP,STATUS); \
2636 }
2637 
2638 BOOLEAN
2639 FatIsIrpTopLevel (
2640     IN PIRP Irp
2641     );
2642 
2643 //
2644 //  The Following routine makes a popup
2645 //
2646 
2647 _Requires_lock_held_(_Global_critical_region_)
2648 VOID
2649 FatPopUpFileCorrupt (
2650     IN PIRP_CONTEXT IrpContext,
2651     IN PFCB Fcb
2652     );
2653 
2654 //
2655 //  Here are the callbacks used by the I/O system for checking for fast I/O or
2656 //  doing a fast query info call, or doing fast lock calls.
2657 //
2658 _Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
2659 BOOLEAN
2660 NTAPI
2661 FatFastIoCheckIfPossible (
2662     IN PFILE_OBJECT FileObject,
2663     IN PLARGE_INTEGER FileOffset,
2664     IN ULONG Length,
2665     IN BOOLEAN Wait,
2666     IN ULONG LockKey,
2667     IN BOOLEAN CheckForReadOperation,
2668     OUT PIO_STATUS_BLOCK IoStatus,
2669     IN PDEVICE_OBJECT DeviceObject
2670     );
2671 
2672 _Function_class_(FAST_IO_QUERY_BASIC_INFO)
2673 BOOLEAN
2674 NTAPI
2675 FatFastQueryBasicInfo (
2676     IN PFILE_OBJECT FileObject,
2677     IN BOOLEAN Wait,
2678     IN OUT PFILE_BASIC_INFORMATION Buffer,
2679     OUT PIO_STATUS_BLOCK IoStatus,
2680     IN PDEVICE_OBJECT DeviceObject
2681     );
2682 
2683 _Function_class_(FAST_IO_QUERY_STANDARD_INFO)
2684 BOOLEAN
2685 NTAPI
2686 FatFastQueryStdInfo (
2687     IN PFILE_OBJECT FileObject,
2688     IN BOOLEAN Wait,
2689     IN OUT PFILE_STANDARD_INFORMATION Buffer,
2690     OUT PIO_STATUS_BLOCK IoStatus,
2691     IN PDEVICE_OBJECT DeviceObject
2692     );
2693 
2694 _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
2695 BOOLEAN
2696 NTAPI
2697 FatFastQueryNetworkOpenInfo (
2698     IN PFILE_OBJECT FileObject,
2699     IN BOOLEAN Wait,
2700     IN OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
2701     OUT PIO_STATUS_BLOCK IoStatus,
2702     IN PDEVICE_OBJECT DeviceObject
2703     );
2704 
2705 _Function_class_(FAST_IO_LOCK)
2706 BOOLEAN
2707 NTAPI
2708 FatFastLock (
2709     IN PFILE_OBJECT FileObject,
2710     IN PLARGE_INTEGER FileOffset,
2711     IN PLARGE_INTEGER Length,
2712     PEPROCESS ProcessId,
2713     ULONG Key,
2714     BOOLEAN FailImmediately,
2715     BOOLEAN ExclusiveLock,
2716     OUT PIO_STATUS_BLOCK IoStatus,
2717     IN PDEVICE_OBJECT DeviceObject
2718     );
2719 
2720 _Function_class_(FAST_IO_UNLOCK_SINGLE)
2721 BOOLEAN
2722 NTAPI
2723 FatFastUnlockSingle (
2724     IN PFILE_OBJECT FileObject,
2725     IN PLARGE_INTEGER FileOffset,
2726     IN PLARGE_INTEGER Length,
2727     PEPROCESS ProcessId,
2728     ULONG Key,
2729     OUT PIO_STATUS_BLOCK IoStatus,
2730     IN PDEVICE_OBJECT DeviceObject
2731     );
2732 
2733 _Function_class_(FAST_IO_UNLOCK_ALL)
2734 BOOLEAN
2735 NTAPI
2736 FatFastUnlockAll (
2737     IN PFILE_OBJECT FileObject,
2738     PEPROCESS ProcessId,
2739     OUT PIO_STATUS_BLOCK IoStatus,
2740     IN PDEVICE_OBJECT DeviceObject
2741     );
2742 
2743 _Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)
2744 BOOLEAN
2745 NTAPI
2746 FatFastUnlockAllByKey (
2747     IN PFILE_OBJECT FileObject,
2748     PVOID ProcessId,
2749     ULONG Key,
2750     OUT PIO_STATUS_BLOCK IoStatus,
2751     IN PDEVICE_OBJECT DeviceObject
2752     );
2753 
2754 
2755 VOID
2756 FatExamineFatEntries(
2757     IN PIRP_CONTEXT IrpContext,
2758     IN PVCB Vcb,
2759     IN ULONG StartIndex OPTIONAL,
2760     IN ULONG EndIndex OPTIONAL,
2761     IN BOOLEAN SetupWindows,
2762     IN PFAT_WINDOW SwitchToWindow OPTIONAL,
2763     IN PULONG BitMapBuffer OPTIONAL
2764     );
2765 
2766 BOOLEAN
2767 FatScanForDataTrack(
2768     IN PIRP_CONTEXT IrpContext,
2769     IN PDEVICE_OBJECT TargetDeviceObject
2770     );
2771 
2772 //
2773 //  The following macro is used to determine is a file has been deleted.
2774 //
2775 //      BOOLEAN
2776 //      IsFileDeleted (
2777 //          IN PIRP_CONTEXT IrpContext,
2778 //          IN PFCB Fcb
2779 //          );
2780 //
2781 
2782 #define IsFileDeleted(IRPCONTEXT,FCB)                      \
2783     (FlagOn((FCB)->FcbState, FCB_STATE_DELETE_ON_CLOSE) && \
2784      ((FCB)->UncleanCount == 0))
2785 
2786 //
2787 //  The following macro is used by the dispatch routines to determine if
2788 //  an operation is to be done with or without Write Through.
2789 //
2790 //      BOOLEAN
2791 //      IsFileWriteThrough (
2792 //          IN PFILE_OBJECT FileObject,
2793 //          IN PVCB Vcb
2794 //          );
2795 //
2796 
2797 #define IsFileWriteThrough(FO,VCB) (             \
2798     BooleanFlagOn((FO)->Flags, FO_WRITE_THROUGH) \
2799 )
2800 
2801 //
2802 //  The following macro is used to set the is fast i/o possible field in
2803 //  the common part of the nonpaged fcb.  It checks that this is actually
2804 //  an FCB (as opposed to a DCB) so that directory oplock code works properly.
2805 //
2806 //
2807 //      BOOLEAN
2808 //      FatIsFastIoPossible (
2809 //          IN PFCB Fcb
2810 //          );
2811 //
2812 
2813 
2814 #define FatIsFastIoPossible(FCB) ((BOOLEAN)                                     \
2815     ((((FCB)->FcbCondition != FcbGood) ||                                       \
2816       (NodeType( (FCB) ) != FAT_NTC_FCB) ||                                     \
2817       !FsRtlOplockIsFastIoPossible( FatGetFcbOplock(FCB) )) ?                   \
2818         FastIoIsNotPossible                                                     \
2819     :                                                                           \
2820         (!FsRtlAreThereCurrentFileLocks( &(FCB)->Specific.Fcb.FileLock ) &&     \
2821          ((FCB)->NonPaged->OutstandingAsyncWrites == 0) &&                      \
2822          !FlagOn( (FCB)->Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED ) ?      \
2823             FastIoIsPossible                                                    \
2824         :                                                                       \
2825             FastIoIsQuestionable                                                \
2826         )                                                                       \
2827     )                                                                           \
2828 )
2829 
2830 
2831 #if (NTDDI_VERSION >= NTDDI_WIN8)
2832 
2833 //
2834 //  Detect whether this file can have an oplock on it.  As of Windows 8 file and
2835 //  directories can have oplocks.
2836 //
2837 
2838 #define FatIsNodeTypeOplockable(N) (    \
2839     ((N) == FAT_NTC_FCB) ||             \
2840     ((N) == FAT_NTC_ROOT_DCB) ||        \
2841     ((N) == FAT_NTC_DCB)                \
2842 )
2843 
2844 #else
2845 
2846 #define FatIsNodeTypeOplockable(N) (    \
2847     ((N) == FAT_NTC_FCB)                \
2848 )
2849 
2850 #endif
2851 
2852 #define FatIsFileOplockable(F) (                \
2853     FatIsNodeTypeOplockable( NodeType( (F) ))   \
2854 )
2855 
2856 //
2857 //  The following macro is used to detemine if the file object is opened
2858 //  for read only access (i.e., it is not also opened for write access or
2859 //  delete access).
2860 //
2861 //      BOOLEAN
2862 //      IsFileObjectReadOnly (
2863 //          IN PFILE_OBJECT FileObject
2864 //          );
2865 //
2866 
2867 #define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
2868 
2869 
2870 //
2871 //  The following two macro are used by the Fsd/Fsp exception handlers to
2872 //  process an exception.  The first macro is the exception filter used in the
2873 //  Fsd/Fsp to decide if an exception should be handled at this level.
2874 //  The second macro decides if the exception is to be finished off by
2875 //  completing the IRP, and cleaning up the Irp Context, or if we should
2876 //  bugcheck.  Exception values such as STATUS_FILE_INVALID (raised by
2877 //  VerfySup.c) cause us to complete the Irp and cleanup, while exceptions
2878 //  such as accvio cause us to bugcheck.
2879 //
2880 //  The basic structure for fsd/fsp exception handling is as follows:
2881 //
2882 //  FatFsdXxx(...)
2883 //  {
2884 //      try {
2885 //
2886 //          ...
2887 //
2888 //      } except(FatExceptionFilter( IrpContext, GetExceptionCode() )) {
2889 //
2890 //          Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
2891 //      }
2892 //
2893 //      Return Status;
2894 //  }
2895 //
2896 //  To explicitly raise an exception that we expect, such as
2897 //  STATUS_FILE_INVALID, use the below macro FatRaiseStatus().  To raise a
2898 //  status from an unknown origin (such as CcFlushCache()), use the macro
2899 //  FatNormalizeAndRaiseStatus.  This will raise the status if it is expected,
2900 //  or raise STATUS_UNEXPECTED_IO_ERROR if it is not.
2901 //
2902 //  If we are vicariously handling exceptions without using FatProcessException(),
2903 //  if there is the possibility that we raised that exception, one *must*
2904 //  reset the IrpContext so a subsequent raise in the course of handling this
2905 //  request that is *not* explicit, i.e. like a pagein error, does not get
2906 //  spoofed into believing that the first raise status is the reason the second
2907 //  occured.  This could have really serious consequences.
2908 //
2909 //  It is an excellent idea to always FatResetExceptionState in these cases.
2910 //
2911 //  Note that when using these two macros, the original status is placed in
2912 //  IrpContext->ExceptionStatus, signaling FatExceptionFilter and
2913 //  FatProcessException that the status we actually raise is by definition
2914 //  expected.
2915 //
2916 
2917 ULONG
2918 FatExceptionFilter (
2919     IN PIRP_CONTEXT IrpContext,
2920     IN PEXCEPTION_POINTERS ExceptionPointer
2921     );
2922 
2923 #if DBG
2924 ULONG
2925 FatBugCheckExceptionFilter (
2926     IN PEXCEPTION_POINTERS ExceptionPointer
2927     );
2928 #endif
2929 
2930 _Requires_lock_held_(_Global_critical_region_)
2931 NTSTATUS
2932 FatProcessException (
2933     IN PIRP_CONTEXT IrpContext,
2934     IN PIRP Irp,
2935     IN NTSTATUS ExceptionCode
2936     );
2937 
2938 //
2939 //  VOID
2940 //  FatRaiseStatus (
2941 //      IN PRIP_CONTEXT IrpContext,
2942 //      IN NT_STATUS Status
2943 //  );
2944 //
2945 //
2946 
2947 #if DBG
2948 #ifdef _MSC_VER
2949 #define DebugBreakOnStatus(S) {                                                      \
2950 __pragma(warning(push))                                                              \
2951 __pragma(warning(disable:4127))                                                      \
2952     if (FatTestRaisedStatus) {                                                       \
2953         if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) {  \
2954 __pragma(warning(pop))                                                               \
2955             DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\
2956             DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n",       \
2957                       &FatTestRaisedStatus );                                        \
2958             NT_ASSERT(FALSE);                                                        \
2959         }                                                                            \
2960     }                                                                                \
2961 }
2962 #else
2963 #define DebugBreakOnStatus(S) {                                                      \
2964     if (FatTestRaisedStatus) {                                                       \
2965         if ((S) == STATUS_DISK_CORRUPT_ERROR || (S) == STATUS_FILE_CORRUPT_ERROR) {  \
2966             DbgPrint( "FAT: Breaking on interesting raised status (0x%08x)\n", (S) );\
2967             DbgPrint( "FAT: Set FatTestRaisedStatus @ 0x%p to 0 to disable\n",       \
2968                       &FatTestRaisedStatus );                                        \
2969             NT_ASSERT(FALSE);                                                        \
2970         }                                                                            \
2971     }                                                                                \
2972 }
2973 #endif
2974 #else
2975 #define DebugBreakOnStatus(S)
2976 #endif
2977 
2978 #define FatRaiseStatus(IRPCONTEXT,STATUS) {             \
2979     (IRPCONTEXT)->ExceptionStatus = (STATUS);           \
2980     DebugBreakOnStatus( (STATUS) )                      \
2981     ExRaiseStatus( (STATUS) );                          \
2982 }
2983 
2984 #define FatResetExceptionState( IRPCONTEXT ) {          \
2985     (IRPCONTEXT)->ExceptionStatus = STATUS_SUCCESS;     \
2986 }
2987 
2988 //
2989 //  VOID
2990 //  FatNormalAndRaiseStatus (
2991 //      IN PRIP_CONTEXT IrpContext,
2992 //      IN NT_STATUS Status
2993 //  );
2994 //
2995 
2996 #define FatNormalizeAndRaiseStatus(IRPCONTEXT,STATUS) {                         \
2997     (IRPCONTEXT)->ExceptionStatus = (STATUS);                                   \
2998     ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \
2999 }
3000 
3001 
3002 //
3003 //  The following macros are used to establish the semantics needed
3004 //  to do a return from within a try-finally clause.  As a rule every
3005 //  try clause must end with a label call try_exit.  For example,
3006 //
3007 //      try {
3008 //              :
3009 //              :
3010 //
3011 //      try_exit: NOTHING;
3012 //      } finally {
3013 //
3014 //              :
3015 //              :
3016 //      }
3017 //
3018 //  Every return statement executed inside of a try clause should use the
3019 //  try_return macro.  If the compiler fully supports the try-finally construct
3020 //  then the macro should be
3021 //
3022 //      #define try_return(S)  { return(S); }
3023 //
3024 //  If the compiler does not support the try-finally construct then the macro
3025 //  should be
3026 //
3027 //      #define try_return(S)  { S; goto try_exit; }
3028 //
3029 
3030 #define try_return(S) { S; goto try_exit; }
3031 #define try_leave(S) { S; _SEH2_LEAVE; }
3032 
3033 
3034 CLUSTER_TYPE
3035 FatInterpretClusterType (
3036     IN PVCB Vcb,
3037     IN FAT_ENTRY Entry
3038     );
3039 
3040 
3041 //
3042 //  These routines define the FileId for FAT.  Lacking a fixed/uniquifiable
3043 //  notion, we simply come up with one which is unique in a given snapshot
3044 //  of the volume.  As long as the parent directory is not moved or compacted,
3045 //  it may even be permanent.
3046 //
3047 
3048 //
3049 //  The internal information used to identify the fcb/dcb on the
3050 //  volume is the byte offset of the dirent of the file on disc.
3051 //  Our root always has fileid 0.  FAT32 roots are chains and can
3052 //  use the LBO of the cluster, 12/16 roots use the lbo in the Vcb.
3053 //
3054 
3055 #define FatGenerateFileIdFromDirentOffset(ParentDcb,DirentOffset)                                   \
3056     ((ParentDcb) ? ((NodeType(ParentDcb) != FAT_NTC_ROOT_DCB || FatIsFat32((ParentDcb)->Vcb)) ?     \
3057                   FatGetLboFromIndex( (ParentDcb)->Vcb,                                             \
3058                                       (ParentDcb)->FirstClusterOfFile ) :                           \
3059                   (ParentDcb)->Vcb->AllocationSupport.RootDirectoryLbo) +                           \
3060                  (DirentOffset)                                                                     \
3061                   :                                                                                 \
3062                  0)
3063 
3064 //
3065 //
3066 
3067 #define FatGenerateFileIdFromFcb(Fcb)                                                               \
3068         FatGenerateFileIdFromDirentOffset( (Fcb)->ParentDcb, (Fcb)->DirentOffsetWithinDirectory )
3069 
3070 //
3071 //  Wrap to handle the ./.. cases appropriately.  Note that we commute NULL parent to 0. This would
3072 //  only occur in an illegal root ".." entry.
3073 //
3074 
3075 #define FATDOT    ((ULONG)0x2020202E)
3076 #define FATDOTDOT ((ULONG)0x20202E2E)
3077 
3078 #define FatGenerateFileIdFromDirentAndOffset(Dcb,Dirent,DirentOffset)                               \
3079     ((*((PULONG)(Dirent)->FileName)) == FATDOT ? FatGenerateFileIdFromFcb(Dcb) :                    \
3080      ((*((PULONG)(Dirent)->FileName)) == FATDOTDOT ? ((Dcb)->ParentDcb ?                            \
3081                                                        FatGenerateFileIdFromFcb((Dcb)->ParentDcb) : \
3082                                                        0) :                                         \
3083       FatGenerateFileIdFromDirentOffset(Dcb,DirentOffset)))
3084 
3085 
3086 //
3087 //  BOOLEAN
3088 //  FatDeviceIsFatFsdo(
3089 //      IN PDEVICE_OBJECT D
3090 //      );
3091 //
3092 //  Evaluates to TRUE if the supplied device object is one of the file system devices
3093 //  we created at initialisation.
3094 //
3095 
3096 #define FatDeviceIsFatFsdo( D)  (((D) == FatData.DiskFileSystemDeviceObject) || ((D) == FatData.CdromFileSystemDeviceObject))
3097 
3098 
3099 //
3100 //  BlockAlign(): Aligns P on the next V boundary.
3101 //  BlockAlignTruncate(): Aligns P on the prev V boundary.
3102 //
3103 
3104 #define BlockAlign(P,V) ((ASSERT( V != 0)), (((P)) + (V-1) & (0-(V))))
3105 #define BlockAlignTruncate(P,V) ((P) & (0-(V)))
3106 
3107 #define IsDirectory(FcbOrDcb) ((NodeType((FcbOrDcb)) == FAT_NTC_DCB) || (NodeType((FcbOrDcb)) == FAT_NTC_ROOT_DCB))
3108 
3109 #endif // _FATPROCS_
3110 
3111 
3112