8 #define USE_ROS_CC_AND_FS
10 #define ROUND_DOWN(n, align) \
11 (((ULONG)n) & ~((align) - 1l))
13 #define ROUND_UP(n, align) \
14 ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
19 unsigned char magic0
, res0
, magic1
;
20 unsigned char OEMName
[8];
21 unsigned short BytesPerSector
;
22 unsigned char SectorsPerCluster
;
23 unsigned short ReservedSectors
;
24 unsigned char FATCount
;
25 unsigned short RootEntries
, Sectors
;
27 unsigned short FATSectors
, SectorsPerTrack
, Heads
;
28 unsigned long HiddenSectors
, SectorsHuge
;
29 unsigned char Drive
, Res1
, Sig
;
30 unsigned long VolumeID
;
31 unsigned char VolumeLabel
[11], SysType
[8];
32 unsigned char Res2
[448];
33 unsigned short Signatur1
;
38 unsigned char magic0
, res0
, magic1
; // 0
39 unsigned char OEMName
[8]; // 3
40 unsigned short BytesPerSector
; // 11
41 unsigned char SectorsPerCluster
; // 13
42 unsigned short ReservedSectors
; // 14
43 unsigned char FATCount
; // 16
44 unsigned short RootEntries
, Sectors
; // 17
45 unsigned char Media
; // 21
46 unsigned short FATSectors
, SectorsPerTrack
, Heads
; // 22
47 unsigned long HiddenSectors
, SectorsHuge
; // 28
48 unsigned long FATSectors32
; // 36
49 unsigned short ExtFlag
; // 40
50 unsigned short FSVersion
; // 42
51 unsigned long RootCluster
; // 44
52 unsigned short FSInfoSector
; // 48
53 unsigned short BootBackup
; // 50
54 unsigned char Res3
[12]; // 52
55 unsigned char Drive
; // 64
56 unsigned char Res4
; // 65
57 unsigned char ExtBootSignature
; // 66
58 unsigned long VolumeID
; // 67
59 unsigned char VolumeLabel
[11], SysType
[8]; // 71
60 unsigned char Res2
[420]; // 90
61 unsigned short Signature1
; // 510
64 struct _BootSectorFatX
66 unsigned char SysType
[4]; // 0
67 unsigned long VolumeID
; // 4
68 unsigned long SectorsPerCluster
; // 8
69 unsigned short FATCount
; // 12
70 unsigned long Unknown
; // 14
71 unsigned char Unused
[4078]; // 18
76 unsigned long ExtBootSignature2
; // 0
77 unsigned char Res6
[480]; // 4
78 unsigned long FSINFOSignature
; // 484
79 unsigned long FreeCluster
; // 488
80 unsigned long NextCluster
; // 492
81 unsigned char Res7
[12]; // 496
82 unsigned long Signatur2
; // 508
85 typedef struct _BootSector BootSector
;
91 struct { unsigned char Filename
[8], Ext
[3]; };
92 unsigned char ShortName
[11];
96 unsigned char CreationTimeMs
;
97 unsigned short CreationTime
,CreationDate
,AccessDate
;
100 unsigned short FirstClusterHigh
; // FAT32
101 unsigned short ExtendedAttributes
; // FAT12/FAT16
103 unsigned short UpdateTime
; //time create/update
104 unsigned short UpdateDate
; //date create/update
105 unsigned short FirstCluster
;
106 unsigned long FileSize
;
109 #define FAT_EAFILE "EA DATA. SF"
111 typedef struct _EAFileHeader FAT_EA_FILE_HEADER
, *PFAT_EA_FILE_HEADER
;
115 unsigned short Signature
; // ED
116 unsigned short Unknown
[15];
117 unsigned short EASetTable
[240];
120 typedef struct _EASetHeader FAT_EA_SET_HEADER
, *PFAT_EA_SET_HEADER
;
124 unsigned short Signature
; // EA
125 unsigned short Offset
; // relative offset, same value as in the EASetTable
126 unsigned short Unknown1
[2];
127 char TargetFileName
[12];
128 unsigned short Unknown2
[3];
129 unsigned int EALength
;
133 typedef struct _EAHeader FAT_EA_HEADER
, *PFAT_EA_HEADER
;
137 unsigned char Unknown
;
138 unsigned char EANameLength
;
139 unsigned short EAValueLength
;
144 typedef struct _FATDirEntry FAT_DIR_ENTRY
, *PFAT_DIR_ENTRY
;
148 unsigned char FilenameLength
; // 0
149 unsigned char Attrib
; // 1
150 unsigned char Filename
[42]; // 2
151 unsigned long FirstCluster
; // 44
152 unsigned long FileSize
; // 48
153 unsigned short UpdateTime
; // 52
154 unsigned short UpdateDate
; // 54
155 unsigned short CreationTime
; // 56
156 unsigned short CreationDate
; // 58
157 unsigned short AccessTime
; // 60
158 unsigned short AccessDate
; // 62
163 unsigned char id
; // sequence number for slot
164 WCHAR name0_4
[5]; // first 5 characters in name
165 unsigned char attr
; // attribute byte
166 unsigned char reserved
; // always 0
167 unsigned char alias_checksum
; // checksum for 8.3 alias
168 WCHAR name5_10
[6]; // 6 more characters in name
169 unsigned char start
[2]; // starting cluster number
170 WCHAR name11_12
[2]; // last 2 characters in name
173 typedef struct _slot slot
;
177 #define VFAT_CASE_LOWER_BASE 8 // base is lower case
178 #define VFAT_CASE_LOWER_EXT 16 // extension is lower case
180 #define LONGNAME_MAX_LENGTH 256 // max length for a long filename
182 #define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
183 #define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
184 #define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
186 #define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
187 #define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
188 #define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
189 #define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
191 #define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
192 #define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
193 #define FATX_ENTRY_LONG(DirEntry) (FALSE)
194 #define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
196 #define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
197 #define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
199 typedef struct _FATXDirEntry FATX_DIR_ENTRY
, *PFATX_DIR_ENTRY
;
207 typedef union _DIR_ENTRY DIR_ENTRY
, *PDIR_ENTRY
;
209 #define BLOCKSIZE 512
217 #define VCB_VOLUME_LOCKED 0x0001
218 #define VCB_DISMOUNT_PENDING 0x0002
219 #define VCB_IS_FATX 0x0004
220 #define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
221 #define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
229 ULONG rootDirectorySectors
;
233 ULONG SectorsPerCluster
;
234 ULONG BytesPerSector
;
235 ULONG BytesPerCluster
;
236 ULONG NumberOfClusters
;
240 } FATINFO
, *PFATINFO
;
243 struct _VFAT_DIRENTRY_CONTEXT
;
245 typedef struct _HASHENTRY
248 struct _VFATFCB
* self
;
249 struct _HASHENTRY
* next
;
253 #define FCB_HASH_TABLE_SIZE 65536
255 typedef struct DEVICE_EXTENSION
*PDEVICE_EXTENSION
;
257 typedef NTSTATUS (*PGET_NEXT_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,PULONG
);
258 typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER
)(PDEVICE_EXTENSION
,PULONG
);
259 typedef NTSTATUS (*PWRITE_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,ULONG
,PULONG
);
261 typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY
)(PVOID
*,PVOID
*,struct _VFATFCB
*,struct _VFAT_DIRENTRY_CONTEXT
*,BOOLEAN
);
263 typedef struct DEVICE_EXTENSION
265 ERESOURCE DirResource
;
266 ERESOURCE FatResource
;
268 KSPIN_LOCK FcbListLock
;
269 LIST_ENTRY FcbListHead
;
271 struct _HASHENTRY
**FcbHashTable
;
273 PDEVICE_OBJECT StorageDevice
;
274 PFILE_OBJECT FATFileObject
;
276 ULONG LastAvailableCluster
;
277 ULONG AvailableClusters
;
278 BOOLEAN AvailableClustersValid
;
280 struct _VFATFCB
*VolumeFcb
;
282 /* Pointers to functions for manipulating FAT. */
283 PGET_NEXT_CLUSTER GetNextCluster
;
284 PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster
;
285 PWRITE_CLUSTER WriteCluster
;
286 ULONG CleanShutBitMask
;
288 /* Pointers to functions for manipulating directory entries. */
289 PGET_NEXT_DIR_ENTRY GetNextDirEntry
;
293 LIST_ENTRY VolumeListEntry
;
296 LIST_ENTRY NotifyList
;
297 PNOTIFY_SYNC NotifySync
;
298 } DEVICE_EXTENSION
, VCB
, *PVCB
;
302 PDRIVER_OBJECT DriverObject
;
303 PDEVICE_OBJECT DeviceObject
;
305 ERESOURCE VolumeListLock
;
306 LIST_ENTRY VolumeListHead
;
307 NPAGED_LOOKASIDE_LIST FcbLookasideList
;
308 NPAGED_LOOKASIDE_LIST CcbLookasideList
;
309 NPAGED_LOOKASIDE_LIST IrpContextLookasideList
;
310 FAST_IO_DISPATCH FastIoDispatch
;
311 CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
;
312 } VFAT_GLOBAL_DATA
, *PVFAT_GLOBAL_DATA
;
314 extern PVFAT_GLOBAL_DATA VfatGlobalData
;
316 #define FCB_CACHE_INITIALIZED 0x0001
317 #define FCB_DELETE_PENDING 0x0002
318 #define FCB_IS_FAT 0x0004
319 #define FCB_IS_PAGE_FILE 0x0008
320 #define FCB_IS_VOLUME 0x0010
321 #define FCB_IS_DIRTY 0x0020
322 #define FCB_IS_FATX_ENTRY 0x0040
324 typedef struct _VFATFCB
326 /* FCB header required by ROS/NT */
327 FSRTL_COMMON_FCB_HEADER RFCB
;
328 SECTION_OBJECT_POINTERS SectionObjectPointers
;
329 ERESOURCE MainResource
;
330 ERESOURCE PagingIoResource
;
331 /* end FCB header required by ROS/NT */
333 /* directory entry for this file or directory */
336 /* Pointer to attributes in entry */
339 /* long file name, points into PathNameBuffer */
340 UNICODE_STRING LongNameU
;
342 /* short file name */
343 UNICODE_STRING ShortNameU
;
345 /* directory name, points into PathNameBuffer */
346 UNICODE_STRING DirNameU
;
348 /* path + long file name 260 max*/
349 UNICODE_STRING PathNameU
;
351 /* buffer for PathNameU */
352 PWCHAR PathNameBuffer
;
354 /* buffer for ShortNameU */
355 WCHAR ShortNameBuffer
[13];
360 /* List of FCB's for this volume */
361 LIST_ENTRY FcbListEntry
;
363 /* pointer to the parent fcb */
364 struct _VFATFCB
*parentFcb
;
366 /* Flags for the fcb */
369 /* pointer to the file object which has initialized the fcb */
370 PFILE_OBJECT FileObject
;
372 /* Directory index for the short name entry */
375 /* Directory index where the long name starts */
378 /* Share access for the file object */
379 SHARE_ACCESS FCBShareAccess
;
381 /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
382 ULONG OpenHandleCount
;
384 /* Entry into the hash table for the path + long name */
387 /* Entry into the hash table for the path + short name */
390 /* List of byte-range locks for this file */
394 * Optimalization: caching of last read/write cluster+offset pair. Can't
395 * be in VFATCCB because it must be reset everytime the allocated clusters
398 FAST_MUTEX LastMutex
;
401 } VFATFCB
, *PVFATFCB
;
403 typedef struct _VFATCCB
405 LARGE_INTEGER CurrentByteOffset
;
406 /* for DirectoryControl */
408 /* for DirectoryControl */
409 UNICODE_STRING SearchPattern
;
410 } VFATCCB
, *PVFATCCB
;
412 #define TAG_CCB 'BCCV'
413 #define TAG_FCB 'BCFV'
414 #define TAG_IRP 'PRIV'
415 #define TAG_VFAT 'TAFV'
417 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
419 typedef struct __DOSTIME
427 typedef struct __DOSDATE
435 #define IRPCONTEXT_CANWAIT 0x0001
436 #define IRPCONTEXT_PENDINGRETURNED 0x0002
441 PDEVICE_OBJECT DeviceObject
;
442 PDEVICE_EXTENSION DeviceExt
;
444 WORK_QUEUE_ITEM WorkQueueItem
;
445 PIO_STACK_LOCATION Stack
;
448 PFILE_OBJECT FileObject
;
451 } VFAT_IRP_CONTEXT
, *PVFAT_IRP_CONTEXT
;
453 typedef struct _VFAT_DIRENTRY_CONTEXT
458 UNICODE_STRING LongNameU
;
459 UNICODE_STRING ShortNameU
;
460 } VFAT_DIRENTRY_CONTEXT
, *PVFAT_DIRENTRY_CONTEXT
;
467 IN PDEVICE_OBJECT pDeviceObject
,
468 IN PLARGE_INTEGER ReadOffset
,
471 IN BOOLEAN Override
);
475 IN PVFAT_IRP_CONTEXT IrpContext
,
476 IN PLARGE_INTEGER ReadOffset
,
478 IN ULONG BufferOffset
,
482 VfatWriteDiskPartial(
483 IN PVFAT_IRP_CONTEXT IrpContext
,
484 IN PLARGE_INTEGER WriteOffset
,
485 IN ULONG WriteLength
,
486 IN ULONG BufferOffset
,
490 VfatBlockDeviceIoControl(
491 IN PDEVICE_OBJECT DeviceObject
,
493 IN PVOID InputBuffer
,
494 IN ULONG InputBufferSize
,
495 IN OUT PVOID OutputBuffer
,
496 IN OUT PULONG pOutputBufferSize
,
497 IN BOOLEAN Override
);
503 PVFAT_IRP_CONTEXT IrpContext
);
509 PVFAT_IRP_CONTEXT IrpContext
);
513 PDEVICE_EXTENSION DeviceExt
,
514 PFILE_OBJECT FileObject
);
520 PVFAT_IRP_CONTEXT IrpContext
);
524 PDEVICE_EXTENSION DeviceExt
,
526 PUNICODE_STRING FileToFindU
,
527 PVFAT_DIRENTRY_CONTEXT DirContext
,
532 PFAT_DIR_ENTRY pEntry
,
533 PUNICODE_STRING NameU
);
537 PDEVICE_EXTENSION DeviceExt
,
543 VfatDirectoryControl(
544 PVFAT_IRP_CONTEXT IrpContext
);
547 FsdDosDateTimeToSystemTime(
548 PDEVICE_EXTENSION DeviceExt
,
551 PLARGE_INTEGER SystemTime
);
554 FsdSystemTimeToDosDateTime(
555 PDEVICE_EXTENSION DeviceExt
,
556 PLARGE_INTEGER SystemTime
,
563 vfatDirEntryGetFirstCluster(
564 PDEVICE_EXTENSION pDeviceExt
,
565 PDIR_ENTRY pDirEntry
);
568 VfatIsDirectoryEmpty(
576 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
584 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
591 PDEVICE_EXTENSION DeviceExt
,
592 PUNICODE_STRING PathNameU
,
595 ULONG RequestedOptions
,
609 PDEVICE_EXTENSION DeviceExt
,
617 VfatSetExtendedAttributes(
618 PFILE_OBJECT FileObject
,
625 VfatInitFastIoRoutines(
626 PFAST_IO_DISPATCH FastIoDispatch
);
630 VfatAcquireForLazyWrite(
636 VfatReleaseFromLazyWrite(
641 VfatAcquireForReadAhead(
647 VfatReleaseFromReadAhead(
654 PDEVICE_EXTENSION DeviceExt
,
655 ULONG CurrentCluster
,
659 FAT12FindAndMarkAvailableCluster(
660 PDEVICE_EXTENSION DeviceExt
,
665 PDEVICE_EXTENSION DeviceExt
,
666 ULONG ClusterToWrite
,
672 PDEVICE_EXTENSION DeviceExt
,
673 ULONG CurrentCluster
,
677 FAT16FindAndMarkAvailableCluster(
678 PDEVICE_EXTENSION DeviceExt
,
683 PDEVICE_EXTENSION DeviceExt
,
684 ULONG ClusterToWrite
,
690 PDEVICE_EXTENSION DeviceExt
,
691 ULONG CurrentCluster
,
695 FAT32FindAndMarkAvailableCluster(
696 PDEVICE_EXTENSION DeviceExt
,
701 PDEVICE_EXTENSION DeviceExt
,
702 ULONG ClusterToWrite
,
708 PDEVICE_EXTENSION DeviceExt
,
716 PDEVICE_EXTENSION DeviceExt
,
721 PDEVICE_EXTENSION DeviceExt
,
722 ULONG CurrentCluster
,
726 GetNextClusterExtend(
727 PDEVICE_EXTENSION DeviceExt
,
728 ULONG CurrentCluster
,
732 CountAvailableClusters(
733 PDEVICE_EXTENSION DeviceExt
,
734 PLARGE_INTEGER Clusters
);
738 PDEVICE_EXTENSION DeviceExt
,
739 ULONG ClusterToWrite
,
746 PDEVICE_EXTENSION pVCB
,
747 PUNICODE_STRING pFileNameU
);
759 PDEVICE_EXTENSION pVCB
,
764 PDEVICE_EXTENSION pVCB
,
769 PDEVICE_EXTENSION pVCB
,
773 vfatGrabFCBFromTable(
774 PDEVICE_EXTENSION pDeviceExt
,
775 PUNICODE_STRING pFileNameU
);
779 PDEVICE_EXTENSION pVCB
);
783 PDEVICE_EXTENSION pVCB
);
794 vfatAttachFCBToFileObject(
795 PDEVICE_EXTENSION vcb
,
797 PFILE_OBJECT fileObject
);
801 PDEVICE_EXTENSION pVCB
,
803 PUNICODE_STRING FileToFindU
,
808 PDEVICE_EXTENSION pVCB
,
809 PVFATFCB
*pParentFCB
,
811 PUNICODE_STRING pFileNameU
);
814 vfatMakeFCBFromDirEntry(
816 PVFATFCB directoryFCB
,
817 PVFAT_DIRENTRY_CONTEXT DirContext
,
823 VfatQueryInformation(
824 PVFAT_IRP_CONTEXT IrpContext
);
828 PVFAT_IRP_CONTEXT IrpContext
);
831 VfatSetAllocationSizeInformation(
832 PFILE_OBJECT FileObject
,
834 PDEVICE_EXTENSION DeviceExt
,
835 PLARGE_INTEGER AllocationSize
);
841 PVFAT_IRP_CONTEXT IrpContext
);
845 PDEVICE_EXTENSION DeviceExt
,
851 VfatFileSystemControl(
852 PVFAT_IRP_CONTEXT IrpContext
);
859 PDRIVER_OBJECT DriverObject
,
860 PUNICODE_STRING RegistryPath
);
867 PVFAT_IRP_CONTEXT IrpContext
);
870 VfatAllocateIrpContext(
871 PDEVICE_OBJECT DeviceObject
,
876 PVFAT_IRP_CONTEXT IrpContext
);
884 PDEVICE_OBJECT DeviceObject
,
901 PVFAT_IRP_CONTEXT IrpContext
);
907 PVFAT_IRP_CONTEXT IrpContext
);
911 PVFAT_IRP_CONTEXT IrpContext
);
915 PDEVICE_EXTENSION DeviceExt
,
917 PULONG CurrentCluster
,
928 PDEVICE_OBJECT DeviceObject
,
935 PUNICODE_STRING PathNameU
,
936 PUNICODE_STRING DirNameU
,
937 PUNICODE_STRING FileNameU
);
951 VfatQueryVolumeInformation(
952 PVFAT_IRP_CONTEXT IrpContext
);
955 VfatSetVolumeInformation(
956 PVFAT_IRP_CONTEXT IrpContext
);
958 #endif /* _FASTFAT_PCH_ */