xref: /reactos/drivers/filesystems/vfatfs/vfat.h (revision 84344399)
1 #ifndef _VFATFS_PCH_
2 #define _VFATFS_PCH_
3 
4 #include <ntifs.h>
5 #include <ntdddisk.h>
6 #include <dos.h>
7 #include <pseh/pseh2.h>
8 #include <section_attribs.h>
9 #ifdef KDBG
10 #include <ndk/kdfuncs.h>
11 #include <reactos/kdros.h>
12 #endif
13 
14 
15 #define USE_ROS_CC_AND_FS
16 #define ENABLE_SWAPOUT
17 
18 /* FIXME: because volume is not cached, we have to perform direct IOs
19  * The day this is fixed, just comment out that line, and check
20  * it still works (and delete old code ;-))
21  */
22 #define VOLUME_IS_NOT_CACHED_WORK_AROUND_IT
23 
24 
25 #define ROUND_DOWN(n, align) \
26     (((ULONG)n) & ~((align) - 1l))
27 
28 #define ROUND_UP(n, align) \
29     ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
30 
31 #define ROUND_DOWN_64(n, align) \
32     (((ULONGLONG)n) & ~((align) - 1LL))
33 
34 #define ROUND_UP_64(n, align) \
35     ROUND_DOWN_64(((ULONGLONG)n) + (align) - 1LL, (align))
36 
37 #include <pshpack1.h>
38 struct _BootSector
39 {
40     unsigned char  magic0, res0, magic1;
41     unsigned char  OEMName[8];
42     unsigned short BytesPerSector;
43     unsigned char  SectorsPerCluster;
44     unsigned short ReservedSectors;
45     unsigned char  FATCount;
46     unsigned short RootEntries, Sectors;
47     unsigned char  Media;
48     unsigned short FATSectors, SectorsPerTrack, Heads;
49     unsigned long  HiddenSectors, SectorsHuge;
50     unsigned char  Drive, Res1, Sig;
51     unsigned long  VolumeID;
52     unsigned char  VolumeLabel[11], SysType[8];
53     unsigned char  Res2[448];
54     unsigned short Signatur1;
55 };
56 
57 struct _BootSector32
58 {
59     unsigned char  magic0, res0, magic1;			// 0
60     unsigned char  OEMName[8];				// 3
61     unsigned short BytesPerSector;			// 11
62     unsigned char  SectorsPerCluster;			// 13
63     unsigned short ReservedSectors;			// 14
64     unsigned char  FATCount;				// 16
65     unsigned short RootEntries, Sectors;			// 17
66     unsigned char  Media;					// 21
67     unsigned short FATSectors, SectorsPerTrack, Heads;	// 22
68     unsigned long  HiddenSectors, SectorsHuge;		// 28
69     unsigned long  FATSectors32;				// 36
70     unsigned short ExtFlag;				// 40
71     unsigned short FSVersion;				// 42
72     unsigned long  RootCluster;				// 44
73     unsigned short FSInfoSector;				// 48
74     unsigned short BootBackup;				// 50
75     unsigned char  Res3[12];				// 52
76     unsigned char  Drive;					// 64
77     unsigned char  Res4;					// 65
78     unsigned char  ExtBootSignature;			// 66
79     unsigned long  VolumeID;				// 67
80     unsigned char  VolumeLabel[11], SysType[8];		// 71
81     unsigned char  Res2[420];				// 90
82     unsigned short Signature1;				// 510
83 };
84 
85 #define FAT_DIRTY_BIT 0x01
86 
87 struct _BootSectorFatX
88 {
89     unsigned char SysType[4];        // 0
90     unsigned long VolumeID;          // 4
91     unsigned long SectorsPerCluster; // 8
92     unsigned short FATCount;         // 12
93     unsigned long Unknown;           // 14
94     unsigned char Unused[4078];      // 18
95 };
96 
97 struct _FsInfoSector
98 {
99     unsigned long  ExtBootSignature2;			// 0
100     unsigned char  Res6[480];				// 4
101     unsigned long  FSINFOSignature;			// 484
102     unsigned long  FreeCluster;				// 488
103     unsigned long  NextCluster;				// 492
104     unsigned char  Res7[12];				// 496
105     unsigned long  Signatur2;				// 508
106 };
107 
108 typedef struct _BootSector BootSector;
109 
110 struct _FATDirEntry
111 {
112     union
113     {
114         struct { unsigned char Filename[8], Ext[3]; };
115         unsigned char ShortName[11];
116     };
117     unsigned char  Attrib;
118     unsigned char  lCase;
119     unsigned char  CreationTimeMs;
120     unsigned short CreationTime,CreationDate,AccessDate;
121     union
122     {
123         unsigned short FirstClusterHigh; // FAT32
124         unsigned short ExtendedAttributes; // FAT12/FAT16
125     };
126     unsigned short UpdateTime;                            //time create/update
127     unsigned short UpdateDate;                            //date create/update
128     unsigned short FirstCluster;
129     unsigned long  FileSize;
130 };
131 
132 #define FAT_EAFILE  "EA DATA. SF"
133 
134 typedef struct _EAFileHeader FAT_EA_FILE_HEADER, *PFAT_EA_FILE_HEADER;
135 
136 struct _EAFileHeader
137 {
138     unsigned short Signature; // ED
139     unsigned short Unknown[15];
140     unsigned short EASetTable[240];
141 };
142 
143 typedef struct _EASetHeader FAT_EA_SET_HEADER, *PFAT_EA_SET_HEADER;
144 
145 struct _EASetHeader
146 {
147     unsigned short Signature; // EA
148     unsigned short Offset; // relative offset, same value as in the EASetTable
149     unsigned short Unknown1[2];
150     char TargetFileName[12];
151     unsigned short Unknown2[3];
152     unsigned int EALength;
153     // EA Header
154 };
155 
156 typedef struct _EAHeader FAT_EA_HEADER, *PFAT_EA_HEADER;
157 
158 struct _EAHeader
159 {
160     unsigned char Unknown;
161     unsigned char EANameLength;
162     unsigned short EAValueLength;
163     // Name Data
164     // Value Data
165 };
166 
167 typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
168 
169 struct _FATXDirEntry
170 {
171     unsigned char FilenameLength; // 0
172     unsigned char Attrib;         // 1
173     unsigned char Filename[42];   // 2
174     unsigned long FirstCluster;   // 44
175     unsigned long FileSize;       // 48
176     unsigned short UpdateTime;    // 52
177     unsigned short UpdateDate;    // 54
178     unsigned short CreationTime;  // 56
179     unsigned short CreationDate;  // 58
180     unsigned short AccessTime;    // 60
181     unsigned short AccessDate;    // 62
182 };
183 
184 struct _slot
185 {
186     unsigned char id;               // sequence number for slot
187     WCHAR  name0_4[5];              // first 5 characters in name
188     unsigned char attr;             // attribute byte
189     unsigned char reserved;         // always 0
190     unsigned char alias_checksum;   // checksum for 8.3 alias
191     WCHAR  name5_10[6];             // 6 more characters in name
192     unsigned char start[2];         // starting cluster number
193     WCHAR  name11_12[2];            // last 2 characters in name
194 };
195 
196 typedef struct _slot slot;
197 
198 #include <poppack.h>
199 
200 #define VFAT_CASE_LOWER_BASE	8  		// base is lower case
201 #define VFAT_CASE_LOWER_EXT 	16 		// extension is lower case
202 
203 #define LONGNAME_MAX_LENGTH 	256		// max length for a long filename
204 
205 #define ENTRY_DELETED(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
206 #define ENTRY_VOLUME(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
207 #define ENTRY_END(IsFatX, DirEntry) (IsFatX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
208 
209 #define FAT_ENTRY_DELETED(DirEntry)  ((DirEntry)->Filename[0] == 0xe5)
210 #define FAT_ENTRY_END(DirEntry)      ((DirEntry)->Filename[0] == 0)
211 #define FAT_ENTRY_LONG(DirEntry)     (((DirEntry)->Attrib & 0x3f) == 0x0f)
212 #define FAT_ENTRY_VOLUME(DirEntry)   (((DirEntry)->Attrib & 0x1f) == 0x08)
213 
214 #define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
215 #define FATX_ENTRY_END(DirEntry)     ((DirEntry)->FilenameLength == 0xff)
216 #define FATX_ENTRY_LONG(DirEntry)    (FALSE)
217 #define FATX_ENTRY_VOLUME(DirEntry)  (((DirEntry)->Attrib & 0x1f) == 0x08)
218 
219 #define FAT_ENTRIES_PER_PAGE   (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
220 #define FATX_ENTRIES_PER_PAGE  (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
221 
222 typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY;
223 
224 union _DIR_ENTRY
225 {
226     FAT_DIR_ENTRY Fat;
227     FATX_DIR_ENTRY FatX;
228 };
229 
230 typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY;
231 
232 #define BLOCKSIZE 512
233 
234 #define FAT16  (1)
235 #define FAT12  (2)
236 #define FAT32  (3)
237 #define FATX16 (4)
238 #define FATX32 (5)
239 
240 #define VCB_VOLUME_LOCKED       0x0001
241 #define VCB_DISMOUNT_PENDING    0x0002
242 #define VCB_IS_FATX             0x0004
243 #define VCB_IS_SYS_OR_HAS_PAGE  0x0008
244 #define VCB_IS_DIRTY            0x4000 /* Volume is dirty */
245 #define VCB_CLEAR_DIRTY         0x8000 /* Clean dirty flag at shutdown */
246 /* VCB condition state */
247 #define VCB_GOOD                0x0010 /* If not set, the VCB is improper for usage */
248 
249 typedef struct
250 {
251     ULONG VolumeID;
252     CHAR VolumeLabel[11];
253     ULONG FATStart;
254     ULONG FATCount;
255     ULONG FATSectors;
256     ULONG rootDirectorySectors;
257     ULONG rootStart;
258     ULONG dataStart;
259     ULONG RootCluster;
260     ULONG SectorsPerCluster;
261     ULONG BytesPerSector;
262     ULONG BytesPerCluster;
263     ULONG NumberOfClusters;
264     ULONG FatType;
265     ULONG Sectors;
266     BOOLEAN FixedMedia;
267     ULONG FSInfoSector;
268 } FATINFO, *PFATINFO;
269 
270 struct _VFATFCB;
271 struct _VFAT_DIRENTRY_CONTEXT;
272 struct _VFAT_MOVE_CONTEXT;
273 struct _VFAT_CLOSE_CONTEXT;
274 
275 typedef struct _HASHENTRY
276 {
277     ULONG Hash;
278     struct _VFATFCB* self;
279     struct _HASHENTRY* next;
280 }
281 HASHENTRY;
282 
283 typedef struct DEVICE_EXTENSION *PDEVICE_EXTENSION;
284 
285 typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG);
286 typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG);
287 typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG);
288 
289 typedef BOOLEAN (*PIS_DIRECTORY_EMPTY)(PDEVICE_EXTENSION,struct _VFATFCB*);
290 typedef NTSTATUS (*PADD_ENTRY)(PDEVICE_EXTENSION,PUNICODE_STRING,struct _VFATFCB**,struct _VFATFCB*,ULONG,UCHAR,struct _VFAT_MOVE_CONTEXT*);
291 typedef NTSTATUS (*PDEL_ENTRY)(PDEVICE_EXTENSION,struct _VFATFCB*,struct _VFAT_MOVE_CONTEXT*);
292 typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN);
293 typedef NTSTATUS (*PGET_DIRTY_STATUS)(PDEVICE_EXTENSION,PBOOLEAN);
294 typedef NTSTATUS (*PSET_DIRTY_STATUS)(PDEVICE_EXTENSION,BOOLEAN);
295 
296 typedef struct _VFAT_DISPATCH
297 {
298     PIS_DIRECTORY_EMPTY IsDirectoryEmpty;
299     PADD_ENTRY AddEntry;
300     PDEL_ENTRY DelEntry;
301     PGET_NEXT_DIR_ENTRY GetNextDirEntry;
302 } VFAT_DISPATCH, *PVFAT_DISPATCH;
303 
304 #define STATISTICS_SIZE_NO_PAD (sizeof(FILESYSTEM_STATISTICS) + sizeof(FAT_STATISTICS))
305 typedef struct _STATISTICS {
306     FILESYSTEM_STATISTICS Base;
307     FAT_STATISTICS Fat;
308     UCHAR Pad[((STATISTICS_SIZE_NO_PAD + 0x3f) & ~0x3f) - STATISTICS_SIZE_NO_PAD];
309 } STATISTICS, *PSTATISTICS;
310 
311 typedef struct DEVICE_EXTENSION
312 {
313     ERESOURCE DirResource;
314     ERESOURCE FatResource;
315 
316     KSPIN_LOCK FcbListLock;
317     LIST_ENTRY FcbListHead;
318     ULONG HashTableSize;
319     struct _HASHENTRY **FcbHashTable;
320 
321     PDEVICE_OBJECT VolumeDevice;
322     PDEVICE_OBJECT StorageDevice;
323     PFILE_OBJECT FATFileObject;
324     FATINFO FatInfo;
325     ULONG LastAvailableCluster;
326     ULONG AvailableClusters;
327     BOOLEAN AvailableClustersValid;
328     ULONG Flags;
329     struct _VFATFCB *VolumeFcb;
330     struct _VFATFCB *RootFcb;
331     PSTATISTICS Statistics;
332 
333     /* Overflow request queue */
334     KSPIN_LOCK OverflowQueueSpinLock;
335     LIST_ENTRY OverflowQueue;
336     ULONG OverflowQueueCount;
337     ULONG PostedRequestCount;
338 
339     /* Pointers to functions for manipulating FAT. */
340     PGET_NEXT_CLUSTER GetNextCluster;
341     PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
342     PWRITE_CLUSTER WriteCluster;
343     PGET_DIRTY_STATUS GetDirtyStatus;
344     PSET_DIRTY_STATUS SetDirtyStatus;
345 
346     ULONG BaseDateYear;
347 
348     LIST_ENTRY VolumeListEntry;
349 
350     /* Notifications */
351     LIST_ENTRY NotifyList;
352     PNOTIFY_SYNC NotifySync;
353 
354     /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE */
355     ULONG OpenHandleCount;
356 
357     /* VPBs for dismount */
358     PVPB IoVPB;
359     PVPB SpareVPB;
360 
361     /* Pointers to functions for manipulating directory entries. */
362     VFAT_DISPATCH Dispatch;
363 } DEVICE_EXTENSION, VCB, *PVCB;
364 
365 FORCEINLINE
366 BOOLEAN
367 VfatIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt,
368                      struct _VFATFCB* Fcb)
369 {
370     return DeviceExt->Dispatch.IsDirectoryEmpty(DeviceExt, Fcb);
371 }
372 
373 FORCEINLINE
374 NTSTATUS
375 VfatAddEntry(PDEVICE_EXTENSION DeviceExt,
376              PUNICODE_STRING NameU,
377              struct _VFATFCB** Fcb,
378              struct _VFATFCB* ParentFcb,
379              ULONG RequestedOptions,
380              UCHAR ReqAttr,
381              struct _VFAT_MOVE_CONTEXT* MoveContext)
382 {
383     return DeviceExt->Dispatch.AddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr, MoveContext);
384 }
385 
386 FORCEINLINE
387 NTSTATUS
388 VfatDelEntry(PDEVICE_EXTENSION DeviceExt,
389              struct _VFATFCB* Fcb,
390              struct _VFAT_MOVE_CONTEXT* MoveContext)
391 {
392     return DeviceExt->Dispatch.DelEntry(DeviceExt, Fcb, MoveContext);
393 }
394 
395 FORCEINLINE
396 NTSTATUS
397 VfatGetNextDirEntry(PDEVICE_EXTENSION DeviceExt,
398                     PVOID *pContext,
399                     PVOID *pPage,
400                     struct _VFATFCB* pDirFcb,
401                     struct _VFAT_DIRENTRY_CONTEXT* DirContext,
402                     BOOLEAN First)
403 {
404     return DeviceExt->Dispatch.GetNextDirEntry(pContext, pPage, pDirFcb, DirContext, First);
405 }
406 
407 #define VFAT_BREAK_ON_CORRUPTION 1
408 
409 typedef struct
410 {
411     PDRIVER_OBJECT DriverObject;
412     PDEVICE_OBJECT DeviceObject;
413     ULONG Flags;
414     ULONG NumberProcessors;
415     ERESOURCE VolumeListLock;
416     LIST_ENTRY VolumeListHead;
417     NPAGED_LOOKASIDE_LIST FcbLookasideList;
418     NPAGED_LOOKASIDE_LIST CcbLookasideList;
419     NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
420     PAGED_LOOKASIDE_LIST CloseContextLookasideList;
421     FAST_IO_DISPATCH FastIoDispatch;
422     CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
423     FAST_MUTEX CloseMutex;
424     ULONG CloseCount;
425     LIST_ENTRY CloseListHead;
426     BOOLEAN CloseWorkerRunning;
427     PIO_WORKITEM CloseWorkItem;
428     BOOLEAN ShutdownStarted;
429 } VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA;
430 
431 extern PVFAT_GLOBAL_DATA VfatGlobalData;
432 
433 #define FCB_CACHE_INITIALIZED   0x0001
434 #define FCB_DELETE_PENDING      0x0002
435 #define FCB_IS_FAT              0x0004
436 #define FCB_IS_PAGE_FILE        0x0008
437 #define FCB_IS_VOLUME           0x0010
438 #define FCB_IS_DIRTY            0x0020
439 #define FCB_DELAYED_CLOSE       0x0040
440 #ifdef KDBG
441 #define FCB_CLEANED_UP          0x0080
442 #define FCB_CLOSED              0x0100
443 #endif
444 
445 #define NODE_TYPE_FCB ((CSHORT)0x0502)
446 
447 typedef struct _VFATFCB
448 {
449     /* FCB header required by ROS/NT */
450     FSRTL_COMMON_FCB_HEADER RFCB;
451     SECTION_OBJECT_POINTERS SectionObjectPointers;
452     ERESOURCE MainResource;
453     ERESOURCE PagingIoResource;
454     /* end FCB header required by ROS/NT */
455 
456     /* directory entry for this file or directory */
457     DIR_ENTRY entry;
458 
459     /* Pointer to attributes in entry */
460     PUCHAR Attributes;
461 
462     /* long file name, points into PathNameBuffer */
463     UNICODE_STRING LongNameU;
464 
465     /* short file name */
466     UNICODE_STRING ShortNameU;
467 
468     /* directory name, points into PathNameBuffer */
469     UNICODE_STRING DirNameU;
470 
471     /* path + long file name 260 max*/
472     UNICODE_STRING PathNameU;
473 
474     /* buffer for PathNameU */
475     PWCHAR PathNameBuffer;
476 
477     /* buffer for ShortNameU */
478     WCHAR ShortNameBuffer[13];
479 
480     /* */
481     LONG RefCount;
482 
483     /* List of FCB's for this volume */
484     LIST_ENTRY FcbListEntry;
485 
486     /* List of FCB's for the parent */
487     LIST_ENTRY ParentListEntry;
488 
489     /* pointer to the parent fcb */
490     struct _VFATFCB *parentFcb;
491 
492     /* List for the children */
493     LIST_ENTRY ParentListHead;
494 
495     /* Flags for the fcb */
496     ULONG Flags;
497 
498     /* pointer to the file object which has initialized the fcb */
499     PFILE_OBJECT FileObject;
500 
501     /* Directory index for the short name entry */
502     ULONG dirIndex;
503 
504     /* Directory index where the long name starts */
505     ULONG startIndex;
506 
507     /* Share access for the file object */
508     SHARE_ACCESS FCBShareAccess;
509 
510     /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
511     ULONG OpenHandleCount;
512 
513     /* Entry into the hash table for the path + long name */
514     HASHENTRY Hash;
515 
516     /* Entry into the hash table for the path + short name */
517     HASHENTRY ShortHash;
518 
519     /* List of byte-range locks for this file */
520     FILE_LOCK FileLock;
521 
522     /*
523      * Optimization: caching of last read/write cluster+offset pair. Can't
524      * be in VFATCCB because it must be reset everytime the allocated clusters
525      * change.
526      */
527     FAST_MUTEX LastMutex;
528     ULONG LastCluster;
529     ULONG LastOffset;
530 
531     struct _VFAT_CLOSE_CONTEXT * CloseContext;
532 } VFATFCB, *PVFATFCB;
533 
534 #define CCB_DELETE_ON_CLOSE     0x0001
535 
536 typedef struct _VFATCCB
537 {
538     LARGE_INTEGER  CurrentByteOffset;
539     ULONG Flags;
540     /* for DirectoryControl */
541     ULONG Entry;
542     /* for DirectoryControl */
543     UNICODE_STRING SearchPattern;
544 } VFATCCB, *PVFATCCB;
545 
546 #define TAG_CCB  'CtaF'
547 #define TAG_FCB  'FtaF'
548 #define TAG_IRP  'ItaF'
549 #define TAG_CLOSE 'xtaF'
550 #define TAG_STATS 'VtaF'
551 #define TAG_BUFFER 'OtaF'
552 #define TAG_VPB 'vtaF'
553 #define TAG_NAME 'ntaF'
554 #define TAG_SEARCH 'LtaF'
555 #define TAG_DIRENT 'DtaF'
556 
557 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
558 
559 typedef struct __DOSTIME
560 {
561     USHORT Second:5;
562     USHORT Minute:6;
563     USHORT Hour:5;
564 }
565 DOSTIME, *PDOSTIME;
566 
567 typedef struct __DOSDATE
568 {
569     USHORT Day:5;
570     USHORT Month:4;
571     USHORT Year:7;
572 }
573 DOSDATE, *PDOSDATE;
574 
575 #define IRPCONTEXT_CANWAIT          0x0001
576 #define IRPCONTEXT_COMPLETE         0x0002
577 #define IRPCONTEXT_QUEUE            0x0004
578 #define IRPCONTEXT_PENDINGRETURNED  0x0008
579 #define IRPCONTEXT_DEFERRED_WRITE   0x0010
580 
581 typedef struct
582 {
583     PIRP Irp;
584     PDEVICE_OBJECT DeviceObject;
585     PDEVICE_EXTENSION DeviceExt;
586     ULONG Flags;
587     WORK_QUEUE_ITEM WorkQueueItem;
588     PIO_STACK_LOCATION Stack;
589     UCHAR MajorFunction;
590     UCHAR MinorFunction;
591     PFILE_OBJECT FileObject;
592     ULONG RefCount;
593     KEVENT Event;
594     CCHAR PriorityBoost;
595 } VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
596 
597 typedef struct _VFAT_DIRENTRY_CONTEXT
598 {
599     ULONG StartIndex;
600     ULONG DirIndex;
601     DIR_ENTRY DirEntry;
602     UNICODE_STRING LongNameU;
603     UNICODE_STRING ShortNameU;
604     PDEVICE_EXTENSION DeviceExt;
605 } VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
606 
607 typedef struct _VFAT_MOVE_CONTEXT
608 {
609     ULONG FirstCluster;
610     ULONG FileSize;
611     USHORT CreationDate;
612     USHORT CreationTime;
613     BOOLEAN InPlace;
614 } VFAT_MOVE_CONTEXT, *PVFAT_MOVE_CONTEXT;
615 
616 typedef struct _VFAT_CLOSE_CONTEXT
617 {
618     PDEVICE_EXTENSION Vcb;
619     PVFATFCB Fcb;
620     LIST_ENTRY CloseListEntry;
621 } VFAT_CLOSE_CONTEXT, *PVFAT_CLOSE_CONTEXT;
622 
623 FORCEINLINE
624 NTSTATUS
625 VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)
626 {
627     PULONG Flags = &IrpContext->Flags;
628 
629     *Flags &= ~IRPCONTEXT_COMPLETE;
630     *Flags |= IRPCONTEXT_QUEUE;
631 
632     return STATUS_PENDING;
633 }
634 
635 FORCEINLINE
636 BOOLEAN
637 vfatFCBIsDirectory(PVFATFCB FCB)
638 {
639     return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_DIRECTORY);
640 }
641 
642 FORCEINLINE
643 BOOLEAN
644 vfatFCBIsReadOnly(PVFATFCB FCB)
645 {
646     return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_READONLY);
647 }
648 
649 FORCEINLINE
650 BOOLEAN
651 vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
652 {
653     return BooleanFlagOn(DeviceExt->Flags, VCB_IS_FATX);
654 }
655 
656 FORCEINLINE
657 VOID
658 vfatReportChange(
659     IN PDEVICE_EXTENSION DeviceExt,
660     IN PVFATFCB Fcb,
661     IN ULONG FilterMatch,
662     IN ULONG Action)
663 {
664     FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
665                                 &(DeviceExt->NotifyList),
666                                 (PSTRING)&Fcb->PathNameU,
667                                 Fcb->PathNameU.Length - Fcb->LongNameU.Length,
668                                 NULL, NULL, FilterMatch, Action, NULL);
669 }
670 
671 #define vfatAddToStat(Vcb, Stat, Inc)                                                                         \
672 {                                                                                                             \
673     PSTATISTICS Stats = &(Vcb)->Statistics[KeGetCurrentProcessorNumber() % VfatGlobalData->NumberProcessors]; \
674     Stats->Stat += Inc;                                                                                       \
675 }
676 
677 /* blockdev.c */
678 
679 NTSTATUS
680 VfatReadDisk(
681     IN PDEVICE_OBJECT pDeviceObject,
682     IN PLARGE_INTEGER ReadOffset,
683     IN ULONG ReadLength,
684     IN PUCHAR Buffer,
685     IN BOOLEAN Override);
686 
687 NTSTATUS
688 VfatReadDiskPartial(
689     IN PVFAT_IRP_CONTEXT IrpContext,
690     IN PLARGE_INTEGER ReadOffset,
691     IN ULONG ReadLength,
692     IN ULONG BufferOffset,
693     IN BOOLEAN Wait);
694 
695 NTSTATUS
696 VfatWriteDisk(
697     IN PDEVICE_OBJECT pDeviceObject,
698     IN PLARGE_INTEGER WriteOffset,
699     IN ULONG WriteLength,
700     IN OUT PUCHAR Buffer,
701     IN BOOLEAN Override);
702 
703 NTSTATUS
704 VfatWriteDiskPartial(
705     IN PVFAT_IRP_CONTEXT IrpContext,
706     IN PLARGE_INTEGER WriteOffset,
707     IN ULONG WriteLength,
708     IN ULONG BufferOffset,
709     IN BOOLEAN Wait);
710 
711 NTSTATUS
712 VfatBlockDeviceIoControl(
713     IN PDEVICE_OBJECT DeviceObject,
714     IN ULONG CtlCode,
715     IN PVOID InputBuffer,
716     IN ULONG InputBufferSize,
717     IN OUT PVOID OutputBuffer,
718     IN OUT PULONG pOutputBufferSize,
719     IN BOOLEAN Override);
720 
721 /* cleanup.c */
722 
723 NTSTATUS
724 VfatCleanup(
725     PVFAT_IRP_CONTEXT IrpContext);
726 
727 /* close.c */
728 
729 NTSTATUS
730 VfatClose(
731     PVFAT_IRP_CONTEXT IrpContext);
732 
733 NTSTATUS
734 VfatCloseFile(
735     PDEVICE_EXTENSION DeviceExt,
736     PFILE_OBJECT FileObject);
737 
738 /* create.c */
739 
740 NTSTATUS
741 VfatCreate(
742     PVFAT_IRP_CONTEXT IrpContext);
743 
744 NTSTATUS
745 FindFile(
746     PDEVICE_EXTENSION DeviceExt,
747     PVFATFCB Parent,
748     PUNICODE_STRING FileToFindU,
749     PVFAT_DIRENTRY_CONTEXT DirContext,
750     BOOLEAN First);
751 
752 VOID
753 vfat8Dot3ToString(
754     PFAT_DIR_ENTRY pEntry,
755     PUNICODE_STRING NameU);
756 
757 /* dir.c */
758 
759 NTSTATUS
760 VfatDirectoryControl(
761     PVFAT_IRP_CONTEXT IrpContext);
762 
763 BOOLEAN
764 FsdDosDateTimeToSystemTime(
765     PDEVICE_EXTENSION DeviceExt,
766     USHORT DosDate,
767     USHORT DosTime,
768     PLARGE_INTEGER SystemTime);
769 
770 BOOLEAN
771 FsdSystemTimeToDosDateTime(
772     PDEVICE_EXTENSION DeviceExt,
773     PLARGE_INTEGER SystemTime,
774     USHORT *pDosDate,
775     USHORT *pDosTime);
776 
777 /* direntry.c */
778 
779 ULONG
780 vfatDirEntryGetFirstCluster(
781     PDEVICE_EXTENSION pDeviceExt,
782     PDIR_ENTRY pDirEntry);
783 
784 /* dirwr.c */
785 
786 NTSTATUS
787 vfatFCBInitializeCacheFromVolume(
788     PVCB vcb,
789     PVFATFCB fcb);
790 
791 NTSTATUS
792 VfatUpdateEntry(
793     IN PDEVICE_EXTENSION DeviceExt,
794     PVFATFCB pFcb);
795 
796 BOOLEAN
797 vfatFindDirSpace(
798     PDEVICE_EXTENSION DeviceExt,
799     PVFATFCB pDirFcb,
800     ULONG nbSlots,
801     PULONG start);
802 
803 NTSTATUS
804 vfatRenameEntry(
805     IN PDEVICE_EXTENSION DeviceExt,
806     IN PVFATFCB pFcb,
807     IN PUNICODE_STRING FileName,
808     IN BOOLEAN CaseChangeOnly);
809 
810 NTSTATUS
811 VfatMoveEntry(
812     IN PDEVICE_EXTENSION DeviceExt,
813     IN PVFATFCB pFcb,
814     IN PUNICODE_STRING FileName,
815     IN PVFATFCB ParentFcb);
816 
817 /* ea.h */
818 
819 NTSTATUS
820 VfatSetExtendedAttributes(
821     PFILE_OBJECT FileObject,
822     PVOID Ea,
823     ULONG EaLength);
824 
825 /* fastio.c */
826 
827 CODE_SEG("INIT")
828 VOID
829 VfatInitFastIoRoutines(
830     PFAST_IO_DISPATCH FastIoDispatch);
831 
832 BOOLEAN
833 NTAPI
834 VfatAcquireForLazyWrite(
835     IN PVOID Context,
836     IN BOOLEAN Wait);
837 
838 VOID
839 NTAPI
840 VfatReleaseFromLazyWrite(
841     IN PVOID Context);
842 
843 /* fat.c */
844 
845 NTSTATUS
846 FAT12GetNextCluster(
847     PDEVICE_EXTENSION DeviceExt,
848     ULONG CurrentCluster,
849     PULONG NextCluster);
850 
851 NTSTATUS
852 FAT12FindAndMarkAvailableCluster(
853     PDEVICE_EXTENSION DeviceExt,
854     PULONG Cluster);
855 
856 NTSTATUS
857 FAT12WriteCluster(
858     PDEVICE_EXTENSION DeviceExt,
859     ULONG ClusterToWrite,
860     ULONG NewValue,
861     PULONG OldValue);
862 
863 NTSTATUS
864 FAT16GetNextCluster(
865     PDEVICE_EXTENSION DeviceExt,
866     ULONG CurrentCluster,
867     PULONG NextCluster);
868 
869 NTSTATUS
870 FAT16FindAndMarkAvailableCluster(
871     PDEVICE_EXTENSION DeviceExt,
872     PULONG Cluster);
873 
874 NTSTATUS
875 FAT16WriteCluster(
876     PDEVICE_EXTENSION DeviceExt,
877     ULONG ClusterToWrite,
878     ULONG NewValue,
879     PULONG OldValue);
880 
881 NTSTATUS
882 FAT32GetNextCluster(
883     PDEVICE_EXTENSION DeviceExt,
884     ULONG CurrentCluster,
885     PULONG NextCluster);
886 
887 NTSTATUS
888 FAT32FindAndMarkAvailableCluster(
889     PDEVICE_EXTENSION DeviceExt,
890     PULONG Cluster);
891 
892 NTSTATUS
893 FAT32WriteCluster(
894     PDEVICE_EXTENSION DeviceExt,
895     ULONG ClusterToWrite,
896     ULONG NewValue,
897     PULONG OldValue);
898 
899 NTSTATUS
900 OffsetToCluster(
901     PDEVICE_EXTENSION DeviceExt,
902     ULONG FirstCluster,
903     ULONG FileOffset,
904     PULONG Cluster,
905     BOOLEAN Extend);
906 
907 ULONGLONG
908 ClusterToSector(
909     PDEVICE_EXTENSION DeviceExt,
910     ULONG Cluster);
911 
912 NTSTATUS
913 GetNextCluster(
914     PDEVICE_EXTENSION DeviceExt,
915     ULONG CurrentCluster,
916     PULONG NextCluster);
917 
918 NTSTATUS
919 GetNextClusterExtend(
920     PDEVICE_EXTENSION DeviceExt,
921     ULONG CurrentCluster,
922     PULONG NextCluster);
923 
924 NTSTATUS
925 CountAvailableClusters(
926     PDEVICE_EXTENSION DeviceExt,
927     PLARGE_INTEGER Clusters);
928 
929 NTSTATUS
930 WriteCluster(
931     PDEVICE_EXTENSION DeviceExt,
932     ULONG ClusterToWrite,
933     ULONG NewValue);
934 
935 NTSTATUS
936 GetDirtyStatus(
937     PDEVICE_EXTENSION DeviceExt,
938     PBOOLEAN DirtyStatus);
939 
940 NTSTATUS
941 FAT16GetDirtyStatus(
942     PDEVICE_EXTENSION DeviceExt,
943     PBOOLEAN DirtyStatus);
944 
945 NTSTATUS
946 FAT32GetDirtyStatus(
947     PDEVICE_EXTENSION DeviceExt,
948     PBOOLEAN DirtyStatus);
949 
950 NTSTATUS
951 SetDirtyStatus(
952     PDEVICE_EXTENSION DeviceExt,
953     BOOLEAN DirtyStatus);
954 
955 NTSTATUS
956 FAT16SetDirtyStatus(
957     PDEVICE_EXTENSION DeviceExt,
958     BOOLEAN DirtyStatus);
959 
960 NTSTATUS
961 FAT32SetDirtyStatus(
962     PDEVICE_EXTENSION DeviceExt,
963     BOOLEAN DirtyStatus);
964 
965 NTSTATUS
966 FAT32UpdateFreeClustersCount(
967     PDEVICE_EXTENSION DeviceExt);
968 
969 /* fcb.c */
970 
971 PVFATFCB
972 vfatNewFCB(
973     PDEVICE_EXTENSION pVCB,
974     PUNICODE_STRING pFileNameU);
975 
976 NTSTATUS
977 vfatSetFCBNewDirName(
978     PDEVICE_EXTENSION pVCB,
979     PVFATFCB Fcb,
980     PVFATFCB ParentFcb);
981 
982 NTSTATUS
983 vfatUpdateFCB(
984     PDEVICE_EXTENSION pVCB,
985     PVFATFCB Fcb,
986     PVFAT_DIRENTRY_CONTEXT DirContext,
987     PVFATFCB ParentFcb);
988 
989 VOID
990 vfatDestroyFCB(
991     PVFATFCB pFCB);
992 
993 VOID
994 vfatDestroyCCB(
995     PVFATCCB pCcb);
996 
997 VOID
998 #ifndef KDBG
999 vfatGrabFCB(
1000 #else
1001 _vfatGrabFCB(
1002 #endif
1003     PDEVICE_EXTENSION pVCB,
1004     PVFATFCB pFCB
1005 #ifdef KDBG
1006     ,
1007     PCSTR File,
1008     ULONG Line,
1009     PCSTR Func
1010 #endif
1011     );
1012 
1013 VOID
1014 #ifndef KDBG
1015 vfatReleaseFCB(
1016 #else
1017 _vfatReleaseFCB(
1018 #endif
1019     PDEVICE_EXTENSION pVCB,
1020     PVFATFCB pFCB
1021 #ifdef KDBG
1022     ,
1023     PCSTR File,
1024     ULONG Line,
1025     PCSTR Func
1026 #endif
1027     );
1028 
1029 #ifdef KDBG
1030 #define vfatGrabFCB(v, f) _vfatGrabFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
1031 #define vfatReleaseFCB(v, f) _vfatReleaseFCB(v, f, __FILE__, __LINE__, __FUNCTION__)
1032 #endif
1033 
1034 PVFATFCB
1035 vfatGrabFCBFromTable(
1036     PDEVICE_EXTENSION pDeviceExt,
1037     PUNICODE_STRING pFileNameU);
1038 
1039 PVFATFCB
1040 vfatMakeRootFCB(
1041     PDEVICE_EXTENSION pVCB);
1042 
1043 PVFATFCB
1044 vfatOpenRootFCB(
1045     PDEVICE_EXTENSION pVCB);
1046 
1047 BOOLEAN
1048 vfatFCBIsDirectory(
1049     PVFATFCB FCB);
1050 
1051 BOOLEAN
1052 vfatFCBIsRoot(
1053     PVFATFCB FCB);
1054 
1055 NTSTATUS
1056 vfatAttachFCBToFileObject(
1057     PDEVICE_EXTENSION vcb,
1058     PVFATFCB fcb,
1059     PFILE_OBJECT fileObject);
1060 
1061 NTSTATUS
1062 vfatDirFindFile(
1063     PDEVICE_EXTENSION pVCB,
1064     PVFATFCB parentFCB,
1065     PUNICODE_STRING FileToFindU,
1066     PVFATFCB *fileFCB);
1067 
1068 NTSTATUS
1069 vfatGetFCBForFile(
1070     PDEVICE_EXTENSION pVCB,
1071     PVFATFCB *pParentFCB,
1072     PVFATFCB *pFCB,
1073     PUNICODE_STRING pFileNameU);
1074 
1075 NTSTATUS
1076 vfatMakeFCBFromDirEntry(
1077     PVCB vcb,
1078     PVFATFCB directoryFCB,
1079     PVFAT_DIRENTRY_CONTEXT DirContext,
1080     PVFATFCB *fileFCB);
1081 
1082 /* finfo.c */
1083 
1084 NTSTATUS
1085 VfatGetStandardInformation(
1086     PVFATFCB FCB,
1087     PFILE_STANDARD_INFORMATION StandardInfo,
1088     PULONG BufferLength);
1089 
1090 NTSTATUS
1091 VfatGetBasicInformation(
1092     PFILE_OBJECT FileObject,
1093     PVFATFCB FCB,
1094     PDEVICE_EXTENSION DeviceExt,
1095     PFILE_BASIC_INFORMATION BasicInfo,
1096     PULONG BufferLength);
1097 
1098 NTSTATUS
1099 VfatQueryInformation(
1100     PVFAT_IRP_CONTEXT IrpContext);
1101 
1102 NTSTATUS
1103 VfatSetInformation(
1104     PVFAT_IRP_CONTEXT IrpContext);
1105 
1106 NTSTATUS
1107 VfatSetAllocationSizeInformation(
1108     PFILE_OBJECT FileObject,
1109     PVFATFCB Fcb,
1110     PDEVICE_EXTENSION DeviceExt,
1111     PLARGE_INTEGER AllocationSize);
1112 
1113 /* flush.c */
1114 
1115 NTSTATUS
1116 VfatFlush(
1117     PVFAT_IRP_CONTEXT IrpContext);
1118 
1119 NTSTATUS
1120 VfatFlushVolume(
1121     PDEVICE_EXTENSION DeviceExt,
1122     PVFATFCB VolumeFcb);
1123 
1124 /* fsctl.c */
1125 
1126 NTSTATUS
1127 VfatFileSystemControl(
1128     PVFAT_IRP_CONTEXT IrpContext);
1129 
1130 /* iface.c */
1131 
1132 CODE_SEG("INIT")
1133 NTSTATUS
1134 NTAPI
1135 DriverEntry(
1136     PDRIVER_OBJECT DriverObject,
1137     PUNICODE_STRING RegistryPath);
1138 
1139 #ifdef KDBG
1140 /* kdbg.c */
1141 KDBG_CLI_ROUTINE vfatKdbgHandler;
1142 #endif
1143 
1144 /* misc.c */
1145 
1146 DRIVER_DISPATCH
1147 VfatBuildRequest;
1148 
1149 NTSTATUS
1150 NTAPI
1151 VfatBuildRequest(
1152     PDEVICE_OBJECT DeviceObject,
1153     PIRP Irp);
1154 
1155 PVOID
1156 VfatGetUserBuffer(
1157     IN PIRP Irp,
1158     IN BOOLEAN Paging);
1159 
1160 NTSTATUS
1161 VfatLockUserBuffer(
1162     IN PIRP Irp,
1163     IN ULONG Length,
1164     IN LOCK_OPERATION Operation);
1165 
1166 BOOLEAN
1167 VfatCheckForDismount(
1168     IN PDEVICE_EXTENSION DeviceExt,
1169     IN BOOLEAN Create);
1170 
1171 VOID
1172 vfatReportChange(
1173     IN PDEVICE_EXTENSION DeviceExt,
1174     IN PVFATFCB Fcb,
1175     IN ULONG FilterMatch,
1176     IN ULONG Action);
1177 
1178 VOID
1179 NTAPI
1180 VfatHandleDeferredWrite(
1181     IN PVOID IrpContext,
1182     IN PVOID Unused);
1183 
1184 /* pnp.c */
1185 
1186 NTSTATUS
1187 VfatPnp(
1188     PVFAT_IRP_CONTEXT IrpContext);
1189 
1190 /* rw.c */
1191 
1192 NTSTATUS
1193 VfatRead(
1194     PVFAT_IRP_CONTEXT IrpContext);
1195 
1196 NTSTATUS
1197 VfatWrite(
1198     PVFAT_IRP_CONTEXT *pIrpContext);
1199 
1200 NTSTATUS
1201 NextCluster(
1202     PDEVICE_EXTENSION DeviceExt,
1203     ULONG FirstCluster,
1204     PULONG CurrentCluster,
1205     BOOLEAN Extend);
1206 
1207 /* shutdown.c */
1208 
1209 DRIVER_DISPATCH
1210 VfatShutdown;
1211 
1212 NTSTATUS
1213 NTAPI
1214 VfatShutdown(
1215     PDEVICE_OBJECT DeviceObject,
1216     PIRP Irp);
1217 
1218 /* string.c */
1219 
1220 VOID
1221 vfatSplitPathName(
1222     PUNICODE_STRING PathNameU,
1223     PUNICODE_STRING DirNameU,
1224     PUNICODE_STRING FileNameU);
1225 
1226 BOOLEAN
1227 vfatIsLongIllegal(
1228     WCHAR c);
1229 
1230 BOOLEAN
1231 IsDotOrDotDot(
1232     PCUNICODE_STRING Name);
1233 
1234 /* volume.c */
1235 
1236 NTSTATUS
1237 VfatQueryVolumeInformation(
1238     PVFAT_IRP_CONTEXT IrpContext);
1239 
1240 NTSTATUS
1241 VfatSetVolumeInformation(
1242     PVFAT_IRP_CONTEXT IrpContext);
1243 
1244 #endif /* _VFATFS_PCH_ */
1245