ReactOS  0.4.15-dev-5455-g015cd25
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 
24 static
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
65  Size = sizeof(PARTITION_INFORMATION);
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  {
247  BootFatX = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _BootSectorFatX), TAG_BUFFER);
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  */
342 static
343 NTSTATUS
345  PVOID Device,
346  ULONG Start,
347  BOOLEAN IsFatX,
348  PUNICODE_STRING VolumeLabel)
349 {
350  PDEVICE_EXTENSION DeviceExt;
352  PVOID Context = NULL;
353  ULONG DirIndex = 0;
355  PVFATFCB pFcb;
357  ULONG SizeDirEntry;
358  ULONG EntriesPerPage;
359  OEM_STRING StringO;
360  BOOLEAN NoCache = (Start != 0);
361  PVOID Buffer;
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 
388  _SEH2_TRY
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 
456  _SEH2_TRY
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  */
506 static
507 NTSTATUS
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;
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 
703  Fcb->Flags = FCB_IS_FAT;
704  Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
707 
708  _SEH2_TRY
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 
793 ByeBye:
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  */
827 static
828 NTSTATUS
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 
921 static
922 NTSTATUS
924  PVFAT_IRP_CONTEXT IrpContext)
925 {
926  DPRINT("VfatGetVolumeBitmap (IrpContext %p)\n", IrpContext);
928 }
929 
930 
931 static
932 NTSTATUS
934  PVFAT_IRP_CONTEXT IrpContext)
935 {
937  LARGE_INTEGER Vcn;
938  PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
940  ULONG MaxExtentCount;
941  PVFATFCB Fcb;
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 
1019 ByeBye:
1021 
1022  return Status;
1023 }
1024 
1025 static
1026 NTSTATUS
1028  PVFAT_IRP_CONTEXT IrpContext)
1029 {
1030  DPRINT("VfatMoveFile(IrpContext %p)\n", IrpContext);
1032 }
1033 
1034 static
1035 NTSTATUS
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  {
1054  *Flags |= VOLUME_IS_DIRTY;
1055  }
1056 
1057  IrpContext->Irp->IoStatus.Information = sizeof(ULONG);
1058 
1059  return STATUS_SUCCESS;
1060 }
1061 
1062 static
1063 NTSTATUS
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 
1083 static
1084 NTSTATUS
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 
1254 static
1255 NTSTATUS
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  {
1286  return STATUS_VOLUME_DISMOUNTED;
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 
1334 static
1335 NTSTATUS
1337  PVFAT_IRP_CONTEXT IrpContext)
1338 {
1339  PVOID Buffer;
1340  ULONG Length;
1341  NTSTATUS Status;
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  {
1350  return STATUS_BUFFER_TOO_SMALL;
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  */
1377 NTSTATUS
1379  PVFAT_IRP_CONTEXT IrpContext)
1380 {
1381  NTSTATUS Status;
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 
1409  case FSCTL_IS_VOLUME_DIRTY:
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 
1421  case FSCTL_UNLOCK_VOLUME:
1422  Status = VfatLockOrUnlockVolume(IrpContext, FALSE);
1423  break;
1424 
1425  case FSCTL_DISMOUNT_VOLUME:
1426  Status = VfatDismountVolume(IrpContext);
1427  break;
1428 
1430  Status = VfatGetStatistics(IrpContext);
1431  break;
1432 
1433  default:
1435  }
1436  break;
1437 
1438  case IRP_MN_MOUNT_VOLUME:
1439  Status = VfatMount(IrpContext);
1440  break;
1441 
1442  case IRP_MN_VERIFY_VOLUME:
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 }
NTSTATUS FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:570
struct _LARGE_INTEGER::@2253 u
_SEH2_TRY
Definition: create.c:4226
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
NTSTATUS CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER Clusters)
Definition: fat.c:541
NTSTATUS FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:28
#define PARTITION_FAT32
Definition: disk.h:95
#define FAT12
Definition: fat.h:167
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
struct _FATDirEntry FAT_DIR_ENTRY
Definition: vfat.h:167
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
struct STARTING_VCN_INPUT_BUFFER * PSTARTING_VCN_INPUT_BUFFER
LIST_ENTRY VolumeListHead
Definition: vfat.h:416
#define ENTRY_END(IsFatX, DirEntry)
Definition: vfat.h:207
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct _FATXDirEntry FATX_DIR_ENTRY
Definition: vfat.h:222
NTSTATUS GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:831
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
struct _Entry Entry
Definition: kefuncs.h:629
Definition: vfat.h:447
BOOLEAN FixedMedia
Definition: vfat.h:266
USHORT MaximumLength
Definition: env_spec_w32.h:370
PFILE_OBJECT FileObject
Definition: ntfs.h:520
Definition: vfat.h:536
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
PVFATFCB vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
Definition: fcb.c:708
struct _VFATCCB * PVFATCCB
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:18
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
PDRIVER_OBJECT DriverObject
Definition: vfat.h:411
CHAR VolumeLabel[11]
Definition: vfat.h:252
#define VCB_IS_DIRTY
Definition: vfat.h:244
ULONG rootStart
Definition: vfat.h:257
unsigned char * PUCHAR
Definition: retypes.h:3
FORCEINLINE PLIST_ENTRY RemoveTailList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:154
LONG NTSTATUS
Definition: precomp.h:26
static NTSTATUS VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1027
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
VOID NTAPI CcUnpinData(IN PVOID Bcb)
Definition: pinsup.c:955
#define VOLUME_IS_DIRTY
Definition: ntifs_ex.h:330
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define VCB_CLEAR_DIRTY
Definition: vfat.h:245
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define MAP_WAIT
FORCEINLINE BOOLEAN vfatFCBIsDirectory(PVFATFCB FCB)
Definition: vfat.h:637
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
ULONG FATStart
Definition: vfat.h:253
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define FAT_ENTRIES_PER_PAGE
Definition: vfat.h:219
VOID vfatDestroyFCB(PVFATFCB pFCB)
Definition: fcb.c:268
NTSTATUS SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1017
ULONG SectorsPerCluster
Definition: vfat.h:260
ULONG BytesPerSector
Definition: ntdddisk.h:409
IO_STATUS_BLOCK IoStatus
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
_SEH2_END
Definition: create.c:4400
NTSTATUS FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:77
STRING OEM_STRING
Definition: umtypes.h:203
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
struct _PARTITION_INFORMATION PARTITION_INFORMATION
PFILE_OBJECT FileObject
Definition: vfat.h:591
ULONG FatType
Definition: vfat.h:264
VOID vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
Definition: fcb.c:335
#define TAG_VPB
Definition: cdprocs.h:106
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
NTSTATUS FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster, PULONG NextCluster)
Definition: fat.c:123
#define ENTRY_VOLUME(IsFatX, DirEntry)
Definition: vfat.h:206
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define PARTITION_XINT13
Definition: disk.h:97
uint32_t ULONG_PTR
Definition: typedefs.h:65
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:244
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
ULONG Sectors
Definition: vfat.h:265
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define L(x)
Definition: ntvdm.h:50
#define TAG_BUFFER
Definition: vfat.h:551
#define FALSE
Definition: types.h:117
static NTSTATUS VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:933
#define FATX32
Definition: fat.h:171
ULONG FATSectors
Definition: vfat.h:255
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define PARTITION_HUGE
Definition: disk.h:92
#define VPB_LOCKED
Definition: iotypes.h:1808
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
PFILE_OBJECT FileObject
Definition: vfat.h:499
ULONG Flags
Definition: vfat.h:496
LARGE_INTEGER StartingVcn
Definition: winioctl.h:608
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:240
NTSTATUS FAT32GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:936
unsigned char BOOLEAN
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400
LONG RefCount
Definition: ntfs.h:535
NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, IN PLARGE_INTEGER ReadOffset, IN ULONG ReadLength, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:70
#define TAG_DIRENT
Definition: nodetype.h:158
ULONG NumberProcessors
Definition: vfat.h:414
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
Definition: bufpool.h:45
NTSTATUS FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:661
#define BufSize
Definition: FsRtlTunnel.c:28
ULONG VolumeID
Definition: vfat.h:251
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:517
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
static NTSTATUS VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:923
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:114
#define PCHAR
Definition: match.c:90
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
static NTSTATUS VfatLockOrUnlockVolume(PVFAT_IRP_CONTEXT IrpContext, BOOLEAN Lock)
Definition: fsctl.c:1085
Status
Definition: gdiplustypes.h:24
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:650
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
static NTSTATUS VfatGetStatistics(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1336
ULONG OpenHandleCount
Definition: ntfs.h:537
int64_t LONGLONG
Definition: typedefs.h:68
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
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
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:412
static NTSTATUS VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1064
static NTSTATUS ReadVolumeLabel(PVOID Device, ULONG Start, BOOLEAN IsFatX, PUNICODE_STRING VolumeLabel)
Definition: fsctl.c:344
NTSTATUS FAT16SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1044
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FATX_ENTRIES_PER_PAGE
Definition: vfat.h:220
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define ASSERT(a)
Definition: mode.c:44
union _DIR_ENTRY * PDIR_ENTRY
Definition: vfat.h:230
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1378
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG BytesPerCluster
Definition: vfat.h:262
#define ObDereferenceObject
Definition: obfuncs.h:203
NTSTATUS FAT16GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:858
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
NTSTATUS FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:173
static NTSTATUS VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1036
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define PARTITION_FAT_16
Definition: disk.h:90
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
#define SL_ALLOW_RAW_MOUNT
Definition: iotypes.h:1841
* PFILE_OBJECT
Definition: iotypes.h:1998
FSRTL_COMMON_FCB_HEADER RFCB
Definition: vfat.h:450
Definition: partlist.h:33
NTSTATUS FAT32FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:312
ULONG Flags
Definition: ntfs.h:536
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID vfatDestroyCCB(PVFATCCB pCcb)
Definition: fcb.c:257
#define FCB_IS_FAT
Definition: vfat.h:435
VOID vfat8Dot3ToString(PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
Definition: create.c:19
char * PBOOLEAN
Definition: retypes.h:11
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4408
#define VCB_IS_FATX
Definition: vfat.h:242
#define VCB_GOOD
Definition: vfat.h:247
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
ULONG BytesPerSector
Definition: vfat.h:261
#define VCB_DISMOUNT_PENDING
Definition: ext2fs.h:782
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
Definition: flush.c:51
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
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
ULONG dataStart
Definition: vfat.h:258
ULONG rootDirectorySectors
Definition: vfat.h:256
UCHAR MinorFunction
Definition: vfat.h:590
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:588
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
NTSYSAPI NTSTATUS NTAPI RtlOemStringToUnicodeString(PUNICODE_STRING DestinationString, PCOEM_STRING SourceString, BOOLEAN AllocateDestinationString)
ERESOURCE MainResource
Definition: ntfs.h:528
NTSTATUS OffsetToCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, ULONG FileOffset, PULONG Cluster, BOOLEAN Extend)
Definition: rw.c:59
#define FAT16
Definition: fat.h:168
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
#define TAG_STATS
Definition: vfat.h:550
Definition: vfat.h:249
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
static NTSTATUS VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, PBOOLEAN RecognizedFS, PFATINFO pFatInfo, BOOLEAN Override)
Definition: fsctl.c:26
struct RETRIEVAL_POINTERS_BUFFER::@3281 Extents[1]
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
ULONG FATCount
Definition: vfat.h:254
struct _DISK_GEOMETRY DISK_GEOMETRY
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
struct RETRIEVAL_POINTERS_BUFFER RETRIEVAL_POINTERS_BUFFER
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
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
NTSTATUS vfatAttachFCBToFileObject(PDEVICE_EXTENSION vcb, PVFATFCB fcb, PFILE_OBJECT fileObject)
Definition: fcb.c:754
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:18
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
ULONG NumberOfClusters
Definition: vfat.h:263
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
NTSTATUS FAT32SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1129
VFAT_DISPATCH FatDispatch
Definition: dirwr.c:1171
NTSTATUS FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue, PULONG OldValue)
Definition: fat.c:621
#define VCB_IS_SYS_OR_HAS_PAGE
Definition: vfat.h:243
unsigned short Sectors
Definition: vfat.h:65
static NTSTATUS VfatMount(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:508
#define FATX16
Definition: fat.h:170
unsigned int * PULONG
Definition: retypes.h:1
static NTSTATUS VfatDismountVolume(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1256
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
Definition: vfat.h:224
#define NULL
Definition: types.h:112
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:714
#define FCB_IS_VOLUME
Definition: ntfs.h:510
#define FAT32
Definition: fat.h:169
BOOLEAN NTAPI ExAcquireResourceSharedLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:885
IN PVCB IN VBO IN ULONG OUT PBCB OUT PVOID IN BOOLEAN IN BOOLEAN Zero
Definition: fatprocs.h:411
struct _STATISTICS STATISTICS
#define VCB_VOLUME_LOCKED
Definition: ext2fs.h:780
#define DPRINT1
Definition: precomp.h:8
#define isprint(c)
Definition: acclib.h:73
ERESOURCE VolumeListLock
Definition: vfat.h:415
NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, ULONG FirstCluster, PULONG CurrentCluster, BOOLEAN Extend)
Definition: rw.c:38
VOID NTAPI FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync)
Definition: notify.c:1590
Definition: iotypes.h:189
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_MOVE_FILE
Definition: winioctl.h:96
#define PARTITION_FAT_12
Definition: disk.h:87
unsigned int ULONG
Definition: retypes.h:1
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
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
ULONG FSInfoSector
Definition: vfat.h:267
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
PVFATFCB vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU)
Definition: fcb.c:128
static NTSTATUS VfatVerify(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:829
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define PARTITION_FAT32_XINT13
Definition: disk.h:96
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define DPRINT
Definition: sndvol32.h:71
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
_In_ PFCB Fcb
Definition: cdprocs.h:159
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
PIO_STACK_LOCATION Stack
Definition: vfat.h:588
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define VPB_MOUNTED
Definition: iotypes.h:1807
ULONG RootCluster
Definition: vfat.h:259
base of all file and directory entries
Definition: entries.h:82
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1673
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define FILESYSTEM_STATISTICS_TYPE_FAT
Definition: winioctl.h:751
_Inout_ PIRP _In_ PDEVICE_OBJECT DeviceToVerify
Definition: cdprocs.h:1407
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
LONGLONG QuadPart
Definition: typedefs.h:114
VFAT_DISPATCH FatXDispatch
Definition: dirwr.c:1164
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14