7 #include <pseh/pseh2.h>
10 #define INIT_SECTION __attribute__((section ("INIT")))
11 #define INIT_FUNCTION INIT_SECTION
13 #define INIT_SECTION /* Done via alloc_text for MSC */
14 #define INIT_FUNCTION INIT_SECTION
17 #define USE_ROS_CC_AND_FS
20 #define ENABLE_SWAPOUT
24 #define ROUND_DOWN(n, align) \
25 (((ULONG)n) & ~((align) - 1l))
27 #define ROUND_UP(n, align) \
28 ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
33 unsigned char magic0
, res0
, magic1
;
34 unsigned char OEMName
[8];
35 unsigned short BytesPerSector
;
36 unsigned char SectorsPerCluster
;
37 unsigned short ReservedSectors
;
38 unsigned char FATCount
;
39 unsigned short RootEntries
, Sectors
;
41 unsigned short FATSectors
, SectorsPerTrack
, Heads
;
42 unsigned long HiddenSectors
, SectorsHuge
;
43 unsigned char Drive
, Res1
, Sig
;
44 unsigned long VolumeID
;
45 unsigned char VolumeLabel
[11], SysType
[8];
46 unsigned char Res2
[448];
47 unsigned short Signatur1
;
52 unsigned char magic0
, res0
, magic1
; // 0
53 unsigned char OEMName
[8]; // 3
54 unsigned short BytesPerSector
; // 11
55 unsigned char SectorsPerCluster
; // 13
56 unsigned short ReservedSectors
; // 14
57 unsigned char FATCount
; // 16
58 unsigned short RootEntries
, Sectors
; // 17
59 unsigned char Media
; // 21
60 unsigned short FATSectors
, SectorsPerTrack
, Heads
; // 22
61 unsigned long HiddenSectors
, SectorsHuge
; // 28
62 unsigned long FATSectors32
; // 36
63 unsigned short ExtFlag
; // 40
64 unsigned short FSVersion
; // 42
65 unsigned long RootCluster
; // 44
66 unsigned short FSInfoSector
; // 48
67 unsigned short BootBackup
; // 50
68 unsigned char Res3
[12]; // 52
69 unsigned char Drive
; // 64
70 unsigned char Res4
; // 65
71 unsigned char ExtBootSignature
; // 66
72 unsigned long VolumeID
; // 67
73 unsigned char VolumeLabel
[11], SysType
[8]; // 71
74 unsigned char Res2
[420]; // 90
75 unsigned short Signature1
; // 510
78 struct _BootSectorFatX
80 unsigned char SysType
[4]; // 0
81 unsigned long VolumeID
; // 4
82 unsigned long SectorsPerCluster
; // 8
83 unsigned short FATCount
; // 12
84 unsigned long Unknown
; // 14
85 unsigned char Unused
[4078]; // 18
90 unsigned long ExtBootSignature2
; // 0
91 unsigned char Res6
[480]; // 4
92 unsigned long FSINFOSignature
; // 484
93 unsigned long FreeCluster
; // 488
94 unsigned long NextCluster
; // 492
95 unsigned char Res7
[12]; // 496
96 unsigned long Signatur2
; // 508
99 typedef struct _BootSector BootSector
;
105 struct { unsigned char Filename
[8], Ext
[3]; };
106 unsigned char ShortName
[11];
108 unsigned char Attrib
;
110 unsigned char CreationTimeMs
;
111 unsigned short CreationTime
,CreationDate
,AccessDate
;
114 unsigned short FirstClusterHigh
; // FAT32
115 unsigned short ExtendedAttributes
; // FAT12/FAT16
117 unsigned short UpdateTime
; //time create/update
118 unsigned short UpdateDate
; //date create/update
119 unsigned short FirstCluster
;
120 unsigned long FileSize
;
123 #define FAT_EAFILE "EA DATA. SF"
125 typedef struct _EAFileHeader FAT_EA_FILE_HEADER
, *PFAT_EA_FILE_HEADER
;
129 unsigned short Signature
; // ED
130 unsigned short Unknown
[15];
131 unsigned short EASetTable
[240];
134 typedef struct _EASetHeader FAT_EA_SET_HEADER
, *PFAT_EA_SET_HEADER
;
138 unsigned short Signature
; // EA
139 unsigned short Offset
; // relative offset, same value as in the EASetTable
140 unsigned short Unknown1
[2];
141 char TargetFileName
[12];
142 unsigned short Unknown2
[3];
143 unsigned int EALength
;
147 typedef struct _EAHeader FAT_EA_HEADER
, *PFAT_EA_HEADER
;
151 unsigned char Unknown
;
152 unsigned char EANameLength
;
153 unsigned short EAValueLength
;
158 typedef struct _FATDirEntry FAT_DIR_ENTRY
, *PFAT_DIR_ENTRY
;
162 unsigned char FilenameLength
; // 0
163 unsigned char Attrib
; // 1
164 unsigned char Filename
[42]; // 2
165 unsigned long FirstCluster
; // 44
166 unsigned long FileSize
; // 48
167 unsigned short UpdateTime
; // 52
168 unsigned short UpdateDate
; // 54
169 unsigned short CreationTime
; // 56
170 unsigned short CreationDate
; // 58
171 unsigned short AccessTime
; // 60
172 unsigned short AccessDate
; // 62
177 unsigned char id
; // sequence number for slot
178 WCHAR name0_4
[5]; // first 5 characters in name
179 unsigned char attr
; // attribute byte
180 unsigned char reserved
; // always 0
181 unsigned char alias_checksum
; // checksum for 8.3 alias
182 WCHAR name5_10
[6]; // 6 more characters in name
183 unsigned char start
[2]; // starting cluster number
184 WCHAR name11_12
[2]; // last 2 characters in name
187 typedef struct _slot slot
;
191 #define VFAT_CASE_LOWER_BASE 8 // base is lower case
192 #define VFAT_CASE_LOWER_EXT 16 // extension is lower case
194 #define LONGNAME_MAX_LENGTH 256 // max length for a long filename
196 #define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
197 #define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
198 #define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
200 #define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
201 #define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
202 #define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
203 #define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
205 #define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
206 #define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
207 #define FATX_ENTRY_LONG(DirEntry) (FALSE)
208 #define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
210 #define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
211 #define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
213 typedef struct _FATXDirEntry FATX_DIR_ENTRY
, *PFATX_DIR_ENTRY
;
221 typedef union _DIR_ENTRY DIR_ENTRY
, *PDIR_ENTRY
;
223 #define BLOCKSIZE 512
231 #define VCB_VOLUME_LOCKED 0x0001
232 #define VCB_DISMOUNT_PENDING 0x0002
233 #define VCB_IS_FATX 0x0004
234 #define VCB_IS_DIRTY 0x4000 /* Volume is dirty */
235 #define VCB_CLEAR_DIRTY 0x8000 /* Clean dirty flag at shutdown */
243 ULONG rootDirectorySectors
;
247 ULONG SectorsPerCluster
;
248 ULONG BytesPerSector
;
249 ULONG BytesPerCluster
;
250 ULONG NumberOfClusters
;
254 } FATINFO
, *PFATINFO
;
257 struct _VFAT_DIRENTRY_CONTEXT
;
259 typedef struct _HASHENTRY
262 struct _VFATFCB
* self
;
263 struct _HASHENTRY
* next
;
267 typedef struct DEVICE_EXTENSION
*PDEVICE_EXTENSION
;
269 typedef NTSTATUS (*PGET_NEXT_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,PULONG
);
270 typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER
)(PDEVICE_EXTENSION
,PULONG
);
271 typedef NTSTATUS (*PWRITE_CLUSTER
)(PDEVICE_EXTENSION
,ULONG
,ULONG
,PULONG
);
273 typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY
)(PVOID
*,PVOID
*,struct _VFATFCB
*,struct _VFAT_DIRENTRY_CONTEXT
*,BOOLEAN
);
275 typedef struct DEVICE_EXTENSION
277 ERESOURCE DirResource
;
278 ERESOURCE FatResource
;
280 KSPIN_LOCK FcbListLock
;
281 LIST_ENTRY FcbListHead
;
283 struct _HASHENTRY
**FcbHashTable
;
285 PDEVICE_OBJECT VolumeDevice
;
286 PDEVICE_OBJECT StorageDevice
;
287 PFILE_OBJECT FATFileObject
;
289 ULONG LastAvailableCluster
;
290 ULONG AvailableClusters
;
291 BOOLEAN AvailableClustersValid
;
293 struct _VFATFCB
*VolumeFcb
;
295 /* Pointers to functions for manipulating FAT. */
296 PGET_NEXT_CLUSTER GetNextCluster
;
297 PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster
;
298 PWRITE_CLUSTER WriteCluster
;
299 ULONG CleanShutBitMask
;
301 /* Pointers to functions for manipulating directory entries. */
302 PGET_NEXT_DIR_ENTRY GetNextDirEntry
;
306 LIST_ENTRY VolumeListEntry
;
309 LIST_ENTRY NotifyList
;
310 PNOTIFY_SYNC NotifySync
;
312 /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE */
313 ULONG OpenHandleCount
;
315 /* VPBs for dismount */
318 } DEVICE_EXTENSION
, VCB
, *PVCB
;
322 PDRIVER_OBJECT DriverObject
;
323 PDEVICE_OBJECT DeviceObject
;
325 ERESOURCE VolumeListLock
;
326 LIST_ENTRY VolumeListHead
;
327 NPAGED_LOOKASIDE_LIST FcbLookasideList
;
328 NPAGED_LOOKASIDE_LIST CcbLookasideList
;
329 NPAGED_LOOKASIDE_LIST IrpContextLookasideList
;
330 FAST_IO_DISPATCH FastIoDispatch
;
331 CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
;
332 } VFAT_GLOBAL_DATA
, *PVFAT_GLOBAL_DATA
;
334 extern PVFAT_GLOBAL_DATA VfatGlobalData
;
336 #define FCB_CACHE_INITIALIZED 0x0001
337 #define FCB_DELETE_PENDING 0x0002
338 #define FCB_IS_FAT 0x0004
339 #define FCB_IS_PAGE_FILE 0x0008
340 #define FCB_IS_VOLUME 0x0010
341 #define FCB_IS_DIRTY 0x0020
342 #define FCB_IS_FATX_ENTRY 0x0040
344 typedef struct _VFATFCB
346 /* FCB header required by ROS/NT */
347 FSRTL_COMMON_FCB_HEADER RFCB
;
348 SECTION_OBJECT_POINTERS SectionObjectPointers
;
349 ERESOURCE MainResource
;
350 ERESOURCE PagingIoResource
;
351 /* end FCB header required by ROS/NT */
353 /* directory entry for this file or directory */
356 /* Pointer to attributes in entry */
359 /* long file name, points into PathNameBuffer */
360 UNICODE_STRING LongNameU
;
362 /* short file name */
363 UNICODE_STRING ShortNameU
;
365 /* directory name, points into PathNameBuffer */
366 UNICODE_STRING DirNameU
;
368 /* path + long file name 260 max*/
369 UNICODE_STRING PathNameU
;
371 /* buffer for PathNameU */
372 PWCHAR PathNameBuffer
;
374 /* buffer for ShortNameU */
375 WCHAR ShortNameBuffer
[13];
380 /* List of FCB's for this volume */
381 LIST_ENTRY FcbListEntry
;
383 /* pointer to the parent fcb */
384 struct _VFATFCB
*parentFcb
;
386 /* Flags for the fcb */
389 /* pointer to the file object which has initialized the fcb */
390 PFILE_OBJECT FileObject
;
392 /* Directory index for the short name entry */
395 /* Directory index where the long name starts */
398 /* Share access for the file object */
399 SHARE_ACCESS FCBShareAccess
;
401 /* Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP */
402 ULONG OpenHandleCount
;
404 /* Entry into the hash table for the path + long name */
407 /* Entry into the hash table for the path + short name */
410 /* List of byte-range locks for this file */
414 * Optimalization: caching of last read/write cluster+offset pair. Can't
415 * be in VFATCCB because it must be reset everytime the allocated clusters
418 FAST_MUTEX LastMutex
;
421 } VFATFCB
, *PVFATFCB
;
423 typedef struct _VFATCCB
425 LARGE_INTEGER CurrentByteOffset
;
426 /* for DirectoryControl */
428 /* for DirectoryControl */
429 UNICODE_STRING SearchPattern
;
430 } VFATCCB
, *PVFATCCB
;
432 #define TAG_CCB 'BCCV'
433 #define TAG_FCB 'BCFV'
434 #define TAG_IRP 'PRIV'
435 #define TAG_VFAT 'TAFV'
437 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
439 typedef struct __DOSTIME
447 typedef struct __DOSDATE
455 #define IRPCONTEXT_CANWAIT 0x0001
456 #define IRPCONTEXT_COMPLETE 0x0002
457 #define IRPCONTEXT_QUEUE 0x0004
458 #define IRPCONTEXT_PENDINGRETURNED 0x0008
463 PDEVICE_OBJECT DeviceObject
;
464 PDEVICE_EXTENSION DeviceExt
;
466 WORK_QUEUE_ITEM WorkQueueItem
;
467 PIO_STACK_LOCATION Stack
;
470 PFILE_OBJECT FileObject
;
474 } VFAT_IRP_CONTEXT
, *PVFAT_IRP_CONTEXT
;
476 typedef struct _VFAT_DIRENTRY_CONTEXT
481 UNICODE_STRING LongNameU
;
482 UNICODE_STRING ShortNameU
;
483 } VFAT_DIRENTRY_CONTEXT
, *PVFAT_DIRENTRY_CONTEXT
;
485 typedef struct _VFAT_MOVE_CONTEXT
491 } VFAT_MOVE_CONTEXT
, *PVFAT_MOVE_CONTEXT
;
495 VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext
)
497 PULONG Flags
= &IrpContext
->Flags
;
499 *Flags
&= ~IRPCONTEXT_COMPLETE
;
500 *Flags
|= IRPCONTEXT_QUEUE
;
502 return STATUS_PENDING
;
509 IN PDEVICE_OBJECT pDeviceObject
,
510 IN PLARGE_INTEGER ReadOffset
,
513 IN BOOLEAN Override
);
517 IN PVFAT_IRP_CONTEXT IrpContext
,
518 IN PLARGE_INTEGER ReadOffset
,
520 IN ULONG BufferOffset
,
524 VfatWriteDiskPartial(
525 IN PVFAT_IRP_CONTEXT IrpContext
,
526 IN PLARGE_INTEGER WriteOffset
,
527 IN ULONG WriteLength
,
528 IN ULONG BufferOffset
,
532 VfatBlockDeviceIoControl(
533 IN PDEVICE_OBJECT DeviceObject
,
535 IN PVOID InputBuffer
,
536 IN ULONG InputBufferSize
,
537 IN OUT PVOID OutputBuffer
,
538 IN OUT PULONG pOutputBufferSize
,
539 IN BOOLEAN Override
);
545 PVFAT_IRP_CONTEXT IrpContext
);
551 PVFAT_IRP_CONTEXT IrpContext
);
555 PDEVICE_EXTENSION DeviceExt
,
556 PFILE_OBJECT FileObject
);
562 PVFAT_IRP_CONTEXT IrpContext
);
566 PDEVICE_EXTENSION DeviceExt
,
568 PUNICODE_STRING FileToFindU
,
569 PVFAT_DIRENTRY_CONTEXT DirContext
,
574 PFAT_DIR_ENTRY pEntry
,
575 PUNICODE_STRING NameU
);
579 PDEVICE_EXTENSION DeviceExt
,
585 VfatDirectoryControl(
586 PVFAT_IRP_CONTEXT IrpContext
);
589 FsdDosDateTimeToSystemTime(
590 PDEVICE_EXTENSION DeviceExt
,
593 PLARGE_INTEGER SystemTime
);
596 FsdSystemTimeToDosDateTime(
597 PDEVICE_EXTENSION DeviceExt
,
598 PLARGE_INTEGER SystemTime
,
605 vfatDirEntryGetFirstCluster(
606 PDEVICE_EXTENSION pDeviceExt
,
607 PDIR_ENTRY pDirEntry
);
610 VfatIsDirectoryEmpty(
618 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
626 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
633 PDEVICE_EXTENSION DeviceExt
,
634 PUNICODE_STRING PathNameU
,
637 ULONG RequestedOptions
,
639 PVFAT_MOVE_CONTEXT MoveContext
);
653 PDEVICE_EXTENSION DeviceExt
,
660 IN PDEVICE_EXTENSION DeviceExt
,
662 IN PUNICODE_STRING FileName
,
663 IN BOOLEAN CaseChangeOnly
);
667 IN PDEVICE_EXTENSION DeviceExt
,
669 IN PUNICODE_STRING FileName
,
670 IN PVFATFCB ParentFcb
);
675 VfatSetExtendedAttributes(
676 PFILE_OBJECT FileObject
,
683 VfatInitFastIoRoutines(
684 PFAST_IO_DISPATCH FastIoDispatch
);
688 VfatAcquireForLazyWrite(
694 VfatReleaseFromLazyWrite(
699 VfatAcquireForReadAhead(
705 VfatReleaseFromReadAhead(
712 PDEVICE_EXTENSION DeviceExt
,
713 ULONG CurrentCluster
,
717 FAT12FindAndMarkAvailableCluster(
718 PDEVICE_EXTENSION DeviceExt
,
723 PDEVICE_EXTENSION DeviceExt
,
724 ULONG ClusterToWrite
,
730 PDEVICE_EXTENSION DeviceExt
,
731 ULONG CurrentCluster
,
735 FAT16FindAndMarkAvailableCluster(
736 PDEVICE_EXTENSION DeviceExt
,
741 PDEVICE_EXTENSION DeviceExt
,
742 ULONG ClusterToWrite
,
748 PDEVICE_EXTENSION DeviceExt
,
749 ULONG CurrentCluster
,
753 FAT32FindAndMarkAvailableCluster(
754 PDEVICE_EXTENSION DeviceExt
,
759 PDEVICE_EXTENSION DeviceExt
,
760 ULONG ClusterToWrite
,
766 PDEVICE_EXTENSION DeviceExt
,
774 PDEVICE_EXTENSION DeviceExt
,
779 PDEVICE_EXTENSION DeviceExt
,
780 ULONG CurrentCluster
,
784 GetNextClusterExtend(
785 PDEVICE_EXTENSION DeviceExt
,
786 ULONG CurrentCluster
,
790 CountAvailableClusters(
791 PDEVICE_EXTENSION DeviceExt
,
792 PLARGE_INTEGER Clusters
);
796 PDEVICE_EXTENSION DeviceExt
,
797 ULONG ClusterToWrite
,
804 PDEVICE_EXTENSION pVCB
,
805 PUNICODE_STRING pFileNameU
);
809 PDEVICE_EXTENSION pVCB
,
811 PUNICODE_STRING LongName
,
812 PUNICODE_STRING ShortName
,
825 PDEVICE_EXTENSION pVCB
,
830 PDEVICE_EXTENSION pVCB
,
834 vfatGrabFCBFromTable(
835 PDEVICE_EXTENSION pDeviceExt
,
836 PUNICODE_STRING pFileNameU
);
840 PDEVICE_EXTENSION pVCB
);
844 PDEVICE_EXTENSION pVCB
);
855 vfatAttachFCBToFileObject(
856 PDEVICE_EXTENSION vcb
,
858 PFILE_OBJECT fileObject
);
862 PDEVICE_EXTENSION pVCB
,
864 PUNICODE_STRING FileToFindU
,
869 PDEVICE_EXTENSION pVCB
,
870 PVFATFCB
*pParentFCB
,
872 PUNICODE_STRING pFileNameU
);
875 vfatMakeFCBFromDirEntry(
877 PVFATFCB directoryFCB
,
878 PVFAT_DIRENTRY_CONTEXT DirContext
,
884 VfatGetStandardInformation(
886 PFILE_STANDARD_INFORMATION StandardInfo
,
887 PULONG BufferLength
);
890 VfatGetBasicInformation(
891 PFILE_OBJECT FileObject
,
893 PDEVICE_OBJECT DeviceObject
,
894 PFILE_BASIC_INFORMATION BasicInfo
,
895 PULONG BufferLength
);
898 VfatQueryInformation(
899 PVFAT_IRP_CONTEXT IrpContext
);
903 PVFAT_IRP_CONTEXT IrpContext
);
906 VfatSetAllocationSizeInformation(
907 PFILE_OBJECT FileObject
,
909 PDEVICE_EXTENSION DeviceExt
,
910 PLARGE_INTEGER AllocationSize
);
916 PVFAT_IRP_CONTEXT IrpContext
);
920 PDEVICE_EXTENSION DeviceExt
,
926 VfatFileSystemControl(
927 PVFAT_IRP_CONTEXT IrpContext
);
934 PDRIVER_OBJECT DriverObject
,
935 PUNICODE_STRING RegistryPath
);
946 PDEVICE_OBJECT DeviceObject
,
961 VfatCheckForDismount(
962 IN PDEVICE_EXTENSION DeviceExt
,
969 PVFAT_IRP_CONTEXT IrpContext
);
975 PVFAT_IRP_CONTEXT IrpContext
);
979 PVFAT_IRP_CONTEXT IrpContext
);
983 PDEVICE_EXTENSION DeviceExt
,
985 PULONG CurrentCluster
,
996 PDEVICE_OBJECT DeviceObject
,
1003 PUNICODE_STRING PathNameU
,
1004 PUNICODE_STRING DirNameU
,
1005 PUNICODE_STRING FileNameU
);
1019 VfatQueryVolumeInformation(
1020 PVFAT_IRP_CONTEXT IrpContext
);
1023 VfatSetVolumeInformation(
1024 PVFAT_IRP_CONTEXT IrpContext
);
1026 #endif /* _FASTFAT_PCH_ */