1 /* $Id: vfat.h,v 1.64 2004/06/23 20:23:59 hbirr Exp $ */
5 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
6 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
10 unsigned char magic0
, res0
, magic1
;
11 unsigned char OEMName
[8];
12 unsigned short BytesPerSector
;
13 unsigned char SectorsPerCluster
;
14 unsigned short ReservedSectors
;
15 unsigned char FATCount
;
16 unsigned short RootEntries
, Sectors
;
18 unsigned short FATSectors
, SectorsPerTrack
, Heads
;
19 unsigned long HiddenSectors
, SectorsHuge
;
20 unsigned char Drive
, Res1
, Sig
;
21 unsigned long VolumeID
;
22 unsigned char VolumeLabel
[11], SysType
[8];
23 unsigned char Res2
[448];
24 unsigned short Signatur1
;
25 } __attribute__((packed
));
29 unsigned char magic0
, res0
, magic1
; // 0
30 unsigned char OEMName
[8]; // 3
31 unsigned short BytesPerSector
; // 11
32 unsigned char SectorsPerCluster
; // 13
33 unsigned short ReservedSectors
; // 14
34 unsigned char FATCount
; // 16
35 unsigned short RootEntries
, Sectors
; // 17
36 unsigned char Media
; // 21
37 unsigned short FATSectors
, SectorsPerTrack
, Heads
; // 22
38 unsigned long HiddenSectors
, SectorsHuge
; // 28
39 unsigned long FATSectors32
; // 36
40 unsigned short ExtFlag
; // 40
41 unsigned short FSVersion
; // 42
42 unsigned long RootCluster
; // 44
43 unsigned short FSInfoSector
; // 48
44 unsigned short BootBackup
; // 50
45 unsigned char Res3
[12]; // 52
46 unsigned char Drive
; // 64
47 unsigned char Res4
; // 65
48 unsigned char ExtBootSignature
; // 66
49 unsigned long VolumeID
; // 67
50 unsigned char VolumeLabel
[11], SysType
[8]; // 71
51 unsigned char Res2
[420]; // 90
52 unsigned short Signature1
; // 510
53 } __attribute__((packed
));
57 unsigned long ExtBootSignature2
; // 0
58 unsigned char Res6
[480]; // 4
59 unsigned long FSINFOSignature
; // 484
60 unsigned long FreeCluster
; // 488
61 unsigned long NextCluster
; // 492
62 unsigned char Res7
[12]; // 496
63 unsigned long Signatur2
; // 508
64 } __attribute__((packed
));
66 typedef struct _BootSector BootSector
;
68 #define VFAT_CASE_LOWER_BASE 8 // base is lower case
69 #define VFAT_CASE_LOWER_EXT 16 // extension is lower case
71 #define ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
72 #define ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
73 #define ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
74 #define ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
78 unsigned char Filename
[8], Ext
[3];
81 unsigned char CreationTimeMs
;
82 unsigned short CreationTime
,CreationDate
,AccessDate
;
83 unsigned short FirstClusterHigh
; // higher
84 unsigned short UpdateTime
; //time create/update
85 unsigned short UpdateDate
; //date create/update
86 unsigned short FirstCluster
;
87 unsigned long FileSize
;
88 } __attribute__((packed
));
90 typedef struct _FATDirEntry FATDirEntry
, FAT_DIR_ENTRY
, *PFAT_DIR_ENTRY
;
94 unsigned char id
; // sequence number for slot
95 WCHAR name0_4
[5]; // first 5 characters in name
96 unsigned char attr
; // attribute byte
97 unsigned char reserved
; // always 0
98 unsigned char alias_checksum
; // checksum for 8.3 alias
99 WCHAR name5_10
[6]; // 6 more characters in name
100 unsigned char start
[2]; // starting cluster number
101 WCHAR name11_12
[2]; // last 2 characters in name
102 } __attribute__((packed
));
105 typedef struct _slot slot
;
107 #define BLOCKSIZE 512
113 #define VCB_VOLUME_LOCKED 0x0001
114 #define VCB_DISMOUNT_PENDING 0x0002
122 ULONG rootDirectorySectors
;
126 ULONG SectorsPerCluster
;
127 ULONG BytesPerSector
;
128 ULONG BytesPerCluster
;
129 ULONG NumberOfClusters
;
133 } FATINFO
, *PFATINFO
;
137 typedef struct _HASHENTRY
140 struct _VFATFCB
* self
;
141 struct _HASHENTRY
* next
;
145 #define FCB_HASH_TABLE_SIZE 1024
149 ERESOURCE DirResource
;
150 ERESOURCE FatResource
;
152 KSPIN_LOCK FcbListLock
;
153 LIST_ENTRY FcbListHead
;
154 struct _HASHENTRY
* FcbHashTable
[FCB_HASH_TABLE_SIZE
];
156 PDEVICE_OBJECT StorageDevice
;
157 PFILE_OBJECT FATFileObject
;
159 ULONG LastAvailableCluster
;
160 ULONG AvailableClusters
;
161 BOOLEAN AvailableClustersValid
;
163 struct _VFATFCB
* VolumeFcb
;
165 LIST_ENTRY VolumeListEntry
;
167 ULONG MediaChangeCount
;
169 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
, VCB
, *PVCB
;
173 PDRIVER_OBJECT DriverObject
;
174 PDEVICE_OBJECT DeviceObject
;
176 ERESOURCE VolumeListLock
;
177 LIST_ENTRY VolumeListHead
;
178 NPAGED_LOOKASIDE_LIST FcbLookasideList
;
179 NPAGED_LOOKASIDE_LIST CcbLookasideList
;
180 NPAGED_LOOKASIDE_LIST IrpContextLookasideList
;
181 } VFAT_GLOBAL_DATA
, *PVFAT_GLOBAL_DATA
;
183 extern PVFAT_GLOBAL_DATA VfatGlobalData
;
185 #define FCB_CACHE_INITIALIZED 0x0001
186 #define FCB_DELETE_PENDING 0x0002
187 #define FCB_IS_FAT 0x0004
188 #define FCB_IS_PAGE_FILE 0x0008
189 #define FCB_IS_VOLUME 0x0010
190 #define FCB_IS_DIRTY 0x0020
192 typedef struct _VFATFCB
194 /* FCB header required by ROS/NT */
195 FSRTL_COMMON_FCB_HEADER RFCB
;
196 SECTION_OBJECT_POINTERS SectionObjectPointers
;
197 ERESOURCE MainResource
;
198 ERESOURCE PagingIoResource
;
199 /* end FCB header required by ROS/NT */
201 /* directory entry for this file or directory */
204 /* long file name, points into PathNameBuffer */
205 UNICODE_STRING LongNameU
;
207 /* short file name */
208 UNICODE_STRING ShortNameU
;
210 /* directory name, points into PathNameBuffer */
211 UNICODE_STRING DirNameU
;
213 /* path + long file name 260 max*/
214 UNICODE_STRING PathNameU
;
216 /* buffer for PathNameU */
217 WCHAR PathNameBuffer
[MAX_PATH
];
219 /* buffer for ShortNameU */
220 WCHAR ShortNameBuffer
[13];
225 /* List of FCB's for this volume */
226 LIST_ENTRY FcbListEntry
;
228 /* pointer to the parent fcb */
229 struct _VFATFCB
* parentFcb
;
231 /* Flags for the fcb */
234 /* pointer to the file object which has initialized the fcb */
235 PFILE_OBJECT FileObject
;
237 /* Directory index for the short name entry */
240 /* Directory index where the long name starts */
243 /* Share access for the file object */
244 SHARE_ACCESS FCBShareAccess
;
246 /* Entry into the hash table for the path + long name */
249 /* Entry into the hash table for the path + short name */
252 /* List of byte-range locks for this file */
255 } VFATFCB
, *PVFATFCB
;
257 typedef struct _VFATCCB
259 LARGE_INTEGER CurrentByteOffset
;
260 /* for DirectoryControl */
262 /* for DirectoryControl */
263 UNICODE_STRING SearchPattern
;
267 } VFATCCB
, *PVFATCCB
;
270 #define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
273 #define TAG_CCB TAG('V', 'C', 'C', 'B')
274 #define TAG_FCB TAG('V', 'F', 'C', 'B')
275 #define TAG_IRP TAG('V', 'I', 'R', 'P')
277 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
279 typedef struct __DOSTIME
287 typedef struct __DOSDATE
295 #define IRPCONTEXT_CANWAIT 0x0001
296 #define IRPCONTEXT_PENDINGRETURNED 0x0002
301 PDEVICE_OBJECT DeviceObject
;
302 PDEVICE_EXTENSION DeviceExt
;
304 WORK_QUEUE_ITEM WorkQueueItem
;
305 PIO_STACK_LOCATION Stack
;
308 PFILE_OBJECT FileObject
;
311 } VFAT_IRP_CONTEXT
, *PVFAT_IRP_CONTEXT
;
313 typedef struct _VFAT_DIRENTRY_CONTEXT
317 FAT_DIR_ENTRY FatDirEntry
;
318 UNICODE_STRING LongNameU
;
319 UNICODE_STRING ShortNameU
;
320 } VFAT_DIRENTRY_CONTEXT
, *PVFAT_DIRENTRY_CONTEXT
;
323 /* ------------------------------------------------------ shutdown.c */
325 NTSTATUS STDCALL
VfatShutdown (PDEVICE_OBJECT DeviceObject
,
328 /* -------------------------------------------------------- volume.c */
330 NTSTATUS
VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext
);
332 NTSTATUS
VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext
);
334 /* ------------------------------------------------------ blockdev.c */
336 NTSTATUS
VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject
,
337 IN PLARGE_INTEGER ReadOffset
,
340 IN BOOLEAN Override
);
342 NTSTATUS
VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext
,
343 IN PLARGE_INTEGER ReadOffset
,
345 IN ULONG BufferOffset
,
348 NTSTATUS
VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext
,
349 IN PLARGE_INTEGER WriteOffset
,
350 IN ULONG WriteLength
,
351 IN ULONG BufferOffset
,
354 NTSTATUS
VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject
,
356 IN PVOID InputBuffer
,
357 IN ULONG InputBufferSize
,
358 IN OUT PVOID OutputBuffer
,
359 IN OUT PULONG pOutputBufferSize
,
360 IN BOOLEAN Override
);
362 /* ----------------------------------------------------------- dir.c */
364 NTSTATUS
VfatDirectoryControl (PVFAT_IRP_CONTEXT
);
366 BOOL
FsdDosDateTimeToFileTime (WORD wDosDate
,
370 BOOL
FsdFileTimeToDosDateTime (TIME
*FileTime
,
374 /* -------------------------------------------------------- create.c */
376 NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext
);
378 NTSTATUS
VfatOpenFile (PDEVICE_EXTENSION DeviceExt
,
379 PFILE_OBJECT FileObject
,
380 PUNICODE_STRING FileNameU
);
382 NTSTATUS
FindFile (PDEVICE_EXTENSION DeviceExt
,
384 PUNICODE_STRING FileToFindU
,
385 PVFAT_DIRENTRY_CONTEXT DirContext
,
388 VOID
vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry
,
389 PUNICODE_STRING NameU
);
391 NTSTATUS
ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt
,
394 /* --------------------------------------------------------- close.c */
396 NTSTATUS
VfatClose (PVFAT_IRP_CONTEXT IrpContext
);
398 NTSTATUS
VfatCloseFile(PDEVICE_EXTENSION DeviceExt
,
399 PFILE_OBJECT FileObject
);
401 /* ------------------------------------------------------- cleanup.c */
403 NTSTATUS
VfatCleanup (PVFAT_IRP_CONTEXT IrpContext
);
405 /* --------------------------------------------------------- fsctl.c */
407 NTSTATUS
VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext
);
409 /* --------------------------------------------------------- finfo.c */
411 NTSTATUS
VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext
);
413 NTSTATUS
VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext
);
416 VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject
,
418 PDEVICE_EXTENSION DeviceExt
,
419 PLARGE_INTEGER AllocationSize
);
421 /* --------------------------------------------------------- iface.c */
423 NTSTATUS STDCALL
DriverEntry (PDRIVER_OBJECT DriverObject
,
424 PUNICODE_STRING RegistryPath
);
426 /* --------------------------------------------------------- dirwr.c */
428 NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt
,
429 PUNICODE_STRING PathNameU
,
430 PFILE_OBJECT pFileObject
,
431 ULONG RequestedOptions
,
434 NTSTATUS
VfatUpdateEntry (PVFATFCB pFcb
);
436 NTSTATUS
VfatDelEntry(PDEVICE_EXTENSION
, PVFATFCB
);
438 /* -------------------------------------------------------- string.c */
441 vfatSplitPathName(PUNICODE_STRING PathNameU
,
442 PUNICODE_STRING DirNameU
,
443 PUNICODE_STRING FileNameU
);
445 BOOLEAN
vfatIsLongIllegal(WCHAR c
);
447 BOOLEAN
wstrcmpjoki (PWSTR s1
,
450 /* ----------------------------------------------------------- fat.c */
452 NTSTATUS
OffsetToCluster (PDEVICE_EXTENSION DeviceExt
,
458 ULONGLONG
ClusterToSector (PDEVICE_EXTENSION DeviceExt
,
461 NTSTATUS
GetNextCluster (PDEVICE_EXTENSION DeviceExt
,
462 ULONG CurrentCluster
,
466 NTSTATUS
CountAvailableClusters (PDEVICE_EXTENSION DeviceExt
,
467 PLARGE_INTEGER Clusters
);
470 WriteCluster(PDEVICE_EXTENSION DeviceExt
,
471 ULONG ClusterToWrite
,
474 /* ------------------------------------------------------ direntry.c */
476 ULONG
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt
,
477 PFAT_DIR_ENTRY pDirEntry
);
479 BOOL
VfatIsDirectoryEmpty(PVFATFCB Fcb
);
481 NTSTATUS
vfatGetNextDirEntry(PVOID
* pContext
,
484 IN PVFAT_DIRENTRY_CONTEXT DirContext
,
487 /* ----------------------------------------------------------- fcb.c */
489 PVFATFCB
vfatNewFCB (PUNICODE_STRING pFileNameU
);
491 VOID
vfatDestroyFCB (PVFATFCB pFCB
);
493 VOID
vfatDestroyCCB(PVFATCCB pCcb
);
495 VOID
vfatGrabFCB (PDEVICE_EXTENSION pVCB
,
498 VOID
vfatReleaseFCB (PDEVICE_EXTENSION pVCB
,
501 VOID
vfatAddFCBToTable (PDEVICE_EXTENSION pVCB
,
504 PVFATFCB
vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt
,
505 PUNICODE_STRING pFileNameU
);
507 PVFATFCB
vfatMakeRootFCB (PDEVICE_EXTENSION pVCB
);
509 PVFATFCB
vfatOpenRootFCB (PDEVICE_EXTENSION pVCB
);
511 BOOL
vfatFCBIsDirectory (PVFATFCB FCB
);
513 BOOL
vfatFCBIsRoot(PVFATFCB FCB
);
515 NTSTATUS
vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb
,
517 PFILE_OBJECT fileObject
);
519 NTSTATUS
vfatDirFindFile (PDEVICE_EXTENSION pVCB
,
521 PUNICODE_STRING FileToFindU
,
524 NTSTATUS
vfatGetFCBForFile (PDEVICE_EXTENSION pVCB
,
525 PVFATFCB
*pParentFCB
,
527 PUNICODE_STRING pFileNameU
);
529 NTSTATUS
vfatMakeFCBFromDirEntry (PVCB vcb
,
530 PVFATFCB directoryFCB
,
531 PVFAT_DIRENTRY_CONTEXT DirContext
,
534 /* ------------------------------------------------------------ rw.c */
536 NTSTATUS
VfatRead (PVFAT_IRP_CONTEXT IrpContext
);
538 NTSTATUS
VfatWrite (PVFAT_IRP_CONTEXT IrpContext
);
540 NTSTATUS
NextCluster(PDEVICE_EXTENSION DeviceExt
,
542 PULONG CurrentCluster
,
545 /* ----------------------------------------------------------- misc.c */
547 NTSTATUS
VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext
);
549 PVFAT_IRP_CONTEXT
VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject
,
552 VOID
VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext
);
554 NTSTATUS STDCALL
VfatBuildRequest (PDEVICE_OBJECT DeviceObject
,
557 PVOID
VfatGetUserBuffer(IN PIRP
);
559 NTSTATUS
VfatLockUserBuffer(IN PIRP
, IN ULONG
,
563 VfatSetExtendedAttributes(PFILE_OBJECT FileObject
,
566 /* ------------------------------------------------------------- flush.c */
568 NTSTATUS
VfatFlush(PVFAT_IRP_CONTEXT IrpContext
);
570 NTSTATUS
VfatFlushVolume(PDEVICE_EXTENSION DeviceExt
, PVFATFCB VolumeFcb
);