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