7 #include <pseh/pseh2.h>
9 #define USE_ROS_CC_AND_FS
11 #define ROUND_DOWN(n, align) \
12 (((ULONG)n) & ~((align) - 1l))
14 #define ROUND_UP(n, align) \
15 ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
20 unsigned char magic0
, res0
, magic1
;
21 unsigned char OEMName
[8];
22 unsigned short BytesPerSector
;
23 unsigned char SectorsPerCluster
;
24 unsigned short ReservedSectors
;
25 unsigned char FATCount
;
26 unsigned short RootEntries
, Sectors
;
28 unsigned short FATSectors
, SectorsPerTrack
, Heads
;
29 unsigned long HiddenSectors
, SectorsHuge
;
30 unsigned char Drive
, Res1
, Sig
;
31 unsigned long VolumeID
;
32 unsigned char VolumeLabel
[11], SysType
[8];
33 unsigned char Res2
[448];
34 unsigned short Signatur1
;
39 unsigned char magic0
, res0
, magic1
; // 0
40 unsigned char OEMName
[8]; // 3
41 unsigned short BytesPerSector
; // 11
42 unsigned char SectorsPerCluster
; // 13
43 unsigned short ReservedSectors
; // 14
44 unsigned char FATCount
; // 16
45 unsigned short RootEntries
, Sectors
; // 17
46 unsigned char Media
; // 21
47 unsigned short FATSectors
, SectorsPerTrack
, Heads
; // 22
48 unsigned long HiddenSectors
, SectorsHuge
; // 28
49 unsigned long FATSectors32
; // 36
50 unsigned short ExtFlag
; // 40
51 unsigned short FSVersion
; // 42
52 unsigned long RootCluster
; // 44
53 unsigned short FSInfoSector
; // 48
54 unsigned short BootBackup
; // 50
55 unsigned char Res3
[12]; // 52
56 unsigned char Drive
; // 64
57 unsigned char Res4
; // 65
58 unsigned char ExtBootSignature
; // 66
59 unsigned long VolumeID
; // 67
60 unsigned char VolumeLabel
[11], SysType
[8]; // 71
61 unsigned char Res2
[420]; // 90
62 unsigned short Signature1
; // 510
65 struct _BootSectorFatX
67 unsigned char SysType
[4]; // 0
68 unsigned long VolumeID
; // 4
69 unsigned long SectorsPerCluster
; // 8
70 unsigned short FATCount
; // 12
71 unsigned long Unknown
; // 14
72 unsigned char Unused
[4078]; // 18
77 unsigned long ExtBootSignature2
; // 0
78 unsigned char Res6
[480]; // 4
79 unsigned long FSINFOSignature
; // 484
80 unsigned long FreeCluster
; // 488
81 unsigned long NextCluster
; // 492
82 unsigned char Res7
[12]; // 496
83 unsigned long Signatur2
; // 508
86 typedef struct _BootSector BootSector
;
92 struct { unsigned char Filename
[8], Ext
[3]; };
93 unsigned char ShortName
[11];
97 unsigned char CreationTimeMs
;
98 unsigned short CreationTime
,CreationDate
,AccessDate
;
101 unsigned short FirstClusterHigh
; // FAT32
102 unsigned short ExtendedAttributes
; // FAT12/FAT16
104 unsigned short UpdateTime
; //time create/update
105 unsigned short UpdateDate
; //date create/update
106 unsigned short FirstCluster
;
107 unsigned long FileSize
;
110 #define FAT_EAFILE "EA DATA. SF"
112 typedef struct _EAFileHeader FAT_EA_FILE_HEADER
, *PFAT_EA_FILE_HEADER
;
116 unsigned short Signature
; // ED
117 unsigned short Unknown
[15];
118 unsigned short EASetTable
[240];
121 typedef struct _EASetHeader FAT_EA_SET_HEADER
, *PFAT_EA_SET_HEADER
;
125 unsigned short Signature
; // EA
126 unsigned short Offset
; // relative offset, same value as in the EASetTable
127 unsigned short Unknown1
[2];
128 char TargetFileName
[12];
129 unsigned short Unknown2
[3];
130 unsigned int EALength
;
134 typedef struct _EAHeader FAT_EA_HEADER
, *PFAT_EA_HEADER
;
138 unsigned char Unknown
;
139 unsigned char EANameLength
;
140 unsigned short EAValueLength
;
145 typedef struct _FATDirEntry FAT_DIR_ENTRY
, *PFAT_DIR_ENTRY
;
149 unsigned char FilenameLength
; // 0
150 unsigned char Attrib
; // 1
151 unsigned char Filename
[42]; // 2
152 unsigned long FirstCluster
; // 44
153 unsigned long FileSize
; // 48
154 unsigned short UpdateTime
; // 52
155 unsigned short UpdateDate
; // 54
156 unsigned short CreationTime
; // 56
157 unsigned short CreationDate
; // 58
158 unsigned short AccessTime
; // 60
159 unsigned short AccessDate
; // 62
164 unsigned char id
; // sequence number for slot
165 WCHAR name0_4
[5]; // first 5 characters in name
166 unsigned char attr
; // attribute byte
167 unsigned char reserved
; // always 0
168 unsigned char alias_checksum
; // checksum for 8.3 alias
169 WCHAR name5_10
[6]; // 6 more characters in name
170 unsigned char start
[2]; // starting cluster number
171 WCHAR name11_12
[2]; // last 2 characters in name
174 typedef struct _slot slot
;
178 #define VFAT_CASE_LOWER_BASE 8 // base is lower case
179 #define VFAT_CASE_LOWER_EXT 16 // extension is lower case
181 #define LONGNAME_MAX_LENGTH 256 // max length for a long filename
183 #define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
184 #define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
185 #define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
187 #define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
188 #define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
189 #define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
190 #define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
192 #define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
193 #define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
194 #define FATX_ENTRY_LONG(DirEntry) (FALSE)
195 #define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
197 #define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
198 #define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
200 typedef struct _FATXDirEntry FATX_DIR_ENTRY
, *PFATX_DIR_ENTRY
;
208 typedef union _DIR_ENTRY DIR_ENTRY
, *PDIR_ENTRY
;
210 #define BLOCKSIZE 512
218 #define VCB_VOLUME_LOCKED 0x0001
219 #define VCB_DISMOUNT_PENDING 0x0002
220 #define VCB_IS_FATX 0x0004
221 #define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
222 #define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
230 ULONG rootDirectorySectors
;
234 ULONG SectorsPerCluster
;
235 ULONG BytesPerSector
;
236 ULONG BytesPerCluster
;
237 ULONG NumberOfClusters
;
241 } FATINFO
, *PFATINFO
;
244 struct _VFAT_DIRENTRY_CONTEXT
;
246 typedef struct _HASHENTRY
249 struct _VFATFCB
* self
;
250 struct _HASHENTRY
* next
;
254 #define FCB_HASH_TABLE_SIZE 65536
256 typedef struct DEVICE_EXTENSION
*PDEVICE_EXTENSION
;
258 typedef NTSTATUS (*PGET_NEXT_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,PULONG
);
259 typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER
)(PDEVICE_EXTENSION
,PULONG
);
260 typedef NTSTATUS (*PWRITE_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,ULONG
,PULONG
);
262 typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY
)(PVOID
*,PVOID
*,struct _VFATFCB
*,struct _VFAT_DIRENTRY_CONTEXT
*,BOOLEAN
);
264 typedef struct DEVICE_EXTENSION
266 ERESOURCE DirResource
;
267 ERESOURCE FatResource
;
269 KSPIN_LOCK FcbListLock
;
270 LIST_ENTRY FcbListHead
;
272 struct _HASHENTRY
**FcbHashTable
;
274 PDEVICE_OBJECT VolumeDevice
;
275 PDEVICE_OBJECT StorageDevice
;
276 PFILE_OBJECT FATFileObject
;
278 ULONG LastAvailableCluster
;
279 ULONG AvailableClusters
;
280 BOOLEAN AvailableClustersValid
;
282 struct _VFATFCB
*VolumeFcb
;
284 /* Pointers to functions for manipulating FAT. */
285 PGET_NEXT_CLUSTER GetNextCluster
;
286 PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster
;
287 PWRITE_CLUSTER WriteCluster
;
288 ULONG CleanShutBitMask
;
290 /* Pointers to functions for manipulating directory entries. */
291 PGET_NEXT_DIR_ENTRY GetNextDirEntry
;
295 LIST_ENTRY VolumeListEntry
;
298 LIST_ENTRY NotifyList
;
299 PNOTIFY_SYNC NotifySync
;
301 /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE */
302 ULONG OpenHandleCount
;
304 /* VPBs for dismount */
307 } DEVICE_EXTENSION
, VCB
, *PVCB
;
311 PDRIVER_OBJECT DriverObject
;
312 PDEVICE_OBJECT DeviceObject
;
314 ERESOURCE VolumeListLock
;
315 LIST_ENTRY VolumeListHead
;
316 NPAGED_LOOKASIDE_LIST FcbLookasideList
;
317 NPAGED_LOOKASIDE_LIST CcbLookasideList
;
318 NPAGED_LOOKASIDE_LIST IrpContextLookasideList
;
319 FAST_IO_DISPATCH FastIoDispatch
;
320 CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
;
321 } VFAT_GLOBAL_DATA
, *PVFAT_GLOBAL_DATA
;
323 extern PVFAT_GLOBAL_DATA VfatGlobalData
;
325 #define FCB_CACHE_INITIALIZED 0x0001
326 #define FCB_DELETE_PENDING 0x0002
327 #define FCB_IS_FAT 0x0004
328 #define FCB_IS_PAGE_FILE 0x0008
329 #define FCB_IS_VOLUME 0x0010
330 #define FCB_IS_DIRTY 0x0020
331 #define FCB_IS_FATX_ENTRY 0x0040
333 typedef struct _VFATFCB
335 /* FCB header required by ROS/NT */
336 FSRTL_COMMON_FCB_HEADER RFCB
;
337 SECTION_OBJECT_POINTERS SectionObjectPointers
;
338 ERESOURCE MainResource
;
339 ERESOURCE PagingIoResource
;
340 /* end FCB header required by ROS/NT */
342 /* directory entry for this file or directory */
345 /* Pointer to attributes in entry */
348 /* long file name, points into PathNameBuffer */
349 UNICODE_STRING LongNameU
;
351 /* short file name */
352 UNICODE_STRING ShortNameU
;
354 /* directory name, points into PathNameBuffer */
355 UNICODE_STRING DirNameU
;
357 /* path + long file name 260 max*/
358 UNICODE_STRING PathNameU
;
360 /* buffer for PathNameU */
361 PWCHAR PathNameBuffer
;
363 /* buffer for ShortNameU */
364 WCHAR ShortNameBuffer
[13];
369 /* List of FCB's for this volume */
370 LIST_ENTRY FcbListEntry
;
372 /* pointer to the parent fcb */
373 struct _VFATFCB
*parentFcb
;
375 /* Flags for the fcb */
378 /* pointer to the file object which has initialized the fcb */
379 PFILE_OBJECT FileObject
;
381 /* Directory index for the short name entry */
384 /* Directory index where the long name starts */
387 /* Share access for the file object */
388 SHARE_ACCESS FCBShareAccess
;
390 /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
391 ULONG OpenHandleCount
;
393 /* Entry into the hash table for the path + long name */
396 /* Entry into the hash table for the path + short name */
399 /* List of byte-range locks for this file */
403 * Optimalization: caching of last read/write cluster+offset pair. Can't
404 * be in VFATCCB because it must be reset everytime the allocated clusters
407 FAST_MUTEX LastMutex
;
410 } VFATFCB
, *PVFATFCB
;
412 typedef struct _VFATCCB
414 LARGE_INTEGER CurrentByteOffset
;
415 /* for DirectoryControl */
417 /* for DirectoryControl */
418 UNICODE_STRING SearchPattern
;
419 } VFATCCB
, *PVFATCCB
;
421 #define TAG_CCB 'BCCV'
422 #define TAG_FCB 'BCFV'
423 #define TAG_IRP 'PRIV'
424 #define TAG_VFAT 'TAFV'
426 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
428 typedef struct __DOSTIME
436 typedef struct __DOSDATE
444 #define IRPCONTEXT_CANWAIT 0x0001
445 #define IRPCONTEXT_PENDINGRETURNED 0x0002
450 PDEVICE_OBJECT DeviceObject
;
451 PDEVICE_EXTENSION DeviceExt
;
453 WORK_QUEUE_ITEM WorkQueueItem
;
454 PIO_STACK_LOCATION Stack
;
457 PFILE_OBJECT FileObject
;
460 } VFAT_IRP_CONTEXT
, *PVFAT_IRP_CONTEXT
;
462 typedef struct _VFAT_DIRENTRY_CONTEXT
467 UNICODE_STRING LongNameU
;
468 UNICODE_STRING ShortNameU
;
469 } VFAT_DIRENTRY_CONTEXT
, *PVFAT_DIRENTRY_CONTEXT
;
471 typedef struct _VFAT_MOVE_CONTEXT
477 } VFAT_MOVE_CONTEXT
, *PVFAT_MOVE_CONTEXT
;
483 IN PDEVICE_OBJECT pDeviceObject
,
484 IN PLARGE_INTEGER ReadOffset
,
487 IN BOOLEAN Override
);
491 IN PVFAT_IRP_CONTEXT IrpContext
,
492 IN PLARGE_INTEGER ReadOffset
,
494 IN ULONG BufferOffset
,
498 VfatWriteDiskPartial(
499 IN PVFAT_IRP_CONTEXT IrpContext
,
500 IN PLARGE_INTEGER WriteOffset
,
501 IN ULONG WriteLength
,
502 IN ULONG BufferOffset
,
506 VfatBlockDeviceIoControl(
507 IN PDEVICE_OBJECT DeviceObject
,
509 IN PVOID InputBuffer
,
510 IN ULONG InputBufferSize
,
511 IN OUT PVOID OutputBuffer
,
512 IN OUT PULONG pOutputBufferSize
,
513 IN BOOLEAN Override
);
519 PVFAT_IRP_CONTEXT IrpContext
);
525 PVFAT_IRP_CONTEXT IrpContext
);
529 PDEVICE_EXTENSION DeviceExt
,
530 PFILE_OBJECT FileObject
);
536 PVFAT_IRP_CONTEXT IrpContext
);
540 PDEVICE_EXTENSION DeviceExt
,
542 PUNICODE_STRING FileToFindU
,
543 PVFAT_DIRENTRY_CONTEXT DirContext
,
548 PFAT_DIR_ENTRY pEntry
,
549 PUNICODE_STRING NameU
);
553 PDEVICE_EXTENSION DeviceExt
,
559 VfatDirectoryControl(
560 PVFAT_IRP_CONTEXT IrpContext
);
563 FsdDosDateTimeToSystemTime(
564 PDEVICE_EXTENSION DeviceExt
,
567 PLARGE_INTEGER SystemTime
);
570 FsdSystemTimeToDosDateTime(
571 PDEVICE_EXTENSION DeviceExt
,
572 PLARGE_INTEGER SystemTime
,
579 vfatDirEntryGetFirstCluster(
580 PDEVICE_EXTENSION pDeviceExt
,
581 PDIR_ENTRY pDirEntry
);
584 VfatIsDirectoryEmpty(
592 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
600 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
607 PDEVICE_EXTENSION DeviceExt
,
608 PUNICODE_STRING PathNameU
,
611 ULONG RequestedOptions
,
613 PVFAT_MOVE_CONTEXT MoveContext
);
627 PDEVICE_EXTENSION DeviceExt
,
634 IN PDEVICE_EXTENSION DeviceExt
,
636 IN PUNICODE_STRING FileName
,
637 IN BOOLEAN CaseChangeOnly
);
641 IN PDEVICE_EXTENSION DeviceExt
,
643 IN PUNICODE_STRING FileName
,
644 IN PVFATFCB ParentFcb
);
649 VfatSetExtendedAttributes(
650 PFILE_OBJECT FileObject
,
657 VfatInitFastIoRoutines(
658 PFAST_IO_DISPATCH FastIoDispatch
);
662 VfatAcquireForLazyWrite(
668 VfatReleaseFromLazyWrite(
673 VfatAcquireForReadAhead(
679 VfatReleaseFromReadAhead(
686 PDEVICE_EXTENSION DeviceExt
,
687 ULONG CurrentCluster
,
691 FAT12FindAndMarkAvailableCluster(
692 PDEVICE_EXTENSION DeviceExt
,
697 PDEVICE_EXTENSION DeviceExt
,
698 ULONG ClusterToWrite
,
704 PDEVICE_EXTENSION DeviceExt
,
705 ULONG CurrentCluster
,
709 FAT16FindAndMarkAvailableCluster(
710 PDEVICE_EXTENSION DeviceExt
,
715 PDEVICE_EXTENSION DeviceExt
,
716 ULONG ClusterToWrite
,
722 PDEVICE_EXTENSION DeviceExt
,
723 ULONG CurrentCluster
,
727 FAT32FindAndMarkAvailableCluster(
728 PDEVICE_EXTENSION DeviceExt
,
733 PDEVICE_EXTENSION DeviceExt
,
734 ULONG ClusterToWrite
,
740 PDEVICE_EXTENSION DeviceExt
,
748 PDEVICE_EXTENSION DeviceExt
,
753 PDEVICE_EXTENSION DeviceExt
,
754 ULONG CurrentCluster
,
758 GetNextClusterExtend(
759 PDEVICE_EXTENSION DeviceExt
,
760 ULONG CurrentCluster
,
764 CountAvailableClusters(
765 PDEVICE_EXTENSION DeviceExt
,
766 PLARGE_INTEGER Clusters
);
770 PDEVICE_EXTENSION DeviceExt
,
771 ULONG ClusterToWrite
,
778 PDEVICE_EXTENSION pVCB
,
779 PUNICODE_STRING pFileNameU
);
783 PDEVICE_EXTENSION pVCB
,
785 PUNICODE_STRING LongName
,
786 PUNICODE_STRING ShortName
,
799 PDEVICE_EXTENSION pVCB
,
804 PDEVICE_EXTENSION pVCB
,
808 vfatGrabFCBFromTable(
809 PDEVICE_EXTENSION pDeviceExt
,
810 PUNICODE_STRING pFileNameU
);
814 PDEVICE_EXTENSION pVCB
);
818 PDEVICE_EXTENSION pVCB
);
829 vfatAttachFCBToFileObject(
830 PDEVICE_EXTENSION vcb
,
832 PFILE_OBJECT fileObject
);
836 PDEVICE_EXTENSION pVCB
,
838 PUNICODE_STRING FileToFindU
,
843 PDEVICE_EXTENSION pVCB
,
844 PVFATFCB
*pParentFCB
,
846 PUNICODE_STRING pFileNameU
);
849 vfatMakeFCBFromDirEntry(
851 PVFATFCB directoryFCB
,
852 PVFAT_DIRENTRY_CONTEXT DirContext
,
858 VfatQueryInformation(
859 PVFAT_IRP_CONTEXT IrpContext
);
863 PVFAT_IRP_CONTEXT IrpContext
);
866 VfatSetAllocationSizeInformation(
867 PFILE_OBJECT FileObject
,
869 PDEVICE_EXTENSION DeviceExt
,
870 PLARGE_INTEGER AllocationSize
);
876 PVFAT_IRP_CONTEXT IrpContext
);
880 PDEVICE_EXTENSION DeviceExt
,
886 VfatFileSystemControl(
887 PVFAT_IRP_CONTEXT IrpContext
);
894 PDRIVER_OBJECT DriverObject
,
895 PUNICODE_STRING RegistryPath
);
902 PVFAT_IRP_CONTEXT IrpContext
);
905 VfatAllocateIrpContext(
906 PDEVICE_OBJECT DeviceObject
,
911 PVFAT_IRP_CONTEXT IrpContext
);
919 PDEVICE_OBJECT DeviceObject
,
933 VfatCheckForDismount(
934 IN PDEVICE_EXTENSION DeviceExt
,
941 PVFAT_IRP_CONTEXT IrpContext
);
947 PVFAT_IRP_CONTEXT IrpContext
);
951 PVFAT_IRP_CONTEXT IrpContext
);
955 PDEVICE_EXTENSION DeviceExt
,
957 PULONG CurrentCluster
,
968 PDEVICE_OBJECT DeviceObject
,
975 PUNICODE_STRING PathNameU
,
976 PUNICODE_STRING DirNameU
,
977 PUNICODE_STRING FileNameU
);
991 VfatQueryVolumeInformation(
992 PVFAT_IRP_CONTEXT IrpContext
);
995 VfatSetVolumeInformation(
996 PVFAT_IRP_CONTEXT IrpContext
);
998 #endif /* _FASTFAT_PCH_ */