ReactOS 0.4.15-dev-7889-g76290a6
fsctl.c
Go to the documentation of this file.
1/*
2 * PROJECT: VFAT Filesystem
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Filesystem routines
5 * COPYRIGHT: Copyright 2002-2013 Eric Kohl <eric.kohl@reactos.org>
6 * Copyright 2008-2018 Pierre Schweitzer <pierre@reactos.org>
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include "vfat.h"
12
13#define NDEBUG
14#include <debug.h>
15
18
19/* FUNCTIONS ****************************************************************/
20
21#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
22 (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
23
24static
27 PDEVICE_OBJECT DeviceToMount,
28 PBOOLEAN RecognizedFS,
29 PFATINFO pFatInfo,
30 BOOLEAN Override)
31{
34 DISK_GEOMETRY DiskGeometry;
35 FATINFO FatInfo;
36 ULONG Size;
37 ULONG Sectors;
39 struct _BootSector* Boot;
40 struct _BootSectorFatX* BootFatX;
41 BOOLEAN PartitionInfoIsValid = FALSE;
42
43 DPRINT("VfatHasFileSystem\n");
44
45 *RecognizedFS = FALSE;
46
47 Size = sizeof(DISK_GEOMETRY);
48 Status = VfatBlockDeviceIoControl(DeviceToMount,
50 NULL,
51 0,
52 &DiskGeometry,
53 &Size,
54 Override);
55 if (!NT_SUCCESS(Status))
56 {
57 DPRINT("VfatBlockDeviceIoControl failed (%x)\n", Status);
58 return Status;
59 }
60
61 FatInfo.FixedMedia = DiskGeometry.MediaType == FixedMedia ? TRUE : FALSE;
62 if (DiskGeometry.MediaType == FixedMedia || DiskGeometry.MediaType == RemovableMedia)
63 {
64 // We have found a hard disk
66 Status = VfatBlockDeviceIoControl(DeviceToMount,
68 NULL,
69 0,
71 &Size,
72 Override);
73 if (!NT_SUCCESS(Status))
74 {
75 DPRINT("VfatBlockDeviceIoControl failed (%x)\n", Status);
76 return Status;
77 }
78
79 DPRINT("Partition Information:\n");
80 DPRINT("StartingOffset %I64x\n", PartitionInfo.StartingOffset.QuadPart / 512);
81 DPRINT("PartitionLength %I64x\n", PartitionInfo.PartitionLength.QuadPart / 512);
82 DPRINT("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
83 DPRINT("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
84 DPRINT("PartitionType %u\n", PartitionInfo.PartitionType);
85 DPRINT("BootIndicator %u\n", PartitionInfo.BootIndicator);
86 DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
87 DPRINT("RewritePartition %u\n", PartitionInfo.RewritePartition);
88 if (PartitionInfo.PartitionType)
89 {
90 if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
91 PartitionInfo.PartitionType == PARTITION_FAT_16 ||
92 PartitionInfo.PartitionType == PARTITION_HUGE ||
93 PartitionInfo.PartitionType == PARTITION_FAT32 ||
94 PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
95 PartitionInfo.PartitionType == PARTITION_XINT13)
96 {
97 PartitionInfoIsValid = TRUE;
98 *RecognizedFS = TRUE;
99 }
100 }
101 else if (DiskGeometry.MediaType == RemovableMedia &&
102 PartitionInfo.PartitionNumber > 0 &&
103 PartitionInfo.StartingOffset.QuadPart == 0 &&
104 PartitionInfo.PartitionLength.QuadPart > 0)
105 {
106 /* This is possible a removable media formated as super floppy */
107 PartitionInfoIsValid = TRUE;
108 *RecognizedFS = TRUE;
109 }
110 }
111 else
112 {
113 *RecognizedFS = TRUE;
114 }
115
116 if (*RecognizedFS)
117 {
119 if (Boot == NULL)
120 {
122 }
123
124 Offset.QuadPart = 0;
125
126 /* Try to recognize FAT12/FAT16/FAT32 partitions */
127 Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, Override);
128 if (NT_SUCCESS(Status))
129 {
130 if (Boot->Signatur1 != 0xaa55)
131 {
132 *RecognizedFS = FALSE;
133 }
134
135 if (*RecognizedFS &&
136 Boot->BytesPerSector != 512 &&
137 Boot->BytesPerSector != 1024 &&
138 Boot->BytesPerSector != 2048 &&
139 Boot->BytesPerSector != 4096)
140 {
141 DPRINT1("BytesPerSector %u\n", Boot->BytesPerSector);
142 *RecognizedFS = FALSE;
143 }
144
145 if (*RecognizedFS &&
146 Boot->FATCount != 1 &&
147 Boot->FATCount != 2)
148 {
149 DPRINT1("FATCount %u\n", Boot->FATCount);
150 *RecognizedFS = FALSE;
151 }
152
153 if (*RecognizedFS &&
154 Boot->Media != 0xf0 &&
155 Boot->Media != 0xf8 &&
156 Boot->Media != 0xf9 &&
157 Boot->Media != 0xfa &&
158 Boot->Media != 0xfb &&
159 Boot->Media != 0xfc &&
160 Boot->Media != 0xfd &&
161 Boot->Media != 0xfe &&
162 Boot->Media != 0xff)
163 {
164 DPRINT1("Media %02x\n", Boot->Media);
165 *RecognizedFS = FALSE;
166 }
167
168 if (*RecognizedFS &&
169 Boot->SectorsPerCluster != 1 &&
170 Boot->SectorsPerCluster != 2 &&
171 Boot->SectorsPerCluster != 4 &&
172 Boot->SectorsPerCluster != 8 &&
173 Boot->SectorsPerCluster != 16 &&
174 Boot->SectorsPerCluster != 32 &&
175 Boot->SectorsPerCluster != 64 &&
176 Boot->SectorsPerCluster != 128)
177 {
178 DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
179 *RecognizedFS = FALSE;
180 }
181
182 if (*RecognizedFS &&
183 Boot->BytesPerSector * Boot->SectorsPerCluster > 64 * 1024)
184 {
185 DPRINT1("ClusterSize %d\n", Boot->BytesPerSector * Boot->SectorsPerCluster);
186 *RecognizedFS = FALSE;
187 }
188
189 if (*RecognizedFS)
190 {
191 FatInfo.VolumeID = Boot->VolumeID;
192 FatInfo.FATStart = Boot->ReservedSectors;
193 FatInfo.FATCount = Boot->FATCount;
194 FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32;
195 FatInfo.BytesPerSector = Boot->BytesPerSector;
196 FatInfo.SectorsPerCluster = Boot->SectorsPerCluster;
197 FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster;
198 FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector;
199 FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
200 FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
201 FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge;
202 Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors;
203 FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster;
204 if (FatInfo.NumberOfClusters < 4085)
205 {
206 DPRINT("FAT12\n");
207 FatInfo.FatType = FAT12;
208 FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
209 RtlCopyMemory(&FatInfo.VolumeLabel, &Boot->VolumeLabel, sizeof(FatInfo.VolumeLabel));
210 }
211 else if (FatInfo.NumberOfClusters >= 65525)
212 {
213 DPRINT("FAT32\n");
214 FatInfo.FatType = FAT32;
215 FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster;
216 FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster);
217 FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID;
218 FatInfo.FSInfoSector = ((struct _BootSector32*) Boot)->FSInfoSector;
219 RtlCopyMemory(&FatInfo.VolumeLabel, &((struct _BootSector32*)Boot)->VolumeLabel, sizeof(FatInfo.VolumeLabel));
220 }
221 else
222 {
223 DPRINT("FAT16\n");
224 FatInfo.FatType = FAT16;
225 FatInfo.RootCluster = FatInfo.rootStart / FatInfo.SectorsPerCluster;
226 RtlCopyMemory(&FatInfo.VolumeLabel, &Boot->VolumeLabel, sizeof(FatInfo.VolumeLabel));
227 }
228
229 if (PartitionInfoIsValid &&
230 FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
231 {
232 *RecognizedFS = FALSE;
233 }
234
235 if (pFatInfo && *RecognizedFS)
236 {
237 *pFatInfo = FatInfo;
238 }
239 }
240 }
241
243 }
244
245 if (!*RecognizedFS && PartitionInfoIsValid)
246 {
248 if (BootFatX == NULL)
249 {
250 *RecognizedFS=FALSE;
252 }
253
254 Offset.QuadPart = 0;
255
256 /* Try to recognize FATX16/FATX32 partitions (Xbox) */
257 Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, Override);
258 if (NT_SUCCESS(Status))
259 {
260 *RecognizedFS = TRUE;
261 if (BootFatX->SysType[0] != 'F' ||
262 BootFatX->SysType[1] != 'A' ||
263 BootFatX->SysType[2] != 'T' ||
264 BootFatX->SysType[3] != 'X')
265 {
266 DPRINT1("SysType %02X%02X%02X%02X (%c%c%c%c)\n",
267 BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3],
268 isprint(BootFatX->SysType[0]) ? BootFatX->SysType[0] : '.',
269 isprint(BootFatX->SysType[1]) ? BootFatX->SysType[1] : '.',
270 isprint(BootFatX->SysType[2]) ? BootFatX->SysType[2] : '.',
271 isprint(BootFatX->SysType[3]) ? BootFatX->SysType[3] : '.');
272
273 *RecognizedFS = FALSE;
274 }
275
276 if (*RecognizedFS &&
277 BootFatX->SectorsPerCluster != 1 &&
278 BootFatX->SectorsPerCluster != 2 &&
279 BootFatX->SectorsPerCluster != 4 &&
280 BootFatX->SectorsPerCluster != 8 &&
281 BootFatX->SectorsPerCluster != 16 &&
282 BootFatX->SectorsPerCluster != 32 &&
283 BootFatX->SectorsPerCluster != 64 &&
284 BootFatX->SectorsPerCluster != 128)
285 {
286 DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
287 *RecognizedFS=FALSE;
288 }
289
290 if (*RecognizedFS)
291 {
292 FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
293 FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
294 FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
295 FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
296 FatInfo.Sectors = (ULONG)(PartitionInfo.PartitionLength.QuadPart / DiskGeometry.BytesPerSector);
297 if (FatInfo.Sectors / FatInfo.SectorsPerCluster < 65525)
298 {
299 DPRINT("FATX16\n");
300 FatInfo.FatType = FATX16;
301 }
302 else
303 {
304 DPRINT("FATX32\n");
305 FatInfo.FatType = FATX32;
306 }
307 FatInfo.VolumeID = BootFatX->VolumeID;
308 FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
309 FatInfo.FATCount = BootFatX->FATCount;
310 FatInfo.FATSectors =
311 ROUND_UP(FatInfo.Sectors / FatInfo.SectorsPerCluster * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) /
312 FatInfo.BytesPerSector;
313 FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
314 FatInfo.RootCluster = (FatInfo.rootStart - 1) / FatInfo.SectorsPerCluster;
315 FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
316 FatInfo.NumberOfClusters = (FatInfo.Sectors - FatInfo.dataStart) / FatInfo.SectorsPerCluster;
317
318 if (pFatInfo && *RecognizedFS)
319 {
320 *pFatInfo = FatInfo;
321 }
322 }
323 }
324 ExFreePoolWithTag(BootFatX, TAG_BUFFER);
325 }
326
327 DPRINT("VfatHasFileSystem done\n");
328 return Status;
329}
330
331/*
332 * FUNCTION: Read the volume label
333 * WARNING: Read this comment carefully before using it (and using it wrong)
334 * Device parameter is expected to be the lower DO is start isn't 0
335 * otherwise, it is expected to be the VCB is start is 0
336 * Start parameter is expected to be, in bytes, the beginning of the root start.
337 * Set it to 0 if you wish to use the associated FCB with caching.
338 * In that specific case, Device parameter is expected to be the VCB!
339 * VolumeLabel parameter is expected to be a preallocated UNICODE_STRING (ie, with buffer)
340 * Its buffer has to be able to contain MAXIMUM_VOLUME_LABEL_LENGTH bytes
341 */
342static
346 ULONG Start,
347 BOOLEAN IsFatX,
348 PUNICODE_STRING VolumeLabel)
349{
350 PDEVICE_EXTENSION DeviceExt;
353 ULONG DirIndex = 0;
355 PVFATFCB pFcb;
357 ULONG SizeDirEntry;
358 ULONG EntriesPerPage;
359 OEM_STRING StringO;
360 BOOLEAN NoCache = (Start != 0);
363
364 if (IsFatX)
365 {
366 SizeDirEntry = sizeof(FATX_DIR_ENTRY);
367 EntriesPerPage = FATX_ENTRIES_PER_PAGE;
368 }
369 else
370 {
371 SizeDirEntry = sizeof(FAT_DIR_ENTRY);
372 EntriesPerPage = FAT_ENTRIES_PER_PAGE;
373 }
374
375 FileOffset.QuadPart = Start;
376 if (!NoCache)
377 {
378 DeviceExt = Device;
379
380 /* FIXME: Check we really have a VCB
381 ASSERT();
382 */
383
384 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
385 pFcb = vfatOpenRootFCB(DeviceExt);
386 ExReleaseResourceLite(&DeviceExt->DirResource);
387
389 {
390 CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT, &Context, (PVOID*)&Entry);
391 }
393 {
395 }
396 _SEH2_END;
397 }
398 else
399 {
401
402 ASSERT(DeviceObject->Type == 3);
403
405 if (Buffer != NULL)
406 {
408 if (!NT_SUCCESS(Status))
409 {
411 }
412 else
413 {
414 Entry = Buffer;
415 }
416 }
417 else
418 {
420 }
421 }
422
423 if (NT_SUCCESS(Status))
424 {
425 while (TRUE)
426 {
427 if (ENTRY_VOLUME(IsFatX, Entry))
428 {
429 /* copy volume label */
430 if (IsFatX)
431 {
432 StringO.Buffer = (PCHAR)Entry->FatX.Filename;
433 StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
434 RtlOemStringToUnicodeString(VolumeLabel, &StringO, FALSE);
435 }
436 else
437 {
438 vfat8Dot3ToString(&Entry->Fat, VolumeLabel);
439 }
440 break;
441 }
442 if (ENTRY_END(IsFatX, Entry))
443 {
444 break;
445 }
446 DirIndex++;
447 Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
448 if ((DirIndex % EntriesPerPage) == 0)
449 {
450 FileOffset.u.LowPart += PAGE_SIZE;
451
452 if (!NoCache)
453 {
455
457 {
458 CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, MAP_WAIT, &Context, (PVOID*)&Entry);
459 }
461 {
463 }
464 _SEH2_END;
465 if (!NT_SUCCESS(Status))
466 {
467 Context = NULL;
468 break;
469 }
470 }
471 else
472 {
474 if (!NT_SUCCESS(Status))
475 {
476 break;
477 }
478 Entry = Buffer;
479 }
480 }
481 }
482 if (Context)
483 {
485 }
486 else if (NoCache)
487 {
489 }
490 }
491
492 if (!NoCache)
493 {
494 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
495 vfatReleaseFCB(DeviceExt, pFcb);
496 ExReleaseResourceLite(&DeviceExt->DirResource);
497 }
498
499 return STATUS_SUCCESS;
500}
501
502
503/*
504 * FUNCTION: Mount the filesystem
505 */
506static
509 PVFAT_IRP_CONTEXT IrpContext)
510{
512 PDEVICE_EXTENSION DeviceExt = NULL;
513 BOOLEAN RecognizedFS;
515 PVFATFCB Fcb = NULL;
516 PVFATFCB VolumeFcb = NULL;
517 PDEVICE_OBJECT DeviceToMount;
518 PVPB Vpb;
519 UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
520 UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
521 UNICODE_STRING VolumeLabelU;
522 ULONG HashTableSize;
523 ULONG i;
524 FATINFO FatInfo;
525 BOOLEAN Dirty;
526
527 DPRINT("VfatMount(IrpContext %p)\n", IrpContext);
528
529 ASSERT(IrpContext);
530
531 if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
532 {
534 goto ByeBye;
535 }
536
537 DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
538 Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;
539
540 Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &FatInfo, FALSE);
541 if (!NT_SUCCESS(Status))
542 {
543 goto ByeBye;
544 }
545
546 if (RecognizedFS == FALSE)
547 {
548 DPRINT("VFAT: Unrecognized Volume\n");
550 goto ByeBye;
551 }
552
553 /* Use prime numbers for the table size */
554 if (FatInfo.FatType == FAT12)
555 {
556 HashTableSize = 4099; // 4096 = 4 * 1024
557 }
558 else if (FatInfo.FatType == FAT16 ||
559 FatInfo.FatType == FATX16)
560 {
561 HashTableSize = 16411; // 16384 = 16 * 1024
562 }
563 else
564 {
565 HashTableSize = 65537; // 65536 = 64 * 1024;
566 }
567 DPRINT("VFAT: Recognized volume\n");
569 ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
570 NULL,
572 DeviceToMount->Characteristics,
573 FALSE,
574 &DeviceObject);
575 if (!NT_SUCCESS(Status))
576 {
577 goto ByeBye;
578 }
579
580 DeviceExt = DeviceObject->DeviceExtension;
581 RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
582 DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
583 DeviceExt->HashTableSize = HashTableSize;
584 DeviceExt->VolumeDevice = DeviceObject;
585
586 KeInitializeSpinLock(&DeviceExt->OverflowQueueSpinLock);
587 InitializeListHead(&DeviceExt->OverflowQueue);
588 DeviceExt->OverflowQueueCount = 0;
589 DeviceExt->PostedRequestCount = 0;
590
591 /* use same vpb as device disk */
592 DeviceObject->Vpb = Vpb;
593 DeviceToMount->Vpb = Vpb;
594
595 RtlCopyMemory(&DeviceExt->FatInfo, &FatInfo, sizeof(FATINFO));
596
597 DPRINT("BytesPerSector: %u\n", DeviceExt->FatInfo.BytesPerSector);
598 DPRINT("SectorsPerCluster: %u\n", DeviceExt->FatInfo.SectorsPerCluster);
599 DPRINT("FATCount: %u\n", DeviceExt->FatInfo.FATCount);
600 DPRINT("FATSectors: %u\n", DeviceExt->FatInfo.FATSectors);
601 DPRINT("RootStart: %u\n", DeviceExt->FatInfo.rootStart);
602 DPRINT("DataStart: %u\n", DeviceExt->FatInfo.dataStart);
603 if (DeviceExt->FatInfo.FatType == FAT32)
604 {
605 DPRINT("RootCluster: %u\n", DeviceExt->FatInfo.RootCluster);
606 }
607
608 switch (DeviceExt->FatInfo.FatType)
609 {
610 case FAT12:
611 DeviceExt->GetNextCluster = FAT12GetNextCluster;
612 DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
613 DeviceExt->WriteCluster = FAT12WriteCluster;
614 /* We don't define dirty bit functions here
615 * FAT12 doesn't have such bit and they won't get called
616 */
617 break;
618
619 case FAT16:
620 case FATX16:
621 DeviceExt->GetNextCluster = FAT16GetNextCluster;
622 DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
623 DeviceExt->WriteCluster = FAT16WriteCluster;
624 DeviceExt->GetDirtyStatus = FAT16GetDirtyStatus;
625 DeviceExt->SetDirtyStatus = FAT16SetDirtyStatus;
626 break;
627
628 case FAT32:
629 case FATX32:
630 DeviceExt->GetNextCluster = FAT32GetNextCluster;
631 DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
632 DeviceExt->WriteCluster = FAT32WriteCluster;
633 DeviceExt->GetDirtyStatus = FAT32GetDirtyStatus;
634 DeviceExt->SetDirtyStatus = FAT32SetDirtyStatus;
635 break;
636 }
637
638 if (DeviceExt->FatInfo.FatType == FATX16 ||
639 DeviceExt->FatInfo.FatType == FATX32)
640 {
641 DeviceExt->Flags |= VCB_IS_FATX;
642 DeviceExt->BaseDateYear = 2000;
643 RtlCopyMemory(&DeviceExt->Dispatch, &FatXDispatch, sizeof(VFAT_DISPATCH));
644 }
645 else
646 {
647 DeviceExt->BaseDateYear = 1980;
648 RtlCopyMemory(&DeviceExt->Dispatch, &FatDispatch, sizeof(VFAT_DISPATCH));
649 }
650
651 DeviceExt->StorageDevice = DeviceToMount;
652 DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
653 DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
654 DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
655 DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
656 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
657
658 DPRINT("FsDeviceObject %p\n", DeviceObject);
659
660 /* Initialize this resource early ... it's used in VfatCleanup */
661 ExInitializeResourceLite(&DeviceExt->DirResource);
662
663 DeviceExt->IoVPB = DeviceObject->Vpb;
664 DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VPB);
665 if (DeviceExt->SpareVPB == NULL)
666 {
668 goto ByeBye;
669 }
670
671 DeviceExt->Statistics = ExAllocatePoolWithTag(NonPagedPool,
673 TAG_STATS);
674 if (DeviceExt->Statistics == NULL)
675 {
677 goto ByeBye;
678 }
679
680 RtlZeroMemory(DeviceExt->Statistics, sizeof(STATISTICS) * VfatGlobalData->NumberProcessors);
681 for (i = 0; i < VfatGlobalData->NumberProcessors; ++i)
682 {
683 DeviceExt->Statistics[i].Base.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
684 DeviceExt->Statistics[i].Base.Version = 1;
685 DeviceExt->Statistics[i].Base.SizeOfCompleteStructure = sizeof(STATISTICS);
686 }
687
688 DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
689 Fcb = vfatNewFCB(DeviceExt, &NameU);
690 if (Fcb == NULL)
691 {
693 goto ByeBye;
694 }
695
696 Status = vfatAttachFCBToFileObject(DeviceExt, Fcb, DeviceExt->FATFileObject);
697 if (!NT_SUCCESS(Status))
698 goto ByeBye;
699
700 DeviceExt->FATFileObject->PrivateCacheMap = NULL;
701 Fcb->FileObject = DeviceExt->FATFileObject;
702
704 Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
707
709 {
710 CcInitializeCacheMap(DeviceExt->FATFileObject,
712 TRUE,
714 Fcb);
715 }
717 {
719 goto ByeBye;
720 }
721 _SEH2_END;
722
723 DeviceExt->LastAvailableCluster = 2;
724 CountAvailableClusters(DeviceExt, NULL);
725 ExInitializeResourceLite(&DeviceExt->FatResource);
726
727 InitializeListHead(&DeviceExt->FcbListHead);
728
729 VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
730 if (VolumeFcb == NULL)
731 {
733 goto ByeBye;
734 }
735
736 VolumeFcb->Flags = FCB_IS_VOLUME;
737 VolumeFcb->RFCB.FileSize.QuadPart = (LONGLONG) DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
738 VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
739 VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
740 DeviceExt->VolumeFcb = VolumeFcb;
741
743 InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
745
746 /* read serial number */
747 DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
748
749 /* read volume label */
750 VolumeLabelU.Buffer = DeviceObject->Vpb->VolumeLabel;
751 VolumeLabelU.Length = 0;
752 VolumeLabelU.MaximumLength = sizeof(DeviceObject->Vpb->VolumeLabel);
753 ReadVolumeLabel(DeviceExt, 0, vfatVolumeIsFatX(DeviceExt), &VolumeLabelU);
754 Vpb->VolumeLabelLength = VolumeLabelU.Length;
755
756 /* read dirty bit status */
757 Status = GetDirtyStatus(DeviceExt, &Dirty);
758 if (NT_SUCCESS(Status))
759 {
760 /* The volume wasn't dirty, it was properly dismounted */
761 if (!Dirty)
762 {
763 /* Mark it dirty now! */
764 SetDirtyStatus(DeviceExt, TRUE);
765 VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
766 }
767 else
768 {
769 DPRINT1("Mounting a dirty volume\n");
770 }
771 }
772
773 VolumeFcb->Flags |= VCB_IS_DIRTY;
774 if (BooleanFlagOn(Vpb->RealDevice->Flags, DO_SYSTEM_BOOT_PARTITION))
775 {
776 SetFlag(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE);
777 }
778
779 /* Initialize the notify list and synchronization object */
780 InitializeListHead(&DeviceExt->NotifyList);
781 FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
782
783 /* The VCB is OK for usage */
784 SetFlag(DeviceExt->Flags, VCB_GOOD);
785
786 /* Send the mount notification */
787 FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);
788
789 DPRINT("Mount success\n");
790
792
793ByeBye:
794 if (!NT_SUCCESS(Status))
795 {
796 /* Cleanup */
797 if (DeviceExt && DeviceExt->FATFileObject)
798 {
799 LARGE_INTEGER Zero = {{0,0}};
800 PVFATCCB Ccb = (PVFATCCB)DeviceExt->FATFileObject->FsContext2;
801
802 CcUninitializeCacheMap(DeviceExt->FATFileObject,
803 &Zero,
804 NULL);
805 ObDereferenceObject(DeviceExt->FATFileObject);
806 if (Ccb)
808 DeviceExt->FATFileObject = NULL;
809 }
810 if (Fcb)
812 if (DeviceExt && DeviceExt->SpareVPB)
813 ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VPB);
814 if (DeviceExt && DeviceExt->Statistics)
815 ExFreePoolWithTag(DeviceExt->Statistics, TAG_STATS);
816 if (DeviceObject)
818 }
819
820 return Status;
821}
822
823
824/*
825 * FUNCTION: Verify the filesystem
826 */
827static
830 PVFAT_IRP_CONTEXT IrpContext)
831{
834 FATINFO FatInfo;
835 BOOLEAN RecognizedFS;
836 PDEVICE_EXTENSION DeviceExt;
837 BOOLEAN AllowRaw;
838 PVPB Vpb;
839 ULONG ChangeCount, BufSize = sizeof(ChangeCount);
840
841 DPRINT("VfatVerify(IrpContext %p)\n", IrpContext);
842
843 DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
844 DeviceExt = DeviceToVerify->DeviceExtension;
845 Vpb = IrpContext->Stack->Parameters.VerifyVolume.Vpb;
846 AllowRaw = BooleanFlagOn(IrpContext->Stack->Flags, SL_ALLOW_RAW_MOUNT);
847
848 if (!BooleanFlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME))
849 {
850 DPRINT("Already verified\n");
851 return STATUS_SUCCESS;
852 }
853
854 Status = VfatBlockDeviceIoControl(DeviceExt->StorageDevice,
856 NULL,
857 0,
858 &ChangeCount,
859 &BufSize,
860 TRUE);
862 {
863 DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
864 Status = (AllowRaw ? STATUS_WRONG_VOLUME : Status);
865 }
866 else
867 {
868 Status = VfatHasFileSystem(DeviceExt->StorageDevice, &RecognizedFS, &FatInfo, TRUE);
869 if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
870 {
871 if (NT_SUCCESS(Status) || AllowRaw)
872 {
874 }
875 }
876 else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
877 {
878 WCHAR BufferU[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)];
879 UNICODE_STRING VolumeLabelU;
880 UNICODE_STRING VpbLabelU;
881
882 VolumeLabelU.Buffer = BufferU;
883 VolumeLabelU.Length = 0;
884 VolumeLabelU.MaximumLength = sizeof(BufferU);
885 Status = ReadVolumeLabel(DeviceExt->StorageDevice, FatInfo.rootStart * FatInfo.BytesPerSector, (FatInfo.FatType >= FATX16), &VolumeLabelU);
886 if (!NT_SUCCESS(Status))
887 {
888 if (AllowRaw)
889 {
891 }
892 }
893 else
894 {
895 VpbLabelU.Buffer = Vpb->VolumeLabel;
896 VpbLabelU.Length = Vpb->VolumeLabelLength;
897 VpbLabelU.MaximumLength = sizeof(Vpb->VolumeLabel);
898
899 if (RtlCompareUnicodeString(&VpbLabelU, &VolumeLabelU, FALSE) != 0)
900 {
902 }
903 else
904 {
905 DPRINT1("Same volume\n");
906 }
907 }
908 }
909 else
910 {
912 }
913 }
914
915 Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
916
917 return Status;
918}
919
920
921static
924 PVFAT_IRP_CONTEXT IrpContext)
925{
926 DPRINT("VfatGetVolumeBitmap (IrpContext %p)\n", IrpContext);
928}
929
930
931static
934 PVFAT_IRP_CONTEXT IrpContext)
935{
937 LARGE_INTEGER Vcn;
938 PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
940 ULONG MaxExtentCount;
942 PDEVICE_EXTENSION DeviceExt;
943 ULONG FirstCluster;
944 ULONG CurrentCluster;
945 ULONG LastCluster;
947
948 DPRINT("VfatGetRetrievalPointers(IrpContext %p)\n", IrpContext);
949
950 DeviceExt = IrpContext->DeviceExt;
951 FileObject = IrpContext->FileObject;
952 Stack = IrpContext->Stack;
953 if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER) ||
954 Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
955 {
957 }
958
959 if (IrpContext->Irp->UserBuffer == NULL ||
960 Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))
961 {
963 }
964
965 Fcb = FileObject->FsContext;
966
968
969 Vcn = ((PSTARTING_VCN_INPUT_BUFFER)Stack->Parameters.DeviceIoControl.Type3InputBuffer)->StartingVcn;
970 RetrievalPointers = IrpContext->Irp->UserBuffer;
971
972 MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0]));
973
974 if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
975 {
977 goto ByeBye;
978 }
979
980 CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
981 Status = OffsetToCluster(DeviceExt, FirstCluster,
982 Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
983 &CurrentCluster, FALSE);
984 if (!NT_SUCCESS(Status))
985 {
986 goto ByeBye;
987 }
988
989 RetrievalPointers->StartingVcn = Vcn;
990 RetrievalPointers->ExtentCount = 0;
991 RetrievalPointers->Extents[0].Lcn.u.HighPart = 0;
992 RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2;
993 LastCluster = 0;
994 while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount)
995 {
996 LastCluster = CurrentCluster;
997 Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
998 Vcn.QuadPart++;
999 if (!NT_SUCCESS(Status))
1000 {
1001 goto ByeBye;
1002 }
1003
1004 if (LastCluster + 1 != CurrentCluster)
1005 {
1006 RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn;
1007 RetrievalPointers->ExtentCount++;
1008 if (RetrievalPointers->ExtentCount < MaxExtentCount)
1009 {
1010 RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0;
1011 RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2;
1012 }
1013 }
1014 }
1015
1016 IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1));
1018
1019ByeBye:
1021
1022 return Status;
1023}
1024
1025static
1028 PVFAT_IRP_CONTEXT IrpContext)
1029{
1030 DPRINT("VfatMoveFile(IrpContext %p)\n", IrpContext);
1032}
1033
1034static
1037 PVFAT_IRP_CONTEXT IrpContext)
1038{
1039 PULONG Flags;
1040
1041 DPRINT("VfatIsVolumeDirty(IrpContext %p)\n", IrpContext);
1042
1043 if (IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength != sizeof(ULONG))
1045 else if (!IrpContext->Irp->AssociatedIrp.SystemBuffer)
1047
1048 Flags = (PULONG)IrpContext->Irp->AssociatedIrp.SystemBuffer;
1049 *Flags = 0;
1050
1051 if (BooleanFlagOn(IrpContext->DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY) &&
1052 !BooleanFlagOn(IrpContext->DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY))
1053 {
1055 }
1056
1057 IrpContext->Irp->IoStatus.Information = sizeof(ULONG);
1058
1059 return STATUS_SUCCESS;
1060}
1061
1062static
1065 PVFAT_IRP_CONTEXT IrpContext)
1066{
1067 PDEVICE_EXTENSION DeviceExt;
1069
1070 DPRINT("VfatMarkVolumeDirty(IrpContext %p)\n", IrpContext);
1071 DeviceExt = IrpContext->DeviceExt;
1072
1073 if (!BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1074 {
1075 Status = SetDirtyStatus(DeviceExt, TRUE);
1076 }
1077
1078 DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
1079
1080 return Status;
1081}
1082
1083static
1086 PVFAT_IRP_CONTEXT IrpContext,
1087 BOOLEAN Lock)
1088{
1090 PDEVICE_EXTENSION DeviceExt;
1091 PVFATFCB Fcb;
1092 PVPB Vpb;
1093
1094 DPRINT("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock);
1095
1096 DeviceExt = IrpContext->DeviceExt;
1097 FileObject = IrpContext->FileObject;
1098 Fcb = FileObject->FsContext;
1099 Vpb = DeviceExt->FATFileObject->Vpb;
1100
1101 /* Only allow locking with the volume open */
1103 {
1104 return STATUS_ACCESS_DENIED;
1105 }
1106
1107 /* Bail out if it's already in the demanded state */
1108 if ((BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && Lock) ||
1109 (!BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && !Lock))
1110 {
1111 return STATUS_ACCESS_DENIED;
1112 }
1113
1114 /* Bail out if it's already in the demanded state */
1115 if ((BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && Lock) ||
1116 (!BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && !Lock))
1117 {
1118 return STATUS_ACCESS_DENIED;
1119 }
1120
1121 if (Lock)
1122 {
1124 }
1125
1126 /* Deny locking if we're not alone */
1127 if (Lock && DeviceExt->OpenHandleCount != 1)
1128 {
1129 PLIST_ENTRY ListEntry;
1130
1131#if 1
1132 /* FIXME: Hack that allows locking the system volume on
1133 * boot so that autochk can run properly
1134 * That hack is, on purpose, really restrictive
1135 * it will only allow locking with two directories
1136 * open: current directory of smss and autochk.
1137 */
1138 BOOLEAN ForceLock = TRUE;
1139 ULONG HandleCount = 0;
1140
1141 /* Only allow boot volume */
1142 if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
1143 {
1144 /* We'll browse all the FCB */
1145 ListEntry = DeviceExt->FcbListHead.Flink;
1146 while (ListEntry != &DeviceExt->FcbListHead)
1147 {
1148 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
1149 ListEntry = ListEntry->Flink;
1150
1151 /* If no handle: that FCB is no problem for locking
1152 * so ignore it
1153 */
1154 if (Fcb->OpenHandleCount == 0)
1155 {
1156 continue;
1157 }
1158
1159 /* Not a dir? We're no longer at boot */
1160 if (!vfatFCBIsDirectory(Fcb))
1161 {
1162 ForceLock = FALSE;
1163 break;
1164 }
1165
1166 /* If we have cached initialized and several handles, we're
1167 not in the boot case
1168 */
1169 if (Fcb->FileObject != NULL && Fcb->OpenHandleCount > 1)
1170 {
1171 ForceLock = FALSE;
1172 break;
1173 }
1174
1175 /* Count the handles */
1176 HandleCount += Fcb->OpenHandleCount;
1177 /* More than two handles? Then, we're not booting anymore */
1178 if (HandleCount > 2)
1179 {
1180 ForceLock = FALSE;
1181 break;
1182 }
1183 }
1184 }
1185 else
1186 {
1187 ForceLock = FALSE;
1188 }
1189
1190 /* Here comes the hack, ignore the failure! */
1191 if (!ForceLock)
1192 {
1193#endif
1194
1195 DPRINT1("Can't lock: %u opened\n", DeviceExt->OpenHandleCount);
1196
1197 ListEntry = DeviceExt->FcbListHead.Flink;
1198 while (ListEntry != &DeviceExt->FcbListHead)
1199 {
1200 Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
1201 ListEntry = ListEntry->Flink;
1202
1203 if (Fcb->OpenHandleCount > 0)
1204 {
1205 DPRINT1("Opened (%u - %u): %wZ\n", Fcb->OpenHandleCount, Fcb->RefCount, &Fcb->PathNameU);
1206 }
1207 }
1208
1210
1211 return STATUS_ACCESS_DENIED;
1212
1213#if 1
1214 /* End of the hack: be verbose about its usage,
1215 * just in case we would mess up everything!
1216 */
1217 }
1218 else
1219 {
1220 DPRINT1("HACK: Using lock-hack!\n");
1221 }
1222#endif
1223 }
1224
1225 /* Finally, proceed */
1226 if (Lock)
1227 {
1228 /* Flush volume & files */
1229 VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
1230
1231 /* The volume is now clean */
1232 if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY) &&
1233 BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1234 {
1235 /* Drop the dirty bit */
1236 if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
1237 ClearFlag(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY);
1238 }
1239
1240 DeviceExt->Flags |= VCB_VOLUME_LOCKED;
1241 Vpb->Flags |= VPB_LOCKED;
1242 }
1243 else
1244 {
1245 DeviceExt->Flags &= ~VCB_VOLUME_LOCKED;
1246 Vpb->Flags &= ~VPB_LOCKED;
1247
1249 }
1250
1251 return STATUS_SUCCESS;
1252}
1253
1254static
1257 PVFAT_IRP_CONTEXT IrpContext)
1258{
1259 PDEVICE_EXTENSION DeviceExt;
1260 PLIST_ENTRY NextEntry;
1261 PVFATFCB Fcb;
1263
1264 DPRINT("VfatDismountVolume(%p)\n", IrpContext);
1265
1266 DeviceExt = IrpContext->DeviceExt;
1267 FileObject = IrpContext->FileObject;
1268
1269 /* We HAVE to be locked. Windows also allows dismount with no lock
1270 * but we're here mainly for 1st stage, so KISS
1271 */
1272 if (!BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
1273 {
1274 return STATUS_ACCESS_DENIED;
1275 }
1276
1277 /* Deny dismount of boot volume */
1278 if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
1279 {
1280 return STATUS_ACCESS_DENIED;
1281 }
1282
1283 /* Race condition? */
1284 if (BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
1285 {
1287 }
1288
1289 /* Notify we'll dismount. Pass that point there's no reason we fail */
1291
1292 ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
1293
1294 /* Flush volume & files */
1295 VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);
1296
1297 /* The volume is now clean */
1298 if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY) &&
1299 BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1300 {
1301 /* Drop the dirty bit */
1302 if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
1303 DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
1304 }
1305
1306 /* Rebrowse the FCB in order to free them now */
1307 while (!IsListEmpty(&DeviceExt->FcbListHead))
1308 {
1309 NextEntry = RemoveTailList(&DeviceExt->FcbListHead);
1310 Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
1311
1312 if (Fcb == DeviceExt->RootFcb)
1313 DeviceExt->RootFcb = NULL;
1314 else if (Fcb == DeviceExt->VolumeFcb)
1315 DeviceExt->VolumeFcb = NULL;
1316
1318 }
1319
1320 /* We are uninitializing, the VCB cannot be used anymore */
1321 ClearFlag(DeviceExt->Flags, VCB_GOOD);
1322
1323 /* Mark we're being dismounted */
1324 DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
1325#ifndef ENABLE_SWAPOUT
1326 IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
1327#endif
1328
1329 ExReleaseResourceLite(&DeviceExt->FatResource);
1330
1331 return STATUS_SUCCESS;
1332}
1333
1334static
1337 PVFAT_IRP_CONTEXT IrpContext)
1338{
1339 PVOID Buffer;
1340 ULONG Length;
1342 PDEVICE_EXTENSION DeviceExt;
1343
1344 DeviceExt = IrpContext->DeviceExt;
1345 Length = IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength;
1346 Buffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
1347
1348 if (Length < sizeof(FILESYSTEM_STATISTICS))
1349 {
1351 }
1352
1353 if (Buffer == NULL)
1354 {
1356 }
1357
1359 {
1362 }
1363 else
1364 {
1366 }
1367
1368 RtlCopyMemory(Buffer, DeviceExt->Statistics, Length);
1369 IrpContext->Irp->IoStatus.Information = Length;
1370
1371 return Status;
1372}
1373
1374/*
1375 * FUNCTION: File system control
1376 */
1379 PVFAT_IRP_CONTEXT IrpContext)
1380{
1382
1383 DPRINT("VfatFileSystemControl(IrpContext %p)\n", IrpContext);
1384
1385 ASSERT(IrpContext);
1386 ASSERT(IrpContext->Irp);
1387 ASSERT(IrpContext->Stack);
1388
1389 IrpContext->Irp->IoStatus.Information = 0;
1390
1391 switch (IrpContext->MinorFunction)
1392 {
1393 case IRP_MN_KERNEL_CALL:
1395 switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
1396 {
1398 Status = VfatGetVolumeBitmap(IrpContext);
1399 break;
1400
1402 Status = VfatGetRetrievalPointers(IrpContext);
1403 break;
1404
1405 case FSCTL_MOVE_FILE:
1406 Status = VfatMoveFile(IrpContext);
1407 break;
1408
1410 Status = VfatIsVolumeDirty(IrpContext);
1411 break;
1412
1414 Status = VfatMarkVolumeDirty(IrpContext);
1415 break;
1416
1417 case FSCTL_LOCK_VOLUME:
1418 Status = VfatLockOrUnlockVolume(IrpContext, TRUE);
1419 break;
1420
1422 Status = VfatLockOrUnlockVolume(IrpContext, FALSE);
1423 break;
1424
1426 Status = VfatDismountVolume(IrpContext);
1427 break;
1428
1430 Status = VfatGetStatistics(IrpContext);
1431 break;
1432
1433 default:
1435 }
1436 break;
1437
1439 Status = VfatMount(IrpContext);
1440 break;
1441
1443 DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n");
1444 Status = VfatVerify(IrpContext);
1445 break;
1446
1447 default:
1448 DPRINT("VFAT FSC: MinorFunction %u\n", IrpContext->MinorFunction);
1450 break;
1451 }
1452
1453 return Status;
1454}
#define BufSize
Definition: FsRtlTunnel.c:28
unsigned char BOOLEAN
#define isprint(c)
Definition: acclib.h:73
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define PARTITION_XINT13
Definition: disk.h:97
#define PARTITION_FAT32
Definition: disk.h:95
#define PARTITION_FAT_12
Definition: disk.h:87
#define PARTITION_HUGE
Definition: disk.h:92
#define PARTITION_FAT_16
Definition: disk.h:90
#define PARTITION_FAT32_XINT13
Definition: disk.h:96
#define FAT32
Definition: fat.h:169
#define FATX16
Definition: fat.h:170
#define FATX32
Definition: fat.h:171
#define FAT12
Definition: fat.h:167
#define FAT16
Definition: fat.h:168
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define TAG_VPB
Definition: cdprocs.h:106
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
_Inout_ PIRP _In_ PDEVICE_OBJECT DeviceToVerify
Definition: cdprocs.h:1409
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TAG_DIRENT
Definition: nodetype.h:158
#define FCB_IS_VOLUME
Definition: ntfs.h:510
VOID vfat8Dot3ToString(PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
Definition: create.c:19
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:28
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:244
NTSTATUS CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER Clusters)
Definition: fat.c:541
NTSTATUS FAT16SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1044
NTSTATUS FAT16GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:858
NTSTATUS SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1017
NTSTATUS FAT32GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:936
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:661
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:570
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:173
NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:123
NTSTATUS FAT32SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1129
NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:77
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:621
NTSTATUS GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:831
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:312
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:59
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define VCB_VOLUME_LOCKED
Definition: ext2fs.h:789
#define VCB_DISMOUNT_PENDING
Definition: ext2fs.h:791
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1675
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:418
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSYSAPI NTSTATUS NTAPI RtlOemStringToUnicodeString(PUNICODE_STRING DestinationString, PCOEM_STRING SourceString, BOOLEAN AllocateDestinationString)
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
struct _DISK_GEOMETRY DISK_GEOMETRY
struct _PARTITION_INFORMATION PARTITION_INFORMATION
@ RemovableMedia
Definition: ntdddisk.h:387
@ FixedMedia
Definition: ntdddisk.h:388
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define MAP_WAIT
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define VOLUME_IS_DIRTY
Definition: ntifs_ex.h:330
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
VOID NTAPI FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
Definition: notify.c:1590
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3187
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:650
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#define L(x)
Definition: ntvdm.h:50
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
BOOLEAN NTAPI CcMapData(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *BcbResult, OUT PVOID *Buffer)
Definition: pinsup.c:694
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:114
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:714
struct STARTING_VCN_INPUT_BUFFER * PSTARTING_VCN_INPUT_BUFFER
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
#define FILESYSTEM_STATISTICS_TYPE_FAT
Definition: winioctl.h:751
#define FSCTL_MOVE_FILE
Definition: winioctl.h:96
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define DPRINT
Definition: sndvol32.h:71
struct _FCB * VolumeFcb
Definition: ntfs.h:115
base of all file and directory entries
Definition: entries.h:83
Definition: vfat.h:250
ULONG FSInfoSector
Definition: vfat.h:267
ULONG dataStart
Definition: vfat.h:258
ULONG Sectors
Definition: vfat.h:265
ULONG rootDirectorySectors
Definition: vfat.h:256
BOOLEAN FixedMedia
Definition: vfat.h:266
ULONG FATCount
Definition: vfat.h:254
ULONG BytesPerSector
Definition: vfat.h:261
ULONG rootStart
Definition: vfat.h:257
ULONG BytesPerCluster
Definition: vfat.h:262
ULONG RootCluster
Definition: vfat.h:259
CHAR VolumeLabel[11]
Definition: vfat.h:252
ULONG SectorsPerCluster
Definition: vfat.h:260
ULONG VolumeID
Definition: vfat.h:251
ULONG NumberOfClusters
Definition: vfat.h:263
ULONG FatType
Definition: vfat.h:264
ULONG FATStart
Definition: vfat.h:253
ULONG FATSectors
Definition: vfat.h:255
LARGE_INTEGER StartingVcn
Definition: winioctl.h:608
struct RETRIEVAL_POINTERS_BUFFER::@3333 Extents[1]
PDRIVER_OBJECT DriverObject
Definition: vfat.h:411
ERESOURCE VolumeListLock
Definition: vfat.h:415
ULONG NumberProcessors
Definition: vfat.h:414
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
LIST_ENTRY VolumeListHead
Definition: vfat.h:416
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
UCHAR MinorFunction
Definition: vfat.h:590
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
PFILE_OBJECT FileObject
Definition: vfat.h:591
unsigned short Sectors
Definition: vfat.h:65
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
ULONG BytesPerSector
Definition: ntdddisk.h:409
ULONG Flags
Definition: ntfs.h:536
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
LONG RefCount
Definition: ntfs.h:535
ULONG OpenHandleCount
Definition: ntfs.h:537
ERESOURCE MainResource
Definition: ntfs.h:528
PFILE_OBJECT FileObject
Definition: ntfs.h:520
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
struct _IO_STACK_LOCATION::@3978::@3998 MountVolume
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3999 VerifyVolume
struct _IO_STACK_LOCATION::@3978::@3993 FileSystemControl
PVOID SystemBuffer
IO_STATUS_BLOCK IoStatus
union _IRP::@1566 AssociatedIrp
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: vfat.h:537
Definition: vfat.h:448
PFILE_OBJECT FileObject
Definition: vfat.h:499
ULONG Flags
Definition: vfat.h:496
FSRTL_COMMON_FCB_HEADER RFCB
Definition: vfat.h:450
Definition: iotypes.h:189
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
STRING OEM_STRING
Definition: umtypes.h:203
Definition: vfat.h:225
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2295 u
@ Start
Definition: partlist.h:33
#define TAG_STATS
Definition: vfat.h:550
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
#define VCB_GOOD
Definition: vfat.h:247
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
#define VCB_IS_SYS_OR_HAS_PAGE
Definition: vfat.h:243
#define ENTRY_VOLUME(IsFatX, DirEntry)
Definition: vfat.h:206
union _DIR_ENTRY * PDIR_ENTRY
Definition: vfat.h:230
#define FATX_ENTRIES_PER_PAGE
Definition: vfat.h:220
#define VCB_IS_FATX
Definition: vfat.h:242
struct _STATISTICS STATISTICS
#define VCB_CLEAR_DIRTY
Definition: vfat.h:245
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
#define TAG_BUFFER
Definition: vfat.h:551
struct _VFATCCB * PVFATCCB
#define ENTRY_END(IsFatX, DirEntry)
Definition: vfat.h:207
#define FCB_IS_FAT
Definition: vfat.h:435
#define VCB_IS_DIRTY
Definition: vfat.h:244
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
#define FAT_ENTRIES_PER_PAGE
Definition: vfat.h:219
NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:70
NTSTATUS VfatBlockDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, IN ULONG CtlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer OPTIONAL, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override)
Definition: blockdev.c:430
PVFATFCB vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
Definition: fcb.c:708
VOID vfatDestroyFCB(PVFATFCB pFCB)
Definition: fcb.c:268
NTSTATUS vfatAttachFCBToFileObject(PDEVICE_EXTENSION vcb, PVFATFCB fcb, PFILE_OBJECT fileObject)
Definition: fcb.c:754
VOID vfatDestroyCCB(PVFATCCB pCcb)
Definition: fcb.c:257
PVFATFCB vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU)
Definition: fcb.c:128
VOID vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:335
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
Definition: flush.c:51
static NTSTATUS VfatDismountVolume(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1256
VFAT_DISPATCH FatXDispatch
Definition: dirwr.c:1164
static NTSTATUS VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:923
static NTSTATUS VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, PBOOLEAN RecognizedFS, PFATINFO pFatInfo, BOOLEAN Override)
Definition: fsctl.c:26
static NTSTATUS VfatMount(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:508
static NTSTATUS VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:933
VFAT_DISPATCH FatDispatch
Definition: dirwr.c:1171
static NTSTATUS VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1027
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1378
static NTSTATUS ReadVolumeLabel(PVOID Device, ULONG Start, BOOLEAN IsFatX, PUNICODE_STRING VolumeLabel)
Definition: fsctl.c:344
static NTSTATUS VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1036
static NTSTATUS VfatLockOrUnlockVolume(PVFAT_IRP_CONTEXT IrpContext, BOOLEAN Lock)
Definition: fsctl.c:1085
static NTSTATUS VfatGetStatistics(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1336
static NTSTATUS VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1064
static NTSTATUS VfatVerify(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:829
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define SL_ALLOW_RAW_MOUNT
Definition: iotypes.h:1841
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_LOCKED
Definition: iotypes.h:1808
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4408
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
#define ObDereferenceObject
Definition: obfuncs.h:203
__wchar_t WCHAR
Definition: xmlstorage.h:180