ReactOS  0.4.15-dev-1203-g0e5a4d5
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 > 64 * 1024)
201  {
202  DPRINT1("ClusterSize %d\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  KeInitializeSpinLock(&DeviceExt->OverflowQueueSpinLock);
604  InitializeListHead(&DeviceExt->OverflowQueue);
605  DeviceExt->OverflowQueueCount = 0;
606  DeviceExt->PostedRequestCount = 0;
607 
608  /* use same vpb as device disk */
609  DeviceObject->Vpb = Vpb;
610  DeviceToMount->Vpb = Vpb;
611 
612  RtlCopyMemory(&DeviceExt->FatInfo, &FatInfo, sizeof(FATINFO));
613 
614  DPRINT("BytesPerSector: %u\n", DeviceExt->FatInfo.BytesPerSector);
615  DPRINT("SectorsPerCluster: %u\n", DeviceExt->FatInfo.SectorsPerCluster);
616  DPRINT("FATCount: %u\n", DeviceExt->FatInfo.FATCount);
617  DPRINT("FATSectors: %u\n", DeviceExt->FatInfo.FATSectors);
618  DPRINT("RootStart: %u\n", DeviceExt->FatInfo.rootStart);
619  DPRINT("DataStart: %u\n", DeviceExt->FatInfo.dataStart);
620  if (DeviceExt->FatInfo.FatType == FAT32)
621  {
622  DPRINT("RootCluster: %u\n", DeviceExt->FatInfo.RootCluster);
623  }
624 
625  switch (DeviceExt->FatInfo.FatType)
626  {
627  case FAT12:
628  DeviceExt->GetNextCluster = FAT12GetNextCluster;
629  DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
630  DeviceExt->WriteCluster = FAT12WriteCluster;
631  /* We don't define dirty bit functions here
632  * FAT12 doesn't have such bit and they won't get called
633  */
634  break;
635 
636  case FAT16:
637  case FATX16:
638  DeviceExt->GetNextCluster = FAT16GetNextCluster;
639  DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
640  DeviceExt->WriteCluster = FAT16WriteCluster;
641  DeviceExt->GetDirtyStatus = FAT16GetDirtyStatus;
642  DeviceExt->SetDirtyStatus = FAT16SetDirtyStatus;
643  break;
644 
645  case FAT32:
646  case FATX32:
647  DeviceExt->GetNextCluster = FAT32GetNextCluster;
648  DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
649  DeviceExt->WriteCluster = FAT32WriteCluster;
650  DeviceExt->GetDirtyStatus = FAT32GetDirtyStatus;
651  DeviceExt->SetDirtyStatus = FAT32SetDirtyStatus;
652  break;
653  }
654 
655  if (DeviceExt->FatInfo.FatType == FATX16 ||
656  DeviceExt->FatInfo.FatType == FATX32)
657  {
658  DeviceExt->Flags |= VCB_IS_FATX;
659  DeviceExt->BaseDateYear = 2000;
660  RtlCopyMemory(&DeviceExt->Dispatch, &FatXDispatch, sizeof(VFAT_DISPATCH));
661  }
662  else
663  {
664  DeviceExt->BaseDateYear = 1980;
665  RtlCopyMemory(&DeviceExt->Dispatch, &FatDispatch, sizeof(VFAT_DISPATCH));
666  }
667 
668  DeviceExt->StorageDevice = DeviceToMount;
669  DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
670  DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
671  DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
672  DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
674 
675  DPRINT("FsDeviceObject %p\n", DeviceObject);
676 
677  /* Initialize this resource early ... it's used in VfatCleanup */
678  ExInitializeResourceLite(&DeviceExt->DirResource);
679 
680  DeviceExt->IoVPB = DeviceObject->Vpb;
681  DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VPB);
682  if (DeviceExt->SpareVPB == NULL)
683  {
685  goto ByeBye;
686  }
687 
688  DeviceExt->Statistics = ExAllocatePoolWithTag(NonPagedPool,
690  TAG_STATS);
691  if (DeviceExt->Statistics == NULL)
692  {
694  goto ByeBye;
695  }
696 
697  RtlZeroMemory(DeviceExt->Statistics, sizeof(STATISTICS) * VfatGlobalData->NumberProcessors);
698  for (i = 0; i < VfatGlobalData->NumberProcessors; ++i)
699  {
700  DeviceExt->Statistics[i].Base.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
701  DeviceExt->Statistics[i].Base.Version = 1;
702  DeviceExt->Statistics[i].Base.SizeOfCompleteStructure = sizeof(STATISTICS);
703  }
704 
705  DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
706  Fcb = vfatNewFCB(DeviceExt, &NameU);
707  if (Fcb == NULL)
708  {
710  goto ByeBye;
711  }
712 
713  Status = vfatAttachFCBToFileObject(DeviceExt, Fcb, DeviceExt->FATFileObject);
714  if (!NT_SUCCESS(Status))
715  goto ByeBye;
716 
717  DeviceExt->FATFileObject->PrivateCacheMap = NULL;
718  Fcb->FileObject = DeviceExt->FATFileObject;
719 
720  Fcb->Flags = FCB_IS_FAT;
721  Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
724 
725  _SEH2_TRY
726  {
727  CcInitializeCacheMap(DeviceExt->FATFileObject,
729  TRUE,
731  Fcb);
732  }
734  {
736  goto ByeBye;
737  }
738  _SEH2_END;
739 
740  DeviceExt->LastAvailableCluster = 2;
741  CountAvailableClusters(DeviceExt, NULL);
742  ExInitializeResourceLite(&DeviceExt->FatResource);
743 
744  InitializeListHead(&DeviceExt->FcbListHead);
745 
746  VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
747  if (VolumeFcb == NULL)
748  {
750  goto ByeBye;
751  }
752 
753  VolumeFcb->Flags = FCB_IS_VOLUME;
754  VolumeFcb->RFCB.FileSize.QuadPart = (LONGLONG) DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
755  VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
756  VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
757  DeviceExt->VolumeFcb = VolumeFcb;
758 
760  InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
762 
763  /* read serial number */
764  DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;
765 
766  /* read volume label */
767  VolumeLabelU.Buffer = DeviceObject->Vpb->VolumeLabel;
768  VolumeLabelU.Length = 0;
769  VolumeLabelU.MaximumLength = sizeof(DeviceObject->Vpb->VolumeLabel);
770  ReadVolumeLabel(DeviceExt, 0, vfatVolumeIsFatX(DeviceExt), &VolumeLabelU);
771  Vpb->VolumeLabelLength = VolumeLabelU.Length;
772 
773  /* read dirty bit status */
774  Status = GetDirtyStatus(DeviceExt, &Dirty);
775  if (NT_SUCCESS(Status))
776  {
777  /* The volume wasn't dirty, it was properly dismounted */
778  if (!Dirty)
779  {
780  /* Mark it dirty now! */
781  SetDirtyStatus(DeviceExt, TRUE);
782  VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
783  }
784  else
785  {
786  DPRINT1("Mounting a dirty volume\n");
787  }
788  }
789 
790  VolumeFcb->Flags |= VCB_IS_DIRTY;
791  if (BooleanFlagOn(Vpb->RealDevice->Flags, DO_SYSTEM_BOOT_PARTITION))
792  {
793  SetFlag(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE);
794  }
795 
796  /* Initialize the notify list and synchronization object */
797  InitializeListHead(&DeviceExt->NotifyList);
798  FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
799 
800  /* The VCB is OK for usage */
801  SetFlag(DeviceExt->Flags, VCB_GOOD);
802 
803  /* Send the mount notification */
804  FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);
805 
806  DPRINT("Mount success\n");
807 
809 
810 ByeBye:
811  if (!NT_SUCCESS(Status))
812  {
813  /* Cleanup */
814  if (DeviceExt && DeviceExt->FATFileObject)
815  {
816  LARGE_INTEGER Zero = {{0,0}};
817  PVFATCCB Ccb = (PVFATCCB)DeviceExt->FATFileObject->FsContext2;
818 
819  CcUninitializeCacheMap(DeviceExt->FATFileObject,
820  &Zero,
821  NULL);
822  ObDereferenceObject(DeviceExt->FATFileObject);
823  if (Ccb)
825  DeviceExt->FATFileObject = NULL;
826  }
827  if (Fcb)
829  if (DeviceExt && DeviceExt->SpareVPB)
830  ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VPB);
831  if (DeviceExt && DeviceExt->Statistics)
832  ExFreePoolWithTag(DeviceExt->Statistics, TAG_STATS);
833  if (DeviceObject)
835  }
836 
837  return Status;
838 }
839 
840 
841 /*
842  * FUNCTION: Verify the filesystem
843  */
844 static
845 NTSTATUS
847  PVFAT_IRP_CONTEXT IrpContext)
848 {
851  FATINFO FatInfo;
852  BOOLEAN RecognizedFS;
853  PDEVICE_EXTENSION DeviceExt;
854  BOOLEAN AllowRaw;
855  PVPB Vpb;
856  ULONG ChangeCount, BufSize = sizeof(ChangeCount);
857 
858  DPRINT("VfatVerify(IrpContext %p)\n", IrpContext);
859 
860  DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
861  DeviceExt = DeviceToVerify->DeviceExtension;
862  Vpb = IrpContext->Stack->Parameters.VerifyVolume.Vpb;
863  AllowRaw = BooleanFlagOn(IrpContext->Stack->Flags, SL_ALLOW_RAW_MOUNT);
864 
865  if (!BooleanFlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME))
866  {
867  DPRINT("Already verified\n");
868  return STATUS_SUCCESS;
869  }
870 
871  Status = VfatBlockDeviceIoControl(DeviceExt->StorageDevice,
873  NULL,
874  0,
875  &ChangeCount,
876  &BufSize,
877  TRUE);
879  {
880  DPRINT("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
881  Status = (AllowRaw ? STATUS_WRONG_VOLUME : Status);
882  }
883  else
884  {
885  Status = VfatHasFileSystem(DeviceExt->StorageDevice, &RecognizedFS, &FatInfo, TRUE);
886  if (!NT_SUCCESS(Status) || RecognizedFS == FALSE)
887  {
888  if (NT_SUCCESS(Status) || AllowRaw)
889  {
891  }
892  }
893  else if (sizeof(FATINFO) == RtlCompareMemory(&FatInfo, &DeviceExt->FatInfo, sizeof(FATINFO)))
894  {
895  WCHAR BufferU[MAXIMUM_VOLUME_LABEL_LENGTH / sizeof(WCHAR)];
896  UNICODE_STRING VolumeLabelU;
897  UNICODE_STRING VpbLabelU;
898 
899  VolumeLabelU.Buffer = BufferU;
900  VolumeLabelU.Length = 0;
901  VolumeLabelU.MaximumLength = sizeof(BufferU);
902  Status = ReadVolumeLabel(DeviceExt->StorageDevice, FatInfo.rootStart * FatInfo.BytesPerSector, (FatInfo.FatType >= FATX16), &VolumeLabelU);
903  if (!NT_SUCCESS(Status))
904  {
905  if (AllowRaw)
906  {
908  }
909  }
910  else
911  {
912  VpbLabelU.Buffer = Vpb->VolumeLabel;
913  VpbLabelU.Length = Vpb->VolumeLabelLength;
914  VpbLabelU.MaximumLength = sizeof(Vpb->VolumeLabel);
915 
916  if (RtlCompareUnicodeString(&VpbLabelU, &VolumeLabelU, FALSE) != 0)
917  {
919  }
920  else
921  {
922  DPRINT1("Same volume\n");
923  }
924  }
925  }
926  else
927  {
929  }
930  }
931 
932  Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
933 
934  return Status;
935 }
936 
937 
938 static
939 NTSTATUS
941  PVFAT_IRP_CONTEXT IrpContext)
942 {
943  DPRINT("VfatGetVolumeBitmap (IrpContext %p)\n", IrpContext);
945 }
946 
947 
948 static
949 NTSTATUS
951  PVFAT_IRP_CONTEXT IrpContext)
952 {
953  PIO_STACK_LOCATION Stack;
954  LARGE_INTEGER Vcn;
955  PRETRIEVAL_POINTERS_BUFFER RetrievalPointers;
957  ULONG MaxExtentCount;
958  PVFATFCB Fcb;
959  PDEVICE_EXTENSION DeviceExt;
960  ULONG FirstCluster;
961  ULONG CurrentCluster;
962  ULONG LastCluster;
964 
965  DPRINT("VfatGetRetrievalPointers(IrpContext %p)\n", IrpContext);
966 
967  DeviceExt = IrpContext->DeviceExt;
968  FileObject = IrpContext->FileObject;
969  Stack = IrpContext->Stack;
970  if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER) ||
971  Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
972  {
974  }
975 
976  if (IrpContext->Irp->UserBuffer == NULL ||
977  Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))
978  {
980  }
981 
982  Fcb = FileObject->FsContext;
983 
985 
986  Vcn = ((PSTARTING_VCN_INPUT_BUFFER)Stack->Parameters.DeviceIoControl.Type3InputBuffer)->StartingVcn;
987  RetrievalPointers = IrpContext->Irp->UserBuffer;
988 
989  MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(RetrievalPointers->ExtentCount) - sizeof(RetrievalPointers->StartingVcn)) / sizeof(RetrievalPointers->Extents[0]));
990 
991  if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
992  {
994  goto ByeBye;
995  }
996 
997  CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
998  Status = OffsetToCluster(DeviceExt, FirstCluster,
999  Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
1000  &CurrentCluster, FALSE);
1001  if (!NT_SUCCESS(Status))
1002  {
1003  goto ByeBye;
1004  }
1005 
1006  RetrievalPointers->StartingVcn = Vcn;
1007  RetrievalPointers->ExtentCount = 0;
1008  RetrievalPointers->Extents[0].Lcn.u.HighPart = 0;
1009  RetrievalPointers->Extents[0].Lcn.u.LowPart = CurrentCluster - 2;
1010  LastCluster = 0;
1011  while (CurrentCluster != 0xffffffff && RetrievalPointers->ExtentCount < MaxExtentCount)
1012  {
1013  LastCluster = CurrentCluster;
1014  Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
1015  Vcn.QuadPart++;
1016  if (!NT_SUCCESS(Status))
1017  {
1018  goto ByeBye;
1019  }
1020 
1021  if (LastCluster + 1 != CurrentCluster)
1022  {
1023  RetrievalPointers->Extents[RetrievalPointers->ExtentCount].NextVcn = Vcn;
1024  RetrievalPointers->ExtentCount++;
1025  if (RetrievalPointers->ExtentCount < MaxExtentCount)
1026  {
1027  RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.HighPart = 0;
1028  RetrievalPointers->Extents[RetrievalPointers->ExtentCount].Lcn.u.LowPart = CurrentCluster - 2;
1029  }
1030  }
1031  }
1032 
1033  IrpContext->Irp->IoStatus.Information = sizeof(RETRIEVAL_POINTERS_BUFFER) + (sizeof(RetrievalPointers->Extents[0]) * (RetrievalPointers->ExtentCount - 1));
1035 
1036 ByeBye:
1038 
1039  return Status;
1040 }
1041 
1042 static
1043 NTSTATUS
1045  PVFAT_IRP_CONTEXT IrpContext)
1046 {
1047  DPRINT("VfatMoveFile(IrpContext %p)\n", IrpContext);
1049 }
1050 
1051 static
1052 NTSTATUS
1054  PVFAT_IRP_CONTEXT IrpContext)
1055 {
1056  PULONG Flags;
1057 
1058  DPRINT("VfatIsVolumeDirty(IrpContext %p)\n", IrpContext);
1059 
1060  if (IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength != sizeof(ULONG))
1062  else if (!IrpContext->Irp->AssociatedIrp.SystemBuffer)
1064 
1065  Flags = (PULONG)IrpContext->Irp->AssociatedIrp.SystemBuffer;
1066  *Flags = 0;
1067 
1068  if (BooleanFlagOn(IrpContext->DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY) &&
1069  !BooleanFlagOn(IrpContext->DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY))
1070  {
1071  *Flags |= VOLUME_IS_DIRTY;
1072  }
1073 
1074  IrpContext->Irp->IoStatus.Information = sizeof(ULONG);
1075 
1076  return STATUS_SUCCESS;
1077 }
1078 
1079 static
1080 NTSTATUS
1082  PVFAT_IRP_CONTEXT IrpContext)
1083 {
1084  PDEVICE_EXTENSION DeviceExt;
1086 
1087  DPRINT("VfatMarkVolumeDirty(IrpContext %p)\n", IrpContext);
1088  DeviceExt = IrpContext->DeviceExt;
1089 
1090  if (!BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1091  {
1092  Status = SetDirtyStatus(DeviceExt, TRUE);
1093  }
1094 
1095  DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;
1096 
1097  return Status;
1098 }
1099 
1100 static
1101 NTSTATUS
1103  PVFAT_IRP_CONTEXT IrpContext,
1104  BOOLEAN Lock)
1105 {
1107  PDEVICE_EXTENSION DeviceExt;
1108  PVFATFCB Fcb;
1109  PVPB Vpb;
1110 
1111  DPRINT("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock);
1112 
1113  DeviceExt = IrpContext->DeviceExt;
1114  FileObject = IrpContext->FileObject;
1115  Fcb = FileObject->FsContext;
1116  Vpb = DeviceExt->FATFileObject->Vpb;
1117 
1118  /* Only allow locking with the volume open */
1120  {
1121  return STATUS_ACCESS_DENIED;
1122  }
1123 
1124  /* Bail out if it's already in the demanded state */
1125  if ((BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && Lock) ||
1126  (!BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED) && !Lock))
1127  {
1128  return STATUS_ACCESS_DENIED;
1129  }
1130 
1131  /* Bail out if it's already in the demanded state */
1132  if ((BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && Lock) ||
1133  (!BooleanFlagOn(Vpb->Flags, VPB_LOCKED) && !Lock))
1134  {
1135  return STATUS_ACCESS_DENIED;
1136  }
1137 
1138  if (Lock)
1139  {
1141  }
1142 
1143  /* Deny locking if we're not alone */
1144  if (Lock && DeviceExt->OpenHandleCount != 1)
1145  {
1146  PLIST_ENTRY ListEntry;
1147 
1148 #if 1
1149  /* FIXME: Hack that allows locking the system volume on
1150  * boot so that autochk can run properly
1151  * That hack is, on purpose, really restrictive
1152  * it will only allow locking with two directories
1153  * open: current directory of smss and autochk.
1154  */
1155  BOOLEAN ForceLock = TRUE;
1156  ULONG HandleCount = 0;
1157 
1158  /* Only allow boot volume */
1159  if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
1160  {
1161  /* We'll browse all the FCB */
1162  ListEntry = DeviceExt->FcbListHead.Flink;
1163  while (ListEntry != &DeviceExt->FcbListHead)
1164  {
1165  Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
1166  ListEntry = ListEntry->Flink;
1167 
1168  /* If no handle: that FCB is no problem for locking
1169  * so ignore it
1170  */
1171  if (Fcb->OpenHandleCount == 0)
1172  {
1173  continue;
1174  }
1175 
1176  /* Not a dir? We're no longer at boot */
1177  if (!vfatFCBIsDirectory(Fcb))
1178  {
1179  ForceLock = FALSE;
1180  break;
1181  }
1182 
1183  /* If we have cached initialized and several handles, we're
1184  not in the boot case
1185  */
1186  if (Fcb->FileObject != NULL && Fcb->OpenHandleCount > 1)
1187  {
1188  ForceLock = FALSE;
1189  break;
1190  }
1191 
1192  /* Count the handles */
1193  HandleCount += Fcb->OpenHandleCount;
1194  /* More than two handles? Then, we're not booting anymore */
1195  if (HandleCount > 2)
1196  {
1197  ForceLock = FALSE;
1198  break;
1199  }
1200  }
1201  }
1202  else
1203  {
1204  ForceLock = FALSE;
1205  }
1206 
1207  /* Here comes the hack, ignore the failure! */
1208  if (!ForceLock)
1209  {
1210 #endif
1211 
1212  DPRINT1("Can't lock: %u opened\n", DeviceExt->OpenHandleCount);
1213 
1214  ListEntry = DeviceExt->FcbListHead.Flink;
1215  while (ListEntry != &DeviceExt->FcbListHead)
1216  {
1217  Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
1218  ListEntry = ListEntry->Flink;
1219 
1220  if (Fcb->OpenHandleCount > 0)
1221  {
1222  DPRINT1("Opened (%u - %u): %wZ\n", Fcb->OpenHandleCount, Fcb->RefCount, &Fcb->PathNameU);
1223  }
1224  }
1225 
1227 
1228  return STATUS_ACCESS_DENIED;
1229 
1230 #if 1
1231  /* End of the hack: be verbose about its usage,
1232  * just in case we would mess up everything!
1233  */
1234  }
1235  else
1236  {
1237  DPRINT1("HACK: Using lock-hack!\n");
1238  }
1239 #endif
1240  }
1241 
1242  /* Finally, proceed */
1243  if (Lock)
1244  {
1245  /* Flush volume & files */
1246  VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
1247 
1248  /* The volume is now clean */
1249  if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY) &&
1250  BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1251  {
1252  /* Drop the dirty bit */
1253  if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
1254  ClearFlag(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY);
1255  }
1256 
1257  DeviceExt->Flags |= VCB_VOLUME_LOCKED;
1258  Vpb->Flags |= VPB_LOCKED;
1259  }
1260  else
1261  {
1262  DeviceExt->Flags &= ~VCB_VOLUME_LOCKED;
1263  Vpb->Flags &= ~VPB_LOCKED;
1264 
1266  }
1267 
1268  return STATUS_SUCCESS;
1269 }
1270 
1271 static
1272 NTSTATUS
1274  PVFAT_IRP_CONTEXT IrpContext)
1275 {
1276  PDEVICE_EXTENSION DeviceExt;
1277  PLIST_ENTRY NextEntry;
1278  PVFATFCB Fcb;
1280 
1281  DPRINT("VfatDismountVolume(%p)\n", IrpContext);
1282 
1283  DeviceExt = IrpContext->DeviceExt;
1284  FileObject = IrpContext->FileObject;
1285 
1286  /* We HAVE to be locked. Windows also allows dismount with no lock
1287  * but we're here mainly for 1st stage, so KISS
1288  */
1289  if (!BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
1290  {
1291  return STATUS_ACCESS_DENIED;
1292  }
1293 
1294  /* Deny dismount of boot volume */
1295  if (BooleanFlagOn(DeviceExt->Flags, VCB_IS_SYS_OR_HAS_PAGE))
1296  {
1297  return STATUS_ACCESS_DENIED;
1298  }
1299 
1300  /* Race condition? */
1301  if (BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
1302  {
1303  return STATUS_VOLUME_DISMOUNTED;
1304  }
1305 
1306  /* Notify we'll dismount. Pass that point there's no reason we fail */
1308 
1309  ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
1310 
1311  /* Flush volume & files */
1312  VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);
1313 
1314  /* The volume is now clean */
1315  if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY) &&
1316  BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY))
1317  {
1318  /* Drop the dirty bit */
1319  if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
1320  DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
1321  }
1322 
1323  /* Rebrowse the FCB in order to free them now */
1324  while (!IsListEmpty(&DeviceExt->FcbListHead))
1325  {
1326  NextEntry = RemoveTailList(&DeviceExt->FcbListHead);
1327  Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
1328 
1329  if (Fcb == DeviceExt->RootFcb)
1330  DeviceExt->RootFcb = NULL;
1331  else if (Fcb == DeviceExt->VolumeFcb)
1332  DeviceExt->VolumeFcb = NULL;
1333 
1335  }
1336 
1337  /* We are uninitializing, the VCB cannot be used anymore */
1338  ClearFlag(DeviceExt->Flags, VCB_GOOD);
1339 
1340  /* Mark we're being dismounted */
1341  DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
1342 #ifndef ENABLE_SWAPOUT
1343  IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
1344 #endif
1345 
1346  ExReleaseResourceLite(&DeviceExt->FatResource);
1347 
1348  return STATUS_SUCCESS;
1349 }
1350 
1351 static
1352 NTSTATUS
1354  PVFAT_IRP_CONTEXT IrpContext)
1355 {
1356  PVOID Buffer;
1357  ULONG Length;
1358  NTSTATUS Status;
1359  PDEVICE_EXTENSION DeviceExt;
1360 
1361  DeviceExt = IrpContext->DeviceExt;
1362  Length = IrpContext->Stack->Parameters.FileSystemControl.OutputBufferLength;
1363  Buffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
1364 
1365  if (Length < sizeof(FILESYSTEM_STATISTICS))
1366  {
1367  return STATUS_BUFFER_TOO_SMALL;
1368  }
1369 
1370  if (Buffer == NULL)
1371  {
1373  }
1374 
1376  {
1379  }
1380  else
1381  {
1383  }
1384 
1385  RtlCopyMemory(Buffer, DeviceExt->Statistics, Length);
1386  IrpContext->Irp->IoStatus.Information = Length;
1387 
1388  return Status;
1389 }
1390 
1391 /*
1392  * FUNCTION: File system control
1393  */
1394 NTSTATUS
1396  PVFAT_IRP_CONTEXT IrpContext)
1397 {
1398  NTSTATUS Status;
1399 
1400  DPRINT("VfatFileSystemControl(IrpContext %p)\n", IrpContext);
1401 
1402  ASSERT(IrpContext);
1403  ASSERT(IrpContext->Irp);
1404  ASSERT(IrpContext->Stack);
1405 
1406  IrpContext->Irp->IoStatus.Information = 0;
1407 
1408  switch (IrpContext->MinorFunction)
1409  {
1410  case IRP_MN_KERNEL_CALL:
1412  switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
1413  {
1415  Status = VfatGetVolumeBitmap(IrpContext);
1416  break;
1417 
1419  Status = VfatGetRetrievalPointers(IrpContext);
1420  break;
1421 
1422  case FSCTL_MOVE_FILE:
1423  Status = VfatMoveFile(IrpContext);
1424  break;
1425 
1426  case FSCTL_IS_VOLUME_DIRTY:
1427  Status = VfatIsVolumeDirty(IrpContext);
1428  break;
1429 
1431  Status = VfatMarkVolumeDirty(IrpContext);
1432  break;
1433 
1434  case FSCTL_LOCK_VOLUME:
1435  Status = VfatLockOrUnlockVolume(IrpContext, TRUE);
1436  break;
1437 
1438  case FSCTL_UNLOCK_VOLUME:
1439  Status = VfatLockOrUnlockVolume(IrpContext, FALSE);
1440  break;
1441 
1442  case FSCTL_DISMOUNT_VOLUME:
1443  Status = VfatDismountVolume(IrpContext);
1444  break;
1445 
1447  Status = VfatGetStatistics(IrpContext);
1448  break;
1449 
1450  default:
1452  }
1453  break;
1454 
1455  case IRP_MN_MOUNT_VOLUME:
1456  Status = VfatMount(IrpContext);
1457  break;
1458 
1459  case IRP_MN_VERIFY_VOLUME:
1460  DPRINT("VFATFS: IRP_MN_VERIFY_VOLUME\n");
1461  Status = VfatVerify(IrpContext);
1462  break;
1463 
1464  default:
1465  DPRINT("VFAT FSC: MinorFunction %u\n", IrpContext->MinorFunction);
1467  break;
1468  }
1469 
1470  return Status;
1471 }
VFAT_DISPATCH FatDispatch
Definition: dirwr.c:1173
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:846
#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
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:416
#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:2029
static NTSTATUS VfatMount(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:525
struct _Entry Entry
Definition: kefuncs.h:627
Definition: vfat.h:447
BOOLEAN FixedMedia
Definition: vfat.h:266
USHORT MaximumLength
Definition: env_spec_w32.h:370
PFILE_OBJECT FileObject
Definition: ntfs.h:516
Definition: vfat.h:536
PDEVICE_EXTENSION DeviceExt
Definition: vfat.h:585
struct _VFATCCB * PVFATCCB
ULONG vfatDirEntryGetFirstCluster(PDEVICE_EXTENSION pDeviceExt, PDIR_ENTRY pFatDirEntry)
Definition: direntry.c:19
#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
NTSTATUS FAT16GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:856
PDRIVER_OBJECT DriverObject
Definition: vfat.h:411
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:637
#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:442
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
NTSTATUS FAT32SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1127
IO_STATUS_BLOCK IoStatus
#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:591
ULONG FatType
Definition: vfat.h:264
#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
#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:69
_SEH2_TRY
Definition: create.c:4226
#define PARTITION_XINT13
Definition: disk.h:97
uint32_t ULONG_PTR
Definition: typedefs.h:65
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:4384
_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:551
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define FALSE
Definition: types.h:117
#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:940
#define VPB_LOCKED
Definition: iotypes.h:1788
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
PFILE_OBJECT FileObject
Definition: vfat.h:499
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG Flags
Definition: vfat.h:496
LARGE_INTEGER StartingVcn
Definition: winioctl.h:527
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:238
NTSTATUS FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
Definition: fat.c:242
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:531
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:414
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:156
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:588
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
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:513
#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:650
struct RETRIEVAL_POINTERS_BUFFER::@3297 Extents[1]
FORCEINLINE BOOLEAN vfatVolumeIsFatX(PDEVICE_EXTENSION DeviceExt)
Definition: vfat.h:651
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4383
ULONG OpenHandleCount
Definition: ntfs.h:533
int64_t LONGLONG
Definition: typedefs.h:68
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4382
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
#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:1166
__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
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:1081
MEDIA_TYPE MediaType
Definition: ntdddisk.h:439
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:1102
_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:1821
* PFILE_OBJECT
Definition: iotypes.h:1978
FSRTL_COMMON_FCB_HEADER RFCB
Definition: vfat.h:450
Definition: partlist.h:33
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG Flags
Definition: ntfs.h:532
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FCB_IS_FAT
Definition: vfat.h:435
VOID vfatDestroyCCB(PVFATCCB pCcb)
Definition: fcb.c:258
char * PBOOLEAN
Definition: retypes.h:11
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4387
#define VCB_IS_FATX
Definition: vfat.h:242
#define VCB_GOOD
Definition: vfat.h:247
Status
Definition: gdiplustypes.h:24
static NTSTATUS VfatIsVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1053
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
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:950
#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
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:361
NTSYSAPI NTSTATUS NTAPI RtlOemStringToUnicodeString(PUNICODE_STRING DestinationString, PCOEM_STRING SourceString, BOOLEAN AllocateDestinationString)
ERESOURCE MainResource
Definition: ntfs.h:524
#define FAT16
Definition: fat.h:168
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1395
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
#define TAG_STATS
Definition: vfat.h:550
static NTSTATUS VfatDismountVolume(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1273
Definition: vfat.h:249
static NTSTATUS VfatGetStatistics(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1353
PVFAT_GLOBAL_DATA VfatGlobalData
Definition: iface.c:40
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: vfat.h:422
#define FCB_IS_VOLUME
Definition: vfat.h:437
NTSTATUS FAT32GetDirtyStatus(PDEVICE_EXTENSION DeviceExt, PBOOLEAN DirtyStatus)
Definition: fat.c:934
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:3148
_SEH2_END
Definition: create.c:4400
struct RETRIEVAL_POINTERS_BUFFER RETRIEVAL_POINTERS_BUFFER
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
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: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
#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
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define FATX16
Definition: fat.h:170
unsigned int * PULONG
Definition: retypes.h:1
PDEVICE_OBJECT DeviceObject
Definition: vfat.h:584
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: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
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:168
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#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:262
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
struct _LARGE_INTEGER::@2267 u
#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:3107
_In_ PFCB Fcb
Definition: cdprocs.h:159
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:588
return STATUS_SUCCESS
Definition: btrfs.c:3014
NTSTATUS SetDirtyStatus(PDEVICE_EXTENSION DeviceExt, BOOLEAN DirtyStatus)
Definition: fat.c:1015
#define VPB_MOUNTED
Definition: iotypes.h:1787
static NTSTATUS VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
Definition: fsctl.c:1044
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:673
#define TAG_DIRENT
Definition: vfat.h:555
_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
#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