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
VfatIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt,struct _VFATFCB * Fcb)367 VfatIsDirectoryEmpty(PDEVICE_EXTENSION DeviceExt,
368 struct _VFATFCB* Fcb)
369 {
370 return DeviceExt->Dispatch.IsDirectoryEmpty(DeviceExt, Fcb);
371 }
372
373 FORCEINLINE
374 NTSTATUS
VfatAddEntry(PDEVICE_EXTENSION DeviceExt,PUNICODE_STRING NameU,struct _VFATFCB ** Fcb,struct _VFATFCB * ParentFcb,ULONG RequestedOptions,UCHAR ReqAttr,struct _VFAT_MOVE_CONTEXT * MoveContext)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
VfatDelEntry(PDEVICE_EXTENSION DeviceExt,struct _VFATFCB * Fcb,struct _VFAT_MOVE_CONTEXT * MoveContext)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
VfatGetNextDirEntry(PDEVICE_EXTENSION DeviceExt,PVOID * pContext,PVOID * pPage,struct _VFATFCB * pDirFcb,struct _VFAT_DIRENTRY_CONTEXT * DirContext,BOOLEAN First)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
VfatMarkIrpContextForQueue(PVFAT_IRP_CONTEXT IrpContext)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
vfatFCBIsDirectory(PVFATFCB FCB)637 vfatFCBIsDirectory(PVFATFCB FCB)
638 {
639 return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_DIRECTORY);
640 }
641
642 FORCEINLINE
643 BOOLEAN
vfatFCBIsReadOnly(PVFATFCB FCB)644 vfatFCBIsReadOnly(PVFATFCB FCB)
645 {
646 return BooleanFlagOn(*FCB->Attributes, FILE_ATTRIBUTE_READONLY);
647 }
648
649 FORCEINLINE
650 BOOLEAN
vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)651 vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
652 {
653 return BooleanFlagOn(DeviceExt->Flags, VCB_IS_FATX);
654 }
655
656 FORCEINLINE
657 VOID
vfatReportChange(IN PDEVICE_EXTENSION DeviceExt,IN PVFATFCB Fcb,IN ULONG FilterMatch,IN ULONG Action)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