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